freestyle 0.1.46 → 0.1.48
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/README.md +51 -0
- package/cli.mjs +116 -2
- package/index.cjs +1791 -1475
- package/index.d.cts +3316 -1724
- package/index.d.mts +3316 -1724
- package/index.mjs +1791 -1475
- package/package.json +1 -1
- package/index.js +0 -391
package/README.md
CHANGED
|
@@ -163,4 +163,55 @@ for (let i = 0; i < 10; i++) {
|
|
|
163
163
|
`,
|
|
164
164
|
});
|
|
165
165
|
}
|
|
166
|
+
|
|
167
|
+
// Restrict outbound requests and attach headers for matching domains.
|
|
168
|
+
await freestyle.serverless.runs.create({
|
|
169
|
+
code: `export default async () => {
|
|
170
|
+
const res = await fetch("https://api.freestyle.sh/some-path");
|
|
171
|
+
return await res.text();
|
|
172
|
+
}`,
|
|
173
|
+
egress: {
|
|
174
|
+
allow: {
|
|
175
|
+
domains: {
|
|
176
|
+
"api.freestyle.sh": [
|
|
177
|
+
{
|
|
178
|
+
transform: [
|
|
179
|
+
{
|
|
180
|
+
headers: {
|
|
181
|
+
"X-Freestyle-Admin-Key": "abc",
|
|
182
|
+
"X-Freestyle-User-Id": "123",
|
|
183
|
+
},
|
|
184
|
+
},
|
|
185
|
+
],
|
|
186
|
+
},
|
|
187
|
+
],
|
|
188
|
+
"*": [],
|
|
189
|
+
},
|
|
190
|
+
},
|
|
191
|
+
},
|
|
192
|
+
});
|
|
193
|
+
|
|
194
|
+
// The same egress config shape is supported for deployments.
|
|
195
|
+
await freestyle.serverless.deployments.create({
|
|
196
|
+
code: "export default () => new Response('ok')",
|
|
197
|
+
egress: {
|
|
198
|
+
allow: {
|
|
199
|
+
domains: {
|
|
200
|
+
"api.freestyle.sh": [
|
|
201
|
+
{
|
|
202
|
+
transform: [
|
|
203
|
+
{
|
|
204
|
+
headers: {
|
|
205
|
+
"X-Freestyle-Admin-Key": "abc",
|
|
206
|
+
"X-Freestyle-User-Id": "123",
|
|
207
|
+
},
|
|
208
|
+
},
|
|
209
|
+
],
|
|
210
|
+
},
|
|
211
|
+
],
|
|
212
|
+
"*": [],
|
|
213
|
+
},
|
|
214
|
+
},
|
|
215
|
+
},
|
|
216
|
+
});
|
|
166
217
|
```
|
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";
|
|
@@ -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) {
|