@asteroidai/cli 1.9.27 → 1.9.30
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/asteroid.js +2 -2
- package/dist/core.js +1 -1
- package/package.json +3 -8
- package/src/account.ts +0 -501
- package/src/args.ts +0 -39
- package/src/auth/credentials.ts +0 -179
- package/src/auth/store.ts +0 -253
- package/src/auth/workos.ts +0 -171
- package/src/commands.ts +0 -13
- package/src/config.ts +0 -125
- package/src/core.ts +0 -41
- package/src/generated/commands.ts +0 -4772
- package/src/http.ts +0 -115
- package/src/main.ts +0 -49
- package/src/output.test.ts +0 -71
- package/src/output.ts +0 -176
- package/src/program.test.ts +0 -155
- package/src/program.ts +0 -293
- package/src/reference.ts +0 -195
- package/src/request.test.ts +0 -164
- package/src/request.ts +0 -252
- package/src/run.test.ts +0 -651
- package/src/run.ts +0 -235
- package/src/sync/activities.ts +0 -80
- package/src/sync/commands.ts +0 -63
- package/src/sync/execution-pull.ts +0 -273
- package/src/sync/node-files.ts +0 -47
- package/src/sync/paths.ts +0 -45
- package/src/sync/run.ts +0 -136
- package/src/sync/sync.test.ts +0 -502
- package/src/sync/types.ts +0 -58
- package/src/sync/workflow-pull.ts +0 -185
- package/src/sync/workflow-push.ts +0 -161
- package/src/types.ts +0 -46
- package/src/ui.ts +0 -35
package/src/request.ts
DELETED
|
@@ -1,252 +0,0 @@
|
|
|
1
|
-
import { readFileSync } from "node:fs";
|
|
2
|
-
import { basename } from "node:path";
|
|
3
|
-
|
|
4
|
-
import { type Parsed, UsageError } from "./args";
|
|
5
|
-
import type { CliCommand, Option } from "./types";
|
|
6
|
-
|
|
7
|
-
export interface BuiltRequest {
|
|
8
|
-
method: CliCommand["method"];
|
|
9
|
-
path: string;
|
|
10
|
-
query: URLSearchParams;
|
|
11
|
-
json?: unknown;
|
|
12
|
-
form?: FormData;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
function camel(segment: string): string {
|
|
16
|
-
return segment.replace(/-([a-z0-9])/g, (_, c: string) => c.toUpperCase());
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
function scalar(option: Option, raw: string): unknown {
|
|
20
|
-
const type = option.type.replace("[]", "");
|
|
21
|
-
if (option.enum && !option.enum.includes(raw)) {
|
|
22
|
-
throw new UsageError(
|
|
23
|
-
`--${option.flag} must be one of ${option.enum.join(", ")}`,
|
|
24
|
-
);
|
|
25
|
-
}
|
|
26
|
-
if (type === "integer" || type === "number") {
|
|
27
|
-
const value = Number(raw);
|
|
28
|
-
if (
|
|
29
|
-
raw.trim() === "" ||
|
|
30
|
-
Number.isNaN(value) ||
|
|
31
|
-
(type === "integer" && !Number.isInteger(value))
|
|
32
|
-
) {
|
|
33
|
-
throw new UsageError(
|
|
34
|
-
`--${option.flag} must be ${type === "integer" ? "an integer" : "a number"}`,
|
|
35
|
-
);
|
|
36
|
-
}
|
|
37
|
-
return value;
|
|
38
|
-
}
|
|
39
|
-
if (type === "boolean") {
|
|
40
|
-
if (raw !== "true" && raw !== "false") {
|
|
41
|
-
throw new UsageError(`--${option.flag} must be true or false`);
|
|
42
|
-
}
|
|
43
|
-
return raw === "true";
|
|
44
|
-
}
|
|
45
|
-
if (type === "json") return parseJson(raw, `--${option.flag}`);
|
|
46
|
-
return raw;
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
function value(option: Option, raws: string[]): unknown {
|
|
50
|
-
if (option.type.endsWith("[]")) return raws.map((raw) => scalar(option, raw));
|
|
51
|
-
return scalar(option, raws.at(-1)!);
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
export interface InputReader {
|
|
55
|
-
text(path: string | 0): Promise<string>;
|
|
56
|
-
bytes(path: string): Promise<Uint8Array<ArrayBuffer>>;
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
export const nodeReader: InputReader = {
|
|
60
|
-
text: async (path) => readFileSync(path, "utf8"),
|
|
61
|
-
bytes: async (path) => new Uint8Array(readFileSync(path)),
|
|
62
|
-
};
|
|
63
|
-
|
|
64
|
-
async function readInput(raw: string, io: InputReader): Promise<string> {
|
|
65
|
-
if (raw === "-") return io.text(0);
|
|
66
|
-
if (raw.startsWith("@")) return io.text(raw.slice(1));
|
|
67
|
-
return raw;
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
async function resolveInputs(
|
|
71
|
-
command: CliCommand,
|
|
72
|
-
parsed: Parsed,
|
|
73
|
-
io: InputReader,
|
|
74
|
-
): Promise<Parsed> {
|
|
75
|
-
const jsonFlags = [...command.query, ...(command.body?.fields ?? [])]
|
|
76
|
-
.filter((option) => option.type === "json")
|
|
77
|
-
.map((option) => option.flag);
|
|
78
|
-
const flags = new Map(parsed.flags);
|
|
79
|
-
for (const flag of jsonFlags) {
|
|
80
|
-
const raws = flags.get(flag);
|
|
81
|
-
if (raws)
|
|
82
|
-
flags.set(flag, await Promise.all(raws.map((raw) => readInput(raw, io))));
|
|
83
|
-
}
|
|
84
|
-
const body =
|
|
85
|
-
parsed.body === undefined ? undefined : await readInput(parsed.body, io);
|
|
86
|
-
return { ...parsed, flags, body };
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
function parseJson(raw: string, label: string): unknown {
|
|
90
|
-
try {
|
|
91
|
-
return JSON.parse(raw);
|
|
92
|
-
} catch {
|
|
93
|
-
throw new UsageError(`${label} is not valid JSON`);
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
function loose(raw: string): unknown {
|
|
98
|
-
if (/^(true|false|null)$/.test(raw) || /^[[{]/.test(raw.trim())) {
|
|
99
|
-
try {
|
|
100
|
-
return JSON.parse(raw);
|
|
101
|
-
} catch {
|
|
102
|
-
return raw;
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
return raw;
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
function setPath(
|
|
109
|
-
target: Record<string, unknown>,
|
|
110
|
-
path: string[],
|
|
111
|
-
value: unknown,
|
|
112
|
-
) {
|
|
113
|
-
let node = target;
|
|
114
|
-
for (const key of path.slice(0, -1)) {
|
|
115
|
-
const next = node[key];
|
|
116
|
-
if (typeof next !== "object" || next === null || Array.isArray(next))
|
|
117
|
-
node[key] = {};
|
|
118
|
-
node = node[key] as Record<string, unknown>;
|
|
119
|
-
}
|
|
120
|
-
node[path.at(-1)!] = value;
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
export interface RequestContext {
|
|
124
|
-
io?: InputReader;
|
|
125
|
-
organizationId?: string;
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
export async function buildRequest(
|
|
129
|
-
command: CliCommand,
|
|
130
|
-
input: Parsed,
|
|
131
|
-
context: RequestContext = {},
|
|
132
|
-
): Promise<BuiltRequest> {
|
|
133
|
-
const io = context.io ?? nodeReader;
|
|
134
|
-
const parsed = await resolveInputs(command, input, io);
|
|
135
|
-
if (parsed.positionals.length !== command.args.length) {
|
|
136
|
-
const expected =
|
|
137
|
-
command.args.map((a) => `<${a.flag}>`).join(" ") || "no arguments";
|
|
138
|
-
throw new UsageError(
|
|
139
|
-
`expected ${expected}, got ${parsed.positionals.length} argument(s)`,
|
|
140
|
-
);
|
|
141
|
-
}
|
|
142
|
-
let path = command.path;
|
|
143
|
-
command.args.forEach((arg, i) => {
|
|
144
|
-
path = path.replace(
|
|
145
|
-
`{${arg.name}}`,
|
|
146
|
-
encodeURIComponent(parsed.positionals[i]),
|
|
147
|
-
);
|
|
148
|
-
});
|
|
149
|
-
|
|
150
|
-
const flags = new Map(parsed.flags);
|
|
151
|
-
const query = new URLSearchParams();
|
|
152
|
-
for (const option of command.query) {
|
|
153
|
-
const raws = flags.get(option.flag);
|
|
154
|
-
flags.delete(option.flag);
|
|
155
|
-
if (!raws) {
|
|
156
|
-
if (option.required) throw new UsageError(`--${option.flag} is required`);
|
|
157
|
-
continue;
|
|
158
|
-
}
|
|
159
|
-
const parsedValue = value(option, raws);
|
|
160
|
-
const values = Array.isArray(parsedValue) ? parsedValue : [parsedValue];
|
|
161
|
-
if (option.explode === false)
|
|
162
|
-
query.append(option.name, values.map(String).join(","));
|
|
163
|
-
else for (const v of values) query.append(option.name, String(v));
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
const built: BuiltRequest = { method: command.method, path, query };
|
|
167
|
-
const body = command.body;
|
|
168
|
-
if (!body) {
|
|
169
|
-
if (parsed.body) throw new UsageError(`${command.command} takes no body`);
|
|
170
|
-
rejectUnknown(flags);
|
|
171
|
-
return built;
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
if (body.contentType === "multipart/form-data") {
|
|
175
|
-
if (parsed.body) {
|
|
176
|
-
throw new UsageError(
|
|
177
|
-
`${command.command} uploads files; use the file flags, not --body`,
|
|
178
|
-
);
|
|
179
|
-
}
|
|
180
|
-
const form = new FormData();
|
|
181
|
-
for (const file of body.files) {
|
|
182
|
-
const paths = flags.get(file) ?? [];
|
|
183
|
-
if (body.required && paths.length === 0) {
|
|
184
|
-
throw new UsageError(`--${file} is required`);
|
|
185
|
-
}
|
|
186
|
-
for (const filePath of paths) {
|
|
187
|
-
form.append(
|
|
188
|
-
file,
|
|
189
|
-
new Blob([await io.bytes(filePath)]),
|
|
190
|
-
basename(filePath),
|
|
191
|
-
);
|
|
192
|
-
}
|
|
193
|
-
flags.delete(file);
|
|
194
|
-
}
|
|
195
|
-
for (const field of body.fields) {
|
|
196
|
-
const raws = flags.get(field.flag);
|
|
197
|
-
flags.delete(field.flag);
|
|
198
|
-
if (raws) for (const raw of raws) form.append(field.name, raw);
|
|
199
|
-
}
|
|
200
|
-
rejectUnknown(flags);
|
|
201
|
-
built.form = form;
|
|
202
|
-
return built;
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
const base = parsed.body ? parseJson(parsed.body, "--body") : {};
|
|
206
|
-
if (typeof base !== "object" || base === null || Array.isArray(base)) {
|
|
207
|
-
throw new UsageError("--body must be a JSON object");
|
|
208
|
-
}
|
|
209
|
-
const json = base as Record<string, unknown>;
|
|
210
|
-
for (const field of body.fields) {
|
|
211
|
-
const raws = flags.get(field.flag);
|
|
212
|
-
if (!raws) continue;
|
|
213
|
-
flags.delete(field.flag);
|
|
214
|
-
json[field.name] = value(field, raws);
|
|
215
|
-
}
|
|
216
|
-
for (const [flag, raws] of [...flags]) {
|
|
217
|
-
const [head, ...rest] = flag.split(".");
|
|
218
|
-
const field = body.fields.find((f) => f.flag === head);
|
|
219
|
-
if (!field || rest.length === 0) continue;
|
|
220
|
-
flags.delete(flag);
|
|
221
|
-
const current = json[field.name];
|
|
222
|
-
json[field.name] =
|
|
223
|
-
typeof current === "object" && current !== null ? current : {};
|
|
224
|
-
setPath(json, [field.name, ...rest.map(camel)], loose(raws.at(-1)!));
|
|
225
|
-
}
|
|
226
|
-
rejectUnknown(flags);
|
|
227
|
-
delete json.organizationId;
|
|
228
|
-
if (body.credentialOrganization) {
|
|
229
|
-
if (!context.organizationId) {
|
|
230
|
-
throw new UsageError(
|
|
231
|
-
"could not tell which organization this credential acts in",
|
|
232
|
-
);
|
|
233
|
-
}
|
|
234
|
-
json.organizationId = context.organizationId;
|
|
235
|
-
}
|
|
236
|
-
for (const field of body.fields) {
|
|
237
|
-
if (field.required && json[field.name] === undefined) {
|
|
238
|
-
throw new UsageError(`--${field.flag} is required`);
|
|
239
|
-
}
|
|
240
|
-
}
|
|
241
|
-
if (body.required || Object.keys(json).length > 0) built.json = json;
|
|
242
|
-
return built;
|
|
243
|
-
}
|
|
244
|
-
|
|
245
|
-
function rejectUnknown(flags: Map<string, string[]>) {
|
|
246
|
-
const unknown = [...flags.keys()];
|
|
247
|
-
if (unknown.length > 0) {
|
|
248
|
-
throw new UsageError(
|
|
249
|
-
`unknown flag${unknown.length > 1 ? "s" : ""}: ${unknown.map((f) => `--${f}`).join(", ")}`,
|
|
250
|
-
);
|
|
251
|
-
}
|
|
252
|
-
}
|