@void/edge 1.3.0 → 1.5.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.d.mts CHANGED
@@ -1,5 +1,4 @@
1
1
  import { AssetConfig, AssetConfig as AssetConfig$1, HeaderRule, HeaderRule as HeaderRule$1, RedirectRule, RedirectRule as RedirectRule$1 } from "@void/deploy-core";
2
- //#region src/access.d.ts
3
2
  type ProjectZeroTrustRouting = Readonly<{
4
3
  teamDomain: string;
5
4
  audiences: ReadonlyArray<Readonly<{
@@ -7,8 +6,8 @@ type ProjectZeroTrustRouting = Readonly<{
7
6
  audience: string;
8
7
  }>>;
9
8
  }>;
10
- //#endregion
11
- //#region src/headers.d.ts
9
+ /** Upgrade public HTTP requests without involving assets or application code. */
10
+ export declare function redirectToHttps(request: Request): Response | undefined;
12
11
  type HeaderRulePolicy = Readonly<{
13
12
  /**
14
13
  * Protect unrelated tenants that share one registrable domain. Direct
@@ -54,8 +53,6 @@ export declare function sanitizeClearSiteData(value: string): string | null;
54
53
  * Returns the original response unchanged when no rules or no matches.
55
54
  */
56
55
  export declare function applyHeaderRules(response: Response, pathname: string, rules?: ReadonlyArray<HeaderRule$1>, policy?: HeaderRulePolicy): Response;
57
- //#endregion
58
- //#region src/pattern.d.ts
59
56
  type CompiledPattern = Readonly<{
60
57
  /**
61
58
  * @deprecated Built on first read for older callers; Void does not use it.
@@ -108,8 +105,6 @@ export declare function matchSegmentPattern(pattern: string, pathname: string):
108
105
  * because `compilePattern` captures anonymous `*` as `splat`.
109
106
  */
110
107
  export declare function substituteParams(destination: string, params: Record<string, string>): string;
111
- //#endregion
112
- //#region src/routing-rules.d.ts
113
108
  type RoutingRuleResult = {
114
109
  type: "redirect";
115
110
  destination: string;
@@ -147,8 +142,6 @@ export declare function applyRoutingRules(pathname: string, rules?: ReadonlyArra
147
142
  * rather than `/new#faq?utm=x` (which browsers treat as fragment text).
148
143
  */
149
144
  export declare function mergeQueryIntoLocation(destination: string, requestSearch: string): string;
150
- //#endregion
151
- //#region src/runtime.d.ts
152
145
  type EdgeAssetFetcher = Readonly<{
153
146
  fetch(request: Request): Promise<Response>;
154
147
  }>;
@@ -156,6 +149,7 @@ type StaticEdgeEnv = Readonly<{
156
149
  ASSETS: EdgeAssetFetcher;
157
150
  }>;
158
151
  type StaticEdgeConfig = Readonly<{
152
+ alwaysUseHttps?: boolean;
159
153
  /** Optional native Worker self-metadata used to identify the served version. */
160
154
  versionMetadataBinding?: string;
161
155
  /**
@@ -178,8 +172,6 @@ type StaticEdgeHandler = Readonly<{
178
172
  * miss, and response-header rules apply to the effective pathname.
179
173
  */
180
174
  export declare function createStaticEdgeHandler(config: StaticEdgeConfig): StaticEdgeHandler;
181
- //#endregion
182
- //#region src/static.d.ts
183
175
  type ResolvedAsset = Readonly<{
184
176
  path: string;
185
177
  hash: string;
@@ -242,8 +234,6 @@ export declare function getContentType(path: string): string;
242
234
  * Any other stored value is authoritative and honored as-is.
243
235
  */
244
236
  export declare function resolveAssetContentType(stored: string | null | undefined, path: string): string | undefined;
245
- //#endregion
246
- //#region src/limits.d.ts
247
237
  /** Shared between the SDK, edge admission and Pages clients. */
248
238
  type UsageLimitData = {
249
239
  code: "usage_limit";
@@ -254,5 +244,4 @@ type UsageLimitData = {
254
244
  };
255
245
  export declare function readUsageLimit(value: unknown): UsageLimitData | null;
256
246
  export declare function usageLimitResponse(limit: UsageLimitData): Response;
257
- //#endregion
258
247
  export type { AssetConfig, ClearSiteDataMember, CompiledPattern, EdgeAssetFetcher, HeaderRule, HeaderRulePolicy, ProjectZeroTrustRouting, RedirectRule, ResolvedAsset, RoutingRuleResult, StaticEdgeConfig, StaticEdgeEnv, StaticEdgeHandler, UsageLimitData };
package/dist/index.mjs CHANGED
@@ -1,4 +1,21 @@
1
- //#region src/pattern.ts
1
+ // src/https.ts
2
+ /** Upgrade public HTTP requests without involving assets or application code. */
3
+ function redirectToHttps(request) {
4
+ const url = new URL(request.url);
5
+ if (url.protocol !== "http:" || url.hostname === "localhost" || url.hostname.endsWith(".localhost") || isIpv4Loopback(url.hostname) || url.hostname === "[::1]" || url.pathname.startsWith("/.well-known/acme-challenge/") || url.pathname.startsWith("/.well-known/pki-validation/")) return;
6
+ url.protocol = "https:";
7
+ url.port = "";
8
+ return Response.redirect(url.href, 308);
9
+ }
10
+ /**
11
+ * `URL` already rewrites every IPv4 form (`127.1`, `0x7f.0.0.1`) to four
12
+ * decimal parts and rejects parts above 255, so only the shape is checked.
13
+ */
14
+ function isIpv4Loopback(hostname) {
15
+ const parts = hostname.split(".");
16
+ return parts.length === 4 && parts[0] === "127" && parts.every((part) => part !== "" && [...part].every((char) => char >= "0" && char <= "9"));
17
+ }
18
+ // src/pattern.ts
2
19
  /**
3
20
  * Path-pattern matchers shared by routing, header, and revalidate rules.
4
21
  *
@@ -366,8 +383,7 @@ function substituteParams(destination, params) {
366
383
  if (/^[/\\]{2}/.test(result) && !/^[/\\]{2}/.test(destination)) return "/" + result.replace(/^[/\\]+/, "");
367
384
  return result;
368
385
  }
369
- //#endregion
370
- //#region src/headers.ts
386
+ // src/headers.ts
371
387
  /**
372
388
  * Headers that rules may never set on a shared domain. void.app is not on the
373
389
  * Public Suffix List, so a `Set-Cookie` with `Domain=.void.app` reaches every
@@ -478,8 +494,7 @@ function applyHeaderRules(response, pathname, rules, policy) {
478
494
  }
479
495
  return newResponse;
480
496
  }
481
- //#endregion
482
- //#region src/routing-rules.ts
497
+ // src/routing-rules.ts
483
498
  /**
484
499
  * Check routing rules (redirects + rewrites) against a request pathname.
485
500
  *
@@ -545,8 +560,7 @@ function mergeQueryIntoLocation(destination, requestSearch) {
545
560
  for (const [key, value] of reqParams) if (!destParams.has(key)) destParams.append(key, value);
546
561
  return base.slice(0, destQueryIdx) + "?" + destParams.toString() + fragment;
547
562
  }
548
- //#endregion
549
- //#region src/runtime.ts
563
+ // src/runtime.ts
550
564
  /**
551
565
  * Create the thin Worker used by direct static, SPA, and SSG deployments.
552
566
  * Routing semantics intentionally match the hosted dispatch Worker: redirects
@@ -564,6 +578,10 @@ function createStaticEdgeHandler(config) {
564
578
  versionId: metadata?.id
565
579
  }, { headers: { "cache-control": "no-store" } });
566
580
  }
581
+ if (config.alwaysUseHttps) {
582
+ const redirect = redirectToHttps(request);
583
+ if (redirect) return redirect;
584
+ }
567
585
  let effectiveUrl = new URL(originalUrl);
568
586
  let effectiveRequest = request;
569
587
  const route = applyRoutingRules(effectiveUrl.pathname, config.redirectRules, effectiveUrl.hostname);
@@ -599,8 +617,7 @@ function rewriteRequest(request, url, originalUrl) {
599
617
  rewritten.headers.set("X-Void-Original-URL", originalUrl);
600
618
  return rewritten;
601
619
  }
602
- //#endregion
603
- //#region src/static.ts
620
+ // src/static.ts
604
621
  /**
605
622
  * Percent-decode a request pathname for a manifest lookup, honoring required
606
623
  * URL encodings and encoded square brackets. Returns the raw value unchanged
@@ -830,8 +847,7 @@ function resolveAssetContentType(stored, path) {
830
847
  if (!stored || stored === "application/octet-stream") return getContentType(path);
831
848
  return stored;
832
849
  }
833
- //#endregion
834
- //#region src/limits.ts
850
+ // src/limits.ts
835
851
  function readUsageLimit(value) {
836
852
  if (!value || typeof value !== "object") return null;
837
853
  const v = value;
@@ -863,5 +879,4 @@ function usageLimitResponse(limit) {
863
879
  headers
864
880
  });
865
881
  }
866
- //#endregion
867
- export { applyHeaderRules, applyRoutingRules, compilePattern, createStaticEdgeHandler, getContentType, matchLiteralPattern, matchPattern, matchPatternCaptures, matchSegmentPattern, mergeQueryIntoLocation, parseClearSiteData, readUsageLimit, resolveAssetContentType, resolveStaticPath, safeDecodePathname, sanitizeClearSiteData, substituteParams, usageLimitResponse };
882
+ export { applyHeaderRules, applyRoutingRules, compilePattern, createStaticEdgeHandler, getContentType, matchLiteralPattern, matchPattern, matchPatternCaptures, matchSegmentPattern, mergeQueryIntoLocation, parseClearSiteData, readUsageLimit, redirectToHttps, resolveAssetContentType, resolveStaticPath, safeDecodePathname, sanitizeClearSiteData, substituteParams, usageLimitResponse };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@void/edge",
3
- "version": "1.3.0",
3
+ "version": "1.5.0",
4
4
  "description": "Routing, headers, and static asset helpers for Void runtimes.",
5
5
  "homepage": "https://void.cloud",
6
6
  "bugs": {
@@ -26,12 +26,12 @@
26
26
  "access": "public"
27
27
  },
28
28
  "dependencies": {
29
- "@void/deploy-core": "1.3.0"
29
+ "@void/deploy-core": "1.5.0"
30
30
  },
31
31
  "devDependencies": {
32
- "@cloudflare/workers-types": "^5.20261019.1",
32
+ "@cloudflare/workers-types": "^5.20261102.1",
33
33
  "typescript": "7.0.2",
34
- "vite-plus": "1.3.0"
34
+ "vite-plus": "1.4.0"
35
35
  },
36
36
  "scripts": {
37
37
  "build": "vp pack",