@yodaos-pkg/ink 0.1.0 → 0.2.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/README.md CHANGED
@@ -36,8 +36,7 @@ Before integrating the SDK, make sure you have one of these two inputs:
36
36
  - This is a good fit when assets live on the server and the browser fetches
37
37
  them on demand.
38
38
 
39
- If you use the VFS flow, the server side usually works together with
40
- `@yodaos-pkg/ink-vfs-server`.
39
+ If you use the VFS flow, provide your own HTTP VFS endpoint on the server side.
41
40
 
42
41
  ## Installation
43
42
 
@@ -47,10 +46,11 @@ If you use the VFS flow, the server side usually works together with
47
46
  npm install @yodaos-pkg/ink
48
47
  ```
49
48
 
50
- If you also want to use the VFS flow, install the server package as well:
49
+ If you also want to use the VFS flow, prepare an HTTP endpoint that exposes:
51
50
 
52
- ```bash
53
- npm install @yodaos-pkg/ink-vfs-server
51
+ ```text
52
+ GET /apps/:appId/manifest
53
+ GET /apps/:appId/files/:path
54
54
  ```
55
55
 
56
56
  ## Core API
@@ -94,6 +94,54 @@ Creates an `InkView` instance and initializes the wasm runtime internally.
94
94
  - Resolves to an `InkView` instance that can then call
95
95
  `bindDomEvents()`, `openBundle()`, and `openFromVfs()`
96
96
 
97
+ ### `configureNetwork(options)`
98
+
99
+ Configures host-controlled request interception for Ink network traffic.
100
+
101
+ **Parameters**
102
+
103
+ - `options.interceptor`
104
+ - Optional
105
+ - A function that receives the outgoing request and returns an action
106
+ - `options.proxyUrl`
107
+ - Optional
108
+ - A convenience option for rewriting requests through a proxy endpoint
109
+ - `options.targetSearchParam`
110
+ - Optional
111
+ - The query parameter name used when `proxyUrl` is provided
112
+ - `options.clear`
113
+ - Optional
114
+ - Clears the previously registered interceptor
115
+
116
+ **What it does**
117
+
118
+ - Registers a global Ink request interceptor
119
+ - Lets hosts continue, rewrite, or block outgoing requests
120
+ - Mirrors the shape of a WebView-style request interception hook
121
+
122
+ **Returns**
123
+
124
+ - `void`
125
+
126
+ ### `createProxyUrlResolver(options)`
127
+
128
+ Creates a request interceptor that rewrites outgoing requests to a host-managed
129
+ proxy endpoint such as `'/__proxy?url=...'`.
130
+
131
+ **Parameters**
132
+
133
+ - `options.proxyUrl`
134
+ - Required
135
+ - The proxy endpoint to call
136
+ - `options.targetSearchParam`
137
+ - Optional
138
+ - The query parameter name that receives the original target URL
139
+
140
+ **Returns**
141
+
142
+ - `InkRequestInterceptor`
143
+ - A reusable interceptor for `configureNetwork()` or `initInk()`
144
+
97
145
  ### `view.bindDomEvents(options?)`
98
146
 
99
147
  Binds common DOM events to the current `InkView`.
@@ -191,6 +239,9 @@ Fetches an Ink bundle from a remote HTTP VFS service and opens it.
191
239
  - `options.headers?: HeadersInit`
192
240
  - Optional
193
241
  - Extra request headers
242
+ - `options.requestInterceptor?: InkRequestInterceptor`
243
+ - Optional
244
+ - Overrides the global interceptor for this VFS load only
194
245
  - `options.initialPage?: string | null`
195
246
  - Optional
196
247
  - Sets the first page to open
@@ -203,6 +254,7 @@ Fetches an Ink bundle from a remote HTTP VFS service and opens it.
203
254
  - Fetches the VFS manifest first
204
255
  - Fetches each file listed in the manifest
205
256
  - Reconstructs the bundle in the browser
257
+ - Applies the request interceptor when one is configured
206
258
  - Calls `openBundle()` automatically
207
259
 
208
260
  **Returns**
@@ -213,6 +265,30 @@ Fetches an Ink bundle from a remote HTTP VFS service and opens it.
213
265
  - `manifest: VfsManifest`
214
266
  - `files: Map<string, Uint8Array>`
215
267
 
268
+ ### `initInk(options)`
269
+
270
+ Initializes the wasm runtime and optionally installs a host networking policy.
271
+
272
+ **Parameters**
273
+
274
+ - `options.wasmUrl?: string | URL | Request`
275
+ - Optional
276
+ - Custom URL for the wasm binary
277
+ - `options.moduleOrPath?: RequestInfo | URL | Response | BufferSource | WebAssembly.Module`
278
+ - Optional
279
+ - Custom wasm module input supported by `wasm-bindgen`
280
+ - `options.requestInterceptor?: InkRequestInterceptor`
281
+ - Optional
282
+ - Installs a host request interceptor before Ink networking starts
283
+ - `options.proxyUrl?: string`
284
+ - Optional
285
+ - Shorthand for a proxy-based interceptor
286
+
287
+ **Returns**
288
+
289
+ - `Promise<{ InkWebView, getInkVersion }>`
290
+ - Resolves to the wasm bindings
291
+
216
292
  ### `view.startRendering()`
