@anapaya/webscion-poc 0.0.1
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 +107 -0
- package/bin/src/angular/index.d.ts +3 -0
- package/bin/src/angular/index.d.ts.map +1 -0
- package/bin/src/angular/index.js +3 -0
- package/bin/src/angular/index.js.map +1 -0
- package/bin/src/angular/interceptor.d.ts +10 -0
- package/bin/src/angular/interceptor.d.ts.map +1 -0
- package/bin/src/angular/interceptor.js +76 -0
- package/bin/src/angular/interceptor.js.map +1 -0
- package/bin/src/index.d.ts +3 -0
- package/bin/src/index.d.ts.map +1 -0
- package/bin/src/index.js +3 -0
- package/bin/src/index.js.map +1 -0
- package/bin/src/scion-stack.d.ts +8 -0
- package/bin/src/scion-stack.d.ts.map +1 -0
- package/bin/src/scion-stack.js +59 -0
- package/bin/src/scion-stack.js.map +1 -0
- package/bin/src/types.d.ts +23 -0
- package/bin/src/types.d.ts.map +1 -0
- package/bin/src/types.js +5 -0
- package/bin/src/types.js.map +1 -0
- package/bin/src/worker/scion-worker.d.ts +2 -0
- package/bin/src/worker/scion-worker.d.ts.map +1 -0
- package/bin/src/worker/scion-worker.js +131 -0
- package/bin/src/worker/scion-worker.js.map +1 -0
- package/package.json +54 -0
package/README.md
ADDED
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
# @anapaya/webscion-poc
|
|
2
|
+
|
|
3
|
+
Proof-of-concept npm package that establishes the architecture for the future WebScion SDK,
|
|
4
|
+
the a browser-based SCION networking stack.
|
|
5
|
+
|
|
6
|
+
## Architecture
|
|
7
|
+
|
|
8
|
+
```text
|
|
9
|
+
┌─────────────────────────────────────────────────────┐
|
|
10
|
+
│ Angular App │
|
|
11
|
+
│ ↓ HttpInterceptor │
|
|
12
|
+
│ ScionStack.fetch() │
|
|
13
|
+
│ ↓ postMessage |
|
|
14
|
+
│ ┌────────────────────────────────────────────────┐ │
|
|
15
|
+
│ │ Web Worker │ │
|
|
16
|
+
│ │ │ │
|
|
17
|
+
│ │ Dispatches original request via scion │ │
|
|
18
|
+
│ │ (not yet implemented) │ │
|
|
19
|
+
│ └────────────────────────────────────────────────┘ │
|
|
20
|
+
└─────────────────────────────────────────────────────┘
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
In a future iteration, the webworker will select an appropriate path for the request and dispatch it
|
|
24
|
+
via the SCION network.
|
|
25
|
+
|
|
26
|
+
## Installation
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
npm install @anapaya/webscion-poc
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## Usage
|
|
33
|
+
|
|
34
|
+
### Explicit Usage
|
|
35
|
+
|
|
36
|
+
```ts
|
|
37
|
+
import { ScionStack } from "@anapaya/webscion-poc";
|
|
38
|
+
|
|
39
|
+
const stack = new ScionStack();
|
|
40
|
+
|
|
41
|
+
const response = await stack.fetch("https://example.com/api/data", {
|
|
42
|
+
method: "POST",
|
|
43
|
+
headers: { "Content-Type": "application/json" },
|
|
44
|
+
body: JSON.stringify({ key: "value" }),
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
const data = await response.json();
|
|
48
|
+
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
### Angular Interceptor
|
|
52
|
+
|
|
53
|
+
```ts
|
|
54
|
+
import { ScionStack } from "@anapaya/webscion-poc";
|
|
55
|
+
import { provideScionInterceptor } from "@anapaya/webscion-poc/angular";
|
|
56
|
+
|
|
57
|
+
const scionStack = new ScionStack();
|
|
58
|
+
|
|
59
|
+
// In your app config or module providers:
|
|
60
|
+
providers: [
|
|
61
|
+
provideScionInterceptor({
|
|
62
|
+
stack: scionStack,
|
|
63
|
+
match: (req) => req.url.startsWith("https://console.anapaya.net/api/"),
|
|
64
|
+
}),
|
|
65
|
+
];
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
## Worker File Deployment
|
|
69
|
+
|
|
70
|
+
By default, the worker file is resolved relative to the package using `import.meta.url`.
|
|
71
|
+
Modern bundlers including angular cli handle this automatically.
|
|
72
|
+
|
|
73
|
+
If your setup requires a custom worker location, you can override it:
|
|
74
|
+
|
|
75
|
+
```ts
|
|
76
|
+
new ScionStack({ workerUrl: "/assets/scion-worker.js" });
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
## Observability
|
|
80
|
+
|
|
81
|
+
Check the browser console to see which requests are dispatched via the worker.
|
|
82
|
+
The web worker logs diagnostic information for every dispatched request:
|
|
83
|
+
|
|
84
|
+
```text
|
|
85
|
+
[webscion] #1 POST /api/data | 142 bytes | SHA-256: a1b2c3... | framing: 0.035ms
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
Each log line includes:
|
|
89
|
+
|
|
90
|
+
- **Sequence number** (`#1`): monotonic counter proving worker statefulness
|
|
91
|
+
- **Method and path**: the HTTP method and URL path
|
|
92
|
+
- **Byte length**: size of the HTTP/1.1 framed representation
|
|
93
|
+
- **SHA-256 hash**: hash of the framed bytes (for verification/debugging)
|
|
94
|
+
- **Framing duration**: time spent serializing the request to HTTP/1.1 bytes
|
|
95
|
+
|
|
96
|
+
## Development
|
|
97
|
+
|
|
98
|
+
```bash
|
|
99
|
+
# Install dependencies
|
|
100
|
+
./pnpm -C pkg/web/webscion install
|
|
101
|
+
|
|
102
|
+
# Run tests
|
|
103
|
+
./pnpm -C pkg/web/webscion test
|
|
104
|
+
|
|
105
|
+
# Build with Bazel
|
|
106
|
+
bazel build //pkg/web/webscion:pkg
|
|
107
|
+
```
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/angular/index.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,uBAAuB,EACvB,wBAAwB,GACzB,MAAM,eAAe,CAAC;AACvB,YAAY,EAAE,uBAAuB,EAAE,MAAM,eAAe,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/angular/index.ts"],"names":[],"mappings":"AAAA,iCAAiC;AAEjC,OAAO,EACL,uBAAuB,EACvB,wBAAwB,GACzB,MAAM,eAAe,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { HttpRequest, type HttpInterceptorFn } from "@angular/common/http";
|
|
2
|
+
import { Provider } from "@angular/core";
|
|
3
|
+
import type { ScionStack } from "../scion-stack";
|
|
4
|
+
export interface ScionInterceptorOptions {
|
|
5
|
+
stack: ScionStack;
|
|
6
|
+
match?: (req: HttpRequest<unknown>) => boolean;
|
|
7
|
+
}
|
|
8
|
+
export declare function provideScionInterceptor(options: ScionInterceptorOptions): Provider[];
|
|
9
|
+
export declare function createScionInterceptorFn(options: ScionInterceptorOptions): HttpInterceptorFn;
|
|
10
|
+
//# sourceMappingURL=interceptor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"interceptor.d.ts","sourceRoot":"","sources":["../../../src/angular/interceptor.ts"],"names":[],"mappings":"AAEA,OAAO,EAIL,WAAW,EAEX,KAAK,iBAAiB,EACvB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAEzC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAEjD,MAAM,WAAW,uBAAuB;IACtC,KAAK,EAAE,UAAU,CAAC;IAClB,KAAK,CAAC,EAAE,CAAC,GAAG,EAAE,WAAW,CAAC,OAAO,CAAC,KAAK,OAAO,CAAC;CAChD;AAED,wBAAgB,uBAAuB,CACrC,OAAO,EAAE,uBAAuB,GAC/B,QAAQ,EAAE,CAWZ;AAED,wBAAgB,wBAAwB,CACtC,OAAO,EAAE,uBAAuB,GAC/B,iBAAiB,CAenB"}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
// Copyright 2026 Anapaya Systems
|
|
2
|
+
import { HttpHeaders, HttpResponse, } from "@angular/common/http";
|
|
3
|
+
import { from, switchMap } from "rxjs";
|
|
4
|
+
export function provideScionInterceptor(options) {
|
|
5
|
+
return [
|
|
6
|
+
{
|
|
7
|
+
provide: "SCION_INTERCEPTOR_OPTIONS",
|
|
8
|
+
useValue: options,
|
|
9
|
+
},
|
|
10
|
+
{
|
|
11
|
+
provide: "HTTP_INTERCEPTORS_FN",
|
|
12
|
+
useValue: createScionInterceptorFn(options),
|
|
13
|
+
},
|
|
14
|
+
];
|
|
15
|
+
}
|
|
16
|
+
export function createScionInterceptorFn(options) {
|
|
17
|
+
const guardedFetch = options.stack.fetch();
|
|
18
|
+
return (req, next) => {
|
|
19
|
+
if (options.match && !options.match(req)) {
|
|
20
|
+
return next(req);
|
|
21
|
+
}
|
|
22
|
+
return from(dispatchViaGuardedFetch(guardedFetch, req)).pipe(switchMap((httpResponse) => [httpResponse]));
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
async function dispatchViaGuardedFetch(guardedFetch, req) {
|
|
26
|
+
const { url, init } = toFetchRequest(req);
|
|
27
|
+
const fetchResponse = await guardedFetch(url, init);
|
|
28
|
+
return toAngularResponse(req.responseType, fetchResponse);
|
|
29
|
+
}
|
|
30
|
+
function toFetchRequest(req) {
|
|
31
|
+
const fetchHeaders = new Headers();
|
|
32
|
+
for (const key of req.headers.keys()) {
|
|
33
|
+
const value = req.headers.get(key);
|
|
34
|
+
if (value !== null) {
|
|
35
|
+
fetchHeaders.set(key, value);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
const init = {
|
|
39
|
+
method: req.method,
|
|
40
|
+
headers: fetchHeaders,
|
|
41
|
+
};
|
|
42
|
+
if (req.body !== null) {
|
|
43
|
+
init.body = req.serializeBody();
|
|
44
|
+
}
|
|
45
|
+
return { url: req.urlWithParams, init };
|
|
46
|
+
}
|
|
47
|
+
async function toAngularResponse(response_type, fetchResponse) {
|
|
48
|
+
const responseHeaders = {};
|
|
49
|
+
fetchResponse.headers.forEach((value, key) => {
|
|
50
|
+
responseHeaders[key] = value;
|
|
51
|
+
});
|
|
52
|
+
const angularHeaders = new HttpHeaders(responseHeaders);
|
|
53
|
+
let body;
|
|
54
|
+
switch (response_type) {
|
|
55
|
+
case "json":
|
|
56
|
+
body = await fetchResponse.json();
|
|
57
|
+
break;
|
|
58
|
+
case "text":
|
|
59
|
+
body = await fetchResponse.text();
|
|
60
|
+
break;
|
|
61
|
+
case "arraybuffer":
|
|
62
|
+
body = await fetchResponse.arrayBuffer();
|
|
63
|
+
break;
|
|
64
|
+
case "blob":
|
|
65
|
+
body = await fetchResponse.blob();
|
|
66
|
+
break;
|
|
67
|
+
}
|
|
68
|
+
return new HttpResponse({
|
|
69
|
+
body,
|
|
70
|
+
headers: angularHeaders,
|
|
71
|
+
status: fetchResponse.status,
|
|
72
|
+
statusText: fetchResponse.statusText,
|
|
73
|
+
url: fetchResponse.url,
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
//# sourceMappingURL=interceptor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"interceptor.js","sourceRoot":"","sources":["../../../src/angular/interceptor.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,UAAU,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AAC/D,YAAY,EACV,iBAAiB,EACjB,aAAa,EACb,cAAc,EACd,mBAAmB,GACpB,MAAM,SAAS,CAAC"}
|
package/bin/src/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,iCAAiC;AAEjC,OAAO,EAAE,UAAU,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { ScionStackOptions } from "./types";
|
|
2
|
+
export declare const DEFAULT_WORKER_URL: string | URL;
|
|
3
|
+
export declare class ScionStack {
|
|
4
|
+
private worker;
|
|
5
|
+
constructor(options?: ScionStackOptions);
|
|
6
|
+
fetch(): typeof globalThis.fetch;
|
|
7
|
+
}
|
|
8
|
+
//# sourceMappingURL=scion-stack.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scion-stack.d.ts","sourceRoot":"","sources":["../../src/scion-stack.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,iBAAiB,EAGlB,MAAM,SAAS,CAAC;AAGjB,eAAO,MAAM,kBAAkB,EAAE,MAAM,GAAG,GAGzC,CAAC;AAEF,qBAAa,UAAU;IACrB,OAAO,CAAC,MAAM,CAAS;gBAEX,OAAO,CAAC,EAAE,iBAAiB;IAKvC,KAAK,IAAI,OAAO,UAAU,CAAC,KAAK;CAgEjC"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
// Copyright 2026 Anapaya Systems
|
|
2
|
+
import { isWorkerErrorResponse } from "./types";
|
|
3
|
+
export const DEFAULT_WORKER_URL = new URL("./worker/scion-worker.js", import.meta.url);
|
|
4
|
+
export class ScionStack {
|
|
5
|
+
worker;
|
|
6
|
+
constructor(options) {
|
|
7
|
+
const workerUrl = options?.workerUrl ?? DEFAULT_WORKER_URL;
|
|
8
|
+
this.worker = new Worker(workerUrl, { type: "module" });
|
|
9
|
+
}
|
|
10
|
+
fetch() {
|
|
11
|
+
return async (input, init) => {
|
|
12
|
+
const request = input instanceof Request ? input : new Request(input, init);
|
|
13
|
+
const url = request.url;
|
|
14
|
+
const method = request.method;
|
|
15
|
+
const headers = {};
|
|
16
|
+
request.headers.forEach((value, key) => {
|
|
17
|
+
headers[key] = value;
|
|
18
|
+
});
|
|
19
|
+
// Preserve the original body type from init (concrete: string, ArrayBuffer,
|
|
20
|
+
// Blob, etc.) instead of request.body which always returns a ReadableStream.
|
|
21
|
+
// This is required for Firefox which doesn't support ReadableStream as a
|
|
22
|
+
// fetch() body. Prefer init.body over input.body, matching standard fetch()
|
|
23
|
+
// precedence.
|
|
24
|
+
let body = null;
|
|
25
|
+
if (init && init.body !== undefined) {
|
|
26
|
+
body = init.body;
|
|
27
|
+
}
|
|
28
|
+
else if (input instanceof Request) {
|
|
29
|
+
body = input.body;
|
|
30
|
+
}
|
|
31
|
+
const msg = { url, method, headers, body };
|
|
32
|
+
const channel = new MessageChannel();
|
|
33
|
+
return new Promise((resolve, reject) => {
|
|
34
|
+
channel.port1.onmessage = (event) => {
|
|
35
|
+
channel.port1.close();
|
|
36
|
+
const res = event.data;
|
|
37
|
+
if (isWorkerErrorResponse(res)) {
|
|
38
|
+
reject(new Error(res.error));
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
resolve(new Response(res.body, {
|
|
42
|
+
status: res.status,
|
|
43
|
+
statusText: res.statusText,
|
|
44
|
+
headers: res.headers,
|
|
45
|
+
}));
|
|
46
|
+
};
|
|
47
|
+
// ArrayBuffer and ArrayBufferView bodies are structured-cloned (copied),
|
|
48
|
+
// matching native fetch() semantics — the caller retains ownership.
|
|
49
|
+
// ReadableStream cannot be cloned and must be transferred.
|
|
50
|
+
const transferables = [channel.port2];
|
|
51
|
+
if (body instanceof ReadableStream) {
|
|
52
|
+
transferables.push(body);
|
|
53
|
+
}
|
|
54
|
+
this.worker.postMessage(msg, transferables);
|
|
55
|
+
});
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
//# sourceMappingURL=scion-stack.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scion-stack.js","sourceRoot":"","sources":["../../src/scion-stack.ts"],"names":[],"mappings":"AAAA,iCAAiC;AAOjC,OAAO,EAAE,qBAAqB,EAAE,MAAM,SAAS,CAAC;AAEhD,MAAM,CAAC,MAAM,kBAAkB,GAAiB,IAAI,GAAG,CACrD,0BAA0B,EAC1B,MAAM,CAAC,IAAI,CAAC,GAAG,CAChB,CAAC;AAEF,MAAM,OAAO,UAAU;IACb,MAAM,CAAS;IAEvB,YAAY,OAA2B;QACrC,MAAM,SAAS,GAAG,OAAO,EAAE,SAAS,IAAI,kBAAkB,CAAC;QAC3D,IAAI,CAAC,MAAM,GAAG,IAAI,MAAM,CAAC,SAAS,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,CAAC;IAC1D,CAAC;IAED,KAAK;QACH,OAAO,KAAK,EACV,KAAwB,EACxB,IAAkB,EACC,EAAE;YACrB,MAAM,OAAO,GACX,KAAK,YAAY,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,OAAO,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;YAE9D,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC;YACxB,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;YAE9B,MAAM,OAAO,GAA2B,EAAE,CAAC;YAC3C,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,GAAG,EAAE,EAAE;gBACrC,OAAO,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;YACvB,CAAC,CAAC,CAAC;YAEH,4EAA4E;YAC5E,6EAA6E;YAC7E,yEAAyE;YACzE,4EAA4E;YAC5E,cAAc;YACd,IAAI,IAAI,GAAoB,IAAI,CAAC;YACjC,IAAI,IAAI,IAAI,IAAI,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;gBACpC,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC;YACnB,CAAC;iBAAM,IAAI,KAAK,YAAY,OAAO,EAAE,CAAC;gBACpC,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC;YACpB,CAAC;YAED,MAAM,GAAG,GAAkB,EAAE,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;YAE1D,MAAM,OAAO,GAAG,IAAI,cAAc,EAAE,CAAC;YAErC,OAAO,IAAI,OAAO,CAAW,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;gBAC/C,OAAO,CAAC,KAAK,CAAC,SAAS,GAAG,CACxB,KAA0C,EAC1C,EAAE;oBACF,OAAO,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;oBACtB,MAAM,GAAG,GAAG,KAAK,CAAC,IAAI,CAAC;oBAEvB,IAAI,qBAAqB,CAAC,GAAG,CAAC,EAAE,CAAC;wBAC/B,MAAM,CAAC,IAAI,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC;wBAC7B,OAAO;oBACT,CAAC;oBAED,OAAO,CACL,IAAI,QAAQ,CAAC,GAAG,CAAC,IAAI,EAAE;wBACrB,MAAM,EAAE,GAAG,CAAC,MAAM;wBAClB,UAAU,EAAE,GAAG,CAAC,UAAU;wBAC1B,OAAO,EAAE,GAAG,CAAC,OAAO;qBACrB,CAAC,CACH,CAAC;gBACJ,CAAC,CAAC;gBAEF,yEAAyE;gBACzE,oEAAoE;gBACpE,2DAA2D;gBAC3D,MAAM,aAAa,GAAmB,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;gBACtD,IAAI,IAAI,YAAY,cAAc,EAAE,CAAC;oBACnC,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gBAC3B,CAAC;gBACD,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,GAAG,EAAE,aAAa,CAAC,CAAC;YAC9C,CAAC,CAAC,CAAC;QACL,CAAC,CAAC;IACJ,CAAC;CACF"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export interface ScionStackOptions {
|
|
2
|
+
workerUrl?: string | URL;
|
|
3
|
+
logLevel?: "debug" | "info" | "warn" | "error";
|
|
4
|
+
}
|
|
5
|
+
export interface WorkerRequest {
|
|
6
|
+
url: string;
|
|
7
|
+
method: string;
|
|
8
|
+
headers: Record<string, string>;
|
|
9
|
+
body: BodyInit | null;
|
|
10
|
+
}
|
|
11
|
+
export interface WorkerResponse {
|
|
12
|
+
status: number;
|
|
13
|
+
statusText: string;
|
|
14
|
+
headers: Record<string, string>;
|
|
15
|
+
body: ReadableStream<Uint8Array> | null;
|
|
16
|
+
seqNr: number;
|
|
17
|
+
}
|
|
18
|
+
export interface WorkerErrorResponse {
|
|
19
|
+
error: string;
|
|
20
|
+
}
|
|
21
|
+
export type WorkerOutgoingMessage = WorkerResponse | WorkerErrorResponse;
|
|
22
|
+
export declare function isWorkerErrorResponse(msg: WorkerOutgoingMessage): msg is WorkerErrorResponse;
|
|
23
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,iBAAiB;IAChC,SAAS,CAAC,EAAE,MAAM,GAAG,GAAG,CAAC;IACzB,QAAQ,CAAC,EAAE,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC;CAChD;AAED,MAAM,WAAW,aAAa;IAC5B,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,IAAI,EAAE,QAAQ,GAAG,IAAI,CAAC;CACvB;AAED,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,IAAI,EAAE,cAAc,CAAC,UAAU,CAAC,GAAG,IAAI,CAAC;IACxC,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,mBAAmB;IAClC,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,MAAM,qBAAqB,GAAG,cAAc,GAAG,mBAAmB,CAAC;AAEzE,wBAAgB,qBAAqB,CACnC,GAAG,EAAE,qBAAqB,GACzB,GAAG,IAAI,mBAAmB,CAE5B"}
|
package/bin/src/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":"AAAA,iCAAiC;AA4BjC,MAAM,UAAU,qBAAqB,CACnC,GAA0B;IAE1B,OAAO,OAAO,IAAI,GAAG,CAAC;AACxB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scion-worker.d.ts","sourceRoot":"","sources":["../../../src/worker/scion-worker.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,CAAC"}
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
// Copyright 2026 Anapaya Systems
|
|
2
|
+
const encoder = new TextEncoder();
|
|
3
|
+
let requestCounter = 0;
|
|
4
|
+
self.onmessage = async (event) => {
|
|
5
|
+
const req = event.data;
|
|
6
|
+
const port = event.ports[0];
|
|
7
|
+
requestCounter++;
|
|
8
|
+
const seqNr = requestCounter;
|
|
9
|
+
try {
|
|
10
|
+
// Convert body to bytes for framing and hashing.
|
|
11
|
+
const bodyBytes = await bodyToBytes(req.body);
|
|
12
|
+
// Frame as HTTP/1.1
|
|
13
|
+
const framingStart = performance.now();
|
|
14
|
+
const framedBytes = frameHttp11(req.url, req.method, req.headers, bodyBytes);
|
|
15
|
+
const framingDuration = performance.now() - framingStart;
|
|
16
|
+
// Compute SHA-256 hash
|
|
17
|
+
const hashBuffer = await crypto.subtle.digest("SHA-256", framedBytes);
|
|
18
|
+
const hashHex = Array.from(new Uint8Array(hashBuffer))
|
|
19
|
+
.map((b) => b.toString(16).padStart(2, "0"))
|
|
20
|
+
.join("");
|
|
21
|
+
// Log diagnostics
|
|
22
|
+
const parsedUrl = new URL(req.url);
|
|
23
|
+
console.log(`[webscion] #${seqNr} ${req.method} ${parsedUrl.pathname} | ${framedBytes.byteLength} bytes | SHA-256: ${hashHex} | framing: ${framingDuration.toFixed(3)}ms`);
|
|
24
|
+
// Dispatch original request via native fetch
|
|
25
|
+
const fetchInit = {
|
|
26
|
+
method: req.method,
|
|
27
|
+
headers: req.headers,
|
|
28
|
+
};
|
|
29
|
+
if (req.body != null && req.method !== "GET" && req.method !== "HEAD") {
|
|
30
|
+
fetchInit.body = req.body;
|
|
31
|
+
}
|
|
32
|
+
const response = await fetch(req.url, fetchInit);
|
|
33
|
+
// Forward response back via the message port
|
|
34
|
+
const responseHeaders = {};
|
|
35
|
+
response.headers.forEach((value, key) => {
|
|
36
|
+
responseHeaders[key] = value;
|
|
37
|
+
});
|
|
38
|
+
const responseBody = response.body;
|
|
39
|
+
const msg = {
|
|
40
|
+
status: response.status,
|
|
41
|
+
statusText: response.statusText,
|
|
42
|
+
headers: responseHeaders,
|
|
43
|
+
body: responseBody,
|
|
44
|
+
seqNr,
|
|
45
|
+
};
|
|
46
|
+
const transferables = [];
|
|
47
|
+
if (responseBody) {
|
|
48
|
+
transferables.push(responseBody);
|
|
49
|
+
}
|
|
50
|
+
port.postMessage(msg, transferables);
|
|
51
|
+
port.close();
|
|
52
|
+
}
|
|
53
|
+
catch (err) {
|
|
54
|
+
const msg = {
|
|
55
|
+
error: err instanceof Error ? err.message : String(err),
|
|
56
|
+
};
|
|
57
|
+
port.postMessage(msg);
|
|
58
|
+
port.close();
|
|
59
|
+
}
|
|
60
|
+
};
|
|
61
|
+
async function bodyToBytes(body) {
|
|
62
|
+
if (body == null) {
|
|
63
|
+
return null;
|
|
64
|
+
}
|
|
65
|
+
if (typeof body === "string") {
|
|
66
|
+
return encoder.encode(body);
|
|
67
|
+
}
|
|
68
|
+
if (body instanceof ArrayBuffer) {
|
|
69
|
+
return new Uint8Array(body);
|
|
70
|
+
}
|
|
71
|
+
if (ArrayBuffer.isView(body)) {
|
|
72
|
+
return new Uint8Array(body.buffer, body.byteOffset, body.byteLength);
|
|
73
|
+
}
|
|
74
|
+
if (body instanceof Blob) {
|
|
75
|
+
return new Uint8Array(await body.arrayBuffer());
|
|
76
|
+
}
|
|
77
|
+
if (body instanceof URLSearchParams) {
|
|
78
|
+
return encoder.encode(body.toString());
|
|
79
|
+
}
|
|
80
|
+
if (body instanceof FormData) {
|
|
81
|
+
// Best-effort: serialize as URL-encoded form data.
|
|
82
|
+
const params = new URLSearchParams();
|
|
83
|
+
body.forEach((value, key) => {
|
|
84
|
+
if (typeof value === "string") {
|
|
85
|
+
params.append(key, value);
|
|
86
|
+
}
|
|
87
|
+
});
|
|
88
|
+
return encoder.encode(params.toString());
|
|
89
|
+
}
|
|
90
|
+
// ReadableStream fallback
|
|
91
|
+
if (body instanceof ReadableStream) {
|
|
92
|
+
const reader = body.getReader();
|
|
93
|
+
const chunks = [];
|
|
94
|
+
let totalLength = 0;
|
|
95
|
+
while (true) {
|
|
96
|
+
const { done, value } = await reader.read();
|
|
97
|
+
if (done)
|
|
98
|
+
break;
|
|
99
|
+
chunks.push(value);
|
|
100
|
+
totalLength += value.byteLength;
|
|
101
|
+
}
|
|
102
|
+
const result = new Uint8Array(new ArrayBuffer(totalLength));
|
|
103
|
+
let offset = 0;
|
|
104
|
+
for (const chunk of chunks) {
|
|
105
|
+
result.set(chunk, offset);
|
|
106
|
+
offset += chunk.byteLength;
|
|
107
|
+
}
|
|
108
|
+
return result;
|
|
109
|
+
}
|
|
110
|
+
return null;
|
|
111
|
+
}
|
|
112
|
+
function frameHttp11(url, method, headers, body) {
|
|
113
|
+
const parsedUrl = new URL(url);
|
|
114
|
+
const path = parsedUrl.pathname + parsedUrl.search;
|
|
115
|
+
const host = parsedUrl.host;
|
|
116
|
+
let headerBlock = `${method} ${path} HTTP/1.1\r\nHost: ${host}\r\n`;
|
|
117
|
+
for (const [key, value] of Object.entries(headers)) {
|
|
118
|
+
headerBlock += `${key}: ${value}\r\n`;
|
|
119
|
+
}
|
|
120
|
+
headerBlock += "\r\n";
|
|
121
|
+
const headerBytes = encoder.encode(headerBlock);
|
|
122
|
+
if (!body || body.byteLength === 0) {
|
|
123
|
+
return headerBytes;
|
|
124
|
+
}
|
|
125
|
+
const result = new Uint8Array(new ArrayBuffer(headerBytes.byteLength + body.byteLength));
|
|
126
|
+
result.set(headerBytes, 0);
|
|
127
|
+
result.set(body, headerBytes.byteLength);
|
|
128
|
+
return result;
|
|
129
|
+
}
|
|
130
|
+
export {};
|
|
131
|
+
//# sourceMappingURL=scion-worker.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scion-worker.js","sourceRoot":"","sources":["../../../src/worker/scion-worker.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@anapaya/webscion-poc",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"main": "./bin/src/index.js",
|
|
6
|
+
"types": "./bin/src/index.d.ts",
|
|
7
|
+
"files": [
|
|
8
|
+
"bin/**",
|
|
9
|
+
"README.md",
|
|
10
|
+
"angular.js",
|
|
11
|
+
"angular.d.ts"
|
|
12
|
+
],
|
|
13
|
+
"exports": {
|
|
14
|
+
".": {
|
|
15
|
+
"import": "./bin/src/index.js",
|
|
16
|
+
"types": "./bin/src/index.d.ts"
|
|
17
|
+
},
|
|
18
|
+
"./angular": {
|
|
19
|
+
"import": "./bin/src/angular/index.js",
|
|
20
|
+
"types": "./bin/src/angular/index.d.ts"
|
|
21
|
+
},
|
|
22
|
+
"./worker": {
|
|
23
|
+
"default": "./bin/src/worker/scion-worker.js"
|
|
24
|
+
}
|
|
25
|
+
},
|
|
26
|
+
"peerDependencies": {
|
|
27
|
+
"@angular/core": "^17.0.0 || ^18.0.0 || ^19.0.0 || ^20.0.0",
|
|
28
|
+
"@angular/common": "^17.0.0 || ^18.0.0 || ^19.0.0 || ^20.0.0"
|
|
29
|
+
},
|
|
30
|
+
"peerDependenciesMeta": {
|
|
31
|
+
"@angular/core": {
|
|
32
|
+
"optional": true
|
|
33
|
+
},
|
|
34
|
+
"@angular/common": {
|
|
35
|
+
"optional": true
|
|
36
|
+
}
|
|
37
|
+
},
|
|
38
|
+
"devDependencies": {
|
|
39
|
+
"@angular/compiler": "^20.0.0",
|
|
40
|
+
"@angular/core": "^20.0.0",
|
|
41
|
+
"@angular/common": "^20.0.0",
|
|
42
|
+
"rxjs": "^7.8.0",
|
|
43
|
+
"typescript": "5.8.3",
|
|
44
|
+
"vitest": "^3.2.1"
|
|
45
|
+
},
|
|
46
|
+
"publishConfig": {
|
|
47
|
+
"registry": "https://registry.npmjs.org",
|
|
48
|
+
"access": "public"
|
|
49
|
+
},
|
|
50
|
+
"scripts": {
|
|
51
|
+
"build": "rm -rf bin && tsc -p tsconfig.json && tsc -p tsconfig.worker.json",
|
|
52
|
+
"test": "vitest run"
|
|
53
|
+
}
|
|
54
|
+
}
|