@akterjs/cli 0.0.0-stage → 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/LICENSE +201 -0
- package/README.md +47 -2
- package/dist/Argument-D81dqizB.mjs +57 -0
- package/dist/Array-B4kuTQeW.mjs +2323 -0
- package/dist/Boolean-kILIvmhE.mjs +26 -0
- package/dist/ChildProcess-BCIwxPGc.mjs +577 -0
- package/dist/CliError-Cf5xqkkj.mjs +633 -0
- package/dist/Command-Dzq9KM-h.mjs +5135 -0
- package/dist/Config-B6OND9WR.mjs +854 -0
- package/dist/Console-BKHUkH6a.mjs +141 -0
- package/dist/Data-CeCULr0-.mjs +251 -0
- package/dist/Digest-CBd3uv5B.mjs +348 -0
- package/dist/Duration-EH9Vy4U6.mjs +791 -0
- package/dist/Effect-CKFpqbmw.mjs +12911 -0
- package/dist/FileSystem-4pPcEb_i.mjs +1366 -0
- package/dist/HttpClientError-BUeMWx70.mjs +303 -0
- package/dist/HttpClientResponse-D5ZKICVV.mjs +855 -0
- package/dist/Match-CGPLZYrV.mjs +434 -0
- package/dist/MutableHashMap-f8nW8AJR.mjs +376 -0
- package/dist/MutableHashSet-_HI572Ya.mjs +155 -0
- package/dist/MutableRef-D4Qv592C.mjs +107 -0
- package/dist/Number-BvkRkfc-.mjs +137 -0
- package/dist/Option-DkxSnBhp.mjs +3967 -0
- package/dist/Order-C1JC991I.mjs +481 -0
- package/dist/Path-Djdv_eF5.mjs +130 -0
- package/dist/Queue-CO5UQ6os.mjs +1394 -0
- package/dist/Redacted-RkJrG5Me.mjs +160 -0
- package/dist/Ref-BIPOxJNH.mjs +267 -0
- package/dist/Runtime-BInIAwK3.mjs +297 -0
- package/dist/Schema-MiKt5K1v.mjs +10999 -0
- package/dist/SecureRandom-B_U4ysO3.mjs +279 -0
- package/dist/Semaphore-DOVJ4ZGS.mjs +177 -0
- package/dist/Stdio-KylmOBX_.mjs +74 -0
- package/dist/Stream-bK9QIETN.mjs +4012 -0
- package/dist/String-q5dcsVe4.mjs +351 -0
- package/dist/TerminalCapabilities-w_44MAca.mjs +1769 -0
- package/dist/WebCrypto-ZI_GNVlw.mjs +33 -0
- package/dist/actor-call.service-CGM_vD9u.mjs +1269 -0
- package/dist/actor-client.adapter-Coem7gF1.mjs +3691 -0
- package/dist/akter-program.config-C4cXx4Fr.mjs +7034 -0
- package/dist/akter.cli.mjs +5 -0
- package/dist/app-cli.config.mjs +49 -0
- package/dist/app-entry.pure.mjs +31 -0
- package/dist/archive/akter-archive.schema.mjs +65 -0
- package/dist/archive/akter-archive.service.mjs +309 -0
- package/dist/archive/archive-cli.config.mjs +45 -0
- package/dist/archive/archive-invalid.errors.mjs +5 -0
- package/dist/archive/archived-lineage.pure.mjs +13 -0
- package/dist/archive/tar.pure.mjs +291 -0
- package/dist/archive/zstd.adapter.mjs +46 -0
- package/dist/bench/bench-report.pure.mjs +120 -0
- package/dist/bench/bench-runner.pure.mjs +89 -0
- package/dist/bench/bench.service.mjs +301 -0
- package/dist/cli-runtime.layer-BqK2mmVL.mjs +1191 -0
- package/dist/cli-runtime.layer.mjs +1 -0
- package/dist/cloud-client.adapter-Cy1BjDbG.mjs +3186 -0
- package/dist/cloud-client.adapter-DOVMoYAj.mjs +304 -0
- package/dist/command/akter-commands.config.mjs +32 -0
- package/dist/command/akter-program.config.mjs +1 -0
- package/dist/credentials/credentials.service.mjs +226 -0
- package/dist/credentials/keychain.adapter.mjs +92 -0
- package/dist/credentials/login.config.mjs +251 -0
- package/dist/deploy/auth/api-attempt.service.mjs +30 -0
- package/dist/deploy/auth/token-refresh.errors.mjs +4 -0
- package/dist/deploy/build-bundle.adapter.mjs +133 -0
- package/dist/deploy/build-manifest.pure.mjs +44 -0
- package/dist/deploy/cloud-client.adapter.mjs +1 -0
- package/dist/deploy/cloud-url.pure.mjs +17 -0
- package/dist/deploy/deploy-failed.errors.mjs +17 -0
- package/dist/deploy/deploy.service.mjs +156 -0
- package/dist/deploy/request-failure.pure.mjs +87 -0
- package/dist/dev-runner.pure.mjs +30 -0
- package/dist/docs/doc-topics.pure.mjs +21 -0
- package/dist/docs/docs.config.mjs +1 -0
- package/dist/docs.config-_21Xi6HU.mjs +190 -0
- package/dist/export/actor-export.service.mjs +267 -0
- package/dist/export/export-failed.errors.mjs +4 -0
- package/dist/export/export-failure.pure.mjs +18 -0
- package/dist/export/ordered-lines.pure.mjs +43 -0
- package/dist/export/ranged-download.pure.mjs +66 -0
- package/dist/export/snapshot-download.pure.mjs +86 -0
- package/dist/history-runner.pure.mjs +186 -0
- package/dist/history-since.pure.mjs +17 -0
- package/dist/hosted-runtime.layer-Cx3IPsEd.mjs +16358 -0
- package/dist/local/environment-cli.config.mjs +90 -0
- package/dist/local/environment-runner.pure.mjs +75 -0
- package/dist/local/local-cli.config.mjs +159 -0
- package/dist/logs/log-follow.config.mjs +21 -0
- package/dist/logs/log-follow.service.mjs +87 -0
- package/dist/logs/log-lines.pure.mjs +44 -0
- package/dist/migrate-runner.pure.mjs +28 -0
- package/dist/operation-input.pure-CS9iUhqK.mjs +1383 -0
- package/dist/operation-registry.pure-DVC8EDgj.mjs +283 -0
- package/dist/registry/actor-call.service.mjs +1 -0
- package/dist/registry/actor-commands.config.mjs +127 -0
- package/dist/registry/actor-refusal.pure.mjs +34 -0
- package/dist/registry/approval.service.mjs +80 -0
- package/dist/registry/cloud-commands.config.mjs +151 -0
- package/dist/registry/cloud-served.pure.mjs +31 -0
- package/dist/registry/operation-call.service.mjs +262 -0
- package/dist/registry/operation-input.pure.mjs +1 -0
- package/dist/registry/operation-output.pure.mjs +91 -0
- package/dist/registry/served-command.config.mjs +57 -0
- package/dist/runner-exited.errors.mjs +10 -0
- package/dist/terminal/cli-exit.errors.mjs +38 -0
- package/dist/terminal/cli-failure.pure.mjs +31 -0
- package/dist/terminal/confirm.adapter.mjs +27 -0
- package/package.json +61 -3
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { R as some, T as join, j as map, l as filter, r as contains, u as findFirst } from "../Array-B4kuTQeW.mjs";
|
|
2
|
+
import { t as match } from "../Boolean-kILIvmhE.mjs";
|
|
3
|
+
import { _ as isSome, b as map$1, c as flatten, cn as isString, f as getOrElse, h as isNone, i as filter$1, o as flatMap, r as exists, u as fromNullishOr, w as some$1 } from "../Option-DkxSnBhp.mjs";
|
|
4
|
+
import { nt as decodeOption, or as fromEntries, pt as fromJsonString, sr as get, y as Json } from "../Schema-MiKt5K1v.mjs";
|
|
5
|
+
// src/registry/cloud-served.pure.ts
|
|
6
|
+
const loopbackHosts = [
|
|
7
|
+
"localhost",
|
|
8
|
+
"127.0.0.1",
|
|
9
|
+
"[::1]"
|
|
10
|
+
];
|
|
11
|
+
const renamed = [["forkId", "commandId"]];
|
|
12
|
+
const renamedFrom = (name) => map$1(findFirst(renamed, ([field]) => field === name), ([, flag]) => flag);
|
|
13
|
+
const keyFields = ["into", "key"];
|
|
14
|
+
const JsonText = fromJsonString(Json);
|
|
15
|
+
const servedBy = (operations) => (actor) => findFirst(operations, ({ command }) => join(command, " ") === join(actor.command, " "));
|
|
16
|
+
const isLocalApp = (url) => exists(flatMap(url, (given) => fromNullishOr(globalThis.URL.parse(given)?.hostname)), (host) => contains(loopbackHosts, host));
|
|
17
|
+
const cloudOnlyFields = ({ actor, cloud }) => filter(cloud.fields, ({ name }) => !some(actor.fields, (field) => field === name) && isNone(renamedFrom(name)));
|
|
18
|
+
const keyText = (text) => getOrElse(filter$1(decodeOption(JsonText)(text), isString), () => text);
|
|
19
|
+
const textOf = (name) => (text) => match(contains(keyFields, name), {
|
|
20
|
+
onFalse: () => text,
|
|
21
|
+
onTrue: () => keyText(text)
|
|
22
|
+
});
|
|
23
|
+
const givenIn = (values) => (flag) => flatten(get(values, flag));
|
|
24
|
+
const valueOf = ({ minted, values }) => (name) => {
|
|
25
|
+
const given = givenIn(values);
|
|
26
|
+
const renaming = renamedFrom(name);
|
|
27
|
+
if (isSome(renaming)) return some$1(getOrElse(given(renaming.value), () => minted));
|
|
28
|
+
return map$1(given(name), textOf(name));
|
|
29
|
+
};
|
|
30
|
+
const cloudValuesOf = (filled) => fromEntries(map(filled.cloud.fields, ({ name }) => [name, valueOf(filled)(name)]));
|
|
31
|
+
export { cloudOnlyFields, cloudValuesOf, isLocalApp, servedBy };
|
|
@@ -0,0 +1,262 @@
|
|
|
1
|
+
import { R as some, T as join } from "../Array-B4kuTQeW.mjs";
|
|
2
|
+
import { t as match } from "../Boolean-kILIvmhE.mjs";
|
|
3
|
+
import { n as log, t as error } from "../Console-BKHUkH6a.mjs";
|
|
4
|
+
import { At as provideContext, B as flatMap, Dt as orElseSucceed, Et as orDie, Gn as mergeAll, Gt as scoped, T as context, Vn as effect, W as fnUntraced, Xt as succeed, aa as Service, et as gen, ht as mapError, in as timeout, l as as, qn as provideMerge, x as catchTag } from "../Effect-CKFpqbmw.mjs";
|
|
5
|
+
import { t as FileSystem } from "../FileSystem-4pPcEb_i.mjs";
|
|
6
|
+
import { C as orElse, S as none, _ as isSome, b as map, cn as isString, f as getOrElse, h as isNone, i as filter, in as isNumber, o as flatMap$1, p as getOrNull, t as all, v as liftPredicate, w as some$1, x as match$1 } from "../Option-DkxSnBhp.mjs";
|
|
7
|
+
import { at as decodeUnknownEffect, b as JsonObject, cr as getSomes, gr as union, lr as has, mr as set, pt as fromJsonString, q as Uint8ArrayFromBase64, sr as get, st as encodeEffect, tt as decodeEffect, y as Json } from "../Schema-MiKt5K1v.mjs";
|
|
8
|
+
import { t as Stdio } from "../Stdio-KylmOBX_.mjs";
|
|
9
|
+
import { M as mkString, T as make, i as decodeText, z as run } from "../Stream-bK9QIETN.mjs";
|
|
10
|
+
import { h as startsWith, p as slice } from "../String-q5dcsVe4.mjs";
|
|
11
|
+
import { f as HttpClient, g as mapRequest, y as isHttpMethod } from "../cloud-client.adapter-Cy1BjDbG.mjs";
|
|
12
|
+
import { E as setUrlParams, S as prependUrl, T as setUrlParam, d as acceptJson, p as bodyJson, w as setHeaders, y as make$1 } from "../HttpClientResponse-D5ZKICVV.mjs";
|
|
13
|
+
import { CliExitError } from "../terminal/cli-exit.errors.mjs";
|
|
14
|
+
import { Credentials } from "../credentials/credentials.service.mjs";
|
|
15
|
+
import { t as CloudClient } from "../cloud-client.adapter-DOVMoYAj.mjs";
|
|
16
|
+
import { Approval } from "./approval.service.mjs";
|
|
17
|
+
import { i as validInput, n as parseInput, r as targetOf, t as checkedSchema } from "../operation-input.pure-CS9iUhqK.mjs";
|
|
18
|
+
import { errorLine, joinedPages, printJson, reported, retryHint, unanswered } from "./operation-output.pure.mjs";
|
|
19
|
+
import { RunnerExitedError } from "../runner-exited.errors.mjs";
|
|
20
|
+
// src/registry/operation-call.service.ts
|
|
21
|
+
const approvalHeader = "akter-approval";
|
|
22
|
+
const callWait = "2 minutes";
|
|
23
|
+
const firstSuccess = 200;
|
|
24
|
+
const firstRedirect = 300;
|
|
25
|
+
const confirmationRequired = 428;
|
|
26
|
+
const fromFile = "@";
|
|
27
|
+
const fromStdin = "-";
|
|
28
|
+
const JsonText = fromJsonString(Json);
|
|
29
|
+
const Base64 = Uint8ArrayFromBase64;
|
|
30
|
+
const commandName = (operation) => `akter ${join(operation.command, " ")}`;
|
|
31
|
+
const unreadable = (message) => () => CliExitError.make({
|
|
32
|
+
code: CliExitError.codes.usage,
|
|
33
|
+
message,
|
|
34
|
+
reason: "InvalidInput"
|
|
35
|
+
});
|
|
36
|
+
const unreadableAnswer = (operation) => () => CliExitError.make({
|
|
37
|
+
code: CliExitError.codes.unavailable,
|
|
38
|
+
message: `The API's answer to ${commandName(operation)} could not be read.`,
|
|
39
|
+
reason: "ResponseUnreadable"
|
|
40
|
+
});
|
|
41
|
+
const mismatch = (operation) => (failure) => CliExitError.make({
|
|
42
|
+
code: CliExitError.codes.failed,
|
|
43
|
+
message: `The API's answer to ${commandName(operation)} doesn't match its schema, so this CLI and the API disagree:\n${failure.message}`,
|
|
44
|
+
reason: "ResponseMismatch"
|
|
45
|
+
});
|
|
46
|
+
const readText = fnUntraced(function* readText(raw) {
|
|
47
|
+
if (raw === fromStdin) {
|
|
48
|
+
const stdio = yield* Stdio;
|
|
49
|
+
return yield* mkString(decodeText(stdio.stdin)).pipe(mapError(unreadable("Could not read --input from stdin.")));
|
|
50
|
+
}
|
|
51
|
+
if (!startsWith(fromFile)(raw)) return raw;
|
|
52
|
+
const file = slice(1)(raw);
|
|
53
|
+
return yield* (yield* FileSystem).readFileString(file).pipe(mapError(unreadable(`Could not read --input from ${file}.`)));
|
|
54
|
+
});
|
|
55
|
+
const inputOf = fnUntraced(function* inputOf(operation, options) {
|
|
56
|
+
const base = yield* match$1(options.input, {
|
|
57
|
+
onNone: () => succeed({}),
|
|
58
|
+
onSome: (raw) => flatMap(readText(raw), parseInput)
|
|
59
|
+
});
|
|
60
|
+
const assembled = union(base, getSomes(options.values), (_given, flag) => flag);
|
|
61
|
+
if (!some(operation.fields, (field) => field.name === "organization") || has(assembled, "organization")) return assembled;
|
|
62
|
+
const organization = yield* Credentials.use((credentials) => credentials.organization(none()));
|
|
63
|
+
return match$1(organization, {
|
|
64
|
+
onNone: () => assembled,
|
|
65
|
+
onSome: (name) => set(assembled, "organization", name)
|
|
66
|
+
});
|
|
67
|
+
});
|
|
68
|
+
const printBinary = fnUntraced(function* printBinary({ json, operation, response }) {
|
|
69
|
+
const buffer = yield* response.arrayBuffer.pipe(mapError(unreadableAnswer(operation)));
|
|
70
|
+
const bytes = new Uint8Array(buffer);
|
|
71
|
+
if (json) {
|
|
72
|
+
const encoded = yield* encodeEffect(Base64)(bytes).pipe(orDie);
|
|
73
|
+
return yield* printJson(true)(encoded);
|
|
74
|
+
}
|
|
75
|
+
const stdio = yield* Stdio;
|
|
76
|
+
return yield* run(make(bytes), stdio.stdout({ endOnDone: false })).pipe(orDie);
|
|
77
|
+
});
|
|
78
|
+
const checkedAnswer = fnUntraced(function* checkedAnswer(operation, response) {
|
|
79
|
+
const value = yield* response.json.pipe(mapError(unreadableAnswer(operation)));
|
|
80
|
+
const schema = yield* checkedSchema(operation.success.schema);
|
|
81
|
+
yield* decodeEffect(schema)(value).pipe(mapError(mismatch(operation)));
|
|
82
|
+
return value;
|
|
83
|
+
});
|
|
84
|
+
const printSuccess = fnUntraced(function* printSuccess(answer) {
|
|
85
|
+
const { json, operation, response } = answer;
|
|
86
|
+
if (operation.success.kind === "binary") return yield* printBinary(answer);
|
|
87
|
+
if (operation.success.kind === "empty") return yield* match(json, {
|
|
88
|
+
onFalse: () => log(`Done: ${commandName(operation)}.`),
|
|
89
|
+
onTrue: () => log("null")
|
|
90
|
+
});
|
|
91
|
+
const value = yield* checkedAnswer(operation, response);
|
|
92
|
+
return yield* printJson(json)(value);
|
|
93
|
+
});
|
|
94
|
+
const bodyOf = fnUntraced(function* bodyOf(response) {
|
|
95
|
+
const text = yield* response.text.pipe(orElseSucceed(() => ""));
|
|
96
|
+
return yield* decodeEffect(JsonText)(text).pipe(orElseSucceed(() => text));
|
|
97
|
+
});
|
|
98
|
+
const printRefusal = fnUntraced(function* printRefusal({ json, operation, response }, body) {
|
|
99
|
+
const code = CliExitError.ofStatus(response.status);
|
|
100
|
+
if (json) yield* printJson(true)(body);
|
|
101
|
+
else {
|
|
102
|
+
const hint = retryHint({
|
|
103
|
+
...operation.annotations,
|
|
104
|
+
status: response.status
|
|
105
|
+
});
|
|
106
|
+
yield* error(`${commandName(operation)} failed: ${errorLine({
|
|
107
|
+
body,
|
|
108
|
+
status: response.status
|
|
109
|
+
})}${hint}`);
|
|
110
|
+
}
|
|
111
|
+
return yield* RunnerExitedError.make({ code });
|
|
112
|
+
});
|
|
113
|
+
const methodOf = (operation) => getOrElse(liftPredicate(operation.method, isHttpMethod), () => "GET");
|
|
114
|
+
const requestFor = ({ operation, options, request }) => {
|
|
115
|
+
const approvalHeaders = match$1(options.approval, {
|
|
116
|
+
onNone: () => ({}),
|
|
117
|
+
onSome: (token) => ({ [approvalHeader]: token })
|
|
118
|
+
});
|
|
119
|
+
const base = make$1(methodOf(operation))(request.path).pipe(setUrlParams(request.query), acceptJson, setHeaders(approvalHeaders));
|
|
120
|
+
return match$1(request.body, {
|
|
121
|
+
onNone: () => succeed(base),
|
|
122
|
+
onSome: (body) => orDie(bodyJson(base, body))
|
|
123
|
+
});
|
|
124
|
+
};
|
|
125
|
+
const printPlan = ({ operation, options, request }) => printJson(options.json)({
|
|
126
|
+
body: getOrNull(request.body),
|
|
127
|
+
dryRun: true,
|
|
128
|
+
method: operation.method,
|
|
129
|
+
operation: operation.id,
|
|
130
|
+
path: request.path,
|
|
131
|
+
query: request.query
|
|
132
|
+
});
|
|
133
|
+
const organizationOf = (input) => filter(get(input, "organization"), isString);
|
|
134
|
+
const approvalAsked = fnUntraced(function* approvalAsked(planned, answer, body) {
|
|
135
|
+
const required = (yield* Approval).isRequired(body);
|
|
136
|
+
const unapproved = isNone(planned.options.approval) && answer.response.status === confirmationRequired;
|
|
137
|
+
return all({
|
|
138
|
+
organization: organizationOf(planned.input),
|
|
139
|
+
required
|
|
140
|
+
}).pipe(filter(() => unapproved), map(({ organization, required: asked }) => ({
|
|
141
|
+
command: commandName(planned.operation),
|
|
142
|
+
organization,
|
|
143
|
+
required: asked
|
|
144
|
+
})));
|
|
145
|
+
});
|
|
146
|
+
const attempt = fnUntraced(function* attempt(planned, http) {
|
|
147
|
+
const { operation, options } = planned;
|
|
148
|
+
const response = yield* flatMap(requestFor(planned), http.execute).pipe(timeout(callWait), mapError((failure) => unanswered({
|
|
149
|
+
command: commandName(operation),
|
|
150
|
+
failure,
|
|
151
|
+
wait: callWait
|
|
152
|
+
})));
|
|
153
|
+
const answer = {
|
|
154
|
+
json: options.json,
|
|
155
|
+
operation,
|
|
156
|
+
response
|
|
157
|
+
};
|
|
158
|
+
if (response.status >= firstSuccess && response.status < firstRedirect) return yield* as(printSuccess(answer), none());
|
|
159
|
+
const body = yield* bodyOf(response);
|
|
160
|
+
const asked = yield* approvalAsked(planned, answer, body);
|
|
161
|
+
if (isSome(asked)) return some$1({
|
|
162
|
+
...asked.value,
|
|
163
|
+
http
|
|
164
|
+
});
|
|
165
|
+
return yield* printRefusal(answer, body);
|
|
166
|
+
}, scoped);
|
|
167
|
+
const nextOf = (page) => flatMap$1(get(page, "next"), (next) => orElse(liftPredicate(next, isString), () => map(liftPredicate(next, isNumber), String)));
|
|
168
|
+
const pageAfter = fnUntraced(function* pageAfter(planned, http, after) {
|
|
169
|
+
const { operation, options } = planned;
|
|
170
|
+
const first = yield* requestFor(planned);
|
|
171
|
+
const request = match$1(after, {
|
|
172
|
+
onNone: () => first,
|
|
173
|
+
onSome: (cursor) => setUrlParam(first, "after", cursor)
|
|
174
|
+
});
|
|
175
|
+
const response = yield* http.execute(request).pipe(timeout(callWait), mapError((failure) => unanswered({
|
|
176
|
+
command: commandName(operation),
|
|
177
|
+
failure,
|
|
178
|
+
wait: callWait
|
|
179
|
+
})));
|
|
180
|
+
if (response.status < firstSuccess || response.status >= firstRedirect) {
|
|
181
|
+
const body = yield* bodyOf(response);
|
|
182
|
+
return yield* printRefusal({
|
|
183
|
+
json: options.json,
|
|
184
|
+
operation,
|
|
185
|
+
response
|
|
186
|
+
}, body);
|
|
187
|
+
}
|
|
188
|
+
const value = yield* checkedAnswer(operation, response);
|
|
189
|
+
return yield* decodeUnknownEffect(JsonObject)(value).pipe(mapError(mismatch(operation)));
|
|
190
|
+
}, scoped);
|
|
191
|
+
const everyPage = fnUntraced(function* everyPage(planned, http) {
|
|
192
|
+
const first = yield* pageAfter(planned, http, none());
|
|
193
|
+
const rest = [];
|
|
194
|
+
let next = nextOf(first);
|
|
195
|
+
while (isSome(next)) {
|
|
196
|
+
const page = yield* pageAfter(planned, http, next);
|
|
197
|
+
rest.push(page);
|
|
198
|
+
next = nextOf(page);
|
|
199
|
+
}
|
|
200
|
+
return yield* printJson(planned.options.json)(joinedPages([first, ...rest]));
|
|
201
|
+
});
|
|
202
|
+
const approved = fnUntraced(function* approved(planned, http) {
|
|
203
|
+
const asked = yield* attempt(planned, http);
|
|
204
|
+
if (isNone(asked)) return;
|
|
205
|
+
const token = yield* Approval.use((approval) => approval.token(asked.value));
|
|
206
|
+
yield* attempt({
|
|
207
|
+
...planned,
|
|
208
|
+
options: {
|
|
209
|
+
...planned.options,
|
|
210
|
+
approval: some$1(token)
|
|
211
|
+
}
|
|
212
|
+
}, http);
|
|
213
|
+
});
|
|
214
|
+
const sendOn = fnUntraced(function* sendOn(planned, http) {
|
|
215
|
+
if (planned.options.all) return yield* everyPage(planned, http);
|
|
216
|
+
return yield* approved(planned, http);
|
|
217
|
+
});
|
|
218
|
+
const send = fnUntraced(function* send(planned) {
|
|
219
|
+
const url = yield* Credentials.use((credentials) => credentials.url(planned.options.url));
|
|
220
|
+
if (!planned.operation.secured) {
|
|
221
|
+
const http = yield* HttpClient;
|
|
222
|
+
return yield* sendOn(planned, mapRequest(http, prependUrl(url.href)));
|
|
223
|
+
}
|
|
224
|
+
const credential = yield* Credentials.use((credentials) => credentials.credentialFor(url));
|
|
225
|
+
const cloud = yield* CloudClient.use((factory) => factory.connect({
|
|
226
|
+
apiKey: credential.secret,
|
|
227
|
+
url
|
|
228
|
+
}));
|
|
229
|
+
return yield* sendOn(planned, cloud.http);
|
|
230
|
+
});
|
|
231
|
+
const callOperation = fnUntraced(function* callOperation(operation, options) {
|
|
232
|
+
const input = yield* inputOf(operation, options);
|
|
233
|
+
const { input: valid, request } = yield* validInput({
|
|
234
|
+
input,
|
|
235
|
+
operation
|
|
236
|
+
});
|
|
237
|
+
if (options.dryRun) return yield* printPlan({
|
|
238
|
+
input: valid,
|
|
239
|
+
operation,
|
|
240
|
+
options,
|
|
241
|
+
request
|
|
242
|
+
});
|
|
243
|
+
const command = commandName(operation);
|
|
244
|
+
yield* Approval.use((approval) => approval.confirm({
|
|
245
|
+
command,
|
|
246
|
+
needed: operation.annotations.confirm && isNone(options.approval),
|
|
247
|
+
question: `${operation.description} Run ${command} for ${targetOf(operation)(valid)}?`
|
|
248
|
+
}));
|
|
249
|
+
return yield* send({
|
|
250
|
+
input: valid,
|
|
251
|
+
operation,
|
|
252
|
+
options,
|
|
253
|
+
request
|
|
254
|
+
});
|
|
255
|
+
});
|
|
256
|
+
var OperationCall = class extends Service()("@akterjs/cli/registry/operation-call.service/OperationCall", { make: gen(function* makeOperationCall() {
|
|
257
|
+
const context$1 = yield* context();
|
|
258
|
+
return { call: (operation, options) => callOperation(operation, options).pipe(catchTag("CliExitError", reported(options.json)), provideContext(context$1)) };
|
|
259
|
+
}) }) {
|
|
260
|
+
static layer = effect(this, this.make).pipe(provideMerge(mergeAll(Credentials.layer, CloudClient.layer, Approval.layer)));
|
|
261
|
+
};
|
|
262
|
+
export { OperationCall };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { t as checkedSchema, n as parseInput, r as targetOf, i as validInput } from "../operation-input.pure-CS9iUhqK.mjs";
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { D as lastNonEmpty, T as join, j as map, p as flatMap, w as isReadonlyArrayNonEmpty } from "../Array-B4kuTQeW.mjs";
|
|
2
|
+
import { t as match } from "../Boolean-kILIvmhE.mjs";
|
|
3
|
+
import { B as flatMap$1, Et as orDie, M as fail, o as andThen, ti as isTimeoutError } from "../Effect-CKFpqbmw.mjs";
|
|
4
|
+
import { n as log, t as error } from "../Console-BKHUkH6a.mjs";
|
|
5
|
+
import { Tn as pipe, cn as isString, d as fromUndefinedOr, f as getOrElse, i as filter, x as match$1 } from "../Option-DkxSnBhp.mjs";
|
|
6
|
+
import { b as JsonObject, ct as encodeOption, fr as map$1, hr as toEntries, mt as is, n as ArraySchema, pr as remove, pt as fromJsonString, sr as get, st as encodeEffect, y as Json } from "../Schema-MiKt5K1v.mjs";
|
|
7
|
+
import { v as trim } from "../String-q5dcsVe4.mjs";
|
|
8
|
+
import { CliExitError } from "../terminal/cli-exit.errors.mjs";
|
|
9
|
+
import { TokenRefreshError } from "../deploy/auth/token-refresh.errors.mjs";
|
|
10
|
+
import { DeployFailedError } from "../deploy/deploy-failed.errors.mjs";
|
|
11
|
+
import { RunnerExitedError } from "../runner-exited.errors.mjs";
|
|
12
|
+
// src/registry/operation-output.pure.ts
|
|
13
|
+
const compact = encodeEffect(fromJsonString(Json));
|
|
14
|
+
const pretty = encodeEffect(fromJsonString(Json, { space: 2 }));
|
|
15
|
+
const compactOption = encodeOption(fromJsonString(Json));
|
|
16
|
+
const encodeExit = encodeEffect(CliExitError);
|
|
17
|
+
const compactJson = (value) => orDie(compact(value));
|
|
18
|
+
const prettyJson = (value) => orDie(pretty(value));
|
|
19
|
+
const exitJson = (failure) => flatMap$1(orDie(encodeExit(failure)), compactJson);
|
|
20
|
+
const shown = (value) => {
|
|
21
|
+
if (isString(value)) return value;
|
|
22
|
+
return getOrElse(compactOption(value), () => "");
|
|
23
|
+
};
|
|
24
|
+
const errorLine = ({ body, status }) => {
|
|
25
|
+
if (!is(JsonObject)(body)) return trim(`HTTP ${status} ${shown(body)}`);
|
|
26
|
+
const tag = pipe(get(body, "_tag"), filter(isString), getOrElse(() => "Error"));
|
|
27
|
+
const fields = pipe(toEntries(remove(body, "_tag")), map(([key, value]) => `${key}: ${shown(value)}`));
|
|
28
|
+
if (isReadonlyArrayNonEmpty(fields)) return `HTTP ${status} ${tag} (${join(fields, ", ")})`;
|
|
29
|
+
return `HTTP ${status} ${tag}`;
|
|
30
|
+
};
|
|
31
|
+
const unavailableStatus = 503;
|
|
32
|
+
/**
|
|
33
|
+
* After a 503 an idempotent change may have stopped partway, as erasing an actor can between releasing its files and
|
|
34
|
+
* destroying its key (FK6); running it again finishes it.
|
|
35
|
+
*/
|
|
36
|
+
const retryHint = ({ idempotent, readOnly, status }) => {
|
|
37
|
+
if (status === unavailableStatus && idempotent && !readOnly) return ". It may have stopped partway, and it is safe to repeat: run the same command again.";
|
|
38
|
+
return "";
|
|
39
|
+
};
|
|
40
|
+
const unavailable = (message) => CliExitError.make({
|
|
41
|
+
code: CliExitError.codes.unavailable,
|
|
42
|
+
message,
|
|
43
|
+
reason: "Unavailable"
|
|
44
|
+
});
|
|
45
|
+
const signInCode = (failure) => match$1(fromUndefinedOr(failure.status), {
|
|
46
|
+
onNone: () => CliExitError.codes.unavailable,
|
|
47
|
+
onSome: CliExitError.ofStatus
|
|
48
|
+
});
|
|
49
|
+
/**
|
|
50
|
+
* A token exchange that failed, with the exit code of what failed it: 3 only when the API refused the key (401 or
|
|
51
|
+
* 403), and 5 when it couldn't answer, answered 5xx, or a refresh failed, since trying again may succeed.
|
|
52
|
+
*/
|
|
53
|
+
const signInFailure = (failure) => {
|
|
54
|
+
if (is(TokenRefreshError)(failure)) return unavailable(failure.message);
|
|
55
|
+
const message = `Signing in failed: ${failure.message}`;
|
|
56
|
+
return CliExitError.make({
|
|
57
|
+
code: signInCode(failure),
|
|
58
|
+
message,
|
|
59
|
+
reason: "SignInFailed"
|
|
60
|
+
});
|
|
61
|
+
};
|
|
62
|
+
const unanswered = ({ command, failure, wait }) => {
|
|
63
|
+
if (is(DeployFailedError)(failure) || is(TokenRefreshError)(failure)) return signInFailure(failure);
|
|
64
|
+
if (isTimeoutError(failure)) return unavailable(`${command} got no answer within ${wait}; the request may still have run.`);
|
|
65
|
+
return unavailable(`${command} could not reach the API: ${failure.message}`);
|
|
66
|
+
};
|
|
67
|
+
const printJson = (json) => (value) => {
|
|
68
|
+
const text = match(json, {
|
|
69
|
+
onFalse: () => prettyJson(value),
|
|
70
|
+
onTrue: () => compactJson(value)
|
|
71
|
+
});
|
|
72
|
+
return flatMap$1(text, (line) => log(line));
|
|
73
|
+
};
|
|
74
|
+
const JsonArray = ArraySchema(Json);
|
|
75
|
+
const arrayAt = (page, key) => getOrElse(filter(get(page, key), is(JsonArray)), () => []);
|
|
76
|
+
const joinedPages = (pages) => {
|
|
77
|
+
const last = lastNonEmpty(pages);
|
|
78
|
+
const joined = map$1(last, (value, key) => match(is(JsonArray)(value), {
|
|
79
|
+
onFalse: () => value,
|
|
80
|
+
onTrue: () => flatMap(pages, (page) => arrayAt(page, key))
|
|
81
|
+
}));
|
|
82
|
+
return remove(joined, "next");
|
|
83
|
+
};
|
|
84
|
+
const reported = (json) => (failure) => {
|
|
85
|
+
const printed = match(json, {
|
|
86
|
+
onFalse: () => error(failure.message),
|
|
87
|
+
onTrue: () => flatMap$1(exitJson(failure), (line) => log(line))
|
|
88
|
+
});
|
|
89
|
+
return andThen(printed, fail(RunnerExitedError.make({ code: failure.code })));
|
|
90
|
+
};
|
|
91
|
+
export { compactJson, errorLine, exitJson, joinedPages, printJson, reported, retryHint, signInFailure, unanswered };
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { T as join, j as map } from "../Array-B4kuTQeW.mjs";
|
|
2
|
+
import { a as option, i as String } from "../Config-B6OND9WR.mjs";
|
|
3
|
+
import { Dt as orElseSucceed, W as fnUntraced, dt as map$1 } from "../Effect-CKFpqbmw.mjs";
|
|
4
|
+
import { C as orElse, S as none, x as match } from "../Option-DkxSnBhp.mjs";
|
|
5
|
+
import { or as fromEntries } from "../Schema-MiKt5K1v.mjs";
|
|
6
|
+
import { f as optional, i as withDescription$1, l as String$1, m as withDescription, r as unlisted, t as make } from "../Command-Dzq9KM-h.mjs";
|
|
7
|
+
import { t as SecureRandom } from "../SecureRandom-B_U4ysO3.mjs";
|
|
8
|
+
import { t as kebab } from "../operation-registry.pure-DVC8EDgj.mjs";
|
|
9
|
+
import { cloudOnlyFields, cloudValuesOf, isLocalApp } from "./cloud-served.pure.mjs";
|
|
10
|
+
import { OperationCall } from "./operation-call.service.mjs";
|
|
11
|
+
// src/registry/served-command.config.ts
|
|
12
|
+
const approval = String$1("approval").pipe(optional, withDescription("On Akter Cloud, a token from an approved request, to run this without a person at the terminal"));
|
|
13
|
+
const cloudFlag = (field) => String$1(kebab(field.name)).pipe(optional, withDescription(`On Akter Cloud: ${field.description}`));
|
|
14
|
+
const appUrlOf = (flag) => map$1(option(String("AKTER_APP_URL")).pipe(orElseSucceed(() => none())), (configured) => orElse(flag, () => configured));
|
|
15
|
+
const onCloud = fnUntraced(function* onCloud({ cloud }, options) {
|
|
16
|
+
const minted = yield* SecureRandom.use((random) => random.uuidV7());
|
|
17
|
+
const values = cloudValuesOf({
|
|
18
|
+
cloud,
|
|
19
|
+
minted,
|
|
20
|
+
values: {
|
|
21
|
+
...options.fields,
|
|
22
|
+
...options.cloud
|
|
23
|
+
}
|
|
24
|
+
});
|
|
25
|
+
return yield* OperationCall.use((service) => service.call(cloud, {
|
|
26
|
+
all: false,
|
|
27
|
+
approval: options.approval,
|
|
28
|
+
dryRun: options.dryRun,
|
|
29
|
+
input: none(),
|
|
30
|
+
json: options.json,
|
|
31
|
+
url: none(),
|
|
32
|
+
values
|
|
33
|
+
}));
|
|
34
|
+
});
|
|
35
|
+
const servedDescription = (served) => {
|
|
36
|
+
const flags = map(cloudOnlyFields(served), ({ name }) => `--${kebab(name)}`);
|
|
37
|
+
return `${served.actor.description} On akter dev it goes to the app at --url. On Akter Cloud it is the Cloud API's ${served.cloud.id}, an operator action: pass ${join(flags, ", ")} instead of --url, and a person confirms it, or --approval carries an approved token.`;
|
|
38
|
+
};
|
|
39
|
+
const servedCommandOf = ({ flags, local, served }) => {
|
|
40
|
+
const [, name] = served.actor.command;
|
|
41
|
+
const cloud = fromEntries(map(cloudOnlyFields(served), (field) => [field.name, cloudFlag(field)]));
|
|
42
|
+
const routed = fnUntraced(function* routed(options) {
|
|
43
|
+
const appUrl = yield* appUrlOf(options.url);
|
|
44
|
+
if (isLocalApp(appUrl)) return yield* local(options);
|
|
45
|
+
return yield* onCloud(served, options);
|
|
46
|
+
});
|
|
47
|
+
const command = make(name, {
|
|
48
|
+
...flags,
|
|
49
|
+
approval,
|
|
50
|
+
cloud
|
|
51
|
+
}, routed).pipe(withDescription$1(servedDescription(served)));
|
|
52
|
+
return match(served.cloud.flag, {
|
|
53
|
+
onNone: () => command,
|
|
54
|
+
onSome: () => unlisted(command)
|
|
55
|
+
});
|
|
56
|
+
};
|
|
57
|
+
export { servedCommandOf };
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { n as errorReported, t as errorExitCode } from "./Runtime-BInIAwK3.mjs";
|
|
2
|
+
import { v as Int, z as TaggedError } from "./Schema-MiKt5K1v.mjs";
|
|
3
|
+
// src/runner-exited.errors.ts
|
|
4
|
+
var RunnerExitedError = class extends TaggedError()("RunnerExitedError", { code: Int }) {
|
|
5
|
+
[errorReported] = false;
|
|
6
|
+
get [errorExitCode]() {
|
|
7
|
+
return this.code;
|
|
8
|
+
}
|
|
9
|
+
};
|
|
10
|
+
export { RunnerExitedError };
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { r as contains } from "../Array-B4kuTQeW.mjs";
|
|
2
|
+
import { t as errorExitCode } from "../Runtime-BInIAwK3.mjs";
|
|
3
|
+
import { F as String, v as Int, z as TaggedError } from "../Schema-MiKt5K1v.mjs";
|
|
4
|
+
// src/terminal/cli-exit.errors.ts
|
|
5
|
+
const exitCodes = {
|
|
6
|
+
authentication: 3,
|
|
7
|
+
confirmation: 4,
|
|
8
|
+
failed: 1,
|
|
9
|
+
unavailable: 5,
|
|
10
|
+
usage: 2
|
|
11
|
+
};
|
|
12
|
+
const badRequest = 400;
|
|
13
|
+
const unauthorized = 401;
|
|
14
|
+
const forbidden = 403;
|
|
15
|
+
const timedOut = 408;
|
|
16
|
+
const unprocessable = 422;
|
|
17
|
+
const preconditionRequired = 428;
|
|
18
|
+
const tooManyRequests = 429;
|
|
19
|
+
const firstServerError = 500;
|
|
20
|
+
const exitCodeOf = (status) => {
|
|
21
|
+
if (contains([badRequest, unprocessable], status)) return exitCodes.usage;
|
|
22
|
+
if (contains([unauthorized, forbidden], status)) return exitCodes.authentication;
|
|
23
|
+
if (status === preconditionRequired) return exitCodes.confirmation;
|
|
24
|
+
if (contains([timedOut, tooManyRequests], status) || status >= firstServerError) return exitCodes.unavailable;
|
|
25
|
+
return exitCodes.failed;
|
|
26
|
+
};
|
|
27
|
+
var CliExitError = class extends TaggedError()("CliExitError", {
|
|
28
|
+
code: Int,
|
|
29
|
+
message: String,
|
|
30
|
+
reason: String
|
|
31
|
+
}) {
|
|
32
|
+
static codes = exitCodes;
|
|
33
|
+
static ofStatus = exitCodeOf;
|
|
34
|
+
get [errorExitCode]() {
|
|
35
|
+
return this.code;
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
export { CliExitError };
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { n as log, t as error } from "../Console-BKHUkH6a.mjs";
|
|
2
|
+
import { B as flatMap, W as fnUntraced, Xt as succeed, _n as when } from "../Effect-CKFpqbmw.mjs";
|
|
3
|
+
import { r as getErrorExitCode } from "../Runtime-BInIAwK3.mjs";
|
|
4
|
+
import { mt as is } from "../Schema-MiKt5K1v.mjs";
|
|
5
|
+
import { t as Stdio } from "../Stdio-KylmOBX_.mjs";
|
|
6
|
+
import { a as ShowHelp } from "../CliError-Cf5xqkkj.mjs";
|
|
7
|
+
import { exitJson } from "../registry/operation-output.pure.mjs";
|
|
8
|
+
import { RunnerExitedError } from "../runner-exited.errors.mjs";
|
|
9
|
+
import { CliExitError } from "./cli-exit.errors.mjs";
|
|
10
|
+
// src/terminal/cli-failure.pure.ts
|
|
11
|
+
const isShowHelp = is(ShowHelp);
|
|
12
|
+
const isExit = is(CliExitError);
|
|
13
|
+
const isRunnerExit = is(RunnerExitedError);
|
|
14
|
+
const noErrors = 0;
|
|
15
|
+
const asExit = (failure) => {
|
|
16
|
+
if (isExit(failure)) return failure;
|
|
17
|
+
return CliExitError.make({
|
|
18
|
+
code: getErrorExitCode(failure),
|
|
19
|
+
message: failure.message,
|
|
20
|
+
reason: "Failed"
|
|
21
|
+
});
|
|
22
|
+
};
|
|
23
|
+
const reportFailure = fnUntraced(function* reportFailure(failure) {
|
|
24
|
+
if (isShowHelp(failure)) return yield* when(RunnerExitedError.make({ code: CliExitError.codes.usage }), succeed(failure.errors.length > noErrors));
|
|
25
|
+
if (isRunnerExit(failure)) return yield* failure;
|
|
26
|
+
const exit = asExit(failure);
|
|
27
|
+
if ((yield* Stdio.use((stdio) => stdio.args)).includes("--json")) yield* flatMap(exitJson(exit), log);
|
|
28
|
+
else yield* error(exit.message);
|
|
29
|
+
return yield* RunnerExitedError.make({ code: exit.code });
|
|
30
|
+
});
|
|
31
|
+
export { reportFailure };
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { At as provideContext, T as context, Vn as effect, W as fnUntraced, Xt as succeed, aa as Service, et as gen, x as catchTag } from "../Effect-CKFpqbmw.mjs";
|
|
2
|
+
import { d as run, n as Confirm, t as TerminalCapabilities } from "../TerminalCapabilities-w_44MAca.mjs";
|
|
3
|
+
import { CliExitError } from "./cli-exit.errors.mjs";
|
|
4
|
+
// src/terminal/confirm.adapter.ts
|
|
5
|
+
const declined = () => CliExitError.make({
|
|
6
|
+
code: CliExitError.codes.confirmation,
|
|
7
|
+
message: "Not confirmed, so nothing was changed.",
|
|
8
|
+
reason: "NotConfirmed"
|
|
9
|
+
});
|
|
10
|
+
const ask = fnUntraced(function* ask({ question, unattended }) {
|
|
11
|
+
const { canPrompt } = yield* TerminalCapabilities;
|
|
12
|
+
if (!canPrompt) return yield* CliExitError.make({
|
|
13
|
+
code: CliExitError.codes.confirmation,
|
|
14
|
+
message: unattended,
|
|
15
|
+
reason: "ConfirmationRequired"
|
|
16
|
+
});
|
|
17
|
+
const confirmed = yield* run(Confirm({ message: question })).pipe(catchTag("QuitError", () => succeed(false)));
|
|
18
|
+
if (!confirmed) return yield* declined();
|
|
19
|
+
return confirmed;
|
|
20
|
+
});
|
|
21
|
+
var Confirmation = class extends Service()("@akterjs/cli/terminal/confirm.adapter/Confirmation", { make: gen(function* makeConfirmation() {
|
|
22
|
+
const context$1 = yield* context();
|
|
23
|
+
return { confirm: (question) => provideContext(ask(question), context$1) };
|
|
24
|
+
}) }) {
|
|
25
|
+
static layer = effect(this, this.make);
|
|
26
|
+
};
|
|
27
|
+
export { Confirmation };
|
package/package.json
CHANGED
|
@@ -1,6 +1,64 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@akterjs/cli",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "The akter command: local engine, deploy, branch, restore, history, export, migrate and bench.",
|
|
5
|
+
"license": "Apache-2.0",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "git+https://github.com/Rika-Labs/akter.git",
|
|
9
|
+
"directory": "packages/cli"
|
|
10
|
+
},
|
|
11
|
+
"bin": {
|
|
12
|
+
"akter": "./dist/akter.cli.mjs"
|
|
13
|
+
},
|
|
14
|
+
"files": [
|
|
15
|
+
"dist",
|
|
16
|
+
"legal"
|
|
17
|
+
],
|
|
18
|
+
"type": "module",
|
|
19
|
+
"sideEffects": false,
|
|
20
|
+
"imports": {
|
|
21
|
+
"#src/*": "./dist/*.mjs"
|
|
22
|
+
},
|
|
23
|
+
"exports": {
|
|
24
|
+
"./program": "./dist/command/akter-program.config.mjs",
|
|
25
|
+
"./package.json": "./package.json"
|
|
26
|
+
},
|
|
27
|
+
"publishConfig": {
|
|
28
|
+
"access": "public",
|
|
29
|
+
"provenance": true
|
|
30
|
+
},
|
|
31
|
+
"dependencies": {
|
|
32
|
+
"esbuild": "0.28.2"
|
|
33
|
+
},
|
|
34
|
+
"devDependencies": {
|
|
35
|
+
"@akterjs/client": "0.1.0",
|
|
36
|
+
"@akterjs/cloud-api": "file:../../../akter-cloud/packages/cloud-api",
|
|
37
|
+
"@akterjs/effect": "0.1.0",
|
|
38
|
+
"@effect/openapi-generator": "4.1.2",
|
|
39
|
+
"@effect/platform-node": "4.1.2",
|
|
40
|
+
"@effect/vitest": "4.1.2",
|
|
41
|
+
"effect": "4.1.2",
|
|
42
|
+
"mutant-cafe": "0.1.6",
|
|
43
|
+
"publint": "0.3.25",
|
|
44
|
+
"tsdown": "0.23.5",
|
|
45
|
+
"vitest": "5.1.0"
|
|
46
|
+
},
|
|
47
|
+
"peerDependencies": {
|
|
48
|
+
"@effect/platform-node": "4.1.2",
|
|
49
|
+
"effect": "4.1.2"
|
|
50
|
+
},
|
|
51
|
+
"engines": {
|
|
52
|
+
"node": ">=24"
|
|
53
|
+
},
|
|
54
|
+
"scripts": {
|
|
55
|
+
"generate": "bun --conditions=@akterjs/source scripts/generate-client.cli.ts",
|
|
56
|
+
"typecheck": "effect-tsgo tsrs --noEmit -p tsconfig.json",
|
|
57
|
+
"lint": "effect-tsgo --tsrs-lint oxlint -c ../../oxlint.config.ts --type-aware --tsconfig tsconfig.json src scripts tests",
|
|
58
|
+
"test": "vitest run",
|
|
59
|
+
"build": "tsdown",
|
|
60
|
+
"measure:startup": "bun scripts/measure-startup.cli.ts",
|
|
61
|
+
"mutants": "GIT_DIR=$(git rev-parse --absolute-git-dir) VITEST_MAX_WORKERS=1 mutant-cafe --advisory && node ../../node_modules/@rikalabs/rules/src/mutants/mutants.cli.mjs --all",
|
|
62
|
+
"mutants:diff": "git diff --relative main...HEAD | GIT_DIR=$(git rev-parse --absolute-git-dir) VITEST_MAX_WORKERS=1 mutant-cafe --in-diff /dev/stdin --advisory && node ../../node_modules/@rikalabs/rules/src/mutants/mutants.cli.mjs"
|
|
63
|
+
}
|
|
6
64
|
}
|