freestyle 0.1.45 → 0.1.47
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/cli.mjs +120 -6
- package/index.cjs +1 -1
- package/index.d.cts +31 -3
- package/index.d.mts +31 -3
- package/index.js +391 -0
- package/index.mjs +1 -1
- package/package.json +1 -1
package/cli.mjs
CHANGED
|
@@ -6,7 +6,7 @@ import { Freestyle, VmSpec } from './index.mjs';
|
|
|
6
6
|
import * as fs from 'fs';
|
|
7
7
|
import * as path from 'path';
|
|
8
8
|
import * as os from 'os';
|
|
9
|
-
import { spawn } from 'child_process';
|
|
9
|
+
import { spawn, spawnSync } from 'child_process';
|
|
10
10
|
|
|
11
11
|
const DEFAULT_STACK_API_URL = "https://api.stack-auth.com";
|
|
12
12
|
const DEFAULT_STACK_APP_URL = "https://dash.freestyle.sh";
|
|
@@ -457,7 +457,7 @@ async function getTeamsForCli() {
|
|
|
457
457
|
const stored = loadStoredAuth(config);
|
|
458
458
|
if (!stored?.refreshToken) {
|
|
459
459
|
throw new Error(
|
|
460
|
-
"No authentication found. Please run 'npx freestyle
|
|
460
|
+
"No authentication found. Please run 'npx freestyle@latest login' first."
|
|
461
461
|
);
|
|
462
462
|
}
|
|
463
463
|
const tokenResponse = await refreshStackAccessToken(
|
|
@@ -480,7 +480,7 @@ async function setDefaultTeam(teamId) {
|
|
|
480
480
|
const stored = loadStoredAuth(config);
|
|
481
481
|
if (!stored?.refreshToken) {
|
|
482
482
|
throw new Error(
|
|
483
|
-
"No authentication found. Please run 'npx freestyle
|
|
483
|
+
"No authentication found. Please run 'npx freestyle@latest login' first."
|
|
484
484
|
);
|
|
485
485
|
}
|
|
486
486
|
const auth = {
|
|
@@ -595,14 +595,14 @@ async function getFreestyleClient(teamId) {
|
|
|
595
595
|
const accessToken = await getStackAccessTokenForCli();
|
|
596
596
|
if (!accessToken) {
|
|
597
597
|
console.error(
|
|
598
|
-
"Error: No API key found. Please run 'npx freestyle
|
|
598
|
+
"Error: No API key found. Please run 'npx freestyle@latest login' or set FREESTYLE_API_KEY in your .env file."
|
|
599
599
|
);
|
|
600
600
|
process.exit(1);
|
|
601
601
|
}
|
|
602
602
|
const resolvedTeamId = process.env.FREESTYLE_TEAM_ID ?? getDefaultTeamId();
|
|
603
603
|
if (!resolvedTeamId) {
|
|
604
604
|
console.error(
|
|
605
|
-
"Error: No team selected. Please run 'npx freestyle
|
|
605
|
+
"Error: No team selected. Please run 'npx freestyle@latest login' to set a default team."
|
|
606
606
|
);
|
|
607
607
|
process.exit(1);
|
|
608
608
|
}
|
|
@@ -1105,6 +1105,27 @@ const runCommand = {
|
|
|
1105
1105
|
}
|
|
1106
1106
|
};
|
|
1107
1107
|
|
|
1108
|
+
function spawnGit(args) {
|
|
1109
|
+
return new Promise((resolve, reject) => {
|
|
1110
|
+
const sigintHandler = () => {
|
|
1111
|
+
};
|
|
1112
|
+
process.on("SIGINT", sigintHandler);
|
|
1113
|
+
const child = spawn("git", args, { stdio: "inherit" });
|
|
1114
|
+
child.on("error", (err) => {
|
|
1115
|
+
process.off("SIGINT", sigintHandler);
|
|
1116
|
+
reject(err);
|
|
1117
|
+
});
|
|
1118
|
+
child.on("close", (code, signal) => {
|
|
1119
|
+
process.off("SIGINT", sigintHandler);
|
|
1120
|
+
if (code === 0) {
|
|
1121
|
+
resolve();
|
|
1122
|
+
} else {
|
|
1123
|
+
const detail = signal ? `signal ${signal}` : `exit code ${code}`;
|
|
1124
|
+
reject(new Error(`git ${args[0]} failed with ${detail}`));
|
|
1125
|
+
}
|
|
1126
|
+
});
|
|
1127
|
+
});
|
|
1128
|
+
}
|
|
1108
1129
|
const gitCommand = {
|
|
1109
1130
|
command: "git <action>",
|
|
1110
1131
|
describe: "Manage Git repositories",
|
|
@@ -1224,6 +1245,99 @@ Total: ${repos.total}`);
|
|
|
1224
1245
|
handleError(error);
|
|
1225
1246
|
}
|
|
1226
1247
|
}
|
|
1248
|
+
).command(
|
|
1249
|
+
"clone <repoId> [directory]",
|
|
1250
|
+
"Clone a repo and persist an access token in the checkout so git push/pull work",
|
|
1251
|
+
(yargs2) => {
|
|
1252
|
+
return yargs2.positional("repoId", {
|
|
1253
|
+
type: "string",
|
|
1254
|
+
description: "Repository ID to clone",
|
|
1255
|
+
demandOption: true
|
|
1256
|
+
}).positional("directory", {
|
|
1257
|
+
type: "string",
|
|
1258
|
+
description: "Destination directory (defaults to <repoId>)"
|
|
1259
|
+
}).option("readonly", {
|
|
1260
|
+
type: "boolean",
|
|
1261
|
+
description: "Provision a read-only token instead of read/write",
|
|
1262
|
+
default: false
|
|
1263
|
+
});
|
|
1264
|
+
},
|
|
1265
|
+
async (argv) => {
|
|
1266
|
+
loadEnv();
|
|
1267
|
+
const args = argv;
|
|
1268
|
+
const permission = args.readonly ? "read" : "write";
|
|
1269
|
+
const destination = args.directory ?? args.repoId;
|
|
1270
|
+
const freestyle = await getFreestyleClient();
|
|
1271
|
+
let identityId;
|
|
1272
|
+
let tokenId;
|
|
1273
|
+
let cloneSucceeded = false;
|
|
1274
|
+
try {
|
|
1275
|
+
console.log(
|
|
1276
|
+
`Provisioning ${permission} access token for ${args.repoId}...`
|
|
1277
|
+
);
|
|
1278
|
+
const { identity, identityId: newIdentityId } = await freestyle.identities.create();
|
|
1279
|
+
identityId = newIdentityId;
|
|
1280
|
+
await identity.permissions.git.grant({
|
|
1281
|
+
repoId: args.repoId,
|
|
1282
|
+
permission
|
|
1283
|
+
});
|
|
1284
|
+
const created = await identity.tokens.create();
|
|
1285
|
+
tokenId = created.tokenId;
|
|
1286
|
+
const url = new URL(`/${args.repoId}`, "https://git.freestyle.sh");
|
|
1287
|
+
url.username = "x-access-token";
|
|
1288
|
+
url.password = created.token;
|
|
1289
|
+
console.log(`Cloning repository ${args.repoId} into ${destination}...`);
|
|
1290
|
+
await spawnGit([
|
|
1291
|
+
"clone",
|
|
1292
|
+
url.toString(),
|
|
1293
|
+
...args.directory ? [args.directory] : []
|
|
1294
|
+
]);
|
|
1295
|
+
spawnSync(
|
|
1296
|
+
"git",
|
|
1297
|
+
["-C", destination, "config", "freestyle.identityId", identityId],
|
|
1298
|
+
{ stdio: "ignore" }
|
|
1299
|
+
);
|
|
1300
|
+
spawnSync(
|
|
1301
|
+
"git",
|
|
1302
|
+
["-C", destination, "config", "freestyle.tokenId", tokenId],
|
|
1303
|
+
{ stdio: "ignore" }
|
|
1304
|
+
);
|
|
1305
|
+
spawnSync(
|
|
1306
|
+
"git",
|
|
1307
|
+
["-C", destination, "config", "freestyle.permission", permission],
|
|
1308
|
+
{ stdio: "ignore" }
|
|
1309
|
+
);
|
|
1310
|
+
cloneSucceeded = true;
|
|
1311
|
+
console.log(`
|
|
1312
|
+
\u2713 Clone complete (${permission} access)`);
|
|
1313
|
+
console.log(
|
|
1314
|
+
` The access token is stored in ${destination}/.git/config;`
|
|
1315
|
+
);
|
|
1316
|
+
console.log(
|
|
1317
|
+
` git push and git pull will work from inside ${destination}.`
|
|
1318
|
+
);
|
|
1319
|
+
} catch (error) {
|
|
1320
|
+
handleError(error);
|
|
1321
|
+
} finally {
|
|
1322
|
+
if (!cloneSucceeded) {
|
|
1323
|
+
if (tokenId && identityId) {
|
|
1324
|
+
try {
|
|
1325
|
+
const identity = freestyle.identities.ref({ identityId });
|
|
1326
|
+
await identity.tokens.revoke({ tokenId });
|
|
1327
|
+
} catch (err) {
|
|
1328
|
+
console.error("Warning: failed to revoke token:", err);
|
|
1329
|
+
}
|
|
1330
|
+
}
|
|
1331
|
+
if (identityId) {
|
|
1332
|
+
try {
|
|
1333
|
+
await freestyle.identities.delete({ identityId });
|
|
1334
|
+
} catch (err) {
|
|
1335
|
+
console.error("Warning: failed to delete identity:", err);
|
|
1336
|
+
}
|
|
1337
|
+
}
|
|
1338
|
+
}
|
|
1339
|
+
}
|
|
1340
|
+
}
|
|
1227
1341
|
).command(
|
|
1228
1342
|
"delete <repoId>",
|
|
1229
1343
|
"Delete a git repository",
|
|
@@ -1923,7 +2037,7 @@ const loginCommand = {
|
|
|
1923
2037
|
if (teams.length > 1) {
|
|
1924
2038
|
console.log(
|
|
1925
2039
|
`
|
|
1926
|
-
\u2139\uFE0F You have ${teams.length} teams
|
|
2040
|
+
\u2139\uFE0F You have ${teams.length} teams.`
|
|
1927
2041
|
);
|
|
1928
2042
|
}
|
|
1929
2043
|
} catch (error) {
|
package/index.cjs
CHANGED
|
@@ -7567,7 +7567,7 @@ class VmsNamespace {
|
|
|
7567
7567
|
function enhanceError(e) {
|
|
7568
7568
|
if (e instanceof VmSetupFailedError) {
|
|
7569
7569
|
if (!e.message.includes("create --snapshot")) {
|
|
7570
|
-
e.message = `${e.message}. Hint: use \`npx freestyle
|
|
7570
|
+
e.message = `${e.message}. Hint: use \`npx freestyle@latest vm create --snapshot ${e.body.snapshotId} --ssh --delete\` to debug.`;
|
|
7571
7571
|
}
|
|
7572
7572
|
if (e.body.diagnostics) {
|
|
7573
7573
|
const d = e.body.diagnostics;
|
package/index.d.cts
CHANGED
|
@@ -5009,6 +5009,18 @@ interface PostV1VmsRequestBody {
|
|
|
5009
5009
|
vmPort?: number | null;
|
|
5010
5010
|
}[] | null;
|
|
5011
5011
|
activityThresholdBytes?: number | null;
|
|
5012
|
+
/**
|
|
5013
|
+
* Optional Docker registry credentials required when using a private image
|
|
5014
|
+
* in `baseImage` or `template.baseImage`.
|
|
5015
|
+
*/
|
|
5016
|
+
dockerCredentials?: null | {
|
|
5017
|
+
/** Docker registry URL (e.g., "ghcr.io", "docker.io") */
|
|
5018
|
+
registry: string;
|
|
5019
|
+
/** Username for the registry */
|
|
5020
|
+
username: string;
|
|
5021
|
+
/** Password or token for the registry */
|
|
5022
|
+
password: string;
|
|
5023
|
+
};
|
|
5012
5024
|
}
|
|
5013
5025
|
interface GetV1VmsSnapshotsQueryParams {
|
|
5014
5026
|
includeDeleted?: boolean | null;
|
|
@@ -5375,6 +5387,18 @@ interface PostV1VmsSnapshotsRequestBody {
|
|
|
5375
5387
|
} | {
|
|
5376
5388
|
type: "persistent";
|
|
5377
5389
|
});
|
|
5390
|
+
/**
|
|
5391
|
+
* Optional Docker registry credentials required when using a private image
|
|
5392
|
+
* in `template.baseImage`.
|
|
5393
|
+
*/
|
|
5394
|
+
dockerCredentials?: null | {
|
|
5395
|
+
/** Docker registry URL (e.g., "ghcr.io", "docker.io") */
|
|
5396
|
+
registry: string;
|
|
5397
|
+
/** Username for the registry */
|
|
5398
|
+
username: string;
|
|
5399
|
+
/** Password or token for the registry */
|
|
5400
|
+
password: string;
|
|
5401
|
+
};
|
|
5378
5402
|
}
|
|
5379
5403
|
interface DeleteV1VmsSnapshotsSnapshotIdPathParams {
|
|
5380
5404
|
/**
|
|
@@ -13361,6 +13385,10 @@ declare const VmBuilder: typeof VmWith;
|
|
|
13361
13385
|
type RawBaseImage = {
|
|
13362
13386
|
dockerfileContent: string;
|
|
13363
13387
|
};
|
|
13388
|
+
/**
|
|
13389
|
+
* Docker registry credentials for pulling private images.
|
|
13390
|
+
*/
|
|
13391
|
+
type DockerCredentials = NonNullable<PostV1VmsRequestBody["dockerCredentials"]>;
|
|
13364
13392
|
/**
|
|
13365
13393
|
* The raw systemd service type from the generated API
|
|
13366
13394
|
*/
|
|
@@ -13389,9 +13417,9 @@ type SystemdServiceInput = Omit<RawSystemdService, "mode" | "exec"> & {
|
|
|
13389
13417
|
*/
|
|
13390
13418
|
bash?: string;
|
|
13391
13419
|
};
|
|
13392
|
-
type VmWaitForConfig = Omit<SystemdServiceInput, "mode" | "exec" | "bash" | "deleteAfterSuccess"> & {
|
|
13420
|
+
type VmWaitForConfig = Partial<Omit<SystemdServiceInput, "mode" | "exec" | "bash" | "deleteAfterSuccess"> & {
|
|
13393
13421
|
intervalSeconds?: number;
|
|
13394
|
-
}
|
|
13422
|
+
}>;
|
|
13395
13423
|
type BackgroundRequestLogger = (message: string) => void;
|
|
13396
13424
|
type SnapshotCreateOptions<T extends Record<string, VmWithLike> = {}> = Omit<PostV1VmsSnapshotsRequestBody, "template"> & {
|
|
13397
13425
|
template?: VmTemplate<T> | PostV1VmsSnapshotsRequestBody["template"];
|
|
@@ -13852,4 +13880,4 @@ declare class Freestyle {
|
|
|
13852
13880
|
declare const freestyle: Freestyle;
|
|
13853
13881
|
|
|
13854
13882
|
export { CronNamespace, Deployment, errors as Errors, FileSystem, Freestyle, GitRepo, Identity, requests as Requests, responses as Responses, Systemd, SystemdService, Vm, VmBaseImage, VmBuilder, VmService, VmSpec, VmTemplate, VmWith, VmWithInstance, debugCreateRequests, freestyle, readFiles };
|
|
13855
|
-
export type { BackgroundRequestLogger, CreateVmOptions, CronSchedule, FreestyleOptions, GitCommitSearchEntry, GitCommitSearchResult, GitDiffFileMatch, GitDiffLineMatch, GitDiffSearchCommit, GitDiffSearchResult, GitFilenameEntry, GitFilenameSearchResult, GitSearchFileResult, GitSearchLineMatch, GitSearchResult, SystemdServiceInput, VmWaitForConfig, VmWithDefaultFieldRecord };
|
|
13883
|
+
export type { BackgroundRequestLogger, CreateVmOptions, CronSchedule, DockerCredentials, FreestyleOptions, GitCommitSearchEntry, GitCommitSearchResult, GitDiffFileMatch, GitDiffLineMatch, GitDiffSearchCommit, GitDiffSearchResult, GitFilenameEntry, GitFilenameSearchResult, GitSearchFileResult, GitSearchLineMatch, GitSearchResult, SystemdServiceInput, VmWaitForConfig, VmWithDefaultFieldRecord };
|
package/index.d.mts
CHANGED
|
@@ -5009,6 +5009,18 @@ interface PostV1VmsRequestBody {
|
|
|
5009
5009
|
vmPort?: number | null;
|
|
5010
5010
|
}[] | null;
|
|
5011
5011
|
activityThresholdBytes?: number | null;
|
|
5012
|
+
/**
|
|
5013
|
+
* Optional Docker registry credentials required when using a private image
|
|
5014
|
+
* in `baseImage` or `template.baseImage`.
|
|
5015
|
+
*/
|
|
5016
|
+
dockerCredentials?: null | {
|
|
5017
|
+
/** Docker registry URL (e.g., "ghcr.io", "docker.io") */
|
|
5018
|
+
registry: string;
|
|
5019
|
+
/** Username for the registry */
|
|
5020
|
+
username: string;
|
|
5021
|
+
/** Password or token for the registry */
|
|
5022
|
+
password: string;
|
|
5023
|
+
};
|
|
5012
5024
|
}
|
|
5013
5025
|
interface GetV1VmsSnapshotsQueryParams {
|
|
5014
5026
|
includeDeleted?: boolean | null;
|
|
@@ -5375,6 +5387,18 @@ interface PostV1VmsSnapshotsRequestBody {
|
|
|
5375
5387
|
} | {
|
|
5376
5388
|
type: "persistent";
|
|
5377
5389
|
});
|
|
5390
|
+
/**
|
|
5391
|
+
* Optional Docker registry credentials required when using a private image
|
|
5392
|
+
* in `template.baseImage`.
|
|
5393
|
+
*/
|
|
5394
|
+
dockerCredentials?: null | {
|
|
5395
|
+
/** Docker registry URL (e.g., "ghcr.io", "docker.io") */
|
|
5396
|
+
registry: string;
|
|
5397
|
+
/** Username for the registry */
|
|
5398
|
+
username: string;
|
|
5399
|
+
/** Password or token for the registry */
|
|
5400
|
+
password: string;
|
|
5401
|
+
};
|
|
5378
5402
|
}
|
|
5379
5403
|
interface DeleteV1VmsSnapshotsSnapshotIdPathParams {
|
|
5380
5404
|
/**
|
|
@@ -13361,6 +13385,10 @@ declare const VmBuilder: typeof VmWith;
|
|
|
13361
13385
|
type RawBaseImage = {
|
|
13362
13386
|
dockerfileContent: string;
|
|
13363
13387
|
};
|
|
13388
|
+
/**
|
|
13389
|
+
* Docker registry credentials for pulling private images.
|
|
13390
|
+
*/
|
|
13391
|
+
type DockerCredentials = NonNullable<PostV1VmsRequestBody["dockerCredentials"]>;
|
|
13364
13392
|
/**
|
|
13365
13393
|
* The raw systemd service type from the generated API
|
|
13366
13394
|
*/
|
|
@@ -13389,9 +13417,9 @@ type SystemdServiceInput = Omit<RawSystemdService, "mode" | "exec"> & {
|
|
|
13389
13417
|
*/
|
|
13390
13418
|
bash?: string;
|
|
13391
13419
|
};
|
|
13392
|
-
type VmWaitForConfig = Omit<SystemdServiceInput, "mode" | "exec" | "bash" | "deleteAfterSuccess"> & {
|
|
13420
|
+
type VmWaitForConfig = Partial<Omit<SystemdServiceInput, "mode" | "exec" | "bash" | "deleteAfterSuccess"> & {
|
|
13393
13421
|
intervalSeconds?: number;
|
|
13394
|
-
}
|
|
13422
|
+
}>;
|
|
13395
13423
|
type BackgroundRequestLogger = (message: string) => void;
|
|
13396
13424
|
type SnapshotCreateOptions<T extends Record<string, VmWithLike> = {}> = Omit<PostV1VmsSnapshotsRequestBody, "template"> & {
|
|
13397
13425
|
template?: VmTemplate<T> | PostV1VmsSnapshotsRequestBody["template"];
|
|
@@ -13852,4 +13880,4 @@ declare class Freestyle {
|
|
|
13852
13880
|
declare const freestyle: Freestyle;
|
|
13853
13881
|
|
|
13854
13882
|
export { CronNamespace, Deployment, errors as Errors, FileSystem, Freestyle, GitRepo, Identity, requests as Requests, responses as Responses, Systemd, SystemdService, Vm, VmBaseImage, VmBuilder, VmService, VmSpec, VmTemplate, VmWith, VmWithInstance, debugCreateRequests, freestyle, readFiles };
|
|
13855
|
-
export type { BackgroundRequestLogger, CreateVmOptions, CronSchedule, FreestyleOptions, GitCommitSearchEntry, GitCommitSearchResult, GitDiffFileMatch, GitDiffLineMatch, GitDiffSearchCommit, GitDiffSearchResult, GitFilenameEntry, GitFilenameSearchResult, GitSearchFileResult, GitSearchLineMatch, GitSearchResult, SystemdServiceInput, VmWaitForConfig, VmWithDefaultFieldRecord };
|
|
13883
|
+
export type { BackgroundRequestLogger, CreateVmOptions, CronSchedule, DockerCredentials, FreestyleOptions, GitCommitSearchEntry, GitCommitSearchResult, GitDiffFileMatch, GitDiffLineMatch, GitDiffSearchCommit, GitDiffSearchResult, GitFilenameEntry, GitFilenameSearchResult, GitSearchFileResult, GitSearchLineMatch, GitSearchResult, SystemdServiceInput, VmWaitForConfig, VmWithDefaultFieldRecord };
|
package/index.js
ADDED
|
@@ -0,0 +1,391 @@
|
|
|
1
|
+
// generated/client.ts
|
|
2
|
+
function errorFromJSON(json, statusCode) {
|
|
3
|
+
if (json && typeof json.message === "string") {
|
|
4
|
+
const error = new Error(json.message);
|
|
5
|
+
Object.assign(error, json);
|
|
6
|
+
return error;
|
|
7
|
+
}
|
|
8
|
+
if (json && json.error && typeof json.error === "string") {
|
|
9
|
+
return new Error(json.error);
|
|
10
|
+
}
|
|
11
|
+
if (typeof json === "string") {
|
|
12
|
+
return new Error(json);
|
|
13
|
+
}
|
|
14
|
+
return new Error(`API Error (${statusCode}): ${JSON.stringify(json)}`);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
class ApiClient {
|
|
18
|
+
baseUrl;
|
|
19
|
+
apiKey;
|
|
20
|
+
fetchFn;
|
|
21
|
+
constructor(config) {
|
|
22
|
+
this.baseUrl = config.baseUrl || "https://api.freestyle.sh";
|
|
23
|
+
this.apiKey = config.apiKey;
|
|
24
|
+
this.fetchFn = config.fetch || fetch;
|
|
25
|
+
}
|
|
26
|
+
buildUrl(path, params, query) {
|
|
27
|
+
let url = path;
|
|
28
|
+
if (params) {
|
|
29
|
+
for (const [key, value] of Object.entries(params)) {
|
|
30
|
+
url = url.replace(`{${key}}`, encodeURIComponent(value));
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
if (query) {
|
|
34
|
+
const searchParams = new URLSearchParams;
|
|
35
|
+
for (const [key, value] of Object.entries(query)) {
|
|
36
|
+
if (value !== undefined && value !== null) {
|
|
37
|
+
searchParams.append(key, String(value));
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
const queryString = searchParams.toString();
|
|
41
|
+
if (queryString) {
|
|
42
|
+
url += `?${queryString}`;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
return this.baseUrl + url;
|
|
46
|
+
}
|
|
47
|
+
async request(method, url, body) {
|
|
48
|
+
const headers = {
|
|
49
|
+
Authorization: `Bearer ${this.apiKey}`
|
|
50
|
+
};
|
|
51
|
+
if (body) {
|
|
52
|
+
headers["Content-Type"] = "application/json";
|
|
53
|
+
}
|
|
54
|
+
const response = await this.fetchFn(url, {
|
|
55
|
+
method,
|
|
56
|
+
headers,
|
|
57
|
+
body: body ? JSON.stringify(body) : undefined
|
|
58
|
+
});
|
|
59
|
+
if (!response.ok) {
|
|
60
|
+
const errorData = await response.json();
|
|
61
|
+
throw errorFromJSON(errorData, response.status);
|
|
62
|
+
}
|
|
63
|
+
return response.json();
|
|
64
|
+
}
|
|
65
|
+
get(path, ...args) {
|
|
66
|
+
const options = args[0];
|
|
67
|
+
const url = this.buildUrl(path, options?.params, options?.query);
|
|
68
|
+
return this.request("GET", url, options?.body);
|
|
69
|
+
}
|
|
70
|
+
post(path, ...args) {
|
|
71
|
+
const options = args[0];
|
|
72
|
+
const url = this.buildUrl(path, options?.params, options?.query);
|
|
73
|
+
return this.request("POST", url, options?.body);
|
|
74
|
+
}
|
|
75
|
+
put(path, ...args) {
|
|
76
|
+
const options = args[0];
|
|
77
|
+
const url = this.buildUrl(path, options?.params, options?.query);
|
|
78
|
+
return this.request("PUT", url, options?.body);
|
|
79
|
+
}
|
|
80
|
+
delete(path, ...args) {
|
|
81
|
+
const options = args[0];
|
|
82
|
+
const url = this.buildUrl(path, options?.params, options?.query);
|
|
83
|
+
return this.request("DELETE", url, options?.body);
|
|
84
|
+
}
|
|
85
|
+
patch(path, ...args) {
|
|
86
|
+
const options = args[0];
|
|
87
|
+
const url = this.buildUrl(path, options?.params, options?.query);
|
|
88
|
+
return this.request("PATCH", url, options?.body);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
// src/index.ts
|
|
92
|
+
class Freestyle {
|
|
93
|
+
apiClient;
|
|
94
|
+
options;
|
|
95
|
+
constructor({ apiKey, baseUrl } = {}) {
|
|
96
|
+
if (!apiKey && !process.env.FREESTYLE_API_KEY) {
|
|
97
|
+
throw new Error("API key is required. Please provide it in the constructor or set the FREESTYLE_API_KEY environment variable.");
|
|
98
|
+
}
|
|
99
|
+
this.options = {
|
|
100
|
+
apiKey: apiKey ?? process.env.FREESTYLE_API_KEY,
|
|
101
|
+
baseUrl: baseUrl ?? process.env.FREESTYLE_API_URL
|
|
102
|
+
};
|
|
103
|
+
this.apiClient = new ApiClient(this.options);
|
|
104
|
+
}
|
|
105
|
+
async executeScript(script, config) {
|
|
106
|
+
return this.apiClient.post("/execute/v1/script", {
|
|
107
|
+
body: { script, config }
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
async deployWebV2(body) {
|
|
111
|
+
return this.apiClient.post("/web/v1/deployment", { body });
|
|
112
|
+
}
|
|
113
|
+
async getLogs(deploymentId) {
|
|
114
|
+
return this.apiClient.get("/observability/v1/logs", {
|
|
115
|
+
query: { deploymentId }
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
async createDomainVerificationRequest(domain) {
|
|
119
|
+
return this.apiClient.post("/domains/v1/verifications", {
|
|
120
|
+
body: { domain }
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
async verifyDomainVerificationRequest(id) {
|
|
124
|
+
return this.apiClient.put("/domains/v1/verifications", {
|
|
125
|
+
body: { id }
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
async verifyDomain(domain) {
|
|
129
|
+
return this.apiClient.put("/domains/v1/verifications", {
|
|
130
|
+
body: { domain }
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
async listDomains(limit, offset) {
|
|
134
|
+
return this.apiClient.get("/domains/v1/domains", {
|
|
135
|
+
query: { limit, offset }
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
async listDomainVerificationRequests() {
|
|
139
|
+
return this.apiClient.get("/domains/v1/verifications", undefined);
|
|
140
|
+
}
|
|
141
|
+
async deleteDomainVerificationRequest(domain, verificationCode) {
|
|
142
|
+
return this.apiClient.delete("/domains/v1/verifications", {
|
|
143
|
+
body: { domain, verificationCode }
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
async listWebDeployments(limit, offset) {
|
|
147
|
+
return this.apiClient.get("/web/v1/deployments", {
|
|
148
|
+
query: { limit: limit ?? 50, offset: offset ?? 0 }
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
async listExecuteRuns(limit, offset) {
|
|
152
|
+
return this.apiClient.get("/execute/v1/deployments", {
|
|
153
|
+
query: { limit, offset }
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
async getExecuteRun(deployment) {
|
|
157
|
+
return this.apiClient.get("/execute/v1/deployments/{deployment}", {
|
|
158
|
+
params: { deployment }
|
|
159
|
+
});
|
|
160
|
+
}
|
|
161
|
+
async provisionWildcard(domain) {
|
|
162
|
+
return this.apiClient.post("/domains/v1/certs/{domain}/wildcard", {
|
|
163
|
+
params: { domain }
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
async insertDomainMapping({
|
|
167
|
+
domain,
|
|
168
|
+
deploymentId
|
|
169
|
+
}) {
|
|
170
|
+
return this.apiClient.post("/domains/v1/mappings/{domain}", {
|
|
171
|
+
params: { domain },
|
|
172
|
+
body: { deploymentId }
|
|
173
|
+
});
|
|
174
|
+
}
|
|
175
|
+
async removeDomainMapping({
|
|
176
|
+
domain
|
|
177
|
+
}) {
|
|
178
|
+
return this.apiClient.delete("/domains/v1/mappings/{domain}", {
|
|
179
|
+
params: { domain }
|
|
180
|
+
});
|
|
181
|
+
}
|
|
182
|
+
async listDomainMappings({
|
|
183
|
+
domain,
|
|
184
|
+
domainOwnership,
|
|
185
|
+
limit = 10,
|
|
186
|
+
offset = 0
|
|
187
|
+
} = {}) {
|
|
188
|
+
return this.apiClient.get("/domains/v1/mappings", {
|
|
189
|
+
query: { domain, domainOwnership, limit, offset }
|
|
190
|
+
});
|
|
191
|
+
}
|
|
192
|
+
async createGitRepository(body) {
|
|
193
|
+
return this.apiClient.post("/git/v1/repo", { body });
|
|
194
|
+
}
|
|
195
|
+
async listGitRepositories({
|
|
196
|
+
limit = 10,
|
|
197
|
+
offset = 0
|
|
198
|
+
} = {}) {
|
|
199
|
+
return this.apiClient.get("/git/v1/repo", {
|
|
200
|
+
query: { limit, offset }
|
|
201
|
+
});
|
|
202
|
+
}
|
|
203
|
+
async deleteGitRepository({
|
|
204
|
+
repo
|
|
205
|
+
}) {
|
|
206
|
+
return this.apiClient.delete("/git/v1/repo/{repo}", {
|
|
207
|
+
params: { repo }
|
|
208
|
+
});
|
|
209
|
+
}
|
|
210
|
+
async createGitIdentity() {
|
|
211
|
+
return this.apiClient.post("/git/v1/identity", undefined);
|
|
212
|
+
}
|
|
213
|
+
async deleteGitIdentity({
|
|
214
|
+
identity
|
|
215
|
+
}) {
|
|
216
|
+
return this.apiClient.delete("/git/v1/identity/{identity}", {
|
|
217
|
+
params: { identity }
|
|
218
|
+
});
|
|
219
|
+
}
|
|
220
|
+
async grantGitPermission({
|
|
221
|
+
repo,
|
|
222
|
+
identity,
|
|
223
|
+
permission
|
|
224
|
+
}) {
|
|
225
|
+
return this.apiClient.post("/git/v1/identity/{identity}/permissions/{repo}", {
|
|
226
|
+
params: { identity, repo },
|
|
227
|
+
body: { permission }
|
|
228
|
+
});
|
|
229
|
+
}
|
|
230
|
+
async updateGitPermission({
|
|
231
|
+
repo,
|
|
232
|
+
identity,
|
|
233
|
+
permission
|
|
234
|
+
}) {
|
|
235
|
+
return this.apiClient.patch("/git/v1/identity/{identity}/permissions/{repo}", {
|
|
236
|
+
params: { identity, repo },
|
|
237
|
+
body: { permission }
|
|
238
|
+
});
|
|
239
|
+
}
|
|
240
|
+
async revokeGitPermission({
|
|
241
|
+
repo,
|
|
242
|
+
identity
|
|
243
|
+
}) {
|
|
244
|
+
return this.apiClient.delete("/git/v1/identity/{identity}/permissions/{repo}", {
|
|
245
|
+
params: { identity, repo }
|
|
246
|
+
});
|
|
247
|
+
}
|
|
248
|
+
async listGitPermissions({
|
|
249
|
+
identity,
|
|
250
|
+
limit,
|
|
251
|
+
offset
|
|
252
|
+
}) {
|
|
253
|
+
return this.apiClient.get("/git/v1/identity/{identity}/permissions", {
|
|
254
|
+
params: { identity },
|
|
255
|
+
query: { limit, offset }
|
|
256
|
+
});
|
|
257
|
+
}
|
|
258
|
+
async getGitPermission({
|
|
259
|
+
repo,
|
|
260
|
+
identity
|
|
261
|
+
}) {
|
|
262
|
+
return this.apiClient.get("/git/v1/identity/{identity}/permissions/{repo}", {
|
|
263
|
+
params: { identity, repo }
|
|
264
|
+
});
|
|
265
|
+
}
|
|
266
|
+
async createGitAccessToken({
|
|
267
|
+
identity
|
|
268
|
+
}) {
|
|
269
|
+
return this.apiClient.post("/git/v1/identity/{identity}/tokens", {
|
|
270
|
+
params: { identity }
|
|
271
|
+
});
|
|
272
|
+
}
|
|
273
|
+
async revokeGitAccessToken({
|
|
274
|
+
identity,
|
|
275
|
+
tokenId
|
|
276
|
+
}) {
|
|
277
|
+
return this.apiClient.delete("/git/v1/identity/{identity}/tokens", {
|
|
278
|
+
params: { identity },
|
|
279
|
+
body: { tokenId }
|
|
280
|
+
});
|
|
281
|
+
}
|
|
282
|
+
async listGitAccessTokens({
|
|
283
|
+
identity
|
|
284
|
+
}) {
|
|
285
|
+
return this.apiClient.get("/git/v1/identity/{identity}/tokens", {
|
|
286
|
+
params: { identity }
|
|
287
|
+
});
|
|
288
|
+
}
|
|
289
|
+
async listGitTriggers({
|
|
290
|
+
repo
|
|
291
|
+
}) {
|
|
292
|
+
return this.apiClient.get("/git/v1/repo/{repo}/trigger", {
|
|
293
|
+
params: { repo }
|
|
294
|
+
});
|
|
295
|
+
}
|
|
296
|
+
async createGitTrigger({
|
|
297
|
+
repo,
|
|
298
|
+
trigger,
|
|
299
|
+
action
|
|
300
|
+
}) {
|
|
301
|
+
return this.apiClient.post("/git/v1/repo/{repo}/trigger", {
|
|
302
|
+
params: { repo },
|
|
303
|
+
body: { trigger, action }
|
|
304
|
+
});
|
|
305
|
+
}
|
|
306
|
+
async deleteGitTrigger({
|
|
307
|
+
repo,
|
|
308
|
+
trigger
|
|
309
|
+
}) {
|
|
310
|
+
return this.apiClient.delete("/git/v1/repo/{repo}/trigger/{trigger}", {
|
|
311
|
+
params: { repo, trigger }
|
|
312
|
+
});
|
|
313
|
+
}
|
|
314
|
+
async setGitRepoDefaultBranch({
|
|
315
|
+
repo_id,
|
|
316
|
+
defaultBranch
|
|
317
|
+
}) {
|
|
318
|
+
return this.apiClient.put("/git/v1/repo/{repo_id}/default-branch", {
|
|
319
|
+
params: { repo_id },
|
|
320
|
+
body: { defaultBranch }
|
|
321
|
+
});
|
|
322
|
+
}
|
|
323
|
+
async getGitRepoDefaultBranch({
|
|
324
|
+
repo_id
|
|
325
|
+
}) {
|
|
326
|
+
return this.apiClient.get("/git/v1/repo/{repo_id}/default-branch", {
|
|
327
|
+
params: { repo_id }
|
|
328
|
+
});
|
|
329
|
+
}
|
|
330
|
+
async getGitRepoContents({
|
|
331
|
+
repo,
|
|
332
|
+
path = "",
|
|
333
|
+
ref
|
|
334
|
+
}) {
|
|
335
|
+
return this.apiClient.get("/git/v1/repo/{repo}/contents/{path}", {
|
|
336
|
+
params: { repo, path },
|
|
337
|
+
query: { ref }
|
|
338
|
+
});
|
|
339
|
+
}
|
|
340
|
+
async configureGitRepoGitHubSync({
|
|
341
|
+
repo_id,
|
|
342
|
+
githubRepoName
|
|
343
|
+
}) {
|
|
344
|
+
throw new Error("Not implemented - endpoint missing from OpenAPI spec");
|
|
345
|
+
}
|
|
346
|
+
async removeGitRepoGitHubSync({ repo_id }) {
|
|
347
|
+
throw new Error("Not implemented - endpoint missing from OpenAPI spec");
|
|
348
|
+
}
|
|
349
|
+
async getGitRepoGitHubSyncConfig({
|
|
350
|
+
repo_id
|
|
351
|
+
}) {
|
|
352
|
+
try {
|
|
353
|
+
return await this.apiClient.get("/git/v1/repo/{repo_id}/github-sync", {
|
|
354
|
+
params: { repo_id }
|
|
355
|
+
});
|
|
356
|
+
} catch (error) {
|
|
357
|
+
if (error.message?.includes("404")) {
|
|
358
|
+
return null;
|
|
359
|
+
}
|
|
360
|
+
throw error;
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
async createDnsRecord(body) {
|
|
364
|
+
return this.apiClient.post("/dns/v1/records", { body });
|
|
365
|
+
}
|
|
366
|
+
async listDnsRecords(query) {
|
|
367
|
+
return this.apiClient.get("/dns/v1/records", { query });
|
|
368
|
+
}
|
|
369
|
+
async deleteDnsRecord(query) {
|
|
370
|
+
return this.apiClient.delete("/dns/v1/records", { query });
|
|
371
|
+
}
|
|
372
|
+
fetch(path, init) {
|
|
373
|
+
const headers = new Headers(init?.headers);
|
|
374
|
+
if (!headers.has("Authorization")) {
|
|
375
|
+
headers.append("Authorization", `Bearer ${this.options.apiKey}`);
|
|
376
|
+
}
|
|
377
|
+
if (!headers.has("Content-Type") && init?.body) {
|
|
378
|
+
headers.append("Content-Type", "application/json");
|
|
379
|
+
}
|
|
380
|
+
const url = new URL(path, this.options.baseUrl ?? "https://api.freestyle.sh");
|
|
381
|
+
return fetch(url, {
|
|
382
|
+
...init ?? {},
|
|
383
|
+
headers
|
|
384
|
+
});
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
var src_default = Freestyle;
|
|
388
|
+
export {
|
|
389
|
+
src_default as default,
|
|
390
|
+
Freestyle
|
|
391
|
+
};
|
package/index.mjs
CHANGED
|
@@ -7565,7 +7565,7 @@ class VmsNamespace {
|
|
|
7565
7565
|
function enhanceError(e) {
|
|
7566
7566
|
if (e instanceof VmSetupFailedError) {
|
|
7567
7567
|
if (!e.message.includes("create --snapshot")) {
|
|
7568
|
-
e.message = `${e.message}. Hint: use \`npx freestyle
|
|
7568
|
+
e.message = `${e.message}. Hint: use \`npx freestyle@latest vm create --snapshot ${e.body.snapshotId} --ssh --delete\` to debug.`;
|
|
7569
7569
|
}
|
|
7570
7570
|
if (e.body.diagnostics) {
|
|
7571
7571
|
const d = e.body.diagnostics;
|