@void/platform 0.26.1 → 0.28.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/README.md CHANGED
@@ -16,7 +16,7 @@ npx void platform install
16
16
  Once the platform is installed, developers connect and deploy:
17
17
 
18
18
  ```sh
19
- npx void connect https://api.example.com
19
+ npx void connect api.example.com
20
20
  npx void deploy
21
21
  ```
22
22
 
package/dist/index.mjs CHANGED
@@ -1,3 +1,4 @@
1
+ import { a as isSourceRevision, c as requiredString, i as isSandboxDrainProtocol, n as isPrintableText, o as isUsageProtocolVersion, s as record, t as assertRecord } from "./validate-DbJR7Q0Z.mjs";
1
2
  import { BUILD_INSTANCE_FREE, BUILD_INSTANCE_LARGE, PLAN_EDITABLE_LIMIT_KEYS, PLAN_LIMITS, createDefaultPlanCatalog, parseBuildInstanceType, parsePlanLimitsPatch, parsePlanName, parsePlatformPlanCatalog, parsePlatformPlanId, validatePlanLimits } from "./plans.mjs";
2
3
  //#region src/app-access.ts
3
4
  const PLATFORM_APP_ACCESS_SETUP_PROOF_PREFIX = "void-platform-app-access-v1";
@@ -125,12 +126,8 @@ function parsePlatformAuthenticationSetup(value) {
125
126
  const DEFAULT_PLATFORM_SESSION_SECONDS = 2592e3;
126
127
  const GOOGLE_OIDC_ISSUER = "https://accounts.google.com";
127
128
  const PLATFORM_AUTH_SETUP_PROOF_PREFIX = "void.platform.auth.setup.v1";
128
- function record(value, name) {
129
- if (!value || typeof value !== "object" || Array.isArray(value)) throw new Error(`${name} must be an object.`);
130
- return value;
131
- }
132
129
  function string(value, name, maximum = 512) {
133
- if (typeof value !== "string" || !value.trim() || value.length > maximum || Array.from(value).some((character) => character.charCodeAt(0) < 32 || character.charCodeAt(0) === 127)) throw new Error(`${name} must be a nonempty string of at most ${maximum} characters.`);
130
+ if (!isPrintableText(value, maximum)) throw new Error(`${name} must be a nonempty string of at most ${maximum} characters.`);
134
131
  return value.trim();
135
132
  }
136
133
  function strings(value, name, maximum = 100) {
@@ -262,13 +259,6 @@ const CONTROL_PLANE_DEFAULTS = {
262
259
  dashboardHostname: null,
263
260
  proxyHostname: null
264
261
  };
265
- function assertRecord$1(value, label) {
266
- if (!value || typeof value !== "object" || Array.isArray(value)) throw new Error(`${label} must be an object.`);
267
- }
268
- function requiredString$1(value, label) {
269
- if (typeof value !== "string" || value.trim() === "") throw new Error(`${label} must be a non-empty string.`);
270
- return value;
271
- }
272
262
  function normalizeInstallationSlug(value) {
273
263
  const slug = value.trim().toLowerCase().replaceAll(/[^a-z0-9-]+/g, "-").replaceAll(/^-+|-+$/g, "").replaceAll(/-{2,}/g, "-");
274
264
  if (!slug) throw new Error("The installation name must contain a letter or number.");
@@ -384,7 +374,7 @@ function createPlatformDeploymentManifest(input) {
384
374
  dedicatedZone: input.application.dedicatedZone ?? false,
385
375
  zoneName,
386
376
  ...workersDev ? { workersDev: { ...workersDev } } : {},
387
- ...input.application.zoneId ? { zoneId: requiredString$1(input.application.zoneId, "application.zoneId") } : {}
377
+ ...input.application.zoneId ? { zoneId: requiredString(input.application.zoneId, "application.zoneId") } : {}
388
378
  },
389
379
  authentication: {
390
380
  providers: [...providers],
@@ -392,7 +382,7 @@ function createPlatformDeploymentManifest(input) {
392
382
  ...input.authentication?.accessProtection ? { accessProtection: true } : {}
393
383
  },
394
384
  capabilities,
395
- ...input.emailSharedZoneId !== void 0 ? { emailSharedZoneId: requiredString$1(input.emailSharedZoneId, "emailSharedZoneId") } : {},
385
+ ...input.emailSharedZoneId !== void 0 ? { emailSharedZoneId: requiredString(input.emailSharedZoneId, "emailSharedZoneId") } : {},
396
386
  ...input.emailSenderDomain !== void 0 ? { emailSenderDomain: normalizeApplicationDomain(input.emailSenderDomain) } : {},
397
387
  controlPlane: {
398
388
  ...CONTROL_PLANE_DEFAULTS,
@@ -402,7 +392,7 @@ function createPlatformDeploymentManifest(input) {
402
392
  dashboardHostname: input.controlPlane?.dashboardHostname ?? new URL(dashboardUrl).hostname
403
393
  } : {}
404
394
  },
405
- displayName: requiredString$1(input.displayName, "displayName").trim(),
395
+ displayName: requiredString(input.displayName, "displayName").trim(),
406
396
  installationSlug,
407
397
  resources,
408
398
  schemaVersion: input.appAccess !== void 0 ? 4 : configurable ? 3 : workersDev ? 2 : 1
@@ -416,30 +406,30 @@ function createPlatformDeploymentManifest(input) {
416
406
  const hostname = new URL(manifest.controlPlane.dashboardUrl).hostname;
417
407
  if (manifest.controlPlane.dashboardHostname !== hostname) throw new Error("The dashboard URL and dashboard hostname must agree.");
418
408
  }
419
- for (const [key, value] of Object.entries(manifest.resources)) requiredString$1(value, `resources.${key}`);
409
+ for (const [key, value] of Object.entries(manifest.resources)) requiredString(value, `resources.${key}`);
420
410
  return manifest;
421
411
  }
422
412
  function parsePlatformDeploymentManifest(value) {
423
- assertRecord$1(value, "Platform deployment manifest");
413
+ assertRecord(value, "Platform deployment manifest");
424
414
  if (value.schemaVersion !== 1 && value.schemaVersion !== 2 && value.schemaVersion !== 3 && value.schemaVersion !== 4) throw new Error(`Unsupported platform deployment schema version: ${String(value.schemaVersion)}.`);
425
415
  const application = value.application;
426
416
  const authentication = value.authentication;
427
417
  const rawCapabilities = value.capabilities;
428
418
  const controlPlane = value.controlPlane;
429
419
  const rawResources = value.resources;
430
- assertRecord$1(application, "application");
420
+ assertRecord(application, "application");
431
421
  let workersDev;
432
422
  if (value.schemaVersion === 2 || (value.schemaVersion === 3 || value.schemaVersion === 4) && application.workersDev !== void 0) {
433
- assertRecord$1(application.workersDev, "application.workersDev");
423
+ assertRecord(application.workersDev, "application.workersDev");
434
424
  workersDev = {
435
- subdomain: requiredString$1(application.workersDev.subdomain, "workersDev.subdomain"),
436
- installationId: requiredString$1(application.workersDev.installationId, "workersDev.installationId")
425
+ subdomain: requiredString(application.workersDev.subdomain, "workersDev.subdomain"),
426
+ installationId: requiredString(application.workersDev.installationId, "workersDev.installationId")
437
427
  };
438
428
  } else if (application.workersDev !== void 0) throw new Error("workers.dev requires platform deployment schema version 2.");
439
- assertRecord$1(rawCapabilities, "capabilities");
440
- assertRecord$1(controlPlane, "controlPlane");
441
- assertRecord$1(authentication, "authentication");
442
- assertRecord$1(rawResources, "resources");
429
+ assertRecord(rawCapabilities, "capabilities");
430
+ assertRecord(controlPlane, "controlPlane");
431
+ assertRecord(authentication, "authentication");
432
+ assertRecord(rawResources, "resources");
443
433
  const capabilityKeys = Object.keys(CORE_CAPABILITIES);
444
434
  const capabilities = {};
445
435
  for (const key of capabilityKeys) {
@@ -456,19 +446,19 @@ function parsePlatformDeploymentManifest(value) {
456
446
  "custom"
457
447
  ].includes(String(value.appAccess)) : value.appAccess !== void 0) throw new Error("Guided app access requires deployment schema version 4 and a valid appAccess choice.");
458
448
  if (authentication.configurable !== void 0 && authentication.configurable !== true) throw new Error("Invalid configurable authentication flag.");
459
- const resourceDefaults = createPlatformResourceNames(requiredString$1(value.installationSlug, "installationSlug"));
449
+ const resourceDefaults = createPlatformResourceNames(requiredString(value.installationSlug, "installationSlug"));
460
450
  const resources = {};
461
- for (const key of Object.keys(resourceDefaults)) resources[key] = requiredString$1(rawResources[key] ?? (key === "emailGatewayWorker" || key === "deploymentQueue" ? resourceDefaults[key] : void 0), `resources.${key}`);
451
+ for (const key of Object.keys(resourceDefaults)) resources[key] = requiredString(rawResources[key] ?? (key === "emailGatewayWorker" || key === "deploymentQueue" ? resourceDefaults[key] : void 0), `resources.${key}`);
462
452
  const readHostname = (key) => {
463
453
  const hostname = controlPlane[key];
464
- return hostname === null ? null : requiredString$1(hostname, `controlPlane.${key}`);
454
+ return hostname === null ? null : requiredString(hostname, `controlPlane.${key}`);
465
455
  };
466
456
  return createPlatformDeploymentManifest({
467
457
  ...value.schemaVersion === 4 ? { appAccess: value.appAccess } : {},
468
458
  application: {
469
- baseDomain: requiredString$1(application.baseDomain, "application.baseDomain"),
459
+ baseDomain: requiredString(application.baseDomain, "application.baseDomain"),
470
460
  dedicatedZone: application.dedicatedZone === true,
471
- zoneName: workersDev && application.zoneName === "" ? "" : requiredString$1(application.zoneName, "application.zoneName"),
461
+ zoneName: workersDev && application.zoneName === "" ? "" : requiredString(application.zoneName, "application.zoneName"),
472
462
  ...workersDev ? { workersDev } : {},
473
463
  ...typeof application.zoneId === "string" ? { zoneId: application.zoneId } : {}
474
464
  },
@@ -478,16 +468,16 @@ function parsePlatformDeploymentManifest(value) {
478
468
  ...authentication.accessProtection === true ? { accessProtection: true } : {}
479
469
  },
480
470
  capabilities,
481
- ...value.emailSharedZoneId !== void 0 ? { emailSharedZoneId: requiredString$1(value.emailSharedZoneId, "emailSharedZoneId") } : {},
482
- ...value.emailSenderDomain !== void 0 ? { emailSenderDomain: requiredString$1(value.emailSenderDomain, "emailSenderDomain") } : {},
471
+ ...value.emailSharedZoneId !== void 0 ? { emailSharedZoneId: requiredString(value.emailSharedZoneId, "emailSharedZoneId") } : {},
472
+ ...value.emailSenderDomain !== void 0 ? { emailSenderDomain: requiredString(value.emailSenderDomain, "emailSenderDomain") } : {},
483
473
  controlPlane: {
484
474
  apiHostname: readHostname("apiHostname"),
485
475
  dashboardHostname: readHostname("dashboardHostname"),
486
- ...controlPlane.dashboardUrl !== void 0 ? { dashboardUrl: requiredString$1(controlPlane.dashboardUrl, "controlPlane.dashboardUrl") } : {},
476
+ ...controlPlane.dashboardUrl !== void 0 ? { dashboardUrl: requiredString(controlPlane.dashboardUrl, "controlPlane.dashboardUrl") } : {},
487
477
  proxyHostname: readHostname("proxyHostname")
488
478
  },
489
- displayName: requiredString$1(value.displayName, "displayName"),
490
- installationSlug: requiredString$1(value.installationSlug, "installationSlug"),
479
+ displayName: requiredString(value.displayName, "displayName"),
480
+ installationSlug: requiredString(value.installationSlug, "installationSlug"),
491
481
  resources
492
482
  });
493
483
  }
@@ -609,13 +599,6 @@ const STATUS_TRANSITIONS = {
609
599
  "uninstalling"
610
600
  ]
611
601
  };
612
- function assertRecord(value, label) {
613
- if (!value || typeof value !== "object" || Array.isArray(value)) throw new Error(`${label} must be an object.`);
614
- }
615
- function requiredString(value, label) {
616
- if (typeof value !== "string" || value.trim() === "") throw new Error(`${label} must be a non-empty string.`);
617
- return value;
618
- }
619
602
  function isInstallationStatus(value) {
620
603
  return typeof value === "string" && Object.hasOwn(STATUS_TRANSITIONS, value);
621
604
  }
@@ -847,15 +830,14 @@ function parseAuthenticationResources(value) {
847
830
  return resources;
848
831
  }
849
832
  function parseUsageProtocolVersion(value) {
850
- if (value === void 0 || value === 0) return 0;
851
- if (value === 1) return 1;
852
- if (value === 2) return 2;
853
- throw new Error("usageProtocolVersion must be 0, 1, or 2.");
833
+ if (value === void 0) return 0;
834
+ if (!isUsageProtocolVersion(value)) throw new Error("usageProtocolVersion must be 0, 1, or 2.");
835
+ return value;
854
836
  }
855
837
  function parseSafetyProtocols(value) {
856
838
  if (value === void 0) return { sandboxDrain: 0 };
857
839
  assertRecord(value, "safetyProtocols");
858
- if (value.sandboxDrain !== 0 && value.sandboxDrain !== 1 && value.sandboxDrain !== 2 && value.sandboxDrain !== 3) throw new Error("safetyProtocols.sandboxDrain must be 0, 1, 2, or 3.");
840
+ if (!isSandboxDrainProtocol(value.sandboxDrain)) throw new Error("safetyProtocols.sandboxDrain must be 0, 1, 2, or 3.");
859
841
  return { sandboxDrain: value.sandboxDrain };
860
842
  }
861
843
  function parsePlatformRuntimeProvenance(value) {
@@ -865,7 +847,7 @@ function parsePlatformRuntimeProvenance(value) {
865
847
  const manifestSha256 = requiredString(value.manifestSha256, "runtime.manifestSha256");
866
848
  if (!/^[0-9a-f]{64}$/.test(manifestSha256)) throw new Error("runtime.manifestSha256 must be a SHA-256 digest.");
867
849
  const sourceRevision = value.sourceRevision === null || value.sourceRevision === void 0 ? null : requiredString(value.sourceRevision, "runtime.sourceRevision");
868
- if (sourceRevision !== null && (sourceRevision.length > 200 || !/^[A-Za-z0-9][A-Za-z0-9._/-]*$/.test(sourceRevision))) throw new Error("runtime.sourceRevision is invalid.");
850
+ if (sourceRevision !== null && !isSourceRevision(sourceRevision)) throw new Error("runtime.sourceRevision is invalid.");
869
851
  return {
870
852
  manifestSha256,
871
853
  source: value.source,
@@ -890,10 +872,14 @@ function readPlatformApplication(env) {
890
872
  zoneName: baseDomain,
891
873
  dedicatedZone: false
892
874
  };
875
+ return parsePlatformApplication(JSON.parse(env.PLATFORM_APPLICATION));
876
+ }
877
+ /** Applies the deployment manifest's application rules to a parsed value. */
878
+ function parsePlatformApplication(value) {
893
879
  return createPlatformDeploymentManifest({
894
880
  installationSlug: "runtime",
895
881
  displayName: "Runtime",
896
- application: JSON.parse(env.PLATFORM_APPLICATION)
882
+ application: value
897
883
  }).application;
898
884
  }
899
885
  function platformWorkersDevAliasKey(hostname) {
@@ -956,7 +942,11 @@ function normalizeOrigin(value, name) {
956
942
  } catch {
957
943
  throw new Error(`${name} must be an absolute URL.`);
958
944
  }
959
- if (!(url.protocol === "http:" && (url.hostname === "localhost" || url.hostname === "127.0.0.1" || url.hostname === "::1")) && url.protocol !== "https:" || url.username || url.password) throw new Error(`${name} must be a credential-free HTTPS URL.`);
945
+ if (!(url.protocol === "http:" && [
946
+ "localhost",
947
+ "127.0.0.1",
948
+ "[::1]"
949
+ ].includes(url.hostname)) && url.protocol !== "https:" || url.username || url.password) throw new Error(`${name} must be a credential-free HTTPS URL.`);
960
950
  if (url.pathname !== "" && url.pathname !== "/" || url.search || url.hash) throw new Error(`${name} must be an origin without a path, query, or fragment.`);
961
951
  return url.origin;
962
952
  }
@@ -964,7 +954,7 @@ function createPlatformDiscoveryDocument(input) {
964
954
  if (!input.displayName.trim()) throw new Error("displayName must not be empty.");
965
955
  if (!input.platformVersion.trim()) throw new Error("platformVersion must not be empty.");
966
956
  if (input.applicationRouting) {
967
- const application = readPlatformApplication({ PLATFORM_APPLICATION: JSON.stringify(input.applicationRouting) });
957
+ const application = parsePlatformApplication(input.applicationRouting);
968
958
  if (!application.workersDev || application.baseDomain !== input.applicationDomain || application.workersDev.installationId !== input.installationId) throw new Error("Application routing must match the discovery domain and installation identity.");
969
959
  }
970
960
  const usageProtocolVersion = parseUsageProtocolVersion(input.usageProtocolVersion);
@@ -990,13 +980,12 @@ function createPlatformDiscoveryDocument(input) {
990
980
  };
991
981
  }
992
982
  function parsePlatformDiscoveryDocument(value) {
993
- if (!value || typeof value !== "object" || Array.isArray(value)) throw new Error("Platform discovery document must be an object.");
994
- const document = value;
983
+ const document = record(value, "Platform discovery document");
995
984
  if (document.schemaVersion !== 1 && document.schemaVersion !== 2 && document.schemaVersion !== 3) throw new Error(`Unsupported platform discovery schema version: ${String(document.schemaVersion)}.`);
996
985
  const capabilities = document.capabilities;
997
986
  if (document.schemaVersion === 1 && document.applicationRouting !== void 0) throw new Error("Application routing requires discovery schema version 2.");
998
987
  if (document.schemaVersion === 2 && document.applicationRouting === void 0) throw new Error("Discovery schema version 2 requires application routing.");
999
- if (!capabilities || typeof capabilities !== "object" || Array.isArray(capabilities)) throw new Error("capabilities must be an object.");
988
+ assertRecord(capabilities, "capabilities");
1000
989
  const capabilityNames = [
1001
990
  "ai",
1002
991
  "customDomains",
@@ -1028,7 +1017,7 @@ function parsePlatformDiscoveryDocument(value) {
1028
1017
  return createPlatformDiscoveryDocument({
1029
1018
  apiUrl,
1030
1019
  applicationDomain: string("applicationDomain"),
1031
- ...document.applicationRouting !== void 0 ? { applicationRouting: readPlatformApplication({ PLATFORM_APPLICATION: JSON.stringify(document.applicationRouting) }) } : {},
1020
+ ...document.applicationRouting !== void 0 ? { applicationRouting: parsePlatformApplication(document.applicationRouting) } : {},
1032
1021
  authenticationProviders: providers,
1033
1022
  ...authentication ? { authentication } : {},
1034
1023
  capabilities: parsedCapabilities,
@@ -1041,8 +1030,7 @@ function parsePlatformDiscoveryDocument(value) {
1041
1030
  });
1042
1031
  }
1043
1032
  function parseAuthentication(value) {
1044
- if (!value || typeof value !== "object" || Array.isArray(value)) throw new Error("Authentication discovery must be an object.");
1045
- const authentication = value;
1033
+ const authentication = record(value, "Authentication discovery");
1046
1034
  if (!Array.isArray(authentication.methods) || authentication.methods.length > 32 || typeof authentication.protectedByAccess !== "boolean" || authentication.setupPending !== void 0 && typeof authentication.setupPending !== "boolean") throw new Error("Authentication discovery requires login methods and a protection flag.");
1047
1035
  const methods = authentication.methods.map(parsePlatformLoginDescriptor);
1048
1036
  if (new Set(methods.map((method) => method.id)).size !== methods.length) throw new Error("Authentication connection IDs must be unique.");
@@ -1277,7 +1265,6 @@ function createPlatformWorkerConfigs(input) {
1277
1265
  proxy,
1278
1266
  emailGateway: {
1279
1267
  ...common,
1280
- workers_dev: publicEndpoints,
1281
1268
  preview_urls: false,
1282
1269
  name: names.emailGatewayWorker,
1283
1270
  main: runtimeEntrypoints.emailGateway,
@@ -1,3 +1,4 @@
1
+ import { a as isSourceRevision, i as isSandboxDrainProtocol, o as isUsageProtocolVersion, r as isRecord } from "./validate-DbJR7Q0Z.mjs";
1
2
  import { createHash } from "node:crypto";
2
3
  import { readFileSync, realpathSync, statSync } from "node:fs";
3
4
  import { fileURLToPath } from "node:url";
@@ -105,26 +106,20 @@ function parsePlatformRuntimeManifest(value) {
105
106
  }
106
107
  function parseSafetyProtocols(value) {
107
108
  if (value === void 0) return { sandboxDrain: 0 };
108
- const protocols = record(value, "runtime manifest safetyProtocols");
109
- if (protocols.sandboxDrain !== 0 && protocols.sandboxDrain !== 1 && protocols.sandboxDrain !== 2 && protocols.sandboxDrain !== 3) throw new Error("runtime manifest safetyProtocols.sandboxDrain must be 0, 1, 2, or 3");
110
- return { sandboxDrain: protocols.sandboxDrain };
109
+ const { sandboxDrain } = record(value, "runtime manifest safetyProtocols");
110
+ if (!isSandboxDrainProtocol(sandboxDrain)) throw new Error("runtime manifest safetyProtocols.sandboxDrain must be 0, 1, 2, or 3");
111
+ return { sandboxDrain };
111
112
  }
112
113
  function usageProtocolVersion(value) {
113
- if (value === void 0 || value === 0) return 0;
114
- if (value === 1) return 1;
115
- if (value === 2) return 2;
116
- throw new Error("runtime manifest usageProtocolVersion must be 0, 1, or 2");
114
+ if (value === void 0) return 0;
115
+ if (!isUsageProtocolVersion(value)) throw new Error("runtime manifest usageProtocolVersion must be 0, 1, or 2");
116
+ return value;
117
117
  }
118
118
  function getPlatformRuntimeDirectory() {
119
119
  return join(dirname(fileURLToPath(import.meta.url)), "runtime");
120
120
  }
121
121
  function readPlatformRuntimeManifest(runtimeDirectory = getPlatformRuntimeDirectory()) {
122
- const path = join(runtimeDirectory, "manifest.json");
123
- try {
124
- return parsePlatformRuntimeManifest(JSON.parse(readFileSync(path, "utf8")));
125
- } catch (error) {
126
- throw new Error(`Void Platform deployment artifacts are missing or invalid at ${path}: ${error instanceof Error ? error.message : String(error)}`);
127
- }
122
+ return readRuntimeManifestFile(join(runtimeDirectory, "manifest.json")).manifest;
128
123
  }
129
124
  function resolvePlatformRuntime(customRuntimeDirectory, baseDirectory = process.cwd()) {
130
125
  const source = customRuntimeDirectory ? "custom" : "package";
@@ -136,22 +131,25 @@ function resolvePlatformRuntime(customRuntimeDirectory, baseDirectory = process.
136
131
  } catch (error) {
137
132
  throw new Error(`Void Platform runtime directory is unavailable at ${requestedDirectory}: ${error instanceof Error ? error.message : String(error)}`);
138
133
  }
139
- const manifestPath = join(directory, "manifest.json");
140
- let manifestContents;
141
- let manifest;
142
- try {
143
- manifestContents = readFileSync(manifestPath);
144
- manifest = parsePlatformRuntimeManifest(JSON.parse(manifestContents.toString("utf8")));
145
- } catch (error) {
146
- throw new Error(`Void Platform deployment artifacts are missing or invalid at ${manifestPath}: ${error instanceof Error ? error.message : String(error)}`);
147
- }
134
+ const { contents, manifest } = readRuntimeManifestFile(join(directory, "manifest.json"));
148
135
  return {
149
136
  directory,
150
137
  manifest,
151
- manifestSha256: createHash("sha256").update(manifestContents).digest("hex"),
138
+ manifestSha256: createHash("sha256").update(contents).digest("hex"),
152
139
  source
153
140
  };
154
141
  }
142
+ function readRuntimeManifestFile(path) {
143
+ try {
144
+ const contents = readFileSync(path);
145
+ return {
146
+ contents,
147
+ manifest: parsePlatformRuntimeManifest(JSON.parse(contents.toString("utf8")))
148
+ };
149
+ } catch (error) {
150
+ throw new Error(`Void Platform deployment artifacts are missing or invalid at ${path}: ${error instanceof Error ? error.message : String(error)}`);
151
+ }
152
+ }
155
153
  function parseArtifact(value, name) {
156
154
  const artifact = record(value, `runtime manifest artifact ${name}`);
157
155
  const path = nonemptyString(artifact.path, `runtime manifest artifact ${name} path`);
@@ -179,7 +177,7 @@ function parseMigration(value, position) {
179
177
  };
180
178
  }
181
179
  function record(value, name) {
182
- if (!value || typeof value !== "object" || Array.isArray(value)) throw new Error(`${name} must be an object`);
180
+ if (!isRecord(value)) throw new Error(`${name} must be an object`);
183
181
  return value;
184
182
  }
185
183
  function array(value, name) {
@@ -192,7 +190,7 @@ function nonemptyString(value, name) {
192
190
  }
193
191
  function sourceRevision(value) {
194
192
  const revision = nonemptyString(value, "runtime manifest sourceRevision");
195
- if (revision.length > 200 || !/^[A-Za-z0-9][A-Za-z0-9._/-]*$/.test(revision)) throw new Error("runtime manifest sourceRevision is invalid");
193
+ if (!isSourceRevision(revision)) throw new Error("runtime manifest sourceRevision is invalid");
196
194
  return revision;
197
195
  }
198
196
  function safeInteger(value, name) {
package/dist/plans.mjs CHANGED
@@ -1,3 +1,4 @@
1
+ import { n as isPrintableText, s as record } from "./validate-DbJR7Q0Z.mjs";
1
2
  //#region src/plans.ts
2
3
  const GB = 1073741824;
3
4
  const PLAN_LIMITS = {
@@ -119,15 +120,11 @@ function parsePlatformPlanId(value) {
119
120
  return value;
120
121
  }
121
122
  function parsePlanName(value) {
122
- if (typeof value !== "string" || !value.trim() || value.length > 80 || Array.from(value).some((character) => character.charCodeAt(0) < 32 || character.charCodeAt(0) === 127)) throw new Error("Plan names must contain 1 to 80 printable characters.");
123
+ if (!isPrintableText(value, 80)) throw new Error("Plan names must contain 1 to 80 printable characters.");
123
124
  return value.trim();
124
125
  }
125
- function object(value, label) {
126
- if (!value || typeof value !== "object" || Array.isArray(value)) throw new Error(label + " must be an object.");
127
- return value;
128
- }
129
126
  function parsePlanLimitsPatch(value) {
130
- const input = object(value, "Plan limits");
127
+ const input = record(value, "Plan limits");
131
128
  for (const [key, limit] of Object.entries(input)) {
132
129
  if (!PLAN_EDITABLE_LIMIT_KEYS.includes(key)) throw new Error("Unknown or unenforced plan limit: " + key + ".");
133
130
  if (!Number.isSafeInteger(limit) || limit < 0) throw new Error(key + " must be a nonnegative safe integer; 0 means unlimited.");
@@ -146,18 +143,18 @@ function parseBuildInstanceType(value) {
146
143
  }
147
144
  /** Strict saved-state validation: invalid configuration must not silently lift quotas. */
148
145
  function parsePlatformPlanCatalog(value) {
149
- const input = object(value, "Plan catalog");
146
+ const input = record(value, "Plan catalog");
150
147
  if (!Number.isSafeInteger(input.revision) || input.revision < 0) throw new Error("Invalid plan catalog revision.");
151
148
  if (!Array.isArray(input.plans) || input.plans.length === 0 || input.plans.length > 100) throw new Error("A plan catalog must contain between 1 and 100 plans.");
152
149
  const ids = /* @__PURE__ */ new Set();
153
150
  const plans = input.plans.map((value) => {
154
- const plan = object(value, "Plan");
151
+ const plan = record(value, "Plan");
155
152
  const id = parsePlatformPlanId(plan.id);
156
153
  if (ids.has(id)) throw new Error("Duplicate plan ID: " + id + ".");
157
154
  ids.add(id);
158
155
  if (typeof plan.archived !== "boolean") throw new Error("archived must be a boolean.");
159
156
  if (typeof plan.allowShortSlugs !== "boolean") throw new Error("allowShortSlugs must be a boolean.");
160
- const limits = object(plan.limits, "Plan limits");
157
+ const limits = record(plan.limits, "Plan limits");
161
158
  const keys = Object.keys(PLAN_LIMITS.free);
162
159
  if (Object.keys(limits).length !== keys.length || keys.some((key) => !Object.hasOwn(limits, key))) throw new Error("Plan limits must contain all supported fields.");
163
160
  validatePlanLimits(limits);
@@ -174,13 +171,13 @@ function parsePlatformPlanCatalog(value) {
174
171
  if (!plans.some((plan) => plan.id === defaultPlanId && !plan.archived)) throw new Error("The default plan must exist and be active.");
175
172
  let reconciliation = null;
176
173
  if (input.reconciliation !== null) {
177
- const operation = object(input.reconciliation, "Plan reconciliation");
174
+ const operation = record(input.reconciliation, "Plan reconciliation");
178
175
  if (operation.revision !== input.revision || typeof operation.complete !== "boolean" || !(operation.cursor === null || typeof operation.cursor === "string") || !Array.isArray(operation.planIds) || operation.planIds.length > 100) throw new Error("Invalid plan reconciliation state.");
179
176
  const planIds = operation.planIds.map(parsePlatformPlanId);
180
177
  if (planIds.some((id) => !ids.has(id))) throw new Error("A reconciliation plan is missing.");
181
178
  let error;
182
179
  if (operation.error !== void 0) {
183
- const failure = object(operation.error, "Plan reconciliation failure");
180
+ const failure = record(operation.error, "Plan reconciliation failure");
184
181
  if (typeof failure.accountId !== "string" || typeof failure.message !== "string" || failure.message.length > 1e3) throw new Error("Invalid plan reconciliation failure.");
185
182
  error = {
186
183
  accountId: failure.accountId,