@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 +1 -1
- package/dist/index.mjs +45 -58
- package/dist/installer.mjs +23 -25
- package/dist/plans.mjs +8 -11
- package/dist/runtime/api/assets/admin/client.js +22 -22
- package/dist/runtime/api/assets/admin/style.css +1 -1
- package/dist/runtime/api/index.js +268 -261
- package/dist/runtime/dispatch/index.js +7 -7
- package/dist/runtime/drizzle/0059_oauth_clients.sql +44 -0
- package/dist/runtime/drizzle/compatibility.json +4 -0
- package/dist/runtime/drizzle/meta/_journal.json +7 -0
- package/dist/runtime/emailGateway/index.js +5 -5
- package/dist/runtime/manifest.json +26 -16
- package/dist/runtime/proxy/index.js +5 -5
- package/dist/validate-DbJR7Q0Z.mjs +30 -0
- package/package.json +1 -1
package/README.md
CHANGED
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 (
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
423
|
+
assertRecord(application.workersDev, "application.workersDev");
|
|
434
424
|
workersDev = {
|
|
435
|
-
subdomain: requiredString
|
|
436
|
-
installationId: requiredString
|
|
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
|
|
440
|
-
assertRecord
|
|
441
|
-
assertRecord
|
|
442
|
-
assertRecord
|
|
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
|
|
449
|
+
const resourceDefaults = createPlatformResourceNames(requiredString(value.installationSlug, "installationSlug"));
|
|
460
450
|
const resources = {};
|
|
461
|
-
for (const key of Object.keys(resourceDefaults)) resources[key] = requiredString
|
|
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
|
|
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
|
|
459
|
+
baseDomain: requiredString(application.baseDomain, "application.baseDomain"),
|
|
470
460
|
dedicatedZone: application.dedicatedZone === true,
|
|
471
|
-
zoneName: workersDev && application.zoneName === "" ? "" : requiredString
|
|
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
|
|
482
|
-
...value.emailSenderDomain !== void 0 ? { emailSenderDomain: requiredString
|
|
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
|
|
476
|
+
...controlPlane.dashboardUrl !== void 0 ? { dashboardUrl: requiredString(controlPlane.dashboardUrl, "controlPlane.dashboardUrl") } : {},
|
|
487
477
|
proxyHostname: readHostname("proxyHostname")
|
|
488
478
|
},
|
|
489
|
-
displayName: requiredString
|
|
490
|
-
installationSlug: requiredString
|
|
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
|
|
851
|
-
if (value
|
|
852
|
-
|
|
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
|
|
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
|
|
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:
|
|
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:" &&
|
|
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 =
|
|
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
|
-
|
|
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
|
-
|
|
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:
|
|
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
|
-
|
|
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,
|
package/dist/installer.mjs
CHANGED
|
@@ -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
|
|
109
|
-
if (
|
|
110
|
-
return { 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
|
|
114
|
-
if (value
|
|
115
|
-
|
|
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
|
-
|
|
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
|
|
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(
|
|
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 (!
|
|
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 (
|
|
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 (
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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,
|