@absolutejs/absolute 0.20.0-beta.30 → 0.20.0-beta.31

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.
@@ -433,6 +433,210 @@ var installAbsoluteMobileStaticDocument = async (manifest, page, localUrl) => {
433
433
  await ready;
434
434
  };
435
435
 
436
+ // node_modules/@absolutejs/http/dist/index.js
437
+ class AbsoluteHttpError extends Error {
438
+ code;
439
+ cause;
440
+ status;
441
+ url;
442
+ constructor(code, message, options = {}) {
443
+ super(message);
444
+ this.name = "AbsoluteHttpError";
445
+ this.code = code;
446
+ this.cause = options.cause;
447
+ this.status = options.status;
448
+ this.url = options.url;
449
+ }
450
+ }
451
+ var loopbackHosts = new Set(["127.0.0.1", "[::1]", "localhost"]);
452
+ var normalizeAbsoluteHttpOrigin = (value) => {
453
+ let url;
454
+ try {
455
+ url = new URL(value);
456
+ } catch (cause) {
457
+ throw new AbsoluteHttpError("origin", "HTTP origin is invalid.", {
458
+ cause
459
+ });
460
+ }
461
+ const loopback = url.protocol === "http:" && loopbackHosts.has(url.hostname);
462
+ if (url.protocol !== "https:" && !loopback)
463
+ throw new AbsoluteHttpError("origin", "HTTP origin must use HTTPS outside loopback development.");
464
+ if (url.username || url.password || url.pathname !== "/" || url.search || url.hash)
465
+ throw new AbsoluteHttpError("origin", "HTTP origin cannot contain credentials, a path, query, or fragment.");
466
+ return url.origin;
467
+ };
468
+ var resolveAbsoluteHttpUrl = (target, origin) => {
469
+ let url;
470
+ try {
471
+ url = new URL(String(target), `${origin}/`);
472
+ } catch (cause) {
473
+ throw new AbsoluteHttpError("origin", "HTTP request URL is invalid.", {
474
+ cause
475
+ });
476
+ }
477
+ if (url.username || url.password)
478
+ throw new AbsoluteHttpError("origin", "HTTP request URLs cannot contain credentials.");
479
+ if (url.origin !== origin)
480
+ throw new AbsoluteHttpError("origin", "Absolute HTTP refused a request outside the configured application origin.", { url: url.href });
481
+ url.hash = "";
482
+ return url;
483
+ };
484
+ var createAbsoluteHttpTransport = ({
485
+ fetch: fetchImpl = globalThis.fetch,
486
+ origin,
487
+ runtime
488
+ }) => ({
489
+ fetch: fetchImpl,
490
+ origin: normalizeAbsoluteHttpOrigin(origin),
491
+ runtime
492
+ });
493
+ var createWebHttpTransport = (options = {}) => {
494
+ const origin = options.origin ?? globalThis.location?.origin;
495
+ if (!origin)
496
+ throw new TypeError("The web HTTP transport requires a browser origin or explicit origin.");
497
+ return createAbsoluteHttpTransport({
498
+ ...options.fetch ? { fetch: options.fetch } : {},
499
+ origin,
500
+ runtime: "web"
501
+ });
502
+ };
503
+ var RUNTIME_REGISTRY = Symbol.for("@absolutejs/http/runtime");
504
+ var registryHost = globalThis;
505
+ var isRuntimeRegistry = (value) => typeof value === "object" && value !== null && Array.isArray(Reflect.get(value, "installations"));
506
+ var runtimeRegistry = (() => {
507
+ const existing = registryHost[RUNTIME_REGISTRY];
508
+ if (isRuntimeRegistry(existing))
509
+ return existing;
510
+ const created = { installations: [] };
511
+ Object.defineProperty(registryHost, RUNTIME_REGISTRY, {
512
+ configurable: false,
513
+ enumerable: false,
514
+ value: created,
515
+ writable: false
516
+ });
517
+ return created;
518
+ })();
519
+ var fallbackTransport = () => {
520
+ if (typeof location !== "undefined" && location.origin)
521
+ return createWebHttpTransport();
522
+ throw new AbsoluteHttpError("not-configured", "Absolute HTTP requires a request-scoped SSR transport outside a browser.");
523
+ };
524
+ var getAbsoluteHttpTransport = () => runtimeRegistry.installations.at(-1)?.transport ?? (runtimeRegistry.fallback ??= fallbackTransport());
525
+ var installAbsoluteHttpTransport = (transport) => {
526
+ const installation = { transport };
527
+ runtimeRegistry.installations.push(installation);
528
+ return () => {
529
+ const index = runtimeRegistry.installations.indexOf(installation);
530
+ if (index >= 0)
531
+ runtimeRegistry.installations.splice(index, 1);
532
+ };
533
+ };
534
+ var forbiddenCredentialHeaders = new Set([
535
+ "authorization",
536
+ "cookie",
537
+ "proxy-authorization"
538
+ ]);
539
+ var transportFor = (configured) => configured ?? getAbsoluteHttpTransport();
540
+ var safeHeaders = (input) => {
541
+ const headers = new Headers(input);
542
+ for (const name of forbiddenCredentialHeaders) {
543
+ if (headers.has(name))
544
+ throw new AbsoluteHttpError("origin", `Absolute HTTP owns the ${name} credential header for trusted transports.`);
545
+ }
546
+ return headers;
547
+ };
548
+ var requestFor = (target, options, transport) => {
549
+ const source = target instanceof Request ? target : undefined;
550
+ const requestedUrl = source ? source.url : target;
551
+ const url = resolveAbsoluteHttpUrl(requestedUrl, transport.origin);
552
+ const headers = safeHeaders(options?.headers ?? source?.headers);
553
+ return new Request(source ?? url, {
554
+ ...options,
555
+ credentials: transport.runtime === "web" ? "same-origin" : "omit",
556
+ headers,
557
+ redirect: "error"
558
+ });
559
+ };
560
+ var normalizeFetchError = (caught, url) => {
561
+ if (caught instanceof AbsoluteHttpError)
562
+ return caught;
563
+ if (caught instanceof DOMException && (caught.name === "AbortError" || caught.name === "TimeoutError"))
564
+ return new AbsoluteHttpError("aborted", "HTTP request was aborted.", {
565
+ cause: caught,
566
+ url
567
+ });
568
+ return new AbsoluteHttpError("network", "HTTP request failed.", {
569
+ cause: caught,
570
+ url
571
+ });
572
+ };
573
+ var requireOk = (response) => {
574
+ if (!response.ok)
575
+ throw new AbsoluteHttpError("http", `HTTP request failed with status ${response.status}.`, { status: response.status, url: response.url });
576
+ return response;
577
+ };
578
+ var parseJson = async (response) => {
579
+ const text = await response.text();
580
+ if (text === "")
581
+ return;
582
+ try {
583
+ return JSON.parse(text);
584
+ } catch (cause) {
585
+ throw new AbsoluteHttpError("response", "HTTP response is not valid JSON.", {
586
+ cause,
587
+ status: response.status,
588
+ url: response.url
589
+ });
590
+ }
591
+ };
592
+ var jsonOptions = (method, body, options) => {
593
+ const headers = new Headers(options?.headers);
594
+ if (body !== undefined && !headers.has("content-type"))
595
+ headers.set("content-type", "application/json");
596
+ let encoded;
597
+ try {
598
+ encoded = body === undefined ? undefined : JSON.stringify(body);
599
+ } catch (cause) {
600
+ throw new AbsoluteHttpError("body", "HTTP body is not JSON serializable.", {
601
+ cause
602
+ });
603
+ }
604
+ return encoded === undefined ? { ...options, headers, method } : { ...options, body: encoded, headers, method };
605
+ };
606
+ var createAbsoluteHttpClient = (options = {}) => {
607
+ const fetchTrusted = async (input, init) => {
608
+ const transport = transportFor(options.transport);
609
+ const request2 = requestFor(input, init, transport);
610
+ try {
611
+ return await transport.fetch(request2);
612
+ } catch (caught) {
613
+ throw normalizeFetchError(caught, request2.url);
614
+ }
615
+ };
616
+ const request = (target, requestOptions) => fetchTrusted(target, requestOptions);
617
+ const json = async (target, requestOptions) => parseJson(requireOk(await request(target, requestOptions)));
618
+ const jsonMethod = (method, target, body, requestOptions) => json(target, jsonOptions(method, body, requestOptions));
619
+ return {
620
+ delete: (target, requestOptions) => {
621
+ const { body, ...optionsWithoutBody } = requestOptions ?? {};
622
+ return jsonMethod("DELETE", target, body, optionsWithoutBody);
623
+ },
624
+ fetch: fetchTrusted,
625
+ get: (target, requestOptions) => json(target, { ...requestOptions, method: "GET" }),
626
+ json,
627
+ origin: () => transportFor(options.transport).origin,
628
+ patch: (target, body, requestOptions) => jsonMethod("PATCH", target, body, requestOptions),
629
+ post: (target, body, requestOptions) => jsonMethod("POST", target, body, requestOptions),
630
+ put: (target, body, requestOptions) => jsonMethod("PUT", target, body, requestOptions),
631
+ request,
632
+ text: async (target, requestOptions) => requireOk(await request(target, requestOptions)).text()
633
+ };
634
+ };
635
+ var http = createAbsoluteHttpClient();
636
+
637
+ // src/mobile/shellHttp.ts
638
+ var installAbsoluteMobileShellHttp = (origin, fetch2 = globalThis.fetch) => installAbsoluteHttpTransport(createAbsoluteHttpTransport({ fetch: fetch2, origin, runtime: "native" }));
639
+
436
640
  // src/mobile/shellBootstrap.ts
