@mercuryworkshop/scramjet 1.0.1 → 1.1.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.
Files changed (59) hide show
  1. package/LICENSE +3 -3
  2. package/README.md +89 -21
  3. package/dist/scramjet.all.js +196 -0
  4. package/dist/scramjet.all.js.map +1 -0
  5. package/dist/scramjet.bundle.js +196 -7
  6. package/dist/scramjet.bundle.js.map +1 -7
  7. package/dist/scramjet.sync.js +2 -0
  8. package/dist/scramjet.sync.js.map +1 -0
  9. package/dist/scramjet.wasm.wasm +0 -0
  10. package/dist/types/client/client.d.ts +78 -0
  11. package/dist/types/client/entry.d.ts +8 -0
  12. package/dist/types/client/events.d.ts +66 -0
  13. package/dist/types/client/helpers.d.ts +1 -0
  14. package/dist/types/client/index.d.ts +8 -0
  15. package/dist/types/client/location.d.ts +2 -0
  16. package/dist/types/client/shared/eval.d.ts +3 -0
  17. package/dist/types/client/shared/sourcemaps.d.ts +19 -0
  18. package/dist/types/client/shared/wrap.d.ts +4 -0
  19. package/dist/types/client/singletonbox.d.ts +12 -0
  20. package/dist/types/client/swruntime.d.ts +40 -0
  21. package/dist/types/controller/controller.d.ts +16 -0
  22. package/dist/types/controller/frame.d.ts +103 -0
  23. package/dist/types/controller/index.d.ts +2 -0
  24. package/dist/types/entry.d.ts +160 -0
  25. package/dist/types/index.d.ts +8 -0
  26. package/dist/types/shared/cookie.d.ts +18 -0
  27. package/dist/types/shared/headers.d.ts +4 -0
  28. package/dist/types/shared/htmlRules.d.ts +6 -0
  29. package/dist/types/shared/index.d.ts +12 -0
  30. package/dist/types/shared/rewriters/css.d.ts +3 -0
  31. package/dist/types/shared/rewriters/headers.d.ts +18 -0
  32. package/dist/types/shared/rewriters/html.d.ts +6 -0
  33. package/dist/types/shared/rewriters/index.d.ts +7 -0
  34. package/dist/types/shared/rewriters/js.d.ts +10 -0
  35. package/dist/types/shared/rewriters/url.d.ts +10 -0
  36. package/dist/types/shared/rewriters/wasm.d.ts +7 -0
  37. package/dist/types/shared/rewriters/worker.d.ts +2 -0
  38. package/dist/types/shared/security/forceReferrer.d.ts +49 -0
  39. package/dist/types/shared/security/index.d.ts +2 -0
  40. package/dist/types/shared/security/siteTests.d.ts +33 -0
  41. package/dist/types/symbols.d.ts +7 -0
  42. package/dist/types/types.d.ts +135 -0
  43. package/dist/types/worker/error.d.ts +2 -0
  44. package/dist/types/worker/fakesw.d.ts +12 -0
  45. package/dist/types/worker/fetch.d.ts +26 -0
  46. package/dist/types/worker/index.d.ts +143 -0
  47. package/lib/index.cjs +7 -0
  48. package/lib/index.d.ts +8 -3
  49. package/lib/noop.js +0 -0
  50. package/package.json +101 -34
  51. package/dist/scramjet.client.js +0 -1
  52. package/dist/scramjet.client.js.map +0 -7
  53. package/dist/scramjet.codecs.js +0 -3
  54. package/dist/scramjet.codecs.js.map +0 -7
  55. package/dist/scramjet.config.js +0 -1
  56. package/dist/scramjet.config.js.map +0 -7
  57. package/dist/scramjet.worker.js +0 -42
  58. package/dist/scramjet.worker.js.map +0 -7
  59. package/lib/index.js +0 -5
