gigadrive 2.15.0 → 2.16.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.cjs CHANGED
@@ -32,7 +32,7 @@ var import_effect31 = require("effect");
32
32
  // package.json
33
33
  var package_default = {
34
34
  name: "gigadrive",
35
- version: "2.15.0",
35
+ version: "2.16.0",
36
36
  repository: {
37
37
  type: "git",
38
38
  url: "https://github.com/Gigadrive/sdk.git",
@@ -3073,6 +3073,7 @@ var describeMicroVm = (vm, now = Date.now()) => {
3073
3073
  `Size: ${vm.vcpus} vCPU, ${formatMemory(vm.memoryMb)} memory, ${formatMemory(vm.diskMb)} disk`,
3074
3074
  `Region: ${vm.region}`,
3075
3075
  `Network: ${vm.network.egress === "deny" ? "outbound traffic blocked" : vm.network.allow && vm.network.allow.length > 0 ? `only ${vm.network.allow.join(", ")}` : "internet access"}`,
3076
+ ...(vm.network.inject ?? []).map((rule) => `Injects: ${rule.headers.join(", ")} for ${rule.domain}`),
3076
3077
  `Previews: ${vm.network.previews === "private" ? "private (preview token required)" : "public"}`,
3077
3078
  `Application: ${vm.applicationId}`,
3078
3079
  `Created: ${vm.createdAt}`
@@ -3383,6 +3384,26 @@ var parseVolumeFlags = (values) => import_effect24.Effect.gen(function* () {
3383
3384
  }
3384
3385
  return volumes;
3385
3386
  });
3387
+ var parseInjectFlags = (values) => import_effect24.Effect.gen(function* () {
3388
+ const rules = /* @__PURE__ */ new Map();
3389
+ for (const value of values) {
3390
+ const colon = value.indexOf(":");
3391
+ const equals = value.indexOf("=", colon + 1);
3392
+ const domain = colon > 0 ? value.slice(0, colon).trim().toLowerCase() : "";
3393
+ const name = colon > 0 && equals > colon ? value.slice(colon + 1, equals).trim() : "";
3394
+ if (domain === "" || name === "" || equals === value.length - 1) {
3395
+ return yield* new InvalidMicroVmOptionsError({
3396
+ // The entry is not echoed: it may hold the credential.
3397
+ message: '--inject must be DOMAIN:HEADER=VALUE, such as "api.openai.com:Authorization=Bearer $OPENAI_API_KEY".'
3398
+ });
3399
+ }
3400
+ rules.set(domain, { ...rules.get(domain), [name]: value.slice(equals + 1) });
3401
+ }
3402
+ if (rules.size > 8) {
3403
+ return yield* new InvalidMicroVmOptionsError({ message: "--inject takes at most 8 domains." });
3404
+ }
3405
+ return [...rules].map(([domain, headers]) => ({ domain, headers }));
3406
+ });
3386
3407
  var checkEgressFlags = (denyEgress, allowEgress) => import_effect24.Effect.gen(function* () {
3387
3408
  if (denyEgress && allowEgress.length > 0) {
3388
3409
  return yield* new InvalidMicroVmOptionsError({
@@ -3413,6 +3434,10 @@ var createInput = (flags) => import_effect24.Effect.gen(function* () {
3413
3434
  if (badPort !== void 0) {
3414
3435
  return yield* new InvalidMicroVmOptionsError({ message: `--port must be between 1 and 65535 (got ${badPort}).` });
3415
3436
  }
3437
+ const inject = yield* parseInjectFlags(flags.inject);
3438
+ if (inject.length > 0 && flags.denyEgress) {
3439
+ return yield* new InvalidMicroVmOptionsError({ message: "--inject cannot be combined with --deny-egress." });
3440
+ }
3416
3441
  const volumes = yield* parseVolumeFlags(flags.volumes);
3417
3442
  if (volumes.length > 0 && flags.pauseOnTimeout) {
3418
3443
  return yield* new InvalidMicroVmOptionsError({ message: "--volume cannot be combined with --pause-on-timeout." });
@@ -3434,11 +3459,12 @@ var createInput = (flags) => import_effect24.Effect.gen(function* () {
3434
3459
  ...env ? { env } : {},
3435
3460
  ...metadata ? { metadata } : {},
3436
3461
  ...volumes.length > 0 ? { volumes } : {},
3437
- ...flags.denyEgress || flags.privatePreviews || flags.allowEgress.length > 0 ? {
3462
+ ...flags.denyEgress || flags.privatePreviews || flags.allowEgress.length > 0 || inject.length > 0 ? {
3438
3463
  network: {
3439
3464
  egress: flags.denyEgress ? "deny" : "allow",
3440
3465
  ...flags.privatePreviews ? { previews: "private" } : {},
3441
- ...flags.allowEgress.length > 0 ? { allow: flags.allowEgress.map((entry) => entry.trim()) } : {}
3466
+ ...flags.allowEgress.length > 0 ? { allow: flags.allowEgress.map((entry) => entry.trim()) } : {},
3467
+ ...inject.length > 0 ? { inject } : {}
3442
3468
  }
3443
3469
  } : {},
3444
3470
  ...import_effect24.Option.match(flags.region, { onNone: () => ({}), onSome: (region) => ({ region }) })
@@ -3529,6 +3555,12 @@ var createCommand = import_cli12.Command.make(
3529
3555
  ),
3530
3556
  import_cli12.Options.repeated
3531
3557
  ),
3558
+ inject: import_cli12.Options.text("inject").pipe(
3559
+ import_cli12.Options.withDescription(
3560
+ "Add a header to HTTPS requests to a domain, as DOMAIN:HEADER=VALUE (repeatable, up to 8 domains); the value never enters the microVM"
3561
+ ),
3562
+ import_cli12.Options.repeated
3563
+ ),
3532
3564
  pauseOnTimeout: import_cli12.Options.boolean("pause-on-timeout").pipe(
3533
3565
  import_cli12.Options.withDescription("Pause the microVM when its timeout ends instead of stopping it")
3534
3566
  ),
@@ -3898,15 +3930,31 @@ var updateMicroVmNetwork = (microvmId, flags) => import_effect24.Effect.gen(func
3898
3930
  });
3899
3931
  }
3900
3932
  yield* checkEgressFlags(flags.denyEgress, flags.allowEgress);
3933
+ const inject = yield* parseInjectFlags(flags.inject);
3934
+ if (inject.length > 0 && flags.denyEgress) {
3935
+ return yield* new InvalidMicroVmOptionsError({ message: "--inject cannot be combined with --deny-egress." });
3936
+ }
3937
+ if (flags.clearInject && (inject.length > 0 || flags.denyEgress)) {
3938
+ return yield* new InvalidMicroVmOptionsError({
3939
+ message: "--clear-inject cannot be combined with --inject or --deny-egress."
3940
+ });
3941
+ }
3901
3942
  const apiClient = yield* ApiClientService;
3902
3943
  const vm = yield* apiClient.request(
3903
3944
  (client) => client.microvms.updateNetwork(
3904
3945
  microvmId,
3905
- flags.denyEgress ? { egress: "deny" } : flags.allowEgress.length > 0 ? { egress: "allow", allow: flags.allowEgress.map((entry) => entry.trim()) } : { egress: "allow" }
3946
+ flags.denyEgress ? { egress: "deny" } : {
3947
+ egress: "allow",
3948
+ ...flags.allowEgress.length > 0 ? { allow: flags.allowEgress.map((entry) => entry.trim()) } : {},
3949
+ ...inject.length > 0 || flags.clearInject ? { inject } : {}
3950
+ }
3906
3951
  )
3907
3952
  );
3908
3953
  const reach = vm.network.egress === "deny" ? "no outbound traffic" : vm.network.allow ? vm.network.allow.join(", ") : "the whole internet";
3909
3954
  yield* import_effect24.Console.log(`${vm.id} now reaches ${reach}.`);
3955
+ for (const rule of vm.network.inject ?? []) {
3956
+ yield* import_effect24.Console.log(`Adds ${rule.headers.join(", ")} to HTTPS requests to ${rule.domain}.`);
3957
+ }
3910
3958
  return vm;
3911
3959
  });
3912
3960
  var networkCommand = import_cli12.Command.make(
@@ -3922,6 +3970,15 @@ var networkCommand = import_cli12.Command.make(
3922
3970
  ),
3923
3971
  allowAllEgress: import_cli12.Options.boolean("allow-all-egress").pipe(
3924
3972
  import_cli12.Options.withDescription("Reach the whole internet again (private networks stay blocked)")
3973
+ ),
3974
+ inject: import_cli12.Options.text("inject").pipe(
3975
+ import_cli12.Options.withDescription(
3976
+ "Add a header to HTTPS requests to a domain, as DOMAIN:HEADER=VALUE (repeatable, up to 8 domains); the value never enters the microVM"
3977
+ ),
3978
+ import_cli12.Options.repeated
3979
+ ),
3980
+ clearInject: import_cli12.Options.boolean("clear-inject").pipe(
3981
+ import_cli12.Options.withDescription("Remove every header rule added with --inject")
3925
3982
  )
3926
3983
  },
3927
3984
  ({ microvmId, ...flags }) => updateMicroVmNetwork(microvmId, flags).pipe(import_effect24.Effect.asVoid, reportErrors2("update the microVM network"))