@mercuryworkshop/scramjet 1.0.2 → 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.
- package/LICENSE +3 -3
- package/README.md +89 -21
- package/dist/scramjet.all.js +196 -0
- package/dist/scramjet.all.js.map +1 -0
- package/dist/scramjet.bundle.js +196 -7
- package/dist/scramjet.bundle.js.map +1 -7
- package/dist/scramjet.sync.js +2 -0
- package/dist/scramjet.sync.js.map +1 -0
- package/dist/scramjet.wasm.wasm +0 -0
- package/dist/types/client/client.d.ts +78 -0
- package/dist/types/client/entry.d.ts +8 -0
- package/dist/types/client/events.d.ts +66 -0
- package/dist/types/client/helpers.d.ts +1 -0
- package/dist/types/client/index.d.ts +8 -0
- package/dist/types/client/location.d.ts +2 -0
- package/dist/types/client/shared/eval.d.ts +3 -0
- package/dist/types/client/shared/sourcemaps.d.ts +19 -0
- package/dist/types/client/shared/wrap.d.ts +4 -0
- package/dist/types/client/singletonbox.d.ts +12 -0
- package/dist/types/client/swruntime.d.ts +40 -0
- package/dist/types/controller/controller.d.ts +16 -0
- package/dist/types/controller/frame.d.ts +103 -0
- package/dist/types/controller/index.d.ts +2 -0
- package/dist/types/entry.d.ts +160 -0
- package/dist/types/index.d.ts +8 -0
- package/dist/types/shared/cookie.d.ts +18 -0
- package/dist/types/shared/headers.d.ts +4 -0
- package/dist/types/shared/htmlRules.d.ts +6 -0
- package/dist/types/shared/index.d.ts +12 -0
- package/dist/types/shared/rewriters/css.d.ts +3 -0
- package/dist/types/shared/rewriters/headers.d.ts +18 -0
- package/dist/types/shared/rewriters/html.d.ts +6 -0
- package/dist/types/shared/rewriters/index.d.ts +7 -0
- package/dist/types/shared/rewriters/js.d.ts +10 -0
- package/dist/types/shared/rewriters/url.d.ts +10 -0
- package/dist/types/shared/rewriters/wasm.d.ts +7 -0
- package/dist/types/shared/rewriters/worker.d.ts +2 -0
- package/dist/types/shared/security/forceReferrer.d.ts +49 -0
- package/dist/types/shared/security/index.d.ts +2 -0
- package/dist/types/shared/security/siteTests.d.ts +33 -0
- package/dist/types/symbols.d.ts +7 -0
- package/dist/types/types.d.ts +135 -0
- package/dist/types/worker/error.d.ts +2 -0
- package/dist/types/worker/fakesw.d.ts +12 -0
- package/dist/types/worker/fetch.d.ts +26 -0
- package/dist/types/worker/index.d.ts +143 -0
- package/lib/index.cjs +7 -7
- package/lib/index.d.ts +8 -3
- package/lib/noop.js +0 -0
- package/package.json +101 -35
- package/dist/scramjet.client.js +0 -1
- package/dist/scramjet.client.js.map +0 -7
- package/dist/scramjet.codecs.js +0 -3
- package/dist/scramjet.codecs.js.map +0 -7
- package/dist/scramjet.config.js +0 -1
- package/dist/scramjet.config.js.map +0 -7
- package/dist/scramjet.worker.js +0 -42
- package/dist/scramjet.worker.js.map +0 -7
|
@@ -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,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,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,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,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
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
const { resolve } = require("node:path");
|
|
4
|
-
|
|
5
|
-
const scramjetPath = resolve(__dirname, "..", "dist");
|
|
6
|
-
|
|
7
|
-
exports.scramjetPath = scramjetPath;
|
|
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
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
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"description": "An experimental web proxy that aims to be the successor to Ultraviolet",
|
|
5
|
-
"
|
|
6
|
-
"types": "./
|
|
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,43 +28,95 @@
|
|
|
14
28
|
],
|
|
15
29
|
"keywords": [],
|
|
16
30
|
"author": "",
|
|
17
|
-
"license": "
|
|
31
|
+
"license": "MIT",
|
|
32
|
+
"ava": {
|
|
33
|
+
"files": [
|
|
34
|
+
"tests/ci/**/*.js"
|
|
35
|
+
],
|
|
36
|
+
"verbose": true
|
|
37
|
+
},
|
|
18
38
|
"devDependencies": {
|
|
19
|
-
"@
|
|
20
|
-
"@
|
|
21
|
-
"@
|
|
22
|
-
"@
|
|
23
|
-
"@
|
|
24
|
-
"@
|
|
25
|
-
"@
|
|
26
|
-
"@
|
|
27
|
-
"@
|
|
28
|
-
"
|
|
29
|
-
"
|
|
30
|
-
"
|
|
31
|
-
"
|
|
32
|
-
"
|
|
33
|
-
"
|
|
34
|
-
"
|
|
35
|
-
"
|
|
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": "^
|
|
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.
|
|
46
|
-
"
|
|
47
|
-
"
|
|
48
|
-
"
|
|
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": "
|
|
52
|
-
"
|
|
53
|
-
"
|
|
54
|
-
"
|
|
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"
|
|
55
121
|
}
|
|
56
122
|
}
|
package/dist/scramjet.client.js
DELETED
|
@@ -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 i(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()=>{i(r).forEach(n=>r.removeItem(n))};case"key":return n=>r[i(r)[n]];case"length":return i(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 c={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(c).forEach(t=>{c[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 console.log(r),Object.keys(c).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(c).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])?(console.log(r),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){return 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 e[0]=self.__scramjet$bundle.rewriters.url.encodeUrl(e[0]),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))}})});})();
|