@@ -0,0 +1,10 @@
1
+ export type URLMeta = {
2
+ origin: URL;
3
+ base: URL;
4
+ topFrameName?: string;
5
+ parentFrameName?: string;
6
+ };
7
+ export declare function rewriteBlob(url: string, meta: URLMeta): string;
8
+ export declare function unrewriteBlob(url: string): string;
9
+ export declare function rewriteUrl(url: string | URL, meta: URLMeta): string;
10
+ export declare function unrewriteUrl(url: string | URL): string;
@@ -0,0 +1,7 @@
1
+ import { Rewriter } from "../../../rewriter/wasm/out/wasm.js";
2
+ import type { JsRewriterOutput } from "../../../rewriter/wasm/out/wasm.js";
3
+ export type { JsRewriterOutput, Rewriter };
4
+ import { URLMeta } from "./url";
5
+ export declare function asyncSetWasm(): Promise<void>;
6
+ export declare const textDecoder: TextDecoder;
7
+ export declare function getRewriter(meta: URLMeta): [Rewriter, () => void];
@@ -0,0 +1,2 @@
1
+ import { URLMeta } from "./url";
2
+ export declare function rewriteWorkers(js: string | Uint8Array, type: string, url: string, meta: URLMeta): string;
@@ -0,0 +1,49 @@
1
+ import { type ReferrerPolicyData } from "../../types";
2
+ /**
3
+ * Initialize tracking for a new request that might redirect
4
+ *
5
+ * @param requestUrl URL of the request being made
6
+ * @param referrer Referrer URL of the request, or `null`
7
+ * @param initialSite Initial Sec-Fetch-Site directive
8
+ */
9
+ export declare function initializeTracker(requestUrl: string, referrer: string | null, initialSite: string): Promise<void>;
10
+ /**
11
+ * Update tracker when a redirect is encountered
12
+ *
13
+ * @param originalUrl URL that is redirecting
14
+ * @param redirectUrl URL being redirected to
15
+ * @param newReferrerPolicy Referrer Policy from the redirect response
16
+ */
17
+ export declare function updateTracker(originalUrl: string, redirectUrl: string, newReferrerPolicy?: string): Promise<void>;
18
+ /**
19
+ * Get most restrictive site value for a request
20
+ *
21
+ * @param requestUrl The URL of the current request
22
+ * @param currentSite The current `Sec-Fetch-Site` directive for this request
23
+ * @returns Most restrictive `Sec-Fetch-Site` directive from the redirect chain
24
+ */
25
+ export declare function getMostRestrictiveSite(requestUrl: string, currentSite: string): Promise<string>;
26
+ /**
27
+ * Clean up tracker after request completes
28
+ * @param requestUrl URL of the completed request
29
+ */
30
+ export declare function cleanTracker(requestUrl: string): Promise<void>;
31
+ /**
32
+ * Clean up expired trackers
33
+ */
34
+ export declare function cleanExpiredTrackers(): Promise<void>;
35
+ /**
36
+ * Store referrer policy for a URL
37
+ *
38
+ * @param url URL to store the policy for
39
+ * @param policy Referrer policy to store
40
+ * @param referrer The referrer URL that set this policy
41
+ */
42
+ export declare function storeReferrerPolicy(url: string, policy: string, referrer: string): Promise<void>;
43
+ /**
44
+ * Get referrer policy data for a URL
45
+ *
46
+ * @param url URL to get the policy for
47
+ * @returns Referrer policy data if found, or `null`
48
+ */
49
+ export declare function getReferrerPolicy(url: string): Promise<ReferrerPolicyData | null>;
@@ -0,0 +1,2 @@
1
+ export * from "./forceReferrer";
2
+ export * from "./siteTests";
@@ -0,0 +1,33 @@
1
+ import { type URLMeta } from "../rewriters/url";
2
+ import type { default as BareClient } from "@mercuryworkshop/bare-mux";
3
+ /**
4
+ * Emulate `Sec-Fetch-Site` header using the referrer (another reason why Force Referrer is now a needed SJ feature)
5
+ */
6
+ export declare function getSiteDirective(meta: URLMeta, referrerURL: URL, client: BareClient): Promise<string>;
7
+ /**
8
+ * Tests if the two URLs are from the same site.
9
+ * This will be used in the response header rewriter.
10
+ *
11
+ * @see https://developer.mozilla.org/en-US/docs/Glossary/Site
12
+ * @see https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Sec-Fetch-Site#directives
13
+ *
14
+ * @param url1 First URL to compare
15
+ * @param url2 Second URL to compare
16
+ * @param client `BareClient` instance used for fetching
17
+ * @returns Whether the two URLs are from the same site
18
+ *
19
+ * @throws {Error} If an error occurs while getting the Public Suffix List
20
+ */
21
+ export declare function isSameSite(url1: URL, url2: URL, client: BareClient): Promise<boolean>;
22
+ /**
23
+ * Gets parsed Public Suffix list from the API.
24
+ *
25
+ * Complies with the standard format.
26
+ * @see https://github.com/publicsuffix/list/wiki/Format#format
27
+ *
28
+ * @param {BareClient} client `BareClient` instance used for fetching
29
+ * @returns {Promise<string[]>} Parsed Public Suffix list
30
+ *
31
+ * @throws {Error} If an error occurs while fetching from the Public Suffix List
32
+ */
33
+ export declare function getPublicSuffixList(client: BareClient): Promise<string[]>;
@@ -0,0 +1,7 @@
1
+ /**
2
+ * @fileoverview
3
+ * See `types.ts` for context on these symbols.
4
+ */
5
+ export declare const SCRAMJETCLIENTNAME = "scramjet client global";
6
+ export declare const SCRAMJETCLIENT: unique symbol;
7
+ export declare const SCRAMJETFRAME: unique symbol;
@@ -0,0 +1,135 @@
1
+ import { ScramjetClient } from "./client/index";
2
+ import { ScramjetFrame } from "./controller/frame";
3
+ import { SCRAMJETCLIENT, SCRAMJETFRAME } from "./symbols";
4
+ import * as controller from "./controller/index";
5
+ import * as client from "./client/entry";
6
+ import * as worker from "./worker/index";
7
+ import { DBSchema } from "idb";
8
+ /**
9
+ * Version information for the current Scramjet build.
10
+ * Contains both the semantic version string and the git commit hash for build identification.
11
+ */
12
+ export interface ScramjetVersionInfo {
13
+ /** The git commit hash that this build was created from */
14
+ build: string;
15
+ /** The semantic version */
16
+ version: string;
17
+ }
18
+ /**
19
+ * Scramjet Feature Flags, configured at build time
20
+ */
21
+ export type ScramjetFlags = {
22
+ serviceworkers: boolean;
23
+ syncxhr: boolean;
24
+ strictRewrites: boolean;
25
+ rewriterLogs: boolean;
26
+ captureErrors: boolean;
27
+ cleanErrors: boolean;
28
+ scramitize: boolean;
29
+ sourcemaps: boolean;
30
+ destructureRewrites: boolean;
31
+ interceptDownloads: boolean;
32
+ allowInvalidJs: boolean;
33
+ allowFailedIntercepts: boolean;
34
+ };
35
+ export interface ScramjetConfig {
36
+ prefix: string;
37
+ globals: {
38
+ wrapfn: string;
39
+ wrappropertybase: string;
40
+ wrappropertyfn: string;
41
+ cleanrestfn: string;
42
+ importfn: string;
43
+ rewritefn: string;
44
+ metafn: string;
45
+ setrealmfn: string;
46
+ pushsourcemapfn: string;
47
+ trysetfn: string;
48
+ templocid: string;
49
+ tempunusedid: string;
50
+ };
51
+ files: {
52
+ wasm: string;
53
+ all: string;
54
+ sync: string;
55
+ };
56
+ flags: ScramjetFlags;
57
+ siteFlags: Record<string, Partial<ScramjetFlags>>;
58
+ codec: {
59
+ encode: string;
60
+ decode: string;
61
+ };
62
+ }
63
+ /**
64
+ * The config for Scramjet initialization.
65
+ */
66
+ export interface ScramjetInitConfig extends Omit<ScramjetConfig, "codec" | "flags"> {
67
+ flags: Partial<ScramjetFlags>;
68
+ codec: {
69
+ encode: (url: string) => string;
70
+ decode: (url: string) => string;
71
+ };
72
+ }
73
+ declare global {
74
+ var $scramjetLoadController: () => typeof controller;
75
+ var $scramjetLoadClient: () => typeof client;
76
+ var $scramjetLoadWorker: () => typeof worker;
77
+ var $scramjetVersion: ScramjetVersionInfo;
78
+ interface Window {
79
+ COOKIE: string;
80
+ WASM: string;
81
+ REAL_WASM: Uint8Array;
82
+ /**
83
+ * The scramjet client belonging to a window.
84
+ */
85
+ [SCRAMJETCLIENT]: ScramjetClient;
86
+ }
87
+ interface HTMLDocument {
88
+ /**
89
+ * Should be the same as window.
90
+ */
91
+ [SCRAMJETCLIENT]: ScramjetClient;
92
+ }
93
+ interface HTMLIFrameElement {
94
+ /**
95
+ * The event target belonging to an iframe element holding an encoded URL.
96
+ */
97
+ [SCRAMJETFRAME]: ScramjetFrame;
98
+ }
99
+ }
100
+ export type SiteDirective = "same-origin" | "same-site" | "cross-site" | "none";
101
+ export interface RedirectTracker {
102
+ originalReferrer: string;
103
+ mostRestrictiveSite: SiteDirective;
104
+ referrerPolicy: string;
105
+ chainStarted: number;
106
+ }
107
+ export interface ReferrerPolicyData {
108
+ policy: string;
109
+ referrer: string;
110
+ }
111
+ export interface ScramjetDB extends DBSchema {
112
+ config: {
113
+ key: string;
114
+ value: ScramjetConfig;
115
+ };
116
+ cookies: {
117
+ key: string;
118
+ value: any;
119
+ };
120
+ redirectTrackers: {
121
+ key: string;
122
+ value: RedirectTracker;
123
+ };
124
+ referrerPolicies: {
125
+ key: string;
126
+ value: ReferrerPolicyData;
127
+ };
128
+ publicSuffixList: {
129
+ key: string;
130
+ value: {
131
+ data: string[];
132
+ expiry: number;
133
+ };
134
+ };
135
+ }
@@ -0,0 +1,2 @@
1
+ export declare function errorTemplate(trace: string, fetchedURL: string): string;
2
+ export declare function renderError(err: unknown, fetchedURL: string): Response;
@@ -0,0 +1,12 @@
1
+ import { type MessageR2W } from "../client/swruntime";
2
+ export declare class FakeServiceWorker {
3
+ handle: MessagePort;
4
+ origin: string;
5
+ syncToken: number;
6
+ promises: Record<number, (val?: MessageR2W) => void>;
7
+ messageChannel: MessageChannel;
8
+ connected: boolean;
9
+ constructor(handle: MessagePort, origin: string);
10
+ handleMessage(data: MessageR2W): void;
11
+ fetch(request: Request): Promise<Response | false>;
12
+ }
@@ -0,0 +1,26 @@
1
+ import { BareResponseFetch } from "@mercuryworkshop/bare-mux";
2
+ import { ScramjetServiceWorker } from "./";
3
+ export declare function handleFetch(this: ScramjetServiceWorker, request: Request, client: Client | null): Promise<Response>;
4
+ type BodyType = string | ArrayBuffer | Blob | ReadableStream<any>;
5
+ export declare class ScramjetHandleResponseEvent extends Event {
6
+ responseBody: BodyType;
7
+ responseHeaders: Record<string, string>;
8
+ status: number;
9
+ statusText: string;
10
+ destination: string;
11
+ url: URL;
12
+ rawResponse: BareResponseFetch;
13
+ client: Client;
14
+ constructor(responseBody: BodyType, responseHeaders: Record<string, string>, status: number, statusText: string, destination: string, url: URL, rawResponse: BareResponseFetch, client: Client);
15
+ }
16
+ export declare class ScramjetRequestEvent extends Event {
17
+ url: URL;
18
+ requestHeaders: Record<string, string>;
19
+ body: BodyType;
20
+ method: string;
21
+ destination: string;
22
+ client: Client;
23
+ constructor(url: URL, requestHeaders: Record<string, string>, body: BodyType, method: string, destination: string, client: Client);
24
+ response?: BareResponseFetch | Promise<BareResponseFetch>;
25
+ }
26
+ export {};
@@ -0,0 +1,143 @@
1
+ /**
2
+ * @fileoverview Contains the core Service Worker logic for Scramjet, which handles the initial request interception and handles client management for the Scramjet service.
3
+ */
4
+ import { FakeServiceWorker } from "./fakesw";
5
+ import BareClient from "@mercuryworkshop/bare-mux";
6
+ import { ScramjetConfig } from "../types";
7
+ import { CookieStore } from "../shared/cookie";
8
+ import { ScramjetDownload } from "../client/events";
9
+ export * from "./error";
10
+ export * from "./fetch";
11
+ export * from "./fakesw";
12
+ /**
13
+ * Main `ScramjetServiceWorker` class created by the `$scramjetLoadWorker` factory, which handles routing the proxy and contains the core logic for request interception.
14
+ */
15
+ export declare class ScramjetServiceWorker extends EventTarget {
16
+ /**
17
+ * `BareClient` instance to fetch requests under a chosen proxy transport.
18
+ */
19
+ client: BareClient;
20
+ /**
21
+ * Current ScramjetConfig saved in memory.
22
+ */
23
+ config: ScramjetConfig;
24
+ /**
25
+ * Recorded sync messages in the message queue.
26
+ */
27
+ syncPool: Record<number, (val?: any) => void>;
28
+ /**
29
+ * Current sync token for collected messages in the queue.
30
+ */
31
+ synctoken: number;
32
+ /**
33
+ * Scramjet's cookie jar for cookie emulation through other storage means, connected to a client.
34
+ */
35
+ cookieStore: CookieStore;
36
+ /**
37
+ * Fake service worker registrations, so that some sites don't complain.
38
+ * This will eventually be replaced with a NestedSW feature under a flag in the future, but this will remain for stability even then.
39
+ */
40
+ serviceWorkers: FakeServiceWorker[];
41
+ /**
42
+ * Initializes the `BareClient` Scramjet uses to fetch requests under a chosen proxy transport, the cookie jar store for proxifying cookies, and inits the listeners for emulation features and dynamic configs set through the Scramjet Controller.
43
+ */
44
+ constructor();
45
+ /**
46
+ * Dispatches a message in the message queues.
47
+ */
48
+ dispatch(client: Client, data: MessageW2C): Promise<MessageC2W>;
49
+ /**
50
+ * Persists the current Scramjet config into an IndexedDB store.
51
+ * Remember, this is because the Scramjet config can be dynamically updated via the Scramjet Controller APIs.
52
+ *
53
+ * @example
54
+ * self.addEventListener("fetch", async (ev) => {
55
+ * await scramjet.loadConfig();
56
+ *
57
+ * ...
58
+ * });
59
+ */
60
+ loadConfig(): Promise<void>;
61
+ /**
62
+ * Whether to route a request from a `FetchEvent` in Scramjet.
63
+ *
64
+ * @example
65
+ * self.addEventListener("fetch", async (ev) => {
66
+ * ...
67
+ *
68
+ * if (scramjet.route(ev)) {
69
+ * ...
70
+ * }
71
+ * });
72
+ * ```
73
+ */
74
+ route({ request }: FetchEvent): boolean;
75
+ /**
76
+ * Handles a `FetchEvent` to be routed in Scramjet.
77
+ * This is the heart of adding Scramjet support to your web proxy.
78
+ *
79
+ * @example
80
+ * self.addEventListener("fetch", async (ev) => {
81
+ * ...
82
+ *
83
+ * if (scramjet.route(ev)) {
84
+ * ev.respondWith(scramjet.fetch(ev));
85
+ * }
86
+ * });
87
+ */
88
+ fetch({ request, clientId }: FetchEvent): Promise<any>;
89
+ }
90
+ /**
91
+ * Scramjet fake Service Worker event message.
92
+ * Contains a `scramjet$type` for identifying the message.
93
+ */
94
+ type RegisterServiceWorkerMessage = {
95
+ scramjet$type: "registerServiceWorker";
96
+ port: MessagePort;
97
+ origin: string;
98
+ };
99
+ /**
100
+ * Scramjet cookie jar event message.
101
+ * Contains a `scramjet$type` for identifying the message.
102
+ */
103
+ type CookieMessage = {
104
+ scramjet$type: "cookie";
105
+ cookie: string;
106
+ url: string;
107
+ };
108
+ /**
109
+ * Scramjet config event message.
110
+ * Contains a `scramjet$type` for identifying the message.
111
+ */
112
+ type ConfigMessage = {
113
+ scramjet$type: "loadConfig";
114
+ config: ScramjetConfig;
115
+ };
116
+ /**
117
+ * Scramjet proxified download event message.
118
+ * Contains a `scramjet$type` for identifying the message.
119
+ */
120
+ type DownloadMessage = {
121
+ scramjet$type: "download";
122
+ download: ScramjetDownload;
123
+ };
124
+ /**
125
+ * Default Scramjet message.
126
+ * Contains a `scramjet$type` for identifying the message.
127
+ */
128
+ type MessageCommon = {
129
+ scramjet$token?: number;
130
+ };
131
+ /**
132
+ * Message types sent from the client to the Service Worker.
133
+ * These are routed by their `scramjet$type` to identify the messages apart from each other.
134
+ */
135
+ type MessageTypeC2W = RegisterServiceWorkerMessage | CookieMessage | ConfigMessage;
136
+ /**
137
+ * w2c (types): Message types sent from the Service Worker to the client.
138
+ */
139
+ type MessageTypeW2C = CookieMessage | DownloadMessage;
140
+ /** c2w: client to Service Worker */
141
+ export type MessageC2W = MessageCommon & MessageTypeC2W;
142
+ /** w2c: Service Worker to client */
143
+ export type MessageW2C = MessageCommon & MessageTypeW2C;
package/lib/index.cjs ADDED
@@ -0,0 +1,7 @@
1
+ "use strict";
2
+
3
+ const { resolve } = require("node:path");
4
+
5
+ const scramjetPath = resolve(__dirname, "..", "dist");
6
+
7
+ exports.scramjetPath = scramjetPath;
package/lib/index.d.ts CHANGED
@@ -1,3 +1,8 @@
1
- declare const scramjetPath: string;
2
-
3
- export { scramjetPath };
1
+ /**
2
+ * @fileoverview
3
+ * Scramjet path export for routing functionality
4
+ */
5
+
6
+ declare const scramjetPath: string;
7
+
8
+ export { scramjetPath };
package/lib/noop.js ADDED
File without changes
package/package.json CHANGED
@@ -1,12 +1,26 @@
1
1
  {
2
2
  "name": "@mercuryworkshop/scramjet",
3
- "version": "1.0.1",
3
+ "version": "1.1.0",
4
4
  "description": "An experimental web proxy that aims to be the successor to Ultraviolet",
5
- "main": "./lib/index.js",
6
- "types": "./lib/index.d.js",
5
+ "type": "module",
6
+ "types": "./dist/types/index.d.ts",
7
7
  "repository": {
8
8
  "type": "git",
9
- "url": "https://github.com/MercuryWorkshop/scramjet"
9
+ "url": "git+https://github.com/MercuryWorkshop/scramjet.git"
10
+ },
11
+ "exports": {
12
+ ".": {
13
+ "types": "./dist/types/index.d.ts",
14
+ "default": "./lib/noop.js"
15
+ },
16
+ "./path": {
17
+ "types": "./lib/index.d.ts",
18
+ "default": "./lib/index.cjs"
19
+ },
20
+ "./bundled": {
21
+ "types": "./dist/types/index.d.ts",
22
+ "default": "./dist/scramjet.bundle.js"
23
+ }
10
24
  },
11
25
  "files": [
12
26
  "dist",
@@ -14,42 +28,95 @@
14
28
  ],
15
29
  "keywords": [],
16
30
  "author": "",
17
- "license": "ISC",
31
+ "license": "MIT",
32
+ "ava": {
33
+ "files": [
34
+ "tests/ci/**/*.js"
35
+ ],
36
+ "verbose": true
37
+ },
18
38
  "devDependencies": {
19
- "@fastify/static": "^7.0.3",
20
- "@mercuryworkshop/bare-as-module3": "^2.2.0-alpha",
21
- "@mercuryworkshop/epoxy-transport": "^1.1.0",
22
- "@mercuryworkshop/libcurl-transport": "^1.3.1",
23
- "@tomphttp/bare-server-node": "^2.0.3",
24
- "@types/eslint": "^8.56.10",
25
- "@types/serviceworker": "^0.0.85",
26
- "@typescript-eslint/eslint-plugin": "^6.21.0",
27
- "@typescript-eslint/parser": "^6.21.0",
28
- "dotenv": "^16.4.5",
29
- "esbuild": "^0.20.2",
30
- "esbuild-plugin-copy": "^2.1.1",
31
- "esbuild-plugin-time": "^1.0.0",
32
- "eslint": "^8.57.0",
33
- "fastify": "^4.26.2",
34
- "tslib": "^2.6.2",
35
- "typescript": "^5.4.5"
39
+ "@8hobbies/typedoc-plugin-404": "^3.2.1",
40
+ "@8hobbies/typedoc-plugin-plausible": "^2.2.0",
41
+ "@catppuccin/vscode": "^3.18.0",
42
+ "@eslint/eslintrc": "^3.3.1",
43
+ "@eslint/js": "^9.35.0",
44
+ "@estruyf/github-actions-reporter": "^1.10.0",
45
+ "@fastify/static": "^8.2.0",
46
+ "@giancosta86/typedoc-readonly": "^1.0.1",
47
+ "@mercuryworkshop/bare-as-module3": "^2.2.5",
48
+ "@mercuryworkshop/epoxy-transport": "^2.1.28",
49
+ "@mercuryworkshop/libcurl-transport": "^1.5.0",
50
+ "@mercuryworkshop/wisp-js": "^0.3.3",
51
+ "@nebula-services/bare-server-node": "^2.0.4",
52
+ "@playwright/test": "^1.55.0",
53
+ "@reside-ic/typedoc-plugin-copy-doc": "^1.1.2",
54
+ "@rsdoctor/rspack-plugin": "^1.2.3",
55
+ "@rslib/core": "^0.13.2",
56
+ "@rspack/cli": "^1.5.3",
57
+ "@rspack/core": "^1.5.3",
58
+ "@shipgirl/typedoc-plugin-versions": "^0.3.2",
59
+ "@stephansama/catppuccin-typedoc": "^1.0.1",
60
+ "@types/eslint": "^9.6.1",
61
+ "@types/estree": "^1.0.8",
62
+ "@types/node": "^24.3.1",
63
+ "@types/serviceworker": "^0.0.152",
64
+ "@typescript-eslint/eslint-plugin": "^8.43.0",
65
+ "@typescript-eslint/parser": "^8.43.0",
66
+ "actionlint": "^2.0.6",
67
+ "ava": "^6.4.1",
68
+ "dotenv": "^17.2.2",
69
+ "eslint": "^9.35.0",
70
+ "fastify": "^5.6.0",
71
+ "glob": "^11.0.3",
72
+ "playwright": "^1.55.0",
73
+ "prettier": "^3.6.2",
74
+ "remark": "^15.0.1",
75
+ "remark-cli": "^12.0.1",
76
+ "remark-frontmatter": "^5.0.0",
77
+ "remark-mdx": "^3.1.1",
78
+ "remark-stringify": "^11.0.0",
79
+ "ts-checker-rspack-plugin": "^1.1.5",
80
+ "tsc-alias": "^1.8.16",
81
+ "tslib": "^2.8.1",
82
+ "typedoc": "^0.28.12",
83
+ "typedoc-material-theme": "^1.4.0",
84
+ "typedoc-plugin-frontmatter": "^1.3.0",
85
+ "typedoc-plugin-include-example": "^2.1.2",
86
+ "typedoc-plugin-markdown": "^4.8.1",
87
+ "typedoc-plugin-mdn-links": "^5.0.9",
88
+ "typescript": "^5.9.2"
36
89
  },
37
- "type": "module",
38
90
  "dependencies": {
39
- "@mercuryworkshop/bare-mux": "^1.1.2",
40
- "@webreflection/idb-map": "^0.1.3",
41
- "astravel": "^0.6.1",
42
- "astring": "^1.8.6",
91
+ "@mercuryworkshop/bare-mux": "^2.1.9",
43
92
  "dom-serializer": "^2.0.0",
44
93
  "domhandler": "^5.0.3",
45
- "domutils": "^3.1.0",
46
- "esbuild-server": "^0.3.0",
47
- "htmlparser2": "^9.1.0",
48
- "meriyah": "^4.4.2"
94
+ "domutils": "^3.2.2",
95
+ "htmlparser2": "10.0.0",
96
+ "idb": "^8.0.3",
97
+ "parse-domain": "^8.2.2",
98
+ "set-cookie-parser": "^2.7.1"
49
99
  },
50
100
  "scripts": {
51
- "build": "node esbuild.js",
52
- "dev": "node esbuild.dev.js",
53
- "prepublish": "pnpm build"
101
+ "build": "rspack build --mode production",
102
+ "build:types": "rslib build && rm -rf dist/temp",
103
+ "build:all": "npm run build && npm run build:types",
104
+ "rewriter:build": "cd rewriter/wasm/ && bash build.sh && cd ../../",
105
+ "dev": "node server.js",
106
+ "dev:debug": "DEBUG=1 node server.js",
107
+ "pub": "npm publish --no-git-checks --access public",
108
+ "format": "prettier --write .",
109
+ "format:docs": "remark \"docs/**/*.{md,mdx}\" --output",
110
+ "lint": "eslint ./src/",
111
+ "lint:fix": "eslint ./src/ --fix",
112
+ "lint:workflows": "actionlint .github/workflows/*.yml",
113
+ "lint:all": "npm run lint && npm run lint:workflows",
114
+ "test": "npm run test:package && npm run test:integration",
115
+ "test:package": "ava tests/ci/packageValidation.js",
116
+ "test:integration": "npx playwright test",
117
+ "preinstall": "npx only-allow pnpm",
118
+ "docs": "typedoc",
119
+ "docs:dev": "typedoc --options typedoc.dev-facing.json",
120
+ "docs:serve": "npx serve _docs; typedoc --watch"
54
121
  }
55
122
  }