437
641
  var MANIFEST_PATH = "./absolute-mobile-manifest.json";
438
642
  var STATUS_ID = "absolute-mobile-status";
@@ -574,6 +778,7 @@ var startAbsoluteMobileShell = async (options = {}) => {
574
778
  const auth = manifest.auth && options.createAuth ? await options.createAuth(manifest.auth, {
575
779
  beforeSignOut: options.beforeSignOut
576
780
  }) : undefined;
781
+ installAbsoluteMobileShellHttp(manifest.productionOrigin, auth?.fetch ?? globalThis.fetch);
577
782
  if (auth)
578
783
  options.connectPush?.(auth);
579
784
  if (auth && manifest.sync?.socketTickets)
@@ -28,4 +28,5 @@ export * from './releaseArtifact';
28
28
  export * from './releasePublisher';
29
29
  export * from './routeMetadataTransform';
30
30
  export * from './routeMatcher';
31
+ export * from './shellHttp';
31
32
  export * from './transport';
@@ -0,0 +1,2 @@
1
+ import { type AbsoluteHttpFetch } from '@absolutejs/http';
2
+ export declare const installAbsoluteMobileShellHttp: (origin: string, fetch?: AbsoluteHttpFetch) => () => void;
package/package.json CHANGED
@@ -10,6 +10,7 @@
10
10
  "@absolutejs/auth": "0.75.0",
11
11
  "@absolutejs/devices": "0.7.0",
12
12
  "@absolutejs/devices-capacitor": "0.8.0",
13
+ "@absolutejs/http": "0.0.1",
13
14
  "@absolutejs/pwa": "0.14.0",
14
15
  "@capacitor/browser": "8.0.4",
15
16
  "@capacitor/keyboard": "8.0.5",
@@ -503,7 +504,7 @@
503
504
  ]
504
505
  }
505
506
  },
506
- "version": "0.20.0-beta.30",
507
+ "version": "0.20.0-beta.31",
507
508
  "workspaces": [
508
509
  "tests/fixtures/*",
509
510
  "tests/fixtures/_packages/*"