217
293
 
218
294
  Starts the continuous render loop.
package/dist/README.md CHANGED
@@ -36,8 +36,7 @@ Before integrating the SDK, make sure you have one of these two inputs:
36
36
  - This is a good fit when assets live on the server and the browser fetches
37
37
  them on demand.
38
38
 
39
- If you use the VFS flow, the server side usually works together with
40
- `@yodaos-pkg/ink-vfs-server`.
39
+ If you use the VFS flow, provide your own HTTP VFS endpoint on the server side.
41
40
 
42
41
  ## Installation
43
42
 
@@ -47,10 +46,11 @@ If you use the VFS flow, the server side usually works together with
47
46
  npm install @yodaos-pkg/ink
48
47
  ```
49
48
 
50
- If you also want to use the VFS flow, install the server package as well:
49
+ If you also want to use the VFS flow, prepare an HTTP endpoint that exposes:
51
50
 
52
- ```bash
53
- npm install @yodaos-pkg/ink-vfs-server
51
+ ```text
52
+ GET /apps/:appId/manifest
53
+ GET /apps/:appId/files/:path
54
54
  ```
55
55
 
56
56
  ## Core API
@@ -94,6 +94,54 @@ Creates an `InkView` instance and initializes the wasm runtime internally.
94
94
  - Resolves to an `InkView` instance that can then call
95
95
  `bindDomEvents()`, `openBundle()`, and `openFromVfs()`
96
96
 
97
+ ### `configureNetwork(options)`
98
+
99
+ Configures host-controlled request interception for Ink network traffic.
100
+
101
+ **Parameters**
102
+
103
+ - `options.interceptor`
104
+ - Optional
105
+ - A function that receives the outgoing request and returns an action
106
+ - `options.proxyUrl`
107
+ - Optional
108
+ - A convenience option for rewriting requests through a proxy endpoint
109
+ - `options.targetSearchParam`
110
+ - Optional
111
+ - The query parameter name used when `proxyUrl` is provided
112
+ - `options.clear`
113
+ - Optional
114
+ - Clears the previously registered interceptor
115
+
116
+ **What it does**
117
+
118
+ - Registers a global Ink request interceptor
119
+ - Lets hosts continue, rewrite, or block outgoing requests
120
+ - Mirrors the shape of a WebView-style request interception hook
121
+
122
+ **Returns**
123
+
124
+ - `void`
125
+
126
+ ### `createProxyUrlResolver(options)`
127
+
128
+ Creates a request interceptor that rewrites outgoing requests to a host-managed
129
+ proxy endpoint such as `'/__proxy?url=...'`.
130
+
131
+ **Parameters**
132
+
133
+ - `options.proxyUrl`
134
+ - Required
135
+ - The proxy endpoint to call
136
+ - `options.targetSearchParam`
137
+ - Optional
138
+ - The query parameter name that receives the original target URL
139
+
140
+ **Returns**
141
+
142
+ - `InkRequestInterceptor`
143
+ - A reusable interceptor for `configureNetwork()` or `initInk()`
144
+
97
145
  ### `view.bindDomEvents(options?)`
98
146
 
99
147
  Binds common DOM events to the current `InkView`.
@@ -191,6 +239,9 @@ Fetches an Ink bundle from a remote HTTP VFS service and opens it.
191
239
  - `options.headers?: HeadersInit`
192
240
  - Optional
193
241
  - Extra request headers
242
+ - `options.requestInterceptor?: InkRequestInterceptor`
243
+ - Optional
244
+ - Overrides the global interceptor for this VFS load only
194
245
  - `options.initialPage?: string | null`
195
246
  - Optional
196
247
  - Sets the first page to open
@@ -203,6 +254,7 @@ Fetches an Ink bundle from a remote HTTP VFS service and opens it.
203
254
  - Fetches the VFS manifest first
204
255
  - Fetches each file listed in the manifest
205
256
  - Reconstructs the bundle in the browser
257
+ - Applies the request interceptor when one is configured
206
258
  - Calls `openBundle()` automatically
207
259
 
208
260
  **Returns**
@@ -213,6 +265,30 @@ Fetches an Ink bundle from a remote HTTP VFS service and opens it.
213
265
  - `manifest: VfsManifest`
214
266
  - `files: Map<string, Uint8Array>`
215
267
 
