gigadrive 2.15.0 → 2.17.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/dist/index.mjs CHANGED
@@ -9,7 +9,7 @@ import { Effect as Effect29, Layer, LogLevel, Logger } from "effect";
9
9
  // package.json
10
10
  var package_default = {
11
11
  name: "gigadrive",
12
- version: "2.15.0",
12
+ version: "2.17.0",
13
13
  repository: {
14
14
  type: "git",
15
15
  url: "https://github.com/Gigadrive/sdk.git",
@@ -3063,6 +3063,7 @@ var describeMicroVm = (vm, now = Date.now()) => {
3063
3063
  `Size: ${vm.vcpus} vCPU, ${formatMemory(vm.memoryMb)} memory, ${formatMemory(vm.diskMb)} disk`,
3064
3064
  `Region: ${vm.region}`,
3065
3065
  `Network: ${vm.network.egress === "deny" ? "outbound traffic blocked" : vm.network.allow && vm.network.allow.length > 0 ? `only ${vm.network.allow.join(", ")}` : "internet access"}`,
3066
+ ...(vm.network.inject ?? []).map((rule) => `Injects: ${rule.headers.join(", ")} for ${rule.domain}`),
3066
3067
  `Previews: ${vm.network.previews === "private" ? "private (preview token required)" : "public"}`,
3067
3068
  `Application: ${vm.applicationId}`,
3068
3069
  `Created: ${vm.createdAt}`
@@ -3373,6 +3374,37 @@ var parseVolumeFlags = (values) => Effect22.gen(function* () {
3373
3374
  }
3374
3375
  return volumes;
3375
3376
  });
3377
+ var parseInjectFlags = (values) => Effect22.gen(function* () {
3378
+ const rules = /* @__PURE__ */ new Map();
3379
+ for (const value of values) {
3380
+ const colon = value.indexOf(":");
3381
+ const equals = value.indexOf("=", colon + 1);
3382
+ const domain = colon > 0 ? value.slice(0, colon).trim().toLowerCase() : "";
3383
+ const name = colon > 0 && equals > colon ? value.slice(colon + 1, equals).trim() : "";
3384
+ if (domain === "" || name === "" || equals === value.length - 1) {
3385
+ return yield* new InvalidMicroVmOptionsError({
3386
+ // The entry is not echoed: it may hold the credential.
3387
+ message: '--inject and --inject-file take DOMAIN:HEADER=VALUE, such as "api.openai.com:Authorization=Bearer $OPENAI_API_KEY".'
3388
+ });
3389
+ }
3390
+ rules.set(domain, { ...rules.get(domain), [name]: value.slice(equals + 1) });
3391
+ }
3392
+ if (rules.size > 8) {
3393
+ return yield* new InvalidMicroVmOptionsError({ message: "--inject takes at most 8 domains." });
3394
+ }
3395
+ return [...rules].map(([domain, headers]) => ({ domain, headers }));
3396
+ });
3397
+ var readInjectRules = (inject, injectFile) => Effect22.gen(function* () {
3398
+ if (Option14.isNone(injectFile)) return yield* parseInjectFlags(inject);
3399
+ const fs = yield* FileSystem8.FileSystem;
3400
+ const content = yield* fs.readFileString(injectFile.value).pipe(
3401
+ Effect22.mapError(
3402
+ () => new InvalidMicroVmOptionsError({ message: `Could not read --inject-file ${injectFile.value}.` })
3403
+ )
3404
+ );
3405
+ const lines = content.split(/\r?\n/).map((line) => line.trim()).filter((line) => line !== "" && !line.startsWith("#"));
3406
+ return yield* parseInjectFlags([...inject, ...lines]);
3407
+ });
3376
3408
  var checkEgressFlags = (denyEgress, allowEgress) => Effect22.gen(function* () {
3377
3409
  if (denyEgress && allowEgress.length > 0) {
3378
3410
  return yield* new InvalidMicroVmOptionsError({
@@ -3403,6 +3435,10 @@ var createInput = (flags) => Effect22.gen(function* () {
3403
3435
  if (badPort !== void 0) {
3404
3436
  return yield* new InvalidMicroVmOptionsError({ message: `--port must be between 1 and 65535 (got ${badPort}).` });
3405
3437
  }
3438
+ const inject = yield* readInjectRules(flags.inject, flags.injectFile);
3439
+ if (inject.length > 0 && flags.denyEgress) {
3440
+ return yield* new InvalidMicroVmOptionsError({ message: "--inject cannot be combined with --deny-egress." });
3441
+ }
3406
3442
  const volumes = yield* parseVolumeFlags(flags.volumes);
3407
3443
  if (volumes.length > 0 && flags.pauseOnTimeout) {
3408
3444
  return yield* new InvalidMicroVmOptionsError({ message: "--volume cannot be combined with --pause-on-timeout." });
@@ -3424,11 +3460,12 @@ var createInput = (flags) => Effect22.gen(function* () {
3424
3460
  ...env ? { env } : {},
3425
3461
  ...metadata ? { metadata } : {},
3426
3462
  ...volumes.length > 0 ? { volumes } : {},
3427
- ...flags.denyEgress || flags.privatePreviews || flags.allowEgress.length > 0 ? {
3463
+ ...flags.denyEgress || flags.privatePreviews || flags.allowEgress.length > 0 || inject.length > 0 ? {
3428
3464
  network: {
3429
3465
  egress: flags.denyEgress ? "deny" : "allow",
3430
3466
  ...flags.privatePreviews ? { previews: "private" } : {},
3431
- ...flags.allowEgress.length > 0 ? { allow: flags.allowEgress.map((entry) => entry.trim()) } : {}
3467
+ ...flags.allowEgress.length > 0 ? { allow: flags.allowEgress.map((entry) => entry.trim()) } : {},
3468
+ ...inject.length > 0 ? { inject } : {}
3432
3469
  }
3433
3470
  } : {},
3434
3471
  ...Option14.match(flags.region, { onNone: () => ({}), onSome: (region) => ({ region }) })
@@ -3519,6 +3556,18 @@ var createCommand = Command12.make(
3519
3556
  ),
3520
3557
  Options7.repeated
3521
3558
  ),
3559
+ inject: Options7.text("inject").pipe(
3560
+ Options7.withDescription(
3561
+ "Add a header to HTTPS requests to a domain, as DOMAIN:HEADER=VALUE (repeatable, up to 8 domains); the value never enters the microVM"
3562
+ ),
3563
+ Options7.repeated
3564
+ ),
3565
+ injectFile: Options7.text("inject-file").pipe(
3566
+ Options7.withDescription(
3567
+ "Read --inject rules from a file, one DOMAIN:HEADER=VALUE per line (/dev/stdin for a pipe), so the values stay out of the command line"
3568
+ ),
3569
+ Options7.optional
3570
+ ),
3522
3571
  pauseOnTimeout: Options7.boolean("pause-on-timeout").pipe(
3523
3572
  Options7.withDescription("Pause the microVM when its timeout ends instead of stopping it")
3524
3573
  ),
@@ -3888,15 +3937,31 @@ var updateMicroVmNetwork = (microvmId, flags) => Effect22.gen(function* () {
3888
3937
  });
3889
3938
  }
3890
3939
  yield* checkEgressFlags(flags.denyEgress, flags.allowEgress);
3940
+ const inject = yield* readInjectRules(flags.inject, flags.injectFile);
3941
+ if (inject.length > 0 && flags.denyEgress) {
3942
+ return yield* new InvalidMicroVmOptionsError({ message: "--inject cannot be combined with --deny-egress." });
3943
+ }
3944
+ if (flags.clearInject && (inject.length > 0 || flags.denyEgress)) {
3945
+ return yield* new InvalidMicroVmOptionsError({
3946
+ message: "--clear-inject cannot be combined with --inject or --deny-egress."
3947
+ });
3948
+ }
3891
3949
  const apiClient = yield* ApiClientService;
3892
3950
  const vm = yield* apiClient.request(
3893
3951
  (client) => client.microvms.updateNetwork(
3894
3952
  microvmId,
3895
- flags.denyEgress ? { egress: "deny" } : flags.allowEgress.length > 0 ? { egress: "allow", allow: flags.allowEgress.map((entry) => entry.trim()) } : { egress: "allow" }
3953
+ flags.denyEgress ? { egress: "deny" } : {
3954
+ egress: "allow",
3955
+ ...flags.allowEgress.length > 0 ? { allow: flags.allowEgress.map((entry) => entry.trim()) } : {},
3956
+ ...inject.length > 0 || flags.clearInject ? { inject } : {}
3957
+ }
3896
3958
  )
3897
3959
  );
3898
3960
  const reach = vm.network.egress === "deny" ? "no outbound traffic" : vm.network.allow ? vm.network.allow.join(", ") : "the whole internet";
3899
3961
  yield* Console12.log(`${vm.id} now reaches ${reach}.`);
3962
+ for (const rule of vm.network.inject ?? []) {
3963
+ yield* Console12.log(`Adds ${rule.headers.join(", ")} to HTTPS requests to ${rule.domain}.`);
3964
+ }
3900
3965
  return vm;
3901
3966
  });
3902
3967
  var networkCommand = Command12.make(
@@ -3912,6 +3977,21 @@ var networkCommand = Command12.make(
3912
3977
  ),
3913
3978
  allowAllEgress: Options7.boolean("allow-all-egress").pipe(
3914
3979
  Options7.withDescription("Reach the whole internet again (private networks stay blocked)")
3980
+ ),
3981
+ inject: Options7.text("inject").pipe(
3982
+ Options7.withDescription(
3983
+ "Add a header to HTTPS requests to a domain, as DOMAIN:HEADER=VALUE (repeatable, up to 8 domains); the value never enters the microVM"
3984
+ ),
3985
+ Options7.repeated
3986
+ ),
3987
+ injectFile: Options7.text("inject-file").pipe(
3988
+ Options7.withDescription(
3989
+ "Read --inject rules from a file, one DOMAIN:HEADER=VALUE per line (/dev/stdin for a pipe), so the values stay out of the command line"
3990
+ ),
3991
+ Options7.optional
3992
+ ),
3993
+ clearInject: Options7.boolean("clear-inject").pipe(
3994
+ Options7.withDescription("Remove every header rule added with --inject")
3915
3995
  )
3916
3996
  },
3917
3997
  ({ microvmId, ...flags }) => updateMicroVmNetwork(microvmId, flags).pipe(Effect22.asVoid, reportErrors2("update the microVM network"))