@@ -1 +0,0 @@
1
- (()=>{function p(){let t=new URL(self.__scramjet$bundle.rewriters.url.decodeUrl(location.href));return t.assign=r=>location.assign(self.__scramjet$bundle.rewriters.url.encodeUrl(r)),t.reload=()=>location.reload(),t.replace=r=>location.replace(self.__scramjet$bundle.rewriters.url.encodeUrl(r)),t.toString=()=>t.href,t}function d(){let t=p();return new Proxy(window.location,{get(r,e){return t[e]},set(r,e,s){return e==="href"?location.href=self.__scramjet$bundle.rewriters.url.encodeUrl(s):t[e]=s,!0}})}window.__location=d();trustedTypes.createPolicy=new Proxy(trustedTypes.createPolicy,{apply(t,r,e){return e[1].createHTML&&(e[1].createHTML=new Proxy(e[1].createHTML,{apply(s,n,o){return self.__scramjet$bundle.rewriters.rewriteHtml(s(...o))}})),e[1].createScript&&(e[1].createScript=new Proxy(e[1].createScript,{apply(s,n,o){return self.__scramjet$bundle.rewriters.rewriteJs(s(...o))}})),e[1].createScriptURL&&(e[1].createScriptURL=new Proxy(e[1].createScriptURL,{apply(s,n,o){return self.__scramjet$bundle.rewriters.url.encodeUrl(s(...o))}})),Reflect.apply(t,r,e)}});var u=new Proxy(Function,{construct(t,r){return r.length===1?Reflect.construct(t,self.__scramjet$bundle.rewriters.rewriteJs(r[0])):Reflect.construct(t,self.__scramjet$bundle.rewriters.rewriteJs(r[r.length-1]))},apply(t,r,e){return e.length===1?Reflect.apply(t,void 0,self.__scramjet$bundle.rewriters.rewriteJs(e[0])):Reflect.apply(t,void 0,[...e.map((s,n)=>n===e.length-1),self.__scramjet$bundle.rewriters.rewriteJs(e[e.length-1])])}});delete window.Function;window.Function=u;delete window.eval;window.eval=t=>window.Function(t);function c(t){return Object.keys(t).filter(r=>r.startsWith(window.__location.host))}function l(t){return new Proxy(t,{get(r,e,s){switch(e){case"getItem":return n=>r.getItem(window.__location.host+"@"+n);case"setItem":return(n,o)=>{r.setItem(window.__location.host+"@"+n,o)};case"removeItem":return n=>{r.removeItem(window.__location.host+"@"+n)};case"clear":return()=>{c(r).forEach(n=>r.removeItem(n))};case"key":return n=>r[c(r)[n]];case"length":return c(r).length}},defineProperty(r,e,s){return r.setItem(e,s.value),!0}})}var m=l(window.localStorage),w=l(window.sessionStorage);delete window.localStorage;delete window.sessionStorage;window.localStorage=m;window.sessionStorage=w;var i={nonce:[HTMLElement],integrity:[HTMLScriptElement,HTMLLinkElement],csp:[HTMLIFrameElement],src:[HTMLImageElement,HTMLMediaElement,HTMLIFrameElement,HTMLEmbedElement,HTMLScriptElement],href:[HTMLAnchorElement,HTMLLinkElement],data:[HTMLObjectElement],action:[HTMLFormElement],formaction:[HTMLButtonElement,HTMLInputElement],srcdoc:[HTMLIFrameElement],srcset:[HTMLImageElement,HTMLSourceElement],imagesrcset:[HTMLLinkElement],style:[HTMLElement]};Object.keys(i).forEach(t=>{i[t].forEach(r=>{let e=Object.getOwnPropertyDescriptor(r.prototype,t);Object.defineProperty(r.prototype,t,{get(){return e.get.call(this,this.dataset[`_${t}`])},set(s){if(this.dataset[`_${t}`]=s,/nonce|integrity|csp/.test(t))this.removeAttribute(t);else if(/src|href|data|action|formaction/.test(t)){if(s instanceof TrustedScriptURL)return;s=self.__scramjet$bundle.rewriters.url.encodeUrl(s)}else t==="srcdoc"?s=self.__scramjet$bundle.rewriters.rewriteHtml(s):/(image)?srcset/.test(t)?s=self.__scramjet$bundle.rewriters.rewriteSrcset(s):t==="style"&&(s=self.__scramjet$bundle.rewriters.rewriteCss(s));e.set.call(this,s)}})})});HTMLElement.prototype.getAttribute=new Proxy(Element.prototype.getAttribute,{apply(t,r,e){return Object.keys(i).includes(e[0])&&(e[0]=`_${e[0]}`),Reflect.apply(t,r,e)}});HTMLElement.prototype.setAttribute=new Proxy(Element.prototype.setAttribute,{apply(t,r,e){if(Object.keys(i).includes(e[0])){if(r.dataset[`_${e[0]}`]=e[1],/nonce|integrity|csp/.test(e[0]))return;/src|href|data|action|formaction/.test(e[0])?e[1]=self.__scramjet$bundle.rewriters.url.encodeUrl(e[1]):e[0]==="srcdoc"?e[1]=self.__scramjet$bundle.rewriters.rewriteHtml(e[1]):/(image)?srcset/.test(e[0])?e[1]=self.__scramjet$bundle.rewriters.rewriteSrcset(e[1]):e[1]==="style"&&(e[1]=self.__scramjet$bundle.rewriters.rewriteCss(e[1]))}return Reflect.apply(t,r,e)}});var f=Object.getOwnPropertyDescriptor(Element.prototype,"innerHTML");Object.defineProperty(HTMLElement.prototype,"innerHTML",{set(t){this instanceof HTMLScriptElement?t instanceof TrustedScript||(t=self.__scramjet$bundle.rewriters.rewriteJs(t)):this instanceof HTMLStyleElement?t=self.__scramjet$bundle.rewriters.rewriteCss(t):t instanceof TrustedHTML||(t=self.__scramjet$bundle.rewriters.rewriteHtml(t)),f.set.call(this,t)}});window.fetch=new Proxy(window.fetch,{apply(t,r,e){return console.log(e),e[0]instanceof Request||(e[0]=self.__scramjet$bundle.rewriters.url.encodeUrl(e[0])),console.log(e),Reflect.apply(t,r,e)}});Headers=new Proxy(Headers,{construct(t,r,e){return r[0]=self.__scramjet$bundle.rewriters.rewriteHeaders(r[0]),Reflect.construct(t,r,e)}});Request=new Proxy(Request,{construct(t,r,e){return typeof r[0]=="string"&&(r[0]=self.__scramjet$bundle.rewriters.url.encodeUrl(r[0])),Reflect.construct(t,r,e)}});Response.redirect=new Proxy(Response.redirect,{apply(t,r,e){return e[0]=self.__scramjet$bundle.rewriters.url.encodeUrl(e[0]),Reflect.apply(t,r,e)}});XMLHttpRequest.prototype.open=new Proxy(XMLHttpRequest.prototype.open,{apply(t,r,e){return e[1]&&(e[1]=self.__scramjet$bundle.rewriters.url.encodeUrl(e[1])),Reflect.apply(t,r,e)}});XMLHttpRequest.prototype.setRequestHeader=new Proxy(XMLHttpRequest.prototype.setRequestHeader,{apply(t,r,e){let s=Object.fromEntries(e);return s=self.__scramjet$bundle.rewriters.rewriteHeaders(s),e=Object.entries(s),Reflect.apply(t,r,e)}});var _=["background","background-image","mask","mask-image","list-style","list-style-image","border-image","border-image-source","cursor"],b=["background","backgroundImage","mask","maskImage","listStyle","listStyleImage","borderImage","borderImageSource","cursor"];CSSStyleDeclaration.prototype.setProperty=new Proxy(CSSStyleDeclaration.prototype.setProperty,{apply(t,r,e){return _.includes(e[0])&&(e[1]=self.__scramjet$bundle.rewriters.rewriteCss(e[1])),Reflect.apply(t,r,e)}});b.forEach(t=>{let r=Object.getOwnPropertyDescriptor(CSSStyleDeclaration.prototype,t);Object.defineProperty(CSSStyleDeclaration.prototype,t,{set(e){r.set.call(this,self.__scramjet$bundle.rewriters.rewriteCss(e))}})});})();