268
+ ### `initInk(options)`
269
+
270
+ Initializes the wasm runtime and optionally installs a host networking policy.
271
+
272
+ **Parameters**
273
+
274
+ - `options.wasmUrl?: string | URL | Request`
275
+ - Optional
276
+ - Custom URL for the wasm binary
277
+ - `options.moduleOrPath?: RequestInfo | URL | Response | BufferSource | WebAssembly.Module`
278
+ - Optional
279
+ - Custom wasm module input supported by `wasm-bindgen`
280
+ - `options.requestInterceptor?: InkRequestInterceptor`
281
+ - Optional
282
+ - Installs a host request interceptor before Ink networking starts
283
+ - `options.proxyUrl?: string`
284
+ - Optional
285
+ - Shorthand for a proxy-based interceptor
286
+
287
+ **Returns**
288
+
289
+ - `Promise<{ InkWebView, getInkVersion }>`
290
+ - Resolves to the wasm bindings
291
+
216
292
  ### `view.startRendering()`
217
293
 
218
294
  Starts the continuous render loop.
package/dist/env.js CHANGED
@@ -2,11 +2,167 @@ let wasmExports = null;
2
2
  const allocationSizes = new Map();
3
3
  const textDecoder = new TextDecoder('utf-8', { fatal: false });
4
4
  const textEncoder = new TextEncoder();
5
+ let inkRequestInterceptor = null;
5
6
 
6
7
  export function __setWasmInstance(exports) {
7
8
  wasmExports = exports;
8
9
  }
9
10
 
