@better-update/cli 0.3.0 → 0.3.2
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/index.js +5319 -0
- package/dist/index.js.map +1 -0
- package/package.json +12 -9
- package/CHANGELOG.md +0 -58
- package/oxlint.config.ts +0 -6
- package/src/app-layer.ts +0 -29
- package/src/application/build-workflow.ts +0 -222
- package/src/application/command-exit.ts +0 -13
- package/src/application/login.ts +0 -87
- package/src/application/update-promote.ts +0 -88
- package/src/application/update-publish.ts +0 -402
- package/src/application/update-rollback.ts +0 -275
- package/src/commands/analytics/adoption.ts +0 -40
- package/src/commands/analytics/channels.ts +0 -35
- package/src/commands/analytics/helpers.ts +0 -3
- package/src/commands/analytics/index.ts +0 -13
- package/src/commands/analytics/platforms.ts +0 -39
- package/src/commands/analytics/updates.ts +0 -35
- package/src/commands/audit-logs/helpers.ts +0 -3
- package/src/commands/audit-logs/index.ts +0 -8
- package/src/commands/audit-logs/list.ts +0 -66
- package/src/commands/branches.ts +0 -70
- package/src/commands/build/android.ts +0 -129
- package/src/commands/build/index.ts +0 -63
- package/src/commands/build/ios.ts +0 -199
- package/src/commands/build/reserve-and-upload.test.ts +0 -263
- package/src/commands/build/reserve-and-upload.ts +0 -160
- package/src/commands/build/run-step.ts +0 -131
- package/src/commands/builds/compatibility-matrix.ts +0 -48
- package/src/commands/builds/delete.ts +0 -15
- package/src/commands/builds/get.ts +0 -34
- package/src/commands/builds/helpers.ts +0 -3
- package/src/commands/builds/index.ts +0 -20
- package/src/commands/builds/install-link.ts +0 -20
- package/src/commands/builds/list.ts +0 -38
- package/src/commands/channels/create.ts +0 -37
- package/src/commands/channels/delete.ts +0 -15
- package/src/commands/channels/helpers.ts +0 -18
- package/src/commands/channels/index.ts +0 -24
- package/src/commands/channels/list.ts +0 -38
- package/src/commands/channels/pause.ts +0 -15
- package/src/commands/channels/resume.ts +0 -15
- package/src/commands/channels/rollout/complete.ts +0 -17
- package/src/commands/channels/rollout/create.ts +0 -36
- package/src/commands/channels/rollout/index.ts +0 -11
- package/src/commands/channels/rollout/revert.ts +0 -17
- package/src/commands/channels/rollout/update.ts +0 -23
- package/src/commands/channels/update.ts +0 -32
- package/src/commands/credentials/delete.ts +0 -24
- package/src/commands/credentials/index.ts +0 -10
- package/src/commands/credentials/list.ts +0 -33
- package/src/commands/credentials/upload.ts +0 -91
- package/src/commands/env/delete.ts +0 -35
- package/src/commands/env/export.ts +0 -27
- package/src/commands/env/get.ts +0 -25
- package/src/commands/env/helpers.ts +0 -13
- package/src/commands/env/import.ts +0 -31
- package/src/commands/env/index.ts +0 -24
- package/src/commands/env/list.ts +0 -44
- package/src/commands/env/pull.ts +0 -27
- package/src/commands/env/set.ts +0 -42
- package/src/commands/fingerprint/compare.ts +0 -25
- package/src/commands/fingerprint/generate.ts +0 -18
- package/src/commands/fingerprint/index.ts +0 -9
- package/src/commands/init.ts +0 -35
- package/src/commands/login.ts +0 -13
- package/src/commands/logout.ts +0 -12
- package/src/commands/projects.ts +0 -84
- package/src/commands/status.ts +0 -48
- package/src/commands/update/delete.ts +0 -15
- package/src/commands/update/helpers.ts +0 -22
- package/src/commands/update/index.ts +0 -22
- package/src/commands/update/list.ts +0 -60
- package/src/commands/update/promote.ts +0 -30
- package/src/commands/update/publish.ts +0 -94
- package/src/commands/update/rollback.ts +0 -42
- package/src/commands/update/rollout/complete.ts +0 -17
- package/src/commands/update/rollout/index.ts +0 -10
- package/src/commands/update/rollout/revert.ts +0 -17
- package/src/commands/update/rollout/set.ts +0 -23
- package/src/index.ts +0 -53
- package/src/lib/android-keystore.test.ts +0 -114
- package/src/lib/android-keystore.ts +0 -76
- package/src/lib/android-signing-gradle.test.ts +0 -95
- package/src/lib/android-signing-gradle.ts +0 -52
- package/src/lib/app-json.ts +0 -81
- package/src/lib/apple-auth.test.ts +0 -402
- package/src/lib/apple-auth.ts +0 -132
- package/src/lib/artifact-finder.test.ts +0 -195
- package/src/lib/artifact-finder.ts +0 -122
- package/src/lib/browser-login.test.ts +0 -88
- package/src/lib/browser-login.ts +0 -193
- package/src/lib/build-profile.test.ts +0 -290
- package/src/lib/build-profile.ts +0 -234
- package/src/lib/cli-schemas.ts +0 -39
- package/src/lib/command-errors.ts +0 -60
- package/src/lib/credentials-downloader.ts +0 -181
- package/src/lib/credentials-manager.ts +0 -354
- package/src/lib/env-exporter.test.ts +0 -96
- package/src/lib/env-exporter.ts +0 -28
- package/src/lib/exit-codes.ts +0 -82
- package/src/lib/expo-config.ts +0 -130
- package/src/lib/expo-export.test.ts +0 -94
- package/src/lib/expo-export.ts +0 -281
- package/src/lib/fingerprint.ts +0 -67
- package/src/lib/format-error.ts +0 -22
- package/src/lib/git-context.ts +0 -56
- package/src/lib/gradle-config.ts +0 -126
- package/src/lib/ios-export-options.test.ts +0 -98
- package/src/lib/ios-export-options.ts +0 -62
- package/src/lib/ios-keychain.ts +0 -181
- package/src/lib/ios-provisioning.test.ts +0 -115
- package/src/lib/ios-provisioning.ts +0 -179
- package/src/lib/output.ts +0 -32
- package/src/lib/pkcs12.ts +0 -73
- package/src/lib/plist.ts +0 -39
- package/src/lib/post-build-validation.ts +0 -146
- package/src/lib/presigned-upload.test.ts +0 -140
- package/src/lib/presigned-upload.ts +0 -35
- package/src/lib/record.ts +0 -5
- package/src/lib/resolve-named-resource.ts +0 -24
- package/src/lib/runtime-version.test.ts +0 -119
- package/src/lib/runtime-version.ts +0 -62
- package/src/lib/sha256.test.ts +0 -108
- package/src/lib/sha256.ts +0 -80
- package/src/lib/signed-payloads.test.ts +0 -181
- package/src/lib/signed-payloads.ts +0 -164
- package/src/lib/string-utils.ts +0 -4
- package/src/lib/temp-dir.ts +0 -14
- package/src/lib/test-utils.ts +0 -13
- package/src/lib/update-platforms.test.ts +0 -45
- package/src/lib/update-platforms.ts +0 -19
- package/src/lib/xcpretty-formatter.ts +0 -21
- package/src/services/api-client.ts +0 -42
- package/src/services/apple-session-store.ts +0 -100
- package/src/services/auth-store.ts +0 -85
- package/src/services/cli-runtime.ts +0 -46
- package/src/services/config-store.ts +0 -108
- package/src/services/presigned-upload.ts +0 -84
- package/src/services/update-asset-uploader.ts +0 -72
- package/src/types/keychain.d.ts +0 -22
- package/tests/e2e/build.test.ts +0 -270
- package/tests/e2e/commands.test.ts +0 -694
- package/tests/e2e/ota-lifecycle.test.ts +0 -275
- package/tests/e2e/publish.test.ts +0 -150
- package/tests/helpers/cli-e2e.ts +0 -426
- package/tests/helpers/pty-driver.ts +0 -142
- package/tests/interactive/harness/provider-prompt.ts +0 -54
- package/tests/interactive/login.test.ts +0 -47
- package/tests/interactive/provider-select.test.ts +0 -59
- package/tsconfig.json +0 -7
- package/vitest.config.ts +0 -38
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
import { Command, Options } from "@effect/cli";
|
|
2
|
-
import { Console, Effect, Option } from "effect";
|
|
3
|
-
|
|
4
|
-
import { filterCredentials, listAllCredentials } from "../../lib/credentials-manager";
|
|
5
|
-
import { printTable } from "../../lib/output";
|
|
6
|
-
import { apiClient } from "../../services/api-client";
|
|
7
|
-
|
|
8
|
-
const platform = Options.choice("platform", ["ios", "android"] as const).pipe(Options.optional);
|
|
9
|
-
|
|
10
|
-
export const listCommand = Command.make("list", { platform }, (opts) =>
|
|
11
|
-
Effect.gen(function* () {
|
|
12
|
-
const api = yield* apiClient;
|
|
13
|
-
const rows = yield* listAllCredentials(api);
|
|
14
|
-
|
|
15
|
-
const filtered = filterCredentials(
|
|
16
|
-
rows,
|
|
17
|
-
Option.match(opts.platform, {
|
|
18
|
-
onNone: () => ({}),
|
|
19
|
-
onSome: (platformValue) => ({ platform: platformValue }),
|
|
20
|
-
}),
|
|
21
|
-
);
|
|
22
|
-
|
|
23
|
-
if (filtered.length === 0) {
|
|
24
|
-
yield* Console.log("No credentials found.");
|
|
25
|
-
return;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
yield* printTable(
|
|
29
|
-
["ID", "Name", "Platform", "Type", "Distribution"],
|
|
30
|
-
filtered.map((row) => [row.id, row.name, row.platform, row.type, row.distribution ?? "-"]),
|
|
31
|
-
);
|
|
32
|
-
}),
|
|
33
|
-
);
|
|
@@ -1,91 +0,0 @@
|
|
|
1
|
-
import { Command, Options } from "@effect/cli";
|
|
2
|
-
import { Console, Effect, Option } from "effect";
|
|
3
|
-
|
|
4
|
-
import { uploadCredential } from "../../lib/credentials-manager";
|
|
5
|
-
import { printKeyValue } from "../../lib/output";
|
|
6
|
-
import { apiClient } from "../../services/api-client";
|
|
7
|
-
|
|
8
|
-
import type { CliCredentialType } from "../../lib/credentials-manager";
|
|
9
|
-
|
|
10
|
-
const platform = Options.choice("platform", ["ios", "android"] as const);
|
|
11
|
-
const type = Options.choice("type", [
|
|
12
|
-
"distribution-certificate",
|
|
13
|
-
"provisioning-profile",
|
|
14
|
-
"push-key",
|
|
15
|
-
"asc-api-key",
|
|
16
|
-
"keystore",
|
|
17
|
-
"google-service-account-key",
|
|
18
|
-
] as const);
|
|
19
|
-
const name = Options.text("name");
|
|
20
|
-
const file = Options.text("file");
|
|
21
|
-
|
|
22
|
-
const password = Options.text("password").pipe(Options.optional);
|
|
23
|
-
const keyAlias = Options.text("key-alias").pipe(Options.optional);
|
|
24
|
-
const keyPassword = Options.text("key-password").pipe(Options.optional);
|
|
25
|
-
const keyId = Options.text("key-id").pipe(Options.optional);
|
|
26
|
-
const issuerId = Options.text("issuer-id").pipe(Options.optional);
|
|
27
|
-
const appleTeamIdentifier = Options.text("apple-team-identifier").pipe(Options.optional);
|
|
28
|
-
|
|
29
|
-
export const uploadCommand = Command.make(
|
|
30
|
-
"upload",
|
|
31
|
-
{
|
|
32
|
-
platform,
|
|
33
|
-
type,
|
|
34
|
-
name,
|
|
35
|
-
file,
|
|
36
|
-
password,
|
|
37
|
-
keyAlias,
|
|
38
|
-
keyPassword,
|
|
39
|
-
keyId,
|
|
40
|
-
issuerId,
|
|
41
|
-
appleTeamIdentifier,
|
|
42
|
-
},
|
|
43
|
-
(opts) =>
|
|
44
|
-
Effect.gen(function* () {
|
|
45
|
-
const api = yield* apiClient;
|
|
46
|
-
|
|
47
|
-
const passwordOpt = Option.getOrUndefined(opts.password);
|
|
48
|
-
const keyAliasOpt = Option.getOrUndefined(opts.keyAlias);
|
|
49
|
-
const keyPasswordOpt = Option.getOrUndefined(opts.keyPassword);
|
|
50
|
-
const keyIdOpt = Option.getOrUndefined(opts.keyId);
|
|
51
|
-
const issuerIdOpt = Option.getOrUndefined(opts.issuerId);
|
|
52
|
-
const appleTeamIdentifierOpt = Option.getOrUndefined(opts.appleTeamIdentifier);
|
|
53
|
-
|
|
54
|
-
const input: {
|
|
55
|
-
readonly platform: typeof opts.platform;
|
|
56
|
-
readonly type: CliCredentialType;
|
|
57
|
-
readonly name: string;
|
|
58
|
-
readonly filePath: string;
|
|
59
|
-
readonly password?: string;
|
|
60
|
-
readonly keyAlias?: string;
|
|
61
|
-
readonly keyPassword?: string;
|
|
62
|
-
readonly keyId?: string;
|
|
63
|
-
readonly issuerId?: string;
|
|
64
|
-
readonly appleTeamIdentifier?: string;
|
|
65
|
-
} = {
|
|
66
|
-
platform: opts.platform,
|
|
67
|
-
type: opts.type,
|
|
68
|
-
name: opts.name,
|
|
69
|
-
filePath: opts.file,
|
|
70
|
-
...(passwordOpt === undefined ? {} : { password: passwordOpt }),
|
|
71
|
-
...(keyAliasOpt === undefined ? {} : { keyAlias: keyAliasOpt }),
|
|
72
|
-
...(keyPasswordOpt === undefined ? {} : { keyPassword: keyPasswordOpt }),
|
|
73
|
-
...(keyIdOpt === undefined ? {} : { keyId: keyIdOpt }),
|
|
74
|
-
...(issuerIdOpt === undefined ? {} : { issuerId: issuerIdOpt }),
|
|
75
|
-
...(appleTeamIdentifierOpt === undefined
|
|
76
|
-
? {}
|
|
77
|
-
: { appleTeamIdentifier: appleTeamIdentifierOpt }),
|
|
78
|
-
};
|
|
79
|
-
|
|
80
|
-
const credential = yield* uploadCredential(api, input);
|
|
81
|
-
|
|
82
|
-
yield* Console.log("Credential uploaded successfully.");
|
|
83
|
-
yield* Console.log("");
|
|
84
|
-
yield* printKeyValue([
|
|
85
|
-
["ID", credential.id],
|
|
86
|
-
["Name", credential.name],
|
|
87
|
-
["Platform", credential.platform],
|
|
88
|
-
["Type", credential.type],
|
|
89
|
-
]);
|
|
90
|
-
}),
|
|
91
|
-
);
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
import { Args, Command, Options } from "@effect/cli";
|
|
2
|
-
import { Console, Effect } from "effect";
|
|
3
|
-
|
|
4
|
-
import { readProjectId } from "../../lib/app-json";
|
|
5
|
-
import { apiClient } from "../../services/api-client";
|
|
6
|
-
import { EnvResourceNotFoundError, handleEnvCommandErrors } from "./helpers";
|
|
7
|
-
|
|
8
|
-
const keyArg = Args.text({ name: "KEY" });
|
|
9
|
-
const environmentOption = Options.text("environment").pipe(Options.withDefault("production"));
|
|
10
|
-
|
|
11
|
-
export const deleteCommand = Command.make(
|
|
12
|
-
"delete",
|
|
13
|
-
{ key: keyArg, environment: environmentOption },
|
|
14
|
-
({ key, environment }) =>
|
|
15
|
-
Effect.gen(function* () {
|
|
16
|
-
const projectId = yield* readProjectId;
|
|
17
|
-
const api = yield* apiClient;
|
|
18
|
-
|
|
19
|
-
const existing = yield* api["env-vars"].list({
|
|
20
|
-
urlParams: { projectId, environment },
|
|
21
|
-
});
|
|
22
|
-
|
|
23
|
-
const match = existing.items.find((item) => item.key === key);
|
|
24
|
-
|
|
25
|
-
if (!match) {
|
|
26
|
-
return yield* new EnvResourceNotFoundError({
|
|
27
|
-
message: `Environment variable ${key} not found in ${environment}`,
|
|
28
|
-
});
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
yield* api["env-vars"].delete({ path: { id: match.id } });
|
|
32
|
-
yield* Console.log(`Deleted ${key} from ${environment}`);
|
|
33
|
-
return undefined;
|
|
34
|
-
}).pipe(handleEnvCommandErrors),
|
|
35
|
-
);
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
import { Command, Options } from "@effect/cli";
|
|
2
|
-
import { Console, Effect } from "effect";
|
|
3
|
-
|
|
4
|
-
import { readProjectId } from "../../lib/app-json";
|
|
5
|
-
import { apiClient } from "../../services/api-client";
|
|
6
|
-
import { handleEnvCommandErrors } from "./helpers";
|
|
7
|
-
|
|
8
|
-
const environmentOption = Options.text("environment").pipe(Options.withDefault("production"));
|
|
9
|
-
|
|
10
|
-
export const exportCommand = Command.make(
|
|
11
|
-
"export",
|
|
12
|
-
{ environment: environmentOption },
|
|
13
|
-
({ environment }) =>
|
|
14
|
-
Effect.gen(function* () {
|
|
15
|
-
const projectId = yield* readProjectId;
|
|
16
|
-
const api = yield* apiClient;
|
|
17
|
-
|
|
18
|
-
const result = yield* api["env-vars"].export({
|
|
19
|
-
urlParams: { projectId, environment },
|
|
20
|
-
});
|
|
21
|
-
|
|
22
|
-
for (const item of result.items) {
|
|
23
|
-
const escaped = item.value.replaceAll("'", String.raw`'\''`);
|
|
24
|
-
yield* Console.log(`${item.key}='${escaped}'`);
|
|
25
|
-
}
|
|
26
|
-
}).pipe(handleEnvCommandErrors),
|
|
27
|
-
);
|
package/src/commands/env/get.ts
DELETED
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
import { Args, Command } from "@effect/cli";
|
|
2
|
-
import { Effect } from "effect";
|
|
3
|
-
|
|
4
|
-
import { printKeyValue } from "../../lib/output";
|
|
5
|
-
import { apiClient } from "../../services/api-client";
|
|
6
|
-
import { handleEnvCommandErrors } from "./helpers";
|
|
7
|
-
|
|
8
|
-
const id = Args.text({ name: "id" });
|
|
9
|
-
|
|
10
|
-
export const getCommand = Command.make("get", { id }, (opts) =>
|
|
11
|
-
Effect.gen(function* () {
|
|
12
|
-
const api = yield* apiClient;
|
|
13
|
-
const envVar = yield* api["env-vars"].get({ path: { id: opts.id } });
|
|
14
|
-
yield* printKeyValue([
|
|
15
|
-
["ID", envVar.id],
|
|
16
|
-
["Key", envVar.key],
|
|
17
|
-
["Environment", envVar.environment],
|
|
18
|
-
["Visibility", envVar.visibility],
|
|
19
|
-
// eslint-disable-next-line eslint-js/no-restricted-syntax -- EnvVar.value nullable at storage; display empty when absent
|
|
20
|
-
["Value", envVar.visibility === "plaintext" ? (envVar.value ?? "") : "******"],
|
|
21
|
-
["Created", envVar.createdAt],
|
|
22
|
-
["Updated", envVar.updatedAt],
|
|
23
|
-
]);
|
|
24
|
-
}).pipe(handleEnvCommandErrors),
|
|
25
|
-
);
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import { Data } from "effect";
|
|
2
|
-
|
|
3
|
-
import { makeCommandErrorHandler } from "../../lib/command-errors";
|
|
4
|
-
|
|
5
|
-
export class EnvResourceNotFoundError extends Data.TaggedError("EnvResourceNotFoundError")<{
|
|
6
|
-
readonly message: string;
|
|
7
|
-
}> {}
|
|
8
|
-
|
|
9
|
-
export const handleEnvCommandErrors = makeCommandErrorHandler({
|
|
10
|
-
EnvResourceNotFoundError: 1,
|
|
11
|
-
SystemError: 6,
|
|
12
|
-
BadArgument: 6,
|
|
13
|
-
});
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
import { Args, Command, Options } from "@effect/cli";
|
|
2
|
-
import { FileSystem } from "@effect/platform";
|
|
3
|
-
import { Console, Effect } from "effect";
|
|
4
|
-
|
|
5
|
-
import { readProjectId } from "../../lib/app-json";
|
|
6
|
-
import { apiClient } from "../../services/api-client";
|
|
7
|
-
import { handleEnvCommandErrors } from "./helpers";
|
|
8
|
-
|
|
9
|
-
const fileArg = Args.text({ name: "file" });
|
|
10
|
-
const environmentOption = Options.text("environment").pipe(Options.withDefault("production"));
|
|
11
|
-
|
|
12
|
-
export const importCommand = Command.make(
|
|
13
|
-
"import",
|
|
14
|
-
{ file: fileArg, environment: environmentOption },
|
|
15
|
-
({ file, environment }) =>
|
|
16
|
-
Effect.gen(function* () {
|
|
17
|
-
const fs = yield* FileSystem.FileSystem;
|
|
18
|
-
const content = yield* fs.readFileString(file);
|
|
19
|
-
|
|
20
|
-
const projectId = yield* readProjectId;
|
|
21
|
-
const api = yield* apiClient;
|
|
22
|
-
|
|
23
|
-
const result = yield* api["env-vars"].bulkImport({
|
|
24
|
-
payload: { projectId, environment, content, visibility: "plaintext" },
|
|
25
|
-
});
|
|
26
|
-
|
|
27
|
-
yield* Console.log(
|
|
28
|
-
`Imported: ${String(result.created)} created, ${String(result.updated)} updated, ${String(result.skipped)} skipped`,
|
|
29
|
-
);
|
|
30
|
-
}).pipe(handleEnvCommandErrors),
|
|
31
|
-
);
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
import { Command } from "@effect/cli";
|
|
2
|
-
import { Console } from "effect";
|
|
3
|
-
|
|
4
|
-
import { deleteCommand } from "./delete";
|
|
5
|
-
import { exportCommand } from "./export";
|
|
6
|
-
import { getCommand } from "./get";
|
|
7
|
-
import { importCommand } from "./import";
|
|
8
|
-
import { listCommand } from "./list";
|
|
9
|
-
import { pullCommand } from "./pull";
|
|
10
|
-
import { setCommand } from "./set";
|
|
11
|
-
|
|
12
|
-
export const envCommand = Command.make("env", {}, () =>
|
|
13
|
-
Console.log("Manage environment variables. Run with --help for subcommands."),
|
|
14
|
-
).pipe(
|
|
15
|
-
Command.withSubcommands([
|
|
16
|
-
listCommand,
|
|
17
|
-
getCommand,
|
|
18
|
-
setCommand,
|
|
19
|
-
deleteCommand,
|
|
20
|
-
importCommand,
|
|
21
|
-
exportCommand,
|
|
22
|
-
pullCommand,
|
|
23
|
-
]),
|
|
24
|
-
);
|
package/src/commands/env/list.ts
DELETED
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
import { Command, Options } from "@effect/cli";
|
|
2
|
-
import { Console, Effect, Option } from "effect";
|
|
3
|
-
|
|
4
|
-
import { readProjectId } from "../../lib/app-json";
|
|
5
|
-
import { printTable } from "../../lib/output";
|
|
6
|
-
import { apiClient } from "../../services/api-client";
|
|
7
|
-
import { handleEnvCommandErrors } from "./helpers";
|
|
8
|
-
|
|
9
|
-
const environmentOption = Options.text("environment").pipe(Options.optional);
|
|
10
|
-
|
|
11
|
-
export const listCommand = Command.make(
|
|
12
|
-
"list",
|
|
13
|
-
{ environment: environmentOption },
|
|
14
|
-
({ environment }) =>
|
|
15
|
-
Effect.gen(function* () {
|
|
16
|
-
const projectId = yield* readProjectId;
|
|
17
|
-
const api = yield* apiClient;
|
|
18
|
-
|
|
19
|
-
const envFilter = Option.match(environment, {
|
|
20
|
-
onNone: () => ({}),
|
|
21
|
-
onSome: (value) => ({ environment: value }),
|
|
22
|
-
});
|
|
23
|
-
|
|
24
|
-
const result = yield* api["env-vars"].list({
|
|
25
|
-
urlParams: { projectId, ...envFilter },
|
|
26
|
-
});
|
|
27
|
-
|
|
28
|
-
if (result.items.length === 0) {
|
|
29
|
-
yield* Console.log("No environment variables found.");
|
|
30
|
-
return;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
yield* printTable(
|
|
34
|
-
["Key", "Environment", "Visibility", "Value"],
|
|
35
|
-
result.items.map((item) => [
|
|
36
|
-
item.key,
|
|
37
|
-
item.environment,
|
|
38
|
-
item.visibility,
|
|
39
|
-
// eslint-disable-next-line eslint-js/no-restricted-syntax -- EnvVar.value nullable at storage; display empty when absent
|
|
40
|
-
item.visibility === "plaintext" ? (item.value ?? "") : "••••••",
|
|
41
|
-
]),
|
|
42
|
-
);
|
|
43
|
-
}).pipe(handleEnvCommandErrors),
|
|
44
|
-
);
|
package/src/commands/env/pull.ts
DELETED
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
import { Command, Options } from "@effect/cli";
|
|
2
|
-
import { Console, Effect } from "effect";
|
|
3
|
-
|
|
4
|
-
import { readProjectId } from "../../lib/app-json";
|
|
5
|
-
import { apiClient } from "../../services/api-client";
|
|
6
|
-
import { handleEnvCommandErrors } from "./helpers";
|
|
7
|
-
|
|
8
|
-
const environmentOption = Options.text("environment").pipe(Options.withDefault("production"));
|
|
9
|
-
|
|
10
|
-
export const pullCommand = Command.make(
|
|
11
|
-
"pull",
|
|
12
|
-
{ environment: environmentOption },
|
|
13
|
-
({ environment }) =>
|
|
14
|
-
Effect.gen(function* () {
|
|
15
|
-
const projectId = yield* readProjectId;
|
|
16
|
-
const api = yield* apiClient;
|
|
17
|
-
|
|
18
|
-
const result = yield* api["env-vars"].export({
|
|
19
|
-
urlParams: { projectId, environment },
|
|
20
|
-
});
|
|
21
|
-
|
|
22
|
-
for (const item of result.items) {
|
|
23
|
-
const escaped = item.value.replaceAll("'", String.raw`'\''`);
|
|
24
|
-
yield* Console.log(`export ${item.key}='${escaped}'`);
|
|
25
|
-
}
|
|
26
|
-
}).pipe(handleEnvCommandErrors),
|
|
27
|
-
);
|
package/src/commands/env/set.ts
DELETED
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
import { Command, Options } from "@effect/cli";
|
|
2
|
-
import { Console, Effect } from "effect";
|
|
3
|
-
|
|
4
|
-
import { readProjectId } from "../../lib/app-json";
|
|
5
|
-
import { keyValueArg } from "../../lib/cli-schemas";
|
|
6
|
-
import { apiClient } from "../../services/api-client";
|
|
7
|
-
import { handleEnvCommandErrors } from "./helpers";
|
|
8
|
-
|
|
9
|
-
const keyValue = keyValueArg("KEY=VALUE");
|
|
10
|
-
const environmentOption = Options.text("environment").pipe(Options.withDefault("production"));
|
|
11
|
-
const visibilityOption = Options.choice("visibility", ["plaintext", "sensitive", "secret"]).pipe(
|
|
12
|
-
Options.withDefault("plaintext" as const),
|
|
13
|
-
);
|
|
14
|
-
|
|
15
|
-
export const setCommand = Command.make(
|
|
16
|
-
"set",
|
|
17
|
-
{ keyValue, environment: environmentOption, visibility: visibilityOption },
|
|
18
|
-
({ keyValue: { key, value }, environment, visibility }) =>
|
|
19
|
-
Effect.gen(function* () {
|
|
20
|
-
const projectId = yield* readProjectId;
|
|
21
|
-
const api = yield* apiClient;
|
|
22
|
-
|
|
23
|
-
const existing = yield* api["env-vars"].list({
|
|
24
|
-
urlParams: { projectId, environment },
|
|
25
|
-
});
|
|
26
|
-
|
|
27
|
-
const match = existing.items.find((item) => item.key === key);
|
|
28
|
-
|
|
29
|
-
if (match) {
|
|
30
|
-
yield* api["env-vars"].update({
|
|
31
|
-
path: { id: match.id },
|
|
32
|
-
payload: { value, visibility },
|
|
33
|
-
});
|
|
34
|
-
yield* Console.log(`Updated ${key} in ${environment}`);
|
|
35
|
-
} else {
|
|
36
|
-
yield* api["env-vars"].create({
|
|
37
|
-
payload: { projectId, environment, key, value, visibility },
|
|
38
|
-
});
|
|
39
|
-
yield* Console.log(`Created ${key} in ${environment}`);
|
|
40
|
-
}
|
|
41
|
-
}).pipe(handleEnvCommandErrors),
|
|
42
|
-
);
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
import { Args, Command } from "@effect/cli";
|
|
2
|
-
import { Console, Effect } from "effect";
|
|
3
|
-
|
|
4
|
-
import { exitWith } from "../../application/command-exit";
|
|
5
|
-
import { runFingerprintFull } from "../../lib/fingerprint";
|
|
6
|
-
import { CliRuntime } from "../../services/cli-runtime";
|
|
7
|
-
|
|
8
|
-
const hash = Args.text({ name: "hash" });
|
|
9
|
-
|
|
10
|
-
export const compareCommand = Command.make("compare", { hash }, (opts) =>
|
|
11
|
-
Effect.gen(function* () {
|
|
12
|
-
const runtime = yield* CliRuntime;
|
|
13
|
-
const projectRoot = yield* runtime.cwd;
|
|
14
|
-
const result = yield* runFingerprintFull(projectRoot);
|
|
15
|
-
|
|
16
|
-
if (result.hash === opts.hash) {
|
|
17
|
-
yield* Console.log("Fingerprints match.");
|
|
18
|
-
return undefined;
|
|
19
|
-
}
|
|
20
|
-
yield* Console.log("Fingerprints differ.");
|
|
21
|
-
yield* Console.log(` Local: ${result.hash}`);
|
|
22
|
-
yield* Console.log(` Provided: ${opts.hash}`);
|
|
23
|
-
return yield* exitWith(1, "Fingerprint mismatch");
|
|
24
|
-
}).pipe(Effect.catchTag("FingerprintError", (error) => exitWith(2, error.message))),
|
|
25
|
-
);
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import { Command } from "@effect/cli";
|
|
2
|
-
import { Console, Effect } from "effect";
|
|
3
|
-
|
|
4
|
-
import { exitWith } from "../../application/command-exit";
|
|
5
|
-
import { runFingerprintFull } from "../../lib/fingerprint";
|
|
6
|
-
import { CliRuntime } from "../../services/cli-runtime";
|
|
7
|
-
|
|
8
|
-
export const generateCommand = Command.make("generate", {}, () =>
|
|
9
|
-
Effect.gen(function* () {
|
|
10
|
-
const runtime = yield* CliRuntime;
|
|
11
|
-
const projectRoot = yield* runtime.cwd;
|
|
12
|
-
const result = yield* runFingerprintFull(projectRoot);
|
|
13
|
-
yield* Console.log(result.hash);
|
|
14
|
-
if (result.sources.length > 0) {
|
|
15
|
-
yield* Console.log(`${result.sources.length} sources`);
|
|
16
|
-
}
|
|
17
|
-
}).pipe(Effect.catchTag("FingerprintError", (error) => exitWith(2, error.message))),
|
|
18
|
-
);
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import { Command } from "@effect/cli";
|
|
2
|
-
import { Console } from "effect";
|
|
3
|
-
|
|
4
|
-
import { compareCommand } from "./compare";
|
|
5
|
-
import { generateCommand } from "./generate";
|
|
6
|
-
|
|
7
|
-
export const fingerprintCommand = Command.make("fingerprint", {}, () =>
|
|
8
|
-
Console.log("Fingerprint utilities. Use --help for subcommands."),
|
|
9
|
-
).pipe(Command.withSubcommands([generateCommand, compareCommand]));
|
package/src/commands/init.ts
DELETED
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
import { Command } from "@effect/cli";
|
|
2
|
-
import { Console, Effect } from "effect";
|
|
3
|
-
|
|
4
|
-
import { readAppJson, readSlug, writeProjectId } from "../lib/app-json";
|
|
5
|
-
import { asString } from "../lib/build-profile";
|
|
6
|
-
import { asRecord } from "../lib/record";
|
|
7
|
-
import { apiClient } from "../services/api-client";
|
|
8
|
-
|
|
9
|
-
export const initCommand = Command.make("init", {}, () =>
|
|
10
|
-
Effect.gen(function* () {
|
|
11
|
-
const appJson = yield* readAppJson;
|
|
12
|
-
const expo = asRecord(appJson["expo"]);
|
|
13
|
-
const name = asString(expo?.["name"]) ?? asString(expo?.["slug"]) ?? "untitled";
|
|
14
|
-
const slug = yield* readSlug;
|
|
15
|
-
|
|
16
|
-
yield* Console.log(`Linking project: ${name} (${slug})`);
|
|
17
|
-
|
|
18
|
-
const api = yield* apiClient;
|
|
19
|
-
const { items } = yield* api.projects.list({ urlParams: { page: 1, limit: 100 } });
|
|
20
|
-
|
|
21
|
-
const existing = items.find((project) => project.slug === slug);
|
|
22
|
-
|
|
23
|
-
if (existing) {
|
|
24
|
-
yield* Console.log(`Found existing project: ${existing.name} (${existing.id})`);
|
|
25
|
-
yield* writeProjectId(existing.id);
|
|
26
|
-
} else {
|
|
27
|
-
yield* Console.log("No existing project found. Creating new project...");
|
|
28
|
-
const project = yield* api.projects.create({ payload: { name, slug } });
|
|
29
|
-
yield* Console.log(`Created project: ${project.name} (${project.id})`);
|
|
30
|
-
yield* writeProjectId(project.id);
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
yield* Console.log("Project linked successfully. ID saved to app.json.");
|
|
34
|
-
}),
|
|
35
|
-
);
|
package/src/commands/login.ts
DELETED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import { Command as CliCommand, Options } from "@effect/cli";
|
|
2
|
-
import { Cause, Effect } from "effect";
|
|
3
|
-
|
|
4
|
-
import { exitWith } from "../application/command-exit";
|
|
5
|
-
import { runLogin } from "../application/login";
|
|
6
|
-
|
|
7
|
-
const manualApiKey = Options.boolean("api-key");
|
|
8
|
-
|
|
9
|
-
const loginFailed = (cause: Cause.Cause<unknown>) => exitWith(1, Cause.pretty(cause));
|
|
10
|
-
|
|
11
|
-
export const loginCommand = CliCommand.make("login", { manualApiKey }, (opts) =>
|
|
12
|
-
runLogin({ manualApiKey: opts.manualApiKey }).pipe(Effect.catchAllCause(loginFailed)),
|
|
13
|
-
);
|
package/src/commands/logout.ts
DELETED
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import { Command } from "@effect/cli";
|
|
2
|
-
import { Console, Effect } from "effect";
|
|
3
|
-
|
|
4
|
-
import { AuthStore } from "../services/auth-store";
|
|
5
|
-
|
|
6
|
-
export const logoutCommand = Command.make("logout", {}, () =>
|
|
7
|
-
Effect.gen(function* () {
|
|
8
|
-
const authStore = yield* AuthStore;
|
|
9
|
-
yield* authStore.clearToken;
|
|
10
|
-
yield* Console.log("Logged out. Auth token removed.");
|
|
11
|
-
}),
|
|
12
|
-
);
|
package/src/commands/projects.ts
DELETED
|
@@ -1,84 +0,0 @@
|
|
|
1
|
-
import { Args, Command, Options } from "@effect/cli";
|
|
2
|
-
import { Console, Effect } from "effect";
|
|
3
|
-
|
|
4
|
-
import { makeCommandErrorHandler } from "../lib/command-errors";
|
|
5
|
-
import { printKeyValue, printTable } from "../lib/output";
|
|
6
|
-
import { apiClient } from "../services/api-client";
|
|
7
|
-
|
|
8
|
-
const handleErrors = makeCommandErrorHandler();
|
|
9
|
-
|
|
10
|
-
const idArg = Args.text({ name: "id" });
|
|
11
|
-
const nameOption = Options.text("name");
|
|
12
|
-
const slugOption = Options.text("slug");
|
|
13
|
-
|
|
14
|
-
const listCommand = Command.make("list", {}, () =>
|
|
15
|
-
Effect.gen(function* () {
|
|
16
|
-
const api = yield* apiClient;
|
|
17
|
-
const { items } = yield* api.projects.list({
|
|
18
|
-
urlParams: { page: 1, limit: 1000 },
|
|
19
|
-
});
|
|
20
|
-
|
|
21
|
-
if (items.length === 0) {
|
|
22
|
-
yield* Console.log("No projects found.");
|
|
23
|
-
return;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
yield* printTable(
|
|
27
|
-
["ID", "Name", "Slug", "Created"],
|
|
28
|
-
items.map((project) => [project.id, project.name, project.slug, project.createdAt]),
|
|
29
|
-
);
|
|
30
|
-
}).pipe(handleErrors),
|
|
31
|
-
);
|
|
32
|
-
|
|
33
|
-
const createCommand = Command.make("create", { name: nameOption, slug: slugOption }, (opts) =>
|
|
34
|
-
Effect.gen(function* () {
|
|
35
|
-
const api = yield* apiClient;
|
|
36
|
-
const project = yield* api.projects.create({
|
|
37
|
-
payload: { name: opts.name, slug: opts.slug },
|
|
38
|
-
});
|
|
39
|
-
yield* printKeyValue([
|
|
40
|
-
["ID", project.id],
|
|
41
|
-
["Name", project.name],
|
|
42
|
-
["Slug", project.slug],
|
|
43
|
-
["Created", project.createdAt],
|
|
44
|
-
]);
|
|
45
|
-
}).pipe(handleErrors),
|
|
46
|
-
);
|
|
47
|
-
|
|
48
|
-
const getCommand = Command.make("get", { id: idArg }, (opts) =>
|
|
49
|
-
Effect.gen(function* () {
|
|
50
|
-
const api = yield* apiClient;
|
|
51
|
-
const project = yield* api.projects.get({ path: { id: opts.id } });
|
|
52
|
-
yield* printKeyValue([
|
|
53
|
-
["ID", project.id],
|
|
54
|
-
["Name", project.name],
|
|
55
|
-
["Slug", project.slug],
|
|
56
|
-
["Created", project.createdAt],
|
|
57
|
-
]);
|
|
58
|
-
}).pipe(handleErrors),
|
|
59
|
-
);
|
|
60
|
-
|
|
61
|
-
const renameCommand = Command.make("rename", { id: idArg, name: nameOption }, (opts) =>
|
|
62
|
-
Effect.gen(function* () {
|
|
63
|
-
const api = yield* apiClient;
|
|
64
|
-
const project = yield* api.projects.rename({
|
|
65
|
-
path: { id: opts.id },
|
|
66
|
-
payload: { name: opts.name },
|
|
67
|
-
});
|
|
68
|
-
yield* Console.log(`Project renamed to "${project.name}".`);
|
|
69
|
-
}).pipe(handleErrors),
|
|
70
|
-
);
|
|
71
|
-
|
|
72
|
-
const deleteCommand = Command.make("delete", { id: idArg }, (opts) =>
|
|
73
|
-
Effect.gen(function* () {
|
|
74
|
-
const api = yield* apiClient;
|
|
75
|
-
yield* api.projects.delete({ path: { id: opts.id } });
|
|
76
|
-
yield* Console.log(`Project ${opts.id} deleted.`);
|
|
77
|
-
}).pipe(handleErrors),
|
|
78
|
-
);
|
|
79
|
-
|
|
80
|
-
export const projectsCommand = Command.make("projects", {}, () =>
|
|
81
|
-
Console.log("Manage projects. Run with --help for subcommands."),
|
|
82
|
-
).pipe(
|
|
83
|
-
Command.withSubcommands([listCommand, createCommand, getCommand, renameCommand, deleteCommand]),
|
|
84
|
-
);
|
package/src/commands/status.ts
DELETED
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
import { Command } from "@effect/cli";
|
|
2
|
-
import { Console, Effect } from "effect";
|
|
3
|
-
|
|
4
|
-
import { readProjectId } from "../lib/app-json";
|
|
5
|
-
import { listAllCredentials } from "../lib/credentials-manager";
|
|
6
|
-
import { printKeyValue } from "../lib/output";
|
|
7
|
-
import { apiClient } from "../services/api-client";
|
|
8
|
-
|
|
9
|
-
export const statusCommand = Command.make("status", {}, () =>
|
|
10
|
-
Effect.gen(function* () {
|
|
11
|
-
const projectId = yield* readProjectId;
|
|
12
|
-
const api = yield* apiClient;
|
|
13
|
-
|
|
14
|
-
const { project, credentials, builds } = yield* Effect.all(
|
|
15
|
-
{
|
|
16
|
-
project: api.projects.get({ path: { id: projectId } }),
|
|
17
|
-
credentials: listAllCredentials(api),
|
|
18
|
-
builds: api.builds.list({ urlParams: { projectId } }),
|
|
19
|
-
},
|
|
20
|
-
{ concurrency: "unbounded" },
|
|
21
|
-
);
|
|
22
|
-
|
|
23
|
-
yield* Console.log("Project");
|
|
24
|
-
yield* Console.log("-------");
|
|
25
|
-
yield* printKeyValue([
|
|
26
|
-
["Name", project.name],
|
|
27
|
-
["ID", project.id],
|
|
28
|
-
["Slug", project.slug],
|
|
29
|
-
["Created", project.createdAt],
|
|
30
|
-
]);
|
|
31
|
-
|
|
32
|
-
yield* Console.log("");
|
|
33
|
-
yield* Console.log("Credentials");
|
|
34
|
-
yield* Console.log("-----------");
|
|
35
|
-
const iosCreds = credentials.filter((cred) => cred.platform === "ios").length;
|
|
36
|
-
const androidCreds = credentials.filter((cred) => cred.platform === "android").length;
|
|
37
|
-
yield* printKeyValue([
|
|
38
|
-
["iOS", String(iosCreds)],
|
|
39
|
-
["Android", String(androidCreds)],
|
|
40
|
-
["Total", String(credentials.length)],
|
|
41
|
-
]);
|
|
42
|
-
|
|
43
|
-
yield* Console.log("");
|
|
44
|
-
yield* Console.log("Builds");
|
|
45
|
-
yield* Console.log("------");
|
|
46
|
-
yield* printKeyValue([["Total", String(builds.total)]]);
|
|
47
|
-
}),
|
|
48
|
-
);
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import { Args, Command } from "@effect/cli";
|
|
2
|
-
import { Console, Effect } from "effect";
|
|
3
|
-
|
|
4
|
-
import { apiClient } from "../../services/api-client";
|
|
5
|
-
import { handleUpdateCommandErrors } from "./helpers";
|
|
6
|
-
|
|
7
|
-
const groupId = Args.text({ name: "groupId" });
|
|
8
|
-
|
|
9
|
-
export const deleteCommand = Command.make("delete", { groupId }, (opts) =>
|
|
10
|
-
Effect.gen(function* () {
|
|
11
|
-
const api = yield* apiClient;
|
|
12
|
-
const result = yield* api.updates.deleteGroup({ path: { groupId: opts.groupId } });
|
|
13
|
-
yield* Console.log(`Deleted ${String(result.deleted)} update(s) from group ${opts.groupId}.`);
|
|
14
|
-
}).pipe(handleUpdateCommandErrors),
|
|
15
|
-
);
|