@rikalabs/akter-cli 0.1.0-alpha.3 → 0.1.0-alpha.5
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/CHANGELOG.md +12 -0
- package/dist/cloud-api/auth.d.ts +7 -4
- package/dist/cloud-api/billing.d.ts +17 -52
- package/dist/cloud-api/contract.d.ts +876 -876
- package/dist/cloud-api/groups/billing.d.ts +4 -13
- package/dist/cloud-api/groups/projects.d.ts +15 -6
- package/dist/cloud-api/index.d.ts +1 -1
- package/dist/cloud-api/index.js +9 -17
- package/dist/cloud-api/projects.d.ts +11 -6
- package/dist/cloud-api/runtime.d.ts +1 -1
- package/dist/inspector-client.js +1 -1
- package/dist/main.js +74 -51
- package/package.json +1 -1
package/dist/main.js
CHANGED
|
@@ -8,7 +8,7 @@ import { FetchHttpClient } from "effect/http";
|
|
|
8
8
|
import { Effect as Effect22, Runtime as Runtime2, Schema as Schema29 } from "effect";
|
|
9
9
|
import { CliError, Command as Command19 } from "effect/cli";
|
|
10
10
|
// package.json
|
|
11
|
-
var version = "0.1.0-alpha.
|
|
11
|
+
var version = "0.1.0-alpha.5";
|
|
12
12
|
|
|
13
13
|
// src/commands/adopt/run.ts
|
|
14
14
|
import {
|
|
@@ -1112,7 +1112,7 @@ class Authentication extends HttpApiMiddleware.Service()("@akter/cloud-api/Authe
|
|
|
1112
1112
|
apiKey: HttpApiSecurity.apiKey({ key: apiKeyHeaderName, in: "header" }),
|
|
1113
1113
|
bearer: HttpApiSecurity.bearer
|
|
1114
1114
|
},
|
|
1115
|
-
error: [Unauthorized, Forbidden]
|
|
1115
|
+
error: [Unauthorized, Forbidden, Unavailable]
|
|
1116
1116
|
}) {
|
|
1117
1117
|
}
|
|
1118
1118
|
// ../../packages/cloud-api/src/identity.ts
|
|
@@ -1304,8 +1304,11 @@ var Environment = Schema13.Struct({
|
|
|
1304
1304
|
projectId: ProjectId,
|
|
1305
1305
|
currentDeploymentId: Schema13.NullOr(DeploymentId),
|
|
1306
1306
|
database: Schema13.optionalKey(Schema13.Struct({
|
|
1307
|
-
source: Schema13.
|
|
1308
|
-
state: Schema13.Literals(["
|
|
1307
|
+
source: Schema13.Literal("customer"),
|
|
1308
|
+
state: Schema13.Literals(["missing", "reachable", "unreachable"]),
|
|
1309
|
+
latency: Schema13.NullOr(NonNegative),
|
|
1310
|
+
latencyWarning: Schema13.Boolean,
|
|
1311
|
+
runnerCap: Schema13.NullOr(Schema13.Int)
|
|
1309
1312
|
}))
|
|
1310
1313
|
});
|
|
1311
1314
|
var CreateEnvironment = Schema13.Struct({ name: EnvironmentName });
|
|
@@ -1776,7 +1779,7 @@ var capFields = {
|
|
|
1776
1779
|
reason: Schema16.optionalKey(Schema16.Literal("unbound"))
|
|
1777
1780
|
};
|
|
1778
1781
|
var CapState = Schema16.Struct({
|
|
1779
|
-
cap: Schema16.Literals(["spend", "connections", "compute"
|
|
1782
|
+
cap: Schema16.Literals(["spend", "connections", "compute"]),
|
|
1780
1783
|
...capFields
|
|
1781
1784
|
});
|
|
1782
1785
|
var BillingSummary = Schema16.Struct({
|
|
@@ -1811,10 +1814,7 @@ var machineSizeFields = {
|
|
|
1811
1814
|
var PlanFeature = Schema16.Literals([
|
|
1812
1815
|
"compute-overage",
|
|
1813
1816
|
"compute-cap",
|
|
1814
|
-
"storage-overage",
|
|
1815
|
-
"storage-cap",
|
|
1816
1817
|
"byo-database",
|
|
1817
|
-
"dedicated-database",
|
|
1818
1818
|
"checkout"
|
|
1819
1819
|
]);
|
|
1820
1820
|
var CatalogPlan = Schema16.Struct({
|
|
@@ -1825,13 +1825,10 @@ var CatalogPlan = Schema16.Struct({
|
|
|
1825
1825
|
allowances: Schema16.Struct({
|
|
1826
1826
|
computeUnitHours: NonNegative,
|
|
1827
1827
|
computeUnitHourCap: Schema16.NullOr(NonNegative),
|
|
1828
|
-
storageGb: NonNegative,
|
|
1829
|
-
storageGbCap: Schema16.NullOr(NonNegative),
|
|
1830
1828
|
concurrentConnections: NonNegativeInt
|
|
1831
1829
|
}),
|
|
1832
1830
|
overage: Schema16.Struct({
|
|
1833
|
-
computeCentsPerUnitHour: NonNegative
|
|
1834
|
-
storageCentsPerGbMonth: NonNegative
|
|
1831
|
+
computeCentsPerUnitHour: NonNegative
|
|
1835
1832
|
}),
|
|
1836
1833
|
features: Schema16.Array(PlanFeature),
|
|
1837
1834
|
provisional: Schema16.Boolean
|
|
@@ -1845,7 +1842,7 @@ var PlanCatalog = Schema16.Struct({
|
|
|
1845
1842
|
computeSizes: Schema16.Array(ComputeSize),
|
|
1846
1843
|
provisional: Schema16.Boolean
|
|
1847
1844
|
});
|
|
1848
|
-
var UsageMeterName = Schema16.
|
|
1845
|
+
var UsageMeterName = Schema16.Literal("runnerHours");
|
|
1849
1846
|
var UsageMeter = Schema16.Struct({
|
|
1850
1847
|
meter: UsageMeterName,
|
|
1851
1848
|
used: NonNegative,
|
|
@@ -1855,7 +1852,6 @@ var UsageMeter = Schema16.Struct({
|
|
|
1855
1852
|
});
|
|
1856
1853
|
var UsagePricing = Schema16.Struct({
|
|
1857
1854
|
computeCentsPerUnitHour: NonNegative,
|
|
1858
|
-
storageCentsPerGbMonth: NonNegative,
|
|
1859
1855
|
provisional: Schema16.optionalKey(Schema16.Boolean)
|
|
1860
1856
|
});
|
|
1861
1857
|
var ComputeUsage = Schema16.Struct({
|
|
@@ -1864,18 +1860,15 @@ var ComputeUsage = Schema16.Struct({
|
|
|
1864
1860
|
machineHours: NonNegative,
|
|
1865
1861
|
computeUnitHours: NonNegative
|
|
1866
1862
|
});
|
|
1867
|
-
var StorageSample = Schema16.Struct({ bytes: NonNegative, sampledAt: Timestamp });
|
|
1868
1863
|
var Usage = Schema16.Struct({
|
|
1869
1864
|
period: BillingPeriod,
|
|
1870
1865
|
meters: Schema16.Array(UsageMeter),
|
|
1871
|
-
latestStorageSample: Schema16.NullOr(StorageSample),
|
|
1872
1866
|
caps: Schema16.Array(CapState),
|
|
1873
1867
|
byProject: Schema16.Array(Schema16.Struct({
|
|
1874
1868
|
projectId: ProjectId,
|
|
1875
1869
|
name: Schema16.String,
|
|
1876
1870
|
computeUnitHours: NonNegative,
|
|
1877
1871
|
compute: Schema16.Array(ComputeUsage),
|
|
1878
|
-
storageGbMonths: NonNegative,
|
|
1879
1872
|
estimatedCostCents: NonNegative
|
|
1880
1873
|
})),
|
|
1881
1874
|
pricing: UsagePricing
|
|
@@ -2422,7 +2415,7 @@ class RuntimeGroup extends HttpApiGroup5.make("runtime").add(HttpApiEndpoint5.ge
|
|
|
2422
2415
|
class CloudApi extends HttpApi.make("akter-cloud").add(AccountGroup, OrganizationsGroup, MembersGroup, InvitationsGroup, ApiKeysGroup, ProjectsGroup, EnvironmentVariablesGroup, DomainsGroup, RegionsGroup, IntegrationsGroup, DeploymentsGroup, RuntimeGroup, BillingGroup, UsageGroup, AuditGroup).middleware(Authentication).prefix("/api").annotateMerge(OpenApi3.annotations({ title: "Akter Cloud API" })) {
|
|
2423
2416
|
}
|
|
2424
2417
|
// src/commands/cloud/deploy.ts
|
|
2425
|
-
import { Clock as Clock3, Config as Config3, Console as
|
|
2418
|
+
import { Clock as Clock3, Config as Config3, Console as Console9, Duration as Duration3, Effect as Effect16, Option as Option8, Schema as Schema26, Stream } from "effect";
|
|
2426
2419
|
import { Command as Command13, Flag as Flag12 } from "effect/cli";
|
|
2427
2420
|
import { ChildProcess, ChildProcessSpawner } from "effect/process";
|
|
2428
2421
|
|
|
@@ -2590,7 +2583,7 @@ var packContext = (input) => Effect13.gen(function* () {
|
|
|
2590
2583
|
});
|
|
2591
2584
|
|
|
2592
2585
|
// src/commands/cloud/client.ts
|
|
2593
|
-
import { Effect as Effect15, Match, Schema as Schema25 } from "effect";
|
|
2586
|
+
import { Console as Console8, Duration as Duration2, Effect as Effect15, Match, Schema as Schema25 } from "effect";
|
|
2594
2587
|
import { HttpClient as HttpClient2, HttpClientRequest as HttpClientRequest2 } from "effect/http";
|
|
2595
2588
|
import { HttpApiClient } from "effect/http-api";
|
|
2596
2589
|
|
|
@@ -2697,6 +2690,21 @@ var signedIn = Effect15.gen(function* () {
|
|
|
2697
2690
|
const credentials = yield* loadCredentials;
|
|
2698
2691
|
return { credentials, client: yield* cloudClient(credentials) };
|
|
2699
2692
|
});
|
|
2693
|
+
var MAX_READ_RETRIES = 5;
|
|
2694
|
+
var readRetryDelay = (attempt) => Duration2.seconds(Math.min(2 ** (attempt - 1), 8));
|
|
2695
|
+
var isTransient = (error) => Match.value(error).pipe(Match.tag("Unavailable", (unavailable) => unavailable.reason === undefined), Match.tag("HttpClientError", ({ reason }) => Match.value(reason).pipe(Match.tag("TransportError", () => true), Match.tag("StatusCodeError", "DecodeError", "EmptyBodyError", ({ response }) => response.status >= 500), Match.orElse(() => false))), Match.orElse(() => false));
|
|
2696
|
+
var retryTransient = (notice) => {
|
|
2697
|
+
let failures = 0;
|
|
2698
|
+
const read = (effect) => effect.pipe(Effect15.tap(() => Effect15.sync(() => {
|
|
2699
|
+
failures = 0;
|
|
2700
|
+
})), Effect15.catchIf((error) => failures < MAX_READ_RETRIES && isTransient(error), () => Effect15.gen(function* () {
|
|
2701
|
+
failures += 1;
|
|
2702
|
+
yield* Console8.error(notice);
|
|
2703
|
+
yield* Effect15.sleep(readRetryDelay(failures));
|
|
2704
|
+
return yield* read(effect);
|
|
2705
|
+
})));
|
|
2706
|
+
return read;
|
|
2707
|
+
};
|
|
2700
2708
|
var octal2 = (mode) => mode.toString(8).padStart(3, "0");
|
|
2701
2709
|
var describe = Match.type().pipe(Match.tagsExhaustive({
|
|
2702
2710
|
NotLoggedIn: () => ({
|
|
@@ -2818,11 +2826,12 @@ var follow = Effect16.fnUntraced(function* (input) {
|
|
|
2818
2826
|
let cursor = 0;
|
|
2819
2827
|
let following = false;
|
|
2820
2828
|
let logComplete = false;
|
|
2829
|
+
const read = retryTransient("The control plane is unavailable; still following the deployment.");
|
|
2821
2830
|
const printLog = Effect16.gen(function* () {
|
|
2822
|
-
const log = yield* input.client.deployments.getBuildLog({ params, query: { after: cursor } });
|
|
2831
|
+
const log = yield* read(input.client.deployments.getBuildLog({ params, query: { after: cursor } }));
|
|
2823
2832
|
const last = log.lines.at(-1);
|
|
2824
2833
|
for (const line of log.lines)
|
|
2825
|
-
yield*
|
|
2834
|
+
yield* Console9.log(` ${line.text}`);
|
|
2826
2835
|
if (last !== undefined)
|
|
2827
2836
|
cursor = last.index + 1;
|
|
2828
2837
|
following = true;
|
|
@@ -2835,7 +2844,7 @@ var follow = Effect16.fnUntraced(function* (input) {
|
|
|
2835
2844
|
if (step.name === "build" && step.status === "succeeded" && following && !logComplete)
|
|
2836
2845
|
yield* printLog;
|
|
2837
2846
|
printed.set(step.name, step.status);
|
|
2838
|
-
yield*
|
|
2847
|
+
yield* Console9.log(` ${step.name} ${step.status}${step.status === "running" ? "" : seconds(step.durationMs)}`);
|
|
2839
2848
|
}
|
|
2840
2849
|
if (!logComplete && detail.steps.some((step) => step.name === "build" && step.status === "running"))
|
|
2841
2850
|
yield* printLog;
|
|
@@ -2844,9 +2853,9 @@ var follow = Effect16.fnUntraced(function* (input) {
|
|
|
2844
2853
|
if (detail.status === "failed") {
|
|
2845
2854
|
const failed = detail.steps.find((step) => step.status === "failed");
|
|
2846
2855
|
if (failed?.name === "build") {
|
|
2847
|
-
const log = yield* input.client.deployments.getBuildLog({ params, query: {} });
|
|
2856
|
+
const log = yield* read(input.client.deployments.getBuildLog({ params, query: {} }));
|
|
2848
2857
|
for (const line of log.lines.slice(-20))
|
|
2849
|
-
yield*
|
|
2858
|
+
yield* Console9.error(` ${line.text}`);
|
|
2850
2859
|
}
|
|
2851
2860
|
return yield* DeploymentFailed.make({
|
|
2852
2861
|
deploymentId: detail.id,
|
|
@@ -2859,8 +2868,8 @@ var follow = Effect16.fnUntraced(function* (input) {
|
|
|
2859
2868
|
deploymentId: detail.id,
|
|
2860
2869
|
seconds: input.timeoutSeconds
|
|
2861
2870
|
});
|
|
2862
|
-
yield* Effect16.sleep(
|
|
2863
|
-
detail = yield* input.client.deployments.get({ params });
|
|
2871
|
+
yield* Effect16.sleep(Duration3.seconds(1));
|
|
2872
|
+
detail = yield* read(input.client.deployments.get({ params }));
|
|
2864
2873
|
}
|
|
2865
2874
|
});
|
|
2866
2875
|
var deployCommand = Command13.make("deploy", flags9, (options) => Effect16.gen(function* () {
|
|
@@ -2875,7 +2884,7 @@ var deployCommand = Command13.make("deploy", flags9, (options) => Effect16.gen(f
|
|
|
2875
2884
|
reason: "ContextTooLarge",
|
|
2876
2885
|
message: `The app directory is ${packed.archive.byteLength} bytes compressed; the control plane accepts at most ${MAX_SOURCE_BYTES}. Exclude more files in .akterignore.`
|
|
2877
2886
|
});
|
|
2878
|
-
yield*
|
|
2887
|
+
yield* Console9.log(`Uploading ${packed.files.length} files (${packed.archive.byteLength} bytes) from ${options.context} to ${credentials.apiUrl}`);
|
|
2879
2888
|
const source = yield* client.deployments.uploadSource({
|
|
2880
2889
|
params: { projectId: options.project },
|
|
2881
2890
|
payload: packed.archive
|
|
@@ -2895,14 +2904,28 @@ var deployCommand = Command13.make("deploy", flags9, (options) => Effect16.gen(f
|
|
|
2895
2904
|
source: { digest: source.digest }
|
|
2896
2905
|
}
|
|
2897
2906
|
});
|
|
2898
|
-
yield*
|
|
2907
|
+
yield* Console9.log(`Deployment ${deployment.id} of ${commitSha.slice(0, 7)} to ${options.environment} started`);
|
|
2899
2908
|
const live = yield* follow({
|
|
2900
2909
|
client,
|
|
2901
2910
|
projectId: options.project,
|
|
2902
2911
|
deployment,
|
|
2903
2912
|
timeoutSeconds: options.timeout
|
|
2904
2913
|
});
|
|
2905
|
-
yield*
|
|
2914
|
+
yield* Console9.log(`Deployment ${live.id} is live in ${options.environment}`);
|
|
2915
|
+
const report = yield* retryTransient("The control plane is unavailable; retrying the database report.")(client.projects.getEnvironment({
|
|
2916
|
+
params: { projectId: options.project, environment: options.environment }
|
|
2917
|
+
})).pipe(Effect16.catch(() => Console9.error("Warning: could not read the database report; the deployment is already live.").pipe(Effect16.as(undefined))));
|
|
2918
|
+
if (report === undefined)
|
|
2919
|
+
return;
|
|
2920
|
+
if (report.currentDeploymentId !== live.id)
|
|
2921
|
+
return yield* Console9.error("Warning: the database report is not for this deployment; skipping its diagnostics.");
|
|
2922
|
+
const { database } = report;
|
|
2923
|
+
if (database !== undefined) {
|
|
2924
|
+
if (database.latencyWarning)
|
|
2925
|
+
yield* Console9.error(`Warning: database p50 latency${database.latency === null ? "" : ` (${database.latency} ms)`} exceeds 5 ms from the runner region; deployment is not refused.`);
|
|
2926
|
+
if (database.runnerCap !== null)
|
|
2927
|
+
yield* Console9.log(`Database runner cap: ${database.runnerCap}`);
|
|
2928
|
+
}
|
|
2906
2929
|
}).pipe(Effect16.catchTags({
|
|
2907
2930
|
ContextInvalid: (error) => fail({ reason: "ContextInvalid", message: error.message }),
|
|
2908
2931
|
DeploymentFailed: (error) => fail({
|
|
@@ -2918,7 +2941,7 @@ var deployCommand = Command13.make("deploy", flags9, (options) => Effect16.gen(f
|
|
|
2918
2941
|
}), reportFailures)).pipe(Command13.withDescription("Upload the app directory, build and roll it out on Akter Cloud, and follow it until it is live"));
|
|
2919
2942
|
|
|
2920
2943
|
// src/commands/cloud/login.ts
|
|
2921
|
-
import { Clock as Clock4, Config as Config4, Console as
|
|
2944
|
+
import { Clock as Clock4, Config as Config4, Console as Console10, Data, Duration as Duration4, Effect as Effect17, Schema as Schema27 } from "effect";
|
|
2922
2945
|
import { Command as Command14, Flag as Flag13 } from "effect/cli";
|
|
2923
2946
|
import { HttpClient as HttpClient3, HttpClientRequest as HttpClientRequest3, HttpClientResponse } from "effect/http";
|
|
2924
2947
|
var CLIENT_ID = "akter-cli";
|
|
@@ -2958,7 +2981,7 @@ var deviceLogin = (apiUrl) => Effect17.gen(function* () {
|
|
|
2958
2981
|
return yield* LoginRefused.make({ status: started.status, error });
|
|
2959
2982
|
}
|
|
2960
2983
|
const code = yield* HttpClientResponse.schemaBodyJson(DeviceCode)(started);
|
|
2961
|
-
yield*
|
|
2984
|
+
yield* Console10.log(`To sign in, open ${code.verification_uri}
|
|
2962
2985
|
and enter the code ${displayCode(code.user_code)}. Waiting for approval…`);
|
|
2963
2986
|
const poll = Effect17.gen(function* () {
|
|
2964
2987
|
const response = yield* post(`${apiUrl}/auth/device/token`, {
|
|
@@ -2982,14 +3005,14 @@ and enter the code ${displayCode(code.user_code)}. Waiting for approval…`);
|
|
|
2982
3005
|
return yield* LoginRefused.make({ status: response.status, error });
|
|
2983
3006
|
});
|
|
2984
3007
|
const deadline = (yield* Clock4.currentTimeMillis) + code.expires_in * 1000;
|
|
2985
|
-
let interval =
|
|
3008
|
+
let interval = Duration4.seconds(code.interval);
|
|
2986
3009
|
while ((yield* Clock4.currentTimeMillis) < deadline) {
|
|
2987
3010
|
yield* Effect17.sleep(interval);
|
|
2988
3011
|
const answer = yield* poll;
|
|
2989
3012
|
if (Poll.$is("Granted")(answer))
|
|
2990
3013
|
return answer.token;
|
|
2991
3014
|
if (Poll.$is("SlowDown")(answer))
|
|
2992
|
-
interval =
|
|
3015
|
+
interval = Duration4.sum(interval, Duration4.seconds(5));
|
|
2993
3016
|
}
|
|
2994
3017
|
return yield* LoginExpired.make({});
|
|
2995
3018
|
});
|
|
@@ -3000,7 +3023,7 @@ var loginCommand = Command14.make("login", flags10, ({ apiUrl }) => Effect17.gen
|
|
|
3000
3023
|
const me = yield* client.account.me().pipe(Effect17.tapError(() => revoke(apiUrl, token)));
|
|
3001
3024
|
const email = me.user?.email ?? "";
|
|
3002
3025
|
const file = yield* saveCredentials({ apiUrl, token, email });
|
|
3003
|
-
yield*
|
|
3026
|
+
yield* Console10.log(`Logged in to ${apiUrl} as ${email}. Credentials saved to ${file}.`);
|
|
3004
3027
|
}).pipe(Effect17.catchTags({
|
|
3005
3028
|
LoginDenied: () => fail({
|
|
3006
3029
|
reason: "LoginDenied",
|
|
@@ -3020,7 +3043,7 @@ var loginCommand = Command14.make("login", flags10, ({ apiUrl }) => Effect17.gen
|
|
|
3020
3043
|
}), reportFailures)).pipe(Command14.withDescription("Sign in to Akter Cloud through the browser and store the session for deploy"));
|
|
3021
3044
|
|
|
3022
3045
|
// src/commands/cloud/logout.ts
|
|
3023
|
-
import { Console as
|
|
3046
|
+
import { Console as Console11, Effect as Effect18, Option as Option9 } from "effect";
|
|
3024
3047
|
import { Command as Command15 } from "effect/cli";
|
|
3025
3048
|
import { HttpClient as HttpClient4, HttpClientRequest as HttpClientRequest4 } from "effect/http";
|
|
3026
3049
|
var logout = Effect18.gen(function* () {
|
|
@@ -3032,17 +3055,17 @@ var logout = Effect18.gen(function* () {
|
|
|
3032
3055
|
var logoutCommand = Command15.make("logout", {}, () => Effect18.gen(function* () {
|
|
3033
3056
|
const { credentials, revoked } = yield* logout;
|
|
3034
3057
|
if (credentials === undefined)
|
|
3035
|
-
return yield*
|
|
3036
|
-
yield*
|
|
3037
|
-
}).pipe(Effect18.catchTag("NotLoggedIn", () =>
|
|
3058
|
+
return yield* Console11.log("Removed the stored credentials.");
|
|
3059
|
+
yield* Console11.log(revoked ? `Logged out of ${credentials.apiUrl}.` : `Removed the stored credentials. ${credentials.apiUrl} could not revoke the session, which ends when it expires.`);
|
|
3060
|
+
}).pipe(Effect18.catchTag("NotLoggedIn", () => Console11.log("Not logged in.")), reportFailures)).pipe(Command15.withDescription("Sign out of Akter Cloud and delete the stored session"));
|
|
3038
3061
|
|
|
3039
3062
|
// src/commands/cloud/whoami.ts
|
|
3040
|
-
import { Console as
|
|
3063
|
+
import { Console as Console12, Effect as Effect19 } from "effect";
|
|
3041
3064
|
import { Command as Command16 } from "effect/cli";
|
|
3042
3065
|
var whoamiCommand = Command16.make("whoami", {}, () => Effect19.gen(function* () {
|
|
3043
3066
|
const { credentials, client } = yield* signedIn;
|
|
3044
3067
|
const me = yield* client.account.me();
|
|
3045
|
-
yield*
|
|
3068
|
+
yield* Console12.log([
|
|
3046
3069
|
`${me.user?.email ?? credentials.email} at ${credentials.apiUrl}`,
|
|
3047
3070
|
...me.organizations.map((membership) => ` ${membership.organization.slug} ${membership.role} ${membership.organization.id}`)
|
|
3048
3071
|
].join(`
|
|
@@ -3050,7 +3073,7 @@ var whoamiCommand = Command16.make("whoami", {}, () => Effect19.gen(function* ()
|
|
|
3050
3073
|
}).pipe(reportFailures)).pipe(Command16.withDescription("Show who the stored Akter Cloud session signs in as"));
|
|
3051
3074
|
|
|
3052
3075
|
// src/commands/cloud/env.ts
|
|
3053
|
-
import { Config as Config5, Console as
|
|
3076
|
+
import { Config as Config5, Console as Console13, DateTime as DateTime2, Effect as Effect20, FileSystem as FileSystem5, Option as Option10, Stdio, Stream as Stream2 } from "effect";
|
|
3054
3077
|
import { Argument as Argument6, Command as Command17, Flag as Flag14 } from "effect/cli";
|
|
3055
3078
|
var scope = {
|
|
3056
3079
|
project: Flag14.String("project").pipe(Flag14.withFallbackConfig(Config5.String("AKTER_PROJECT")), Flag14.withSchema(ProjectId)),
|
|
@@ -3101,7 +3124,7 @@ var list2 = Command17.make("list", scope, ({ project, environment }) => Effect20
|
|
|
3101
3124
|
params: { projectId: project, environment }
|
|
3102
3125
|
});
|
|
3103
3126
|
for (const variable of variables)
|
|
3104
|
-
yield*
|
|
3127
|
+
yield* Console13.log(`${variable.name} ${DateTime2.formatIso(variable.updatedAt)}`);
|
|
3105
3128
|
}).pipe(reportFailures)).pipe(Command17.withDescription("List variable names and update times; values cannot be read back"));
|
|
3106
3129
|
var set = Command17.make("set", { ...scope, name, file: Flag14.File("file", { mustExist: true }).pipe(Flag14.optional) }, (options) => Effect20.gen(function* () {
|
|
3107
3130
|
const { client } = yield* signedIn;
|
|
@@ -3114,13 +3137,13 @@ var set = Command17.make("set", { ...scope, name, file: Flag14.File("file", { mu
|
|
|
3114
3137
|
},
|
|
3115
3138
|
payload: { value }
|
|
3116
3139
|
});
|
|
3117
|
-
yield*
|
|
3140
|
+
yield* Console13.log(`Set ${options.name} in ${options.environment}. The value takes effect on the next deployment.`);
|
|
3118
3141
|
}).pipe(reportFailures)).pipe(Command17.withDescription("Set a write-only value from piped stdin or --file"));
|
|
3119
3142
|
var unset = Command17.make("unset", { ...scope, name }, ({ project, environment, name }) => Effect20.gen(function* () {
|
|
3120
3143
|
const { client } = yield* signedIn;
|
|
3121
3144
|
yield* client.environmentVariables.delete({ params: { projectId: project, environment, name } });
|
|
3122
|
-
yield*
|
|
3123
|
-
}).pipe(reportFailures)).pipe(Command17.withDescription("Remove
|
|
3145
|
+
yield* Console13.log(`Unset ${name} in ${environment}. The change takes effect on the next deployment.`);
|
|
3146
|
+
}).pipe(reportFailures)).pipe(Command17.withDescription("Remove an environment variable"));
|
|
3124
3147
|
var importVariables = Command17.make("import", { ...scope, file: Argument6.String("file").pipe(Argument6.withDefault("-")) }, ({ project, environment, file }) => Effect20.gen(function* () {
|
|
3125
3148
|
const { client } = yield* signedIn;
|
|
3126
3149
|
const content = yield* input(file, 1048576);
|
|
@@ -3128,12 +3151,12 @@ var importVariables = Command17.make("import", { ...scope, file: Argument6.Strin
|
|
|
3128
3151
|
params: { projectId: project, environment },
|
|
3129
3152
|
payload: { content }
|
|
3130
3153
|
});
|
|
3131
|
-
yield*
|
|
3154
|
+
yield* Console13.log(`Imported ${result.created.length} new and ${result.updated.length} updated variables in ${environment}.`);
|
|
3132
3155
|
}).pipe(reportFailures)).pipe(Command17.withDescription("Import a dotenv file atomically; use - or no file for stdin"));
|
|
3133
3156
|
var envCommand = Command17.make("env").pipe(Command17.withDescription("Manage encrypted, write-only Akter Cloud environment variables"), Command17.withSubcommands([list2, set, unset, importVariables]));
|
|
3134
3157
|
|
|
3135
3158
|
// src/commands/cloud/logs.ts
|
|
3136
|
-
import { Config as Config6, Console as
|
|
3159
|
+
import { Config as Config6, Console as Console14, DateTime as DateTime3, Effect as Effect21, Option as Option11, Schema as Schema28 } from "effect";
|
|
3137
3160
|
import { Command as Command18, Flag as Flag15 } from "effect/cli";
|
|
3138
3161
|
var colourSequence = new RegExp(`${String.fromCodePoint(27)}\\[[0-?]*[ -/]*[@-~]`, "gu");
|
|
3139
3162
|
var logsCommand = Command18.make("logs", {
|
|
@@ -3150,11 +3173,11 @@ var logsCommand = Command18.make("logs", {
|
|
|
3150
3173
|
let more = false;
|
|
3151
3174
|
let failures = 0;
|
|
3152
3175
|
const retryRead = (error) => Effect21.gen(function* () {
|
|
3153
|
-
if (!options.follow || failures >=
|
|
3176
|
+
if (!options.follow || failures >= MAX_READ_RETRIES)
|
|
3154
3177
|
return yield* error;
|
|
3155
3178
|
failures += 1;
|
|
3156
|
-
yield*
|
|
3157
|
-
yield* Effect21.sleep(
|
|
3179
|
+
yield* Console14.error("Log read unavailable; reconnecting from the last cursor.");
|
|
3180
|
+
yield* Effect21.sleep(readRetryDelay(failures));
|
|
3158
3181
|
return;
|
|
3159
3182
|
});
|
|
3160
3183
|
while (true) {
|
|
@@ -3176,7 +3199,7 @@ var logsCommand = Command18.make("logs", {
|
|
|
3176
3199
|
continue;
|
|
3177
3200
|
failures = 0;
|
|
3178
3201
|
for (const line of page.lines)
|
|
3179
|
-
yield*
|
|
3202
|
+
yield* Console14.log(`${DateTime3.formatIso(line.at)} ${line.runnerId} ${line.stream} ${line.text.replace(colourSequence, "").replace(/\p{Cc}|[\u061c\u200e\u200f\u2028\u2029\u202a-\u202e\u2066-\u2069]/gu, "�")}${line.clipped ? " …" : ""}`);
|
|
3180
3203
|
cursor = page.cursor;
|
|
3181
3204
|
more = page.more;
|
|
3182
3205
|
if (!options.follow && !more)
|
package/package.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"name":"@rikalabs/akter-cli","version":"0.1.0-alpha.
|
|
1
|
+
{"name":"@rikalabs/akter-cli","version":"0.1.0-alpha.5","files":["dist","CHANGELOG.md","README.md","LICENSE","NOTICE"],"dependencies":{"@effect/platform-bun":"4.0.2","@effect/platform-node":"4.0.2","@rikalabs/akter":"0.1.0-alpha.5"},"peerDependencies":{"@effect/sql-pg":"^4.0.2","@effect/sql-pglite":"^4.0.2","drizzle-orm":"^1.0.0-rc.5-5935859","effect":"^4.0.2"},"bin":{"akter":"dist/main.js"},"publishConfig":{"access":"public"},"description":"The Akter command-line tool for local development and Akter Cloud","keywords":["actors","akter","durable","effect","pglite","postgres"],"homepage":"https://github.com/Rika-Labs/akter#readme","bugs":"https://github.com/Rika-Labs/akter/issues","license":"Apache-2.0","author":"Rika Labs","repository":{"type":"git","url":"git+https://github.com/Rika-Labs/akter.git","directory":"apps/cli"},"type":"module","types":"./dist/main.d.ts","exports":{".":{"types":"./dist/main.d.ts","default":"./dist/main.js"},"./cloud-api":{"types":"./dist/cloud-api/index.d.ts","default":"./dist/cloud-api/index.js"}},"engines":{"bun":">=1.4.2","node":">=24.0.0"}}
|