11
+ function ensureFetchImplementation(fetchImpl) {
12
+ const resolved = fetchImpl || globalThis.fetch;
13
+ if (typeof resolved !== 'function') {
14
+ throw new Error('A fetch implementation is required for Ink networking.');
15
+ }
16
+ return resolved;
17
+ }
18
+
19
+ function headersToObject(headersLike) {
20
+ if (!headersLike) {
21
+ return {};
22
+ }
23
+ if (typeof Headers !== 'undefined' && headersLike instanceof Headers) {
24
+ const result = {};
25
+ for (const [name, value] of headersLike.entries()) {
26
+ result[name] = value;
27
+ }
28
+ return result;
29
+ }
30
+ if (Array.isArray(headersLike)) {
31
+ const result = {};
32
+ for (const entry of headersLike) {
33
+ if (!Array.isArray(entry) || entry.length < 2) {
34
+ continue;
35
+ }
36
+ result[String(entry[0])] = String(entry[1]);
37
+ }
38
+ return result;
39
+ }
40
+ if (headersLike && typeof headersLike === 'object') {
41
+ return Object.fromEntries(
42
+ Object.entries(headersLike).map(([name, value]) => [name, Array.isArray(value) ? value.join(', ') : String(value)]),
43
+ );
44
+ }
45
+ return {};
46
+ }
47
+
48
+ function cloneBody(body) {
49
+ if (body == null) {
50
+ return null;
51
+ }
52
+ if (typeof body === 'string') {
53
+ return body;
54
+ }
55
+ if (body instanceof Uint8Array) {
56
+ return new Uint8Array(body);
57
+ }
58
+ if (ArrayBuffer.isView(body)) {
59
+ return new Uint8Array(body.buffer.slice(body.byteOffset, body.byteOffset + body.byteLength));
60
+ }
61
+ if (body instanceof ArrayBuffer) {
62
+ return body.slice(0);
63
+ }
64
+ return body;
65
+ }
66
+
67
+ function normalizeRequest(input, init = {}, metadata = {}) {
68
+ const url = typeof input === 'string' ? input : String(input);
69
+ return {
70
+ url,
71
+ method: String(init.method || 'GET').toUpperCase(),
72
+ headers: headersToObject(init.headers),
73
+ body: cloneBody(init.body),
74
+ metadata: metadata && typeof metadata === 'object' ? { ...metadata } : {},
75
+ };
76
+ }
77
+
78
+ function normalizeInterceptorResult(request, result) {
79
+ if (result == null || result === false) {
80
+ return {
81
+ url: request.url,
82
+ init: {
83
+ method: request.method,
84
+ headers: request.headers,
85
+ body: request.body,
86
+ },
87
+ };
88
+ }
89
+
90
+ if (typeof result !== 'object') {
91
+ throw new TypeError('Ink request interceptor must return an object, null, or undefined.');
92
+ }
93
+
94
+ const action = result.action || 'rewrite';
95
+ if (action === 'continue') {
96
+ return {
97
+ url: request.url,
98
+ init: {
99
+ method: request.method,
100
+ headers: request.headers,
101
+ body: request.body,
102
+ },
103
+ };
104
+ }
105
+
106
+ if (action === 'block') {
107
+ throw new Error(result.reason || `Ink request blocked: ${request.url}`);
108
+ }
109
+
110
+ if (action !== 'rewrite') {
111
+ throw new Error(`Unsupported Ink request interceptor action: ${action}`);
112
+ }
113
+
114
+ return {
115
+ url: typeof result.url === 'string' && result.url ? result.url : request.url,
116
+ init: {
117
+ method: typeof result.method === 'string' && result.method ? result.method : request.method,
118
+ headers: result.headers ? headersToObject(result.headers) : request.headers,
119
+ body: Object.prototype.hasOwnProperty.call(result, 'body') ? result.body : request.body,
120
+ },
121
+ };
122
+ }
123
+
124
+ async function resolveInkFetchRequest(input, init = {}, metadata = {}, interceptorOverride = null) {
125
+ const request = normalizeRequest(input, init, metadata);
126
+ const interceptor = interceptorOverride || inkRequestInterceptor;
127
+ if (!interceptor) {
128
+ return {
129
+ url: request.url,
130
+ init: {
131
+ method: request.method,
132
+ headers: request.headers,
133
+ body: request.body,
134
+ },
135
+ };
136
+ }
137
+ const result = await interceptor(request);
138
+ return normalizeInterceptorResult(request, result);
139
+ }
140
+
141
+ export function setInkRequestInterceptor(interceptor) {
142
+ if (interceptor != null && typeof interceptor !== 'function') {
143
+ throw new TypeError('Ink request interceptor must be a function, null, or undefined.');
144
+ }
145
+ inkRequestInterceptor = interceptor || null;
146
+ }
147
+
148
+ export function clearInkRequestInterceptor() {
149
+ inkRequestInterceptor = null;
150
+ }
151
+
152
+ export async function __inkFetch(input, init, metadata) {
153
+ const resolved = await resolveInkFetchRequest(input, init, metadata);
154
+ const fetchImpl = ensureFetchImplementation();
155
+ return fetchImpl(resolved.url, resolved.init);
156
+ }
157
+
158
+ export async function fetchWithInkRequestInterceptor(input, init = {}, options = {}) {
159
+ const resolved = await resolveInkFetchRequest(input, init, options.metadata, options.interceptor || null);
160
+ const fetchImpl = ensureFetchImplementation(options.fetch);
161
+ return fetchImpl(resolved.url, resolved.init);
162
+ }
163
+
164
+ globalThis.__inkFetch = __inkFetch;
165
+
10
166
  function requireWasm() {
11
167
  if (!wasmExports) {
12
168
  throw new Error('Wasm exports are not initialized');
package/dist/index.d.ts CHANGED
@@ -12,6 +12,9 @@ export type BundleFiles =
12
12
  export interface InitInkOptions {
13
13
  wasmUrl?: string | URL | Request;
14
14
  moduleOrPath?: RequestInfo | URL | Response | BufferSource | WebAssembly.Module;
15
+ proxyUrl?: string;
16
+ targetSearchParam?: string;
17
+ requestInterceptor?: InkRequestInterceptor;
15
18
  }
16
19
 
17
20
  export interface CreateInkViewOptions {
@@ -35,6 +38,7 @@ export interface LoadBundleFromVfsOptions {
35
38
  fetch?: typeof globalThis.fetch;
36
39
  signal?: AbortSignal;
37
40
  headers?: HeadersInit;
41
+ requestInterceptor?: InkRequestInterceptor;
38
42
  }
39
43
 
40
44
  export interface OpenFromVfsOptions extends LoadBundleFromVfsOptions {
@@ -42,6 +46,39 @@ export interface OpenFromVfsOptions extends LoadBundleFromVfsOptions {
42
46
  query?: string | Record<string, unknown> | null;
43
47
  }
44
48
 
49
+ export interface InkInterceptedRequest {
50
+ url: string;
51
+ method: string;
52
+ headers: Record<string, string>;
53
+ body: BodyInit | ArrayBuffer | ArrayBufferView | Uint8Array | null;
54
+ metadata: Record<string, unknown>;
55
+ }
56
+
57
+ export type InkInterceptedRequestAction =
58
+ | { action?: 'continue' }
59
+ | {
60
+ action: 'rewrite';
61
+ url?: string;
62
+ method?: string;
63
+ headers?: HeadersInit | Record<string, string>;
64
+ body?: BodyInit | ArrayBuffer | ArrayBufferView | Uint8Array | null;
65
+ }
66
+ | {
67
+ action: 'block';
68
+ reason?: string;
69
+ };
70
+
71
+ export type InkRequestInterceptor = (
72
+ request: InkInterceptedRequest,
73
+ ) => InkInterceptedRequestAction | Promise<InkInterceptedRequestAction>;
74
+
75
+ export interface ConfigureNetworkOptions {
76
+ proxyUrl?: string;
77
+ targetSearchParam?: string;
78
+ interceptor?: InkRequestInterceptor;
79
+ clear?: boolean;
80
+ }
81
+
45
82
  export interface VfsManifestEntry {
46
83
  path: string;
47
84
  size?: number;
@@ -78,6 +115,17 @@ export declare function normalizeBundleFiles(files: BundleFiles): Map<string, Ui
78
115
 
79
116
  export declare function serializeQuery(query: string | Record<string, unknown> | null | undefined): string | null;
80
117
 
118
+ export declare function createProxyUrlResolver(options: {
119
+ proxyUrl: string;
120
+ targetSearchParam?: string;
121
+ }): InkRequestInterceptor;
122
+
123
+ export declare function setInkRequestInterceptor(interceptor: InkRequestInterceptor | null | undefined): void;
124
+
125
+ export declare function clearInkRequestInterceptor(): void;
126
+
127
+ export declare function configureNetwork(options?: ConfigureNetworkOptions): void;
128
+
81
129
  export declare function createVfsUrls(input: {
82
130
  baseUrl: string;
83
131
  appId: string;
@@ -112,4 +160,8 @@ export declare function createFrameworkBindings(): {
112
160
  ensureLeadingSlash(path: string): string;
113
161
  initInk: typeof initInk;
114
162
  createInkView: typeof createInkView;
163
+ configureNetwork: typeof configureNetwork;
164
+ setInkRequestInterceptor: typeof setInkRequestInterceptor;
165
+ clearInkRequestInterceptor: typeof clearInkRequestInterceptor;
166
+ createProxyUrlResolver: typeof createProxyUrlResolver;
115
167
  };
package/dist/index.js CHANGED
@@ -2,6 +2,11 @@ import initInkWasm, {
2
2
  InkWebView as RawInkWebView,
3
3
  get_version as getInkVersionFromWasm,
4
4
  } from './pkg/ink_web.js';
5
+ import {
6
+ clearInkRequestInterceptor as clearInkRequestInterceptorBridge,
7
+ fetchWithInkRequestInterceptor,
8
+ setInkRequestInterceptor as setInkRequestInterceptorBridge,
9
+ } from './env.js';
5
10
 
6
11
  let bindingsPromise;
7
12
 
@@ -97,6 +102,51 @@ export function serializeQuery(query) {
97
102
  return JSON.stringify(query);
98
103
  }
99
104
 
105
+ export function createProxyUrlResolver({ proxyUrl, targetSearchParam = 'url' }) {
106
+ if (typeof proxyUrl !== 'string' || !proxyUrl.trim()) {
107
+ throw new Error('`proxyUrl` must be a non-empty string.');
108
+ }
109
+ if (typeof targetSearchParam !== 'string' || !targetSearchParam.trim()) {
110
+ throw new Error('`targetSearchParam` must be a non-empty string.');
111
+ }
112
+
113
+ const normalizedProxyUrl = proxyUrl.trim();
114
+ const normalizedTargetSearchParam = targetSearchParam.trim();
115
+ return (request) => {
116
+ const target = new URL(normalizedProxyUrl, globalThis.location?.href || 'http://localhost');
117
+ target.searchParams.set(normalizedTargetSearchParam, request.url);
118
+ return {
119
+ action: 'rewrite',
120
+ url: target.toString(),
121
+ method: request.method,
122
+ headers: request.headers,
123
+ body: request.body,
124
+ };
125
+ };
126
+ }
127
+
128
+ export function setInkRequestInterceptor(interceptor) {
129
+ setInkRequestInterceptorBridge(interceptor);
130
+ }
131
+
132
+ export function clearInkRequestInterceptor() {
133
+ clearInkRequestInterceptorBridge();
134
+ }
135
+
136
+ export function configureNetwork(options = {}) {
137
+ if (options.interceptor) {
138
+ setInkRequestInterceptor(options.interceptor);
139
+ return;
140
+ }
141
+ if (options.proxyUrl) {
142
+ setInkRequestInterceptor(createProxyUrlResolver(options));
143
+ return;
144
+ }
145
+ if (options.clear) {
146
+ clearInkRequestInterceptor();
147
+ }
148
+ }
149
+
100
150
  async function buildHttpError(response, bodyReader = (res) => res.text()) {
101
151
  let details = response.statusText;
102
152
  try {
@@ -137,11 +187,21 @@ export async function loadBundleFromVfs({
137
187
  fetch: fetchImpl,
138
188
  signal,
139
189
  headers,
190
+ requestInterceptor,
140
191
  }) {
141
192
  const resolvedFetch = ensureFetch(fetchImpl);
193
+ const wrappedFetch = async (url, init) =>
194
+ fetchWithInkRequestInterceptor(url, init, {
195
+ fetch: resolvedFetch,
196
+ interceptor: requestInterceptor || null,
197
+ metadata: {
198
+ kind: 'vfs',
199
+ appId,
200
+ },
201
+ });
142
202
  const { manifestUrl, fileUrl } = createVfsUrls({ baseUrl, appId });
143
203
 
144
- const manifestResponse = await resolvedFetch(manifestUrl, {
204
+ const manifestResponse = await wrappedFetch(manifestUrl, {
145
205
  method: 'GET',
146
206
  headers,
147
207
  signal,
@@ -162,7 +222,7 @@ export async function loadBundleFromVfs({
162
222
  throw new Error('Each VFS manifest entry must include a non-empty `path`.');
163
223
  }
164
224
 
165
- const response = await resolvedFetch(fileUrl(entry.path), {
225
+ const response = await wrappedFetch(fileUrl(entry.path), {
166
226
  method: 'GET',
167
227
  headers,
168
228
  signal,
@@ -217,6 +277,12 @@ function ensureAnimationFrameApi() {
217
277
  }
218
278
 
219
279
  export async function initInk(options = {}) {
280
+ if (options.requestInterceptor) {
281
+ setInkRequestInterceptor(options.requestInterceptor);
282
+ } else if (options.proxyUrl) {
283
+ setInkRequestInterceptor(createProxyUrlResolver(options));
284
+ }
285
+
220
286
  if (!bindingsPromise) {
221
287
  const initInput = options.wasmUrl || options.moduleOrPath || new URL('./pkg/ink_web_bg.wasm', import.meta.url);
222
288
  bindingsPromise = initInkWasm(initInput).then(() => ({
@@ -377,13 +443,23 @@ export class InkView {
377
443
  return this;
378
444
  }
379
445
 
380
- async openFromVfs({ appId, baseUrl, initialPage = null, query = null, fetch, signal, headers }) {
446
+ async openFromVfs({
447
+ appId,
448
+ baseUrl,
449
+ initialPage = null,
450
+ query = null,
451
+ fetch,
452
+ signal,
453
+ headers,
454
+ requestInterceptor,
455
+ }) {
381
456
  const bundle = await loadBundleFromVfs({
382
457
  appId,
383
458
  baseUrl,
384
459
  fetch,
385
460
  signal,
386
461
  headers,
462
+ requestInterceptor,
387
463
  });
388
464
  this.openBundle({
389
465
  appId: bundle.appId,
@@ -472,5 +548,9 @@ export function createFrameworkBindings() {
472
548
  ensureLeadingSlash,
473
549
  initInk,
474
550
  createInkView,
551
+ configureNetwork,
552
+ setInkRequestInterceptor,
553
+ clearInkRequestInterceptor,
554
+ createProxyUrlResolver,
475
555
  };
476
556
  }
@@ -17,7 +17,7 @@ This package compiles the Ink engine into Wasm, enabling it to run in modern web
17
17
  ./build.sh
18
18
  ```
19
19
 
20
- 2. Start the bundled Node static server and proxy:
20
+ 2. Start the bundled Node static server:
21
21
 
22
22
  ```bash
23
23
  npm run dev --prefix playground
@@ -29,6 +29,6 @@ npm run dev --prefix playground
29
29
  http://localhost:8080
30
30
  ```
31
31
 
32
- The local server also exposes a same-origin `/__proxy` endpoint for external HTTP resources so
33
- the demo can load remote images and other browser-fetched assets without direct cross-origin
34
- requests from the page.
32
+ The playground host configures a same-origin `/__proxy` interceptor example for
33
+ external HTTP resources. This proxy behavior is no longer hard-coded inside
34
+ `ink-web`; hosts now opt into request interception explicitly from the SDK side.
@@ -41,11 +41,11 @@ export interface InitOutput {
41
41
  readonly inkwebview_render: (a: number, b: number) => void;
42
42
  readonly inkwebview_resize: (a: number, b: number, c: number, d: number) => void;
43
43
  readonly main: () => void;
44
- readonly __wasm_bindgen_func_elem_8675: (a: number, b: number) => void;
45
- readonly __wasm_bindgen_func_elem_12871: (a: number, b: number) => void;
46
- readonly __wasm_bindgen_func_elem_8855: (a: number, b: number, c: number) => void;
47
- readonly __wasm_bindgen_func_elem_12872: (a: number, b: number, c: number) => void;
48
- readonly __wasm_bindgen_func_elem_8856: (a: number, b: number) => void;
44
+ readonly __wasm_bindgen_func_elem_8655: (a: number, b: number) => void;
45
+ readonly __wasm_bindgen_func_elem_12872: (a: number, b: number) => void;
46
+ readonly __wasm_bindgen_func_elem_8822: (a: number, b: number, c: number) => void;
47
+ readonly __wasm_bindgen_func_elem_12873: (a: number, b: number, c: number) => void;
48
+ readonly __wasm_bindgen_func_elem_8821: (a: number, b: number) => void;
49
49
  readonly __wbindgen_export: (a: number, b: number) => number;
50
50
  readonly __wbindgen_export2: (a: number, b: number, c: number, d: number) => number;
51
51
  readonly __wbindgen_export3: (a: number) => void;
@@ -314,6 +314,10 @@ function __wbg_get_imports() {
314
314
  const ret = getObject(arg0).call(getObject(arg1));
315
315
  return addHeapObject(ret);
316
316
  }, arguments); },
317
+ __wbg_call_e8c868596c950cf6: function() { return handleError(function (arg0, arg1, arg2, arg3, arg4) {
318
+ const ret = getObject(arg0).call(getObject(arg1), getObject(arg2), getObject(arg3), getObject(arg4));
319
+ return addHeapObject(ret);
320
+ }, arguments); },
317
321
  __wbg_clearRect_1eed255045515c55: function(arg0, arg1, arg2, arg3, arg4) {
318
322
  getObject(arg0).clearRect(arg1, arg2, arg3, arg4);
319
323
  },
@@ -433,10 +437,6 @@ function __wbg_get_imports() {
433
437
  __wbg_error_9a7fe3f932034cde: function(arg0) {
434
438
  console.error(getObject(arg0));
435
439
  },
436
- __wbg_fetch_7f864e6b0cbd00ea: function(arg0, arg1, arg2, arg3) {
437
- const ret = getObject(arg0).fetch(getStringFromWasm0(arg1, arg2), getObject(arg3));
438
- return addHeapObject(ret);
439
- },
440
440
  __wbg_fillRect_d44afec47e3a3fab: function(arg0, arg1, arg2, arg3, arg4) {
441
441
  getObject(arg0).fillRect(arg1, arg2, arg3, arg4);
442
442
  },
@@ -943,28 +943,28 @@ function __wbg_get_imports() {
943
943
  return ret;
944
944
  },
945
945
  __wbindgen_cast_0000000000000001: function(arg0, arg1) {
946
- // Cast intrinsic for `Closure(Closure { dtor_idx: 2341, function: Function { arguments: [NamedExternref("CloseEvent")], shim_idx: 2298, ret: Unit, inner_ret: Some(Unit) }, mutable: true }) -> Externref`.
947
- const ret = makeMutClosure(arg0, arg1, wasm.__wasm_bindgen_func_elem_8675, __wasm_bindgen_func_elem_8855);
946
+ // Cast intrinsic for `Closure(Closure { dtor_idx: 2276, function: Function { arguments: [NamedExternref("CloseEvent")], shim_idx: 2278, ret: Unit, inner_ret: Some(Unit) }, mutable: true }) -> Externref`.
947
+ const ret = makeMutClosure(arg0, arg1, wasm.__wasm_bindgen_func_elem_8655, __wasm_bindgen_func_elem_8822);
948
948
  return addHeapObject(ret);
949
949
  },
950
950
  __wbindgen_cast_0000000000000002: function(arg0, arg1) {
951
- // Cast intrinsic for `Closure(Closure { dtor_idx: 2341, function: Function { arguments: [NamedExternref("Event")], shim_idx: 2298, ret: Unit, inner_ret: Some(Unit) }, mutable: true }) -> Externref`.
952
- const ret = makeMutClosure(arg0, arg1, wasm.__wasm_bindgen_func_elem_8675, __wasm_bindgen_func_elem_8855);
951
+ // Cast intrinsic for `Closure(Closure { dtor_idx: 2276, function: Function { arguments: [NamedExternref("Event")], shim_idx: 2278, ret: Unit, inner_ret: Some(Unit) }, mutable: true }) -> Externref`.
952
+ const ret = makeMutClosure(arg0, arg1, wasm.__wasm_bindgen_func_elem_8655, __wasm_bindgen_func_elem_8822);
953
953
  return addHeapObject(ret);
954
954
  },
955
955
  __wbindgen_cast_0000000000000003: function(arg0, arg1) {
956
- // Cast intrinsic for `Closure(Closure { dtor_idx: 2341, function: Function { arguments: [NamedExternref("MessageEvent")], shim_idx: 2298, ret: Unit, inner_ret: Some(Unit) }, mutable: true }) -> Externref`.
957
- const ret = makeMutClosure(arg0, arg1, wasm.__wasm_bindgen_func_elem_8675, __wasm_bindgen_func_elem_8855);
956
+ // Cast intrinsic for `Closure(Closure { dtor_idx: 2276, function: Function { arguments: [NamedExternref("MessageEvent")], shim_idx: 2278, ret: Unit, inner_ret: Some(Unit) }, mutable: true }) -> Externref`.
957
+ const ret = makeMutClosure(arg0, arg1, wasm.__wasm_bindgen_func_elem_8655, __wasm_bindgen_func_elem_8822);
958
958
  return addHeapObject(ret);
959
959
  },
960
960
  __wbindgen_cast_0000000000000004: function(arg0, arg1) {
961
- // Cast intrinsic for `Closure(Closure { dtor_idx: 2341, function: Function { arguments: [], shim_idx: 2344, ret: Unit, inner_ret: Some(Unit) }, mutable: true }) -> Externref`.
962
- const ret = makeMutClosure(arg0, arg1, wasm.__wasm_bindgen_func_elem_8675, __wasm_bindgen_func_elem_8856);
961
+ // Cast intrinsic for `Closure(Closure { dtor_idx: 2276, function: Function { arguments: [], shim_idx: 2280, ret: Unit, inner_ret: Some(Unit) }, mutable: true }) -> Externref`.
962
+ const ret = makeMutClosure(arg0, arg1, wasm.__wasm_bindgen_func_elem_8655, __wasm_bindgen_func_elem_8821);
963
963
  return addHeapObject(ret);
964
964
  },
965
965
  __wbindgen_cast_0000000000000005: function(arg0, arg1) {
966
966
  // Cast intrinsic for `Closure(Closure { dtor_idx: 3267, function: Function { arguments: [Externref], shim_idx: 3268, ret: Unit, inner_ret: Some(Unit) }, mutable: true }) -> Externref`.
967
- const ret = makeMutClosure(arg0, arg1, wasm.__wasm_bindgen_func_elem_12871, __wasm_bindgen_func_elem_12872);
967
+ const ret = makeMutClosure(arg0, arg1, wasm.__wasm_bindgen_func_elem_12872, __wasm_bindgen_func_elem_12873);
968
968
  return addHeapObject(ret);
969
969
  },
970
970
  __wbindgen_cast_0000000000000006: function(arg0) {
@@ -1019,16 +1019,16 @@ function __wbg_get_imports() {
1019
1019
  };
1020
1020
  }
1021
1021
 
1022
- function __wasm_bindgen_func_elem_8856(arg0, arg1) {
1023
- wasm.__wasm_bindgen_func_elem_8856(arg0, arg1);
1022
+ function __wasm_bindgen_func_elem_8821(arg0, arg1) {
1023
+ wasm.__wasm_bindgen_func_elem_8821(arg0, arg1);
1024
1024
  }
1025
1025
 
1026
- function __wasm_bindgen_func_elem_8855(arg0, arg1, arg2) {
1027
- wasm.__wasm_bindgen_func_elem_8855(arg0, arg1, addHeapObject(arg2));
1026
+ function __wasm_bindgen_func_elem_8822(arg0, arg1, arg2) {
1027
+ wasm.__wasm_bindgen_func_elem_8822(arg0, arg1, addHeapObject(arg2));
1028
1028
  }
1029
1029
 
1030
- function __wasm_bindgen_func_elem_12872(arg0, arg1, arg2) {
1031
- wasm.__wasm_bindgen_func_elem_12872(arg0, arg1, addHeapObject(arg2));
1030
+ function __wasm_bindgen_func_elem_12873(arg0, arg1, arg2) {
1031
+ wasm.__wasm_bindgen_func_elem_12873(arg0, arg1, addHeapObject(arg2));
1032
1032
  }
1033
1033
 
1034
1034
 
Binary file
@@ -16,11 +16,11 @@ export const inkwebview_openBundle: (a: number, b: number, c: number, d: number,
16
16
  export const inkwebview_render: (a: number, b: number) => void;
17
17
  export const inkwebview_resize: (a: number, b: number, c: number, d: number) => void;
18
18
  export const main: () => void;
19
- export const __wasm_bindgen_func_elem_8675: (a: number, b: number) => void;
20
- export const __wasm_bindgen_func_elem_12871: (a: number, b: number) => void;
21
- export const __wasm_bindgen_func_elem_8855: (a: number, b: number, c: number) => void;
22
- export const __wasm_bindgen_func_elem_12872: (a: number, b: number, c: number) => void;
23
- export const __wasm_bindgen_func_elem_8856: (a: number, b: number) => void;
19
+ export const __wasm_bindgen_func_elem_8655: (a: number, b: number) => void;
20
+ export const __wasm_bindgen_func_elem_12872: (a: number, b: number) => void;
21
+ export const __wasm_bindgen_func_elem_8822: (a: number, b: number, c: number) => void;
22
+ export const __wasm_bindgen_func_elem_12873: (a: number, b: number, c: number) => void;
23
+ export const __wasm_bindgen_func_elem_8821: (a: number, b: number) => void;
24
24
  export const __wbindgen_export: (a: number, b: number) => number;
25
25
  export const __wbindgen_export2: (a: number, b: number, c: number, d: number) => number;
26
26
  export const __wbindgen_export3: (a: number) => void;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yodaos-pkg/ink",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "description": "Ink Web SDK for browser rendering and VFS-backed app loading",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",