iframe-bridge-kit 1.1.0 → 1.1.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 +38 -76
- package/dist/full/core.js +1 -1
- package/dist/full/core.mjs +1 -1
- package/dist/index.d.mts +7 -16
- package/dist/index.d.ts +7 -16
- package/dist/index.js +156 -42
- package/dist/index.mjs +155 -40
- package/dist/mini/core.js +1 -1
- package/dist/mini/core.mjs +1 -1
- package/dist/vite.js +46 -84
- package/dist/vite.mjs +46 -84
- package/package.json +1 -1
- package/dist/full/parent-core.js +0 -1
- package/dist/full/parent-core.mjs +0 -1
- package/dist/mini/parent-core.js +0 -1
- package/dist/mini/parent-core.mjs +0 -1
package/dist/index.mjs
CHANGED
|
@@ -1,52 +1,167 @@
|
|
|
1
1
|
// src/index.ts
|
|
2
2
|
import { WindowMessenger, connect } from "penpal";
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
3
|
+
|
|
4
|
+
// src/callbacks.ts
|
|
5
|
+
var callbackRefType = "iframe-bridge-kit.callback";
|
|
6
|
+
var callbackInvokeMethod = "__iframeBridgeInvokeCallback";
|
|
7
|
+
var isObject = (value) => typeof value === "object" && value !== null;
|
|
8
|
+
var isPlainObject = (value) => {
|
|
9
|
+
const proto = Object.getPrototypeOf(value);
|
|
10
|
+
return proto === Object.prototype || proto === null;
|
|
11
|
+
};
|
|
12
|
+
var isCallbackDescriptor = (value) => {
|
|
13
|
+
return isObject(value) && value.__iframeBridgeType === callbackRefType && typeof value.id === "string";
|
|
14
|
+
};
|
|
15
|
+
var createCallbackBridge = (getRemote) => {
|
|
16
|
+
const localCallbacks = /* @__PURE__ */ new Map();
|
|
17
|
+
const localCallbackIds = /* @__PURE__ */ new WeakMap();
|
|
18
|
+
const remoteCallbacks = /* @__PURE__ */ new Map();
|
|
19
|
+
let nextCallbackId = 0;
|
|
20
|
+
const registerLocalCallback = (fn) => {
|
|
21
|
+
let id = localCallbackIds.get(fn);
|
|
22
|
+
if (!id) {
|
|
23
|
+
id = `${Date.now().toString(36)}-${(++nextCallbackId).toString(36)}`;
|
|
24
|
+
localCallbackIds.set(fn, id);
|
|
25
|
+
}
|
|
26
|
+
localCallbacks.set(id, fn);
|
|
27
|
+
return {
|
|
28
|
+
__iframeBridgeType: callbackRefType,
|
|
29
|
+
id
|
|
30
|
+
};
|
|
31
|
+
};
|
|
32
|
+
const serialize = (value, seen = /* @__PURE__ */ new WeakMap()) => {
|
|
33
|
+
if (typeof value === "function") {
|
|
34
|
+
return registerLocalCallback(value);
|
|
35
|
+
}
|
|
36
|
+
if (!isObject(value)) {
|
|
37
|
+
return value;
|
|
38
|
+
}
|
|
39
|
+
if (seen.has(value)) {
|
|
40
|
+
return seen.get(value);
|
|
41
|
+
}
|
|
42
|
+
if (Array.isArray(value)) {
|
|
43
|
+
const copy2 = [];
|
|
44
|
+
seen.set(value, copy2);
|
|
45
|
+
value.forEach((item, index) => {
|
|
46
|
+
copy2[index] = serialize(item, seen);
|
|
47
|
+
});
|
|
48
|
+
return copy2;
|
|
49
|
+
}
|
|
50
|
+
if (!isPlainObject(value)) {
|
|
51
|
+
return value;
|
|
52
|
+
}
|
|
53
|
+
const copy = {};
|
|
54
|
+
seen.set(value, copy);
|
|
55
|
+
Object.keys(value).forEach((key) => {
|
|
56
|
+
copy[key] = serialize(value[key], seen);
|
|
57
|
+
});
|
|
58
|
+
return copy;
|
|
59
|
+
};
|
|
60
|
+
const deserialize = (value, seen = /* @__PURE__ */ new WeakMap()) => {
|
|
61
|
+
if (!isObject(value)) {
|
|
62
|
+
return value;
|
|
63
|
+
}
|
|
64
|
+
if (isCallbackDescriptor(value)) {
|
|
65
|
+
let callback = remoteCallbacks.get(value.id);
|
|
66
|
+
if (!callback) {
|
|
67
|
+
callback = async (...args) => {
|
|
68
|
+
const remote = await getRemote();
|
|
69
|
+
const result = await remote[callbackInvokeMethod](value.id, serialize(args));
|
|
70
|
+
return deserialize(result);
|
|
71
|
+
};
|
|
72
|
+
remoteCallbacks.set(value.id, callback);
|
|
8
73
|
}
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
74
|
+
return callback;
|
|
75
|
+
}
|
|
76
|
+
if (seen.has(value)) {
|
|
77
|
+
return seen.get(value);
|
|
78
|
+
}
|
|
79
|
+
if (Array.isArray(value)) {
|
|
80
|
+
const copy2 = [];
|
|
81
|
+
seen.set(value, copy2);
|
|
82
|
+
value.forEach((item, index) => {
|
|
83
|
+
copy2[index] = deserialize(item, seen);
|
|
16
84
|
});
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
remote.onMessage(type, data);
|
|
22
|
-
}
|
|
23
|
-
};
|
|
85
|
+
return copy2;
|
|
86
|
+
}
|
|
87
|
+
if (!isPlainObject(value)) {
|
|
88
|
+
return value;
|
|
24
89
|
}
|
|
90
|
+
const copy = {};
|
|
91
|
+
seen.set(value, copy);
|
|
92
|
+
Object.keys(value).forEach((key) => {
|
|
93
|
+
copy[key] = deserialize(value[key], seen);
|
|
94
|
+
});
|
|
95
|
+
return copy;
|
|
96
|
+
};
|
|
97
|
+
const invokeLocalCallback = async (id, args) => {
|
|
98
|
+
const callback = localCallbacks.get(id);
|
|
99
|
+
if (!callback) {
|
|
100
|
+
throw new Error(`Callback "${id}" is not available`);
|
|
101
|
+
}
|
|
102
|
+
const result = await callback(...deserialize(args));
|
|
103
|
+
return serialize(result);
|
|
104
|
+
};
|
|
105
|
+
const clearCallbacks = () => {
|
|
106
|
+
localCallbacks.clear();
|
|
107
|
+
remoteCallbacks.clear();
|
|
25
108
|
};
|
|
26
|
-
};
|
|
27
|
-
var defineIframeBridge = (name, methods) => {
|
|
28
109
|
return {
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
const [data] = args;
|
|
42
|
-
remote.onMessage(type, data);
|
|
43
|
-
},
|
|
44
|
-
destroy: conn.destroy
|
|
45
|
-
};
|
|
110
|
+
serialize,
|
|
111
|
+
deserialize,
|
|
112
|
+
invokeLocalCallback,
|
|
113
|
+
clearCallbacks
|
|
114
|
+
};
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
// src/index.ts
|
|
118
|
+
var resolveRemoteWindow = (target) => {
|
|
119
|
+
if (typeof HTMLIFrameElement !== "undefined" && target instanceof HTMLIFrameElement) {
|
|
120
|
+
if (!target.contentWindow) {
|
|
121
|
+
throw new Error("remoteWindow is null");
|
|
46
122
|
}
|
|
123
|
+
return target.contentWindow;
|
|
124
|
+
}
|
|
125
|
+
return target;
|
|
126
|
+
};
|
|
127
|
+
var defineBridge = (name, methods) => {
|
|
128
|
+
return async (target, allowedOrigins = ["*"]) => {
|
|
129
|
+
const remoteWindow = resolveRemoteWindow(target);
|
|
130
|
+
let remotePromise;
|
|
131
|
+
const callbacks = createCallbackBridge(() => remotePromise);
|
|
132
|
+
const bridgeMethods = Object.keys(methods).reduce((wrapped, methodName) => {
|
|
133
|
+
if (methodName === callbackInvokeMethod) {
|
|
134
|
+
throw new Error(`Method name "${callbackInvokeMethod}" is reserved by iframe-bridge-kit`);
|
|
135
|
+
}
|
|
136
|
+
wrapped[methodName] = async (...args) => {
|
|
137
|
+
const result = await methods[methodName].apply(methods, callbacks.deserialize(args));
|
|
138
|
+
return callbacks.serialize(result);
|
|
139
|
+
};
|
|
140
|
+
return wrapped;
|
|
141
|
+
}, {
|
|
142
|
+
[callbackInvokeMethod]: callbacks.invokeLocalCallback
|
|
143
|
+
});
|
|
144
|
+
const conn = connect({
|
|
145
|
+
messenger: new WindowMessenger({
|
|
146
|
+
remoteWindow,
|
|
147
|
+
allowedOrigins
|
|
148
|
+
}),
|
|
149
|
+
channel: "iframe-bridge-channel",
|
|
150
|
+
methods: bridgeMethods
|
|
151
|
+
});
|
|
152
|
+
remotePromise = conn.promise;
|
|
153
|
+
const remote = await remotePromise;
|
|
154
|
+
return {
|
|
155
|
+
emit(type, data) {
|
|
156
|
+
return remote.onMessage(type, callbacks.serialize(data));
|
|
157
|
+
},
|
|
158
|
+
destroy() {
|
|
159
|
+
callbacks.clearCallbacks();
|
|
160
|
+
conn.destroy();
|
|
161
|
+
}
|
|
162
|
+
};
|
|
47
163
|
};
|
|
48
164
|
};
|
|
49
165
|
export {
|
|
50
|
-
defineBridge
|
|
51
|
-
defineIframeBridge
|
|
166
|
+
defineBridge
|
|
52
167
|
};
|
package/dist/mini/core.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";var
|
|
1
|
+
"use strict";var m=Object.defineProperty;var _=Object.getOwnPropertyDescriptor;var x=Object.getOwnPropertyNames;var B=Object.prototype.hasOwnProperty;var E=(o,t)=>{for(var n in t)m(o,n,{get:t[n],enumerable:!0})},F=(o,t,n,i)=>{if(t&&typeof t=="object"||typeof t=="function")for(let a of x(t))!B.call(o,a)&&a!==n&&m(o,a,{get:()=>t[a],enumerable:!(i=_(t,a))||i.enumerable});return o};var A=o=>F(m({},"__esModule",{value:!0}),o);var T={};E(T,{createBridgeClient:()=>I,default:()=>W});module.exports=A(T);var h=require("penpal");var C="iframe-bridge-kit.callback",b="__iframeBridgeInvokeCallback",p=o=>typeof o=="object"&&o!==null,u=o=>{let t=Object.getPrototypeOf(o);return t===Object.prototype||t===null},j=o=>p(o)&&o.__iframeBridgeType===C&&typeof o.id=="string",R=o=>{let t=new Map,n=new WeakMap,i=new Map,a=0,d=e=>{let r=n.get(e);return r||(r=`${Date.now().toString(36)}-${(++a).toString(36)}`,n.set(e,r)),t.set(r,e),{__iframeBridgeType:C,id:r}},c=(e,r=new WeakMap)=>{if(typeof e=="function")return d(e);if(!p(e))return e;if(r.has(e))return r.get(e);if(Array.isArray(e)){let s=[];return r.set(e,s),e.forEach((g,y)=>{s[y]=c(g,r)}),s}if(!u(e))return e;let l={};return r.set(e,l),Object.keys(e).forEach(s=>{l[s]=c(e[s],r)}),l},f=(e,r=new WeakMap)=>{if(!p(e))return e;if(j(e)){let s=i.get(e.id);return s||(s=async(...g)=>{let P=await(await o())[b](e.id,c(g));return f(P)},i.set(e.id,s)),s}if(r.has(e))return r.get(e);if(Array.isArray(e)){let s=[];return r.set(e,s),e.forEach((g,y)=>{s[y]=f(g,r)}),s}if(!u(e))return e;let l={};return r.set(e,l),Object.keys(e).forEach(s=>{l[s]=f(e[s],r)}),l};return{serialize:c,deserialize:f,invokeLocalCallback:async(e,r)=>{let l=t.get(e);if(!l)throw new Error(`Callback "${e}" is not available`);let s=await l(...f(r));return c(s)},clearCallbacks:()=>{t.clear(),i.clear()}}};var O="iframe-bridge-channel",M=["__AllowedOrigins__"],w=class{msgProxy=new Map;initCallbacks=new Set;conn;remotePromise;inited=!1;connectionId=0;callbacks=R(()=>this.getRemote());api;constructor(){let t={onMessage:this.onMessage,offMessage:this.offMessage,isInit:this.isInit,onInit:this.onInit,destroy:this.destroy};this.api=new Proxy({},{get:(n,i)=>{if(i!=="then"&&typeof i=="string")return i in t?t[i]:async(...a)=>{let c=(await this.getRemote())[i];if(typeof c!="function")throw new Error(`Remote method "${String(i)}" is not available`);return this.callbacks.deserialize(await c(...this.callbacks.serialize(a)))}}})}connect=(t,n=M)=>{this.conn?.destroy(),this.inited=!1;let i=++this.connectionId;return this.conn=(0,h.connect)({messenger:new h.WindowMessenger({remoteWindow:t,allowedOrigins:n}),channel:O,methods:{onMessage:this.receiveMessage,[b]:this.callbacks.invokeLocalCallback}}),this.remotePromise=this.conn.promise.then(a=>(i===this.connectionId&&(this.inited=!0,this.notifyInit()),a)),this.remotePromise};getRemote=()=>{if(!this.remotePromise){if(typeof window>"u"||window.parent===window)throw new Error("remoteWindow is not configured. Pass a Window when creating the bridge client.");return this.connect(window.parent)}return this.remotePromise};receiveMessage=(t,n)=>{let i=this.msgProxy.get(t);if(i){let a=this.callbacks.deserialize(n);return i.forEach(d=>d(a)),!0}};notifyInit=()=>{let t=Array.from(this.initCallbacks);this.initCallbacks.clear(),t.forEach(n=>n(this.api))};onMessage=(t,n,i)=>{let a=i?(c=>{n(c),this.offMessage(t,a)}):n,d=this.msgProxy.get(t);return d?d.add(a):this.msgProxy.set(t,new Set([a])),()=>this.offMessage(t,a)};offMessage=(t,n)=>{if(!n){this.msgProxy.delete(t);return}let i=this.msgProxy.get(t);i&&i.delete(n)};isInit=()=>this.inited;onInit=t=>{if(this.inited){t(this.api);return}this.initCallbacks.add(t)};destroy=()=>{this.connectionId++,this.conn?.destroy(),this.conn=void 0,this.remotePromise=void 0,this.inited=!1,this.initCallbacks.clear(),this.callbacks.clearCallbacks()}},I=(o,t=M)=>{let n=new w;return n.connect(o,t),n.api},k,W=()=>(k||(k=I(window.parent)),k);0&&(module.exports={createBridgeClient});
|
package/dist/mini/core.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{WindowMessenger as
|
|
1
|
+
import{WindowMessenger as I,connect as P}from"penpal";var w="iframe-bridge-kit.callback",m="__iframeBridgeInvokeCallback",h=s=>typeof s=="object"&&s!==null,k=s=>{let e=Object.getPrototypeOf(s);return e===Object.prototype||e===null},M=s=>h(s)&&s.__iframeBridgeType===w&&typeof s.id=="string",u=s=>{let e=new Map,r=new WeakMap,i=new Map,a=0,d=t=>{let n=r.get(t);return n||(n=`${Date.now().toString(36)}-${(++a).toString(36)}`,r.set(t,n)),e.set(n,t),{__iframeBridgeType:w,id:n}},c=(t,n=new WeakMap)=>{if(typeof t=="function")return d(t);if(!h(t))return t;if(n.has(t))return n.get(t);if(Array.isArray(t)){let o=[];return n.set(t,o),t.forEach((g,y)=>{o[y]=c(g,n)}),o}if(!k(t))return t;let l={};return n.set(t,l),Object.keys(t).forEach(o=>{l[o]=c(t[o],n)}),l},f=(t,n=new WeakMap)=>{if(!h(t))return t;if(M(t)){let o=i.get(t.id);return o||(o=async(...g)=>{let R=await(await s())[m](t.id,c(g));return f(R)},i.set(t.id,o)),o}if(n.has(t))return n.get(t);if(Array.isArray(t)){let o=[];return n.set(t,o),t.forEach((g,y)=>{o[y]=f(g,n)}),o}if(!k(t))return t;let l={};return n.set(t,l),Object.keys(t).forEach(o=>{l[o]=f(t[o],n)}),l};return{serialize:c,deserialize:f,invokeLocalCallback:async(t,n)=>{let l=e.get(t);if(!l)throw new Error(`Callback "${t}" is not available`);let o=await l(...f(n));return c(o)},clearCallbacks:()=>{e.clear(),i.clear()}}};var _="iframe-bridge-channel",C=["__AllowedOrigins__"],b=class{msgProxy=new Map;initCallbacks=new Set;conn;remotePromise;inited=!1;connectionId=0;callbacks=u(()=>this.getRemote());api;constructor(){let e={onMessage:this.onMessage,offMessage:this.offMessage,isInit:this.isInit,onInit:this.onInit,destroy:this.destroy};this.api=new Proxy({},{get:(r,i)=>{if(i!=="then"&&typeof i=="string")return i in e?e[i]:async(...a)=>{let c=(await this.getRemote())[i];if(typeof c!="function")throw new Error(`Remote method "${String(i)}" is not available`);return this.callbacks.deserialize(await c(...this.callbacks.serialize(a)))}}})}connect=(e,r=C)=>{this.conn?.destroy(),this.inited=!1;let i=++this.connectionId;return this.conn=P({messenger:new I({remoteWindow:e,allowedOrigins:r}),channel:_,methods:{onMessage:this.receiveMessage,[m]:this.callbacks.invokeLocalCallback}}),this.remotePromise=this.conn.promise.then(a=>(i===this.connectionId&&(this.inited=!0,this.notifyInit()),a)),this.remotePromise};getRemote=()=>{if(!this.remotePromise){if(typeof window>"u"||window.parent===window)throw new Error("remoteWindow is not configured. Pass a Window when creating the bridge client.");return this.connect(window.parent)}return this.remotePromise};receiveMessage=(e,r)=>{let i=this.msgProxy.get(e);if(i){let a=this.callbacks.deserialize(r);return i.forEach(d=>d(a)),!0}};notifyInit=()=>{let e=Array.from(this.initCallbacks);this.initCallbacks.clear(),e.forEach(r=>r(this.api))};onMessage=(e,r,i)=>{let a=i?(c=>{r(c),this.offMessage(e,a)}):r,d=this.msgProxy.get(e);return d?d.add(a):this.msgProxy.set(e,new Set([a])),()=>this.offMessage(e,a)};offMessage=(e,r)=>{if(!r){this.msgProxy.delete(e);return}let i=this.msgProxy.get(e);i&&i.delete(r)};isInit=()=>this.inited;onInit=e=>{if(this.inited){e(this.api);return}this.initCallbacks.add(e)};destroy=()=>{this.connectionId++,this.conn?.destroy(),this.conn=void 0,this.remotePromise=void 0,this.inited=!1,this.initCallbacks.clear(),this.callbacks.clearCallbacks()}},x=(s,e=C)=>{let r=new b;return r.connect(s,e),r.api},p,O=()=>(p||(p=x(window.parent)),p);export{x as createBridgeClient,O as default};
|
package/dist/vite.js
CHANGED
|
@@ -36,11 +36,12 @@ module.exports = __toCommonJS(vite_exports);
|
|
|
36
36
|
var ts = __toESM(require("typescript"));
|
|
37
37
|
var path = __toESM(require("path"));
|
|
38
38
|
var fs = __toESM(require("fs"));
|
|
39
|
+
var import_module = require("module");
|
|
39
40
|
|
|
40
41
|
// package.json
|
|
41
42
|
var package_default = {
|
|
42
43
|
name: "iframe-bridge-kit",
|
|
43
|
-
version: "1.1.
|
|
44
|
+
version: "1.1.1",
|
|
44
45
|
description: "A type-safe communication bridge for iframes. Define strongly typed RPC APIs for cross-window messaging with ease.",
|
|
45
46
|
main: "dist/index.js",
|
|
46
47
|
module: "dist/index.mjs",
|
|
@@ -100,6 +101,20 @@ var package_default = {
|
|
|
100
101
|
|
|
101
102
|
// src/vite.ts
|
|
102
103
|
var packageName = package_default.name;
|
|
104
|
+
var requireFromCwd = (0, import_module.createRequire)(path.join(process.cwd(), "package.json"));
|
|
105
|
+
function getCoreDirs(variant) {
|
|
106
|
+
const dirs = [];
|
|
107
|
+
try {
|
|
108
|
+
const viteEntry = requireFromCwd.resolve(`${packageName}/vite`);
|
|
109
|
+
dirs.push(path.join(path.dirname(viteEntry), variant));
|
|
110
|
+
} catch {
|
|
111
|
+
}
|
|
112
|
+
dirs.push(
|
|
113
|
+
path.resolve(process.cwd(), "node_modules", packageName, "dist", variant),
|
|
114
|
+
path.resolve(process.cwd(), "dist", variant)
|
|
115
|
+
);
|
|
116
|
+
return Array.from(new Set(dirs));
|
|
117
|
+
}
|
|
103
118
|
function extractScriptFromVue(code) {
|
|
104
119
|
const scriptRegex = /<script(?:\s+setup)?(?:\s+lang\s*=\s*["']?(ts|typescript)["']?)?[^>]*>([\s\S]*?)<\/script>/i;
|
|
105
120
|
const match = code.match(scriptRegex);
|
|
@@ -248,7 +263,7 @@ function parseBridgeFromCode(code, filePath) {
|
|
|
248
263
|
collectTypeImports(stmt);
|
|
249
264
|
}
|
|
250
265
|
}
|
|
251
|
-
const
|
|
266
|
+
const defineBridgeNames = /* @__PURE__ */ new Set();
|
|
252
267
|
for (const stmt of sourceFile.statements) {
|
|
253
268
|
if (ts.isImportDeclaration(stmt) && ts.isStringLiteral(stmt.moduleSpecifier) && stmt.moduleSpecifier.text === packageName) {
|
|
254
269
|
const namedBindings = stmt.importClause?.namedBindings;
|
|
@@ -256,21 +271,17 @@ function parseBridgeFromCode(code, filePath) {
|
|
|
256
271
|
for (const element of namedBindings.elements) {
|
|
257
272
|
const originalName = element.propertyName?.text ?? element.name.text;
|
|
258
273
|
if (originalName === "defineBridge") {
|
|
259
|
-
|
|
260
|
-
}
|
|
261
|
-
if (originalName === "defineIframeBridge") {
|
|
262
|
-
bridgeFactories.set(element.name.text, "parent");
|
|
274
|
+
defineBridgeNames.add(element.name.text);
|
|
263
275
|
}
|
|
264
276
|
}
|
|
265
277
|
}
|
|
266
278
|
}
|
|
267
279
|
}
|
|
268
|
-
if (
|
|
280
|
+
if (defineBridgeNames.size === 0) {
|
|
269
281
|
return { results, cleanup };
|
|
270
282
|
}
|
|
271
283
|
const visit = (node) => {
|
|
272
|
-
if (ts.isCallExpression(node) && ts.isIdentifier(node.expression) &&
|
|
273
|
-
const target = bridgeFactories.get(node.expression.text);
|
|
284
|
+
if (ts.isCallExpression(node) && ts.isIdentifier(node.expression) && defineBridgeNames.has(node.expression.text)) {
|
|
274
285
|
const [nameArg, methodsArg] = node.arguments;
|
|
275
286
|
if (!nameArg || !ts.isStringLiteral(nameArg)) {
|
|
276
287
|
return;
|
|
@@ -367,12 +378,8 @@ function parseBridgeFromCode(code, filePath) {
|
|
|
367
378
|
}
|
|
368
379
|
}
|
|
369
380
|
const emitMap = [];
|
|
370
|
-
let emitTypeName;
|
|
371
381
|
if (node.typeArguments && node.typeArguments.length > 0) {
|
|
372
382
|
const emitTypeNode = node.typeArguments[0];
|
|
373
|
-
if (ts.isTypeReferenceNode(emitTypeNode) && ts.isIdentifier(emitTypeNode.typeName)) {
|
|
374
|
-
emitTypeName = emitTypeNode.typeName.text;
|
|
375
|
-
}
|
|
376
383
|
const emitType = checker.getTypeFromTypeNode(emitTypeNode);
|
|
377
384
|
emitType.getProperties().forEach((prop) => {
|
|
378
385
|
const name = prop.getName();
|
|
@@ -386,13 +393,11 @@ function parseBridgeFromCode(code, filePath) {
|
|
|
386
393
|
mergeImports(bridgeImports, typeImports);
|
|
387
394
|
results.push({
|
|
388
395
|
name: bridgeName,
|
|
389
|
-
target,
|
|
390
396
|
methods,
|
|
391
397
|
sourceFile: filePath,
|
|
392
398
|
typeDeclarations,
|
|
393
399
|
imports: bridgeImports,
|
|
394
|
-
emitMap
|
|
395
|
-
emitTypeName
|
|
400
|
+
emitMap
|
|
396
401
|
});
|
|
397
402
|
}
|
|
398
403
|
ts.forEachChild(node, visit);
|
|
@@ -564,52 +569,6 @@ function generateDtsContent(info, outDir, preserveModules = []) {
|
|
|
564
569
|
lines.push("");
|
|
565
570
|
}
|
|
566
571
|
}
|
|
567
|
-
const localTypeDeclarations = info.typeDeclarations.filter(({ name }) => name !== info.emitTypeName && name !== "EmitMap");
|
|
568
|
-
if (localTypeDeclarations.length > 0) {
|
|
569
|
-
lines.push("// Local type definitions");
|
|
570
|
-
for (const { content } of localTypeDeclarations) {
|
|
571
|
-
lines.push(content);
|
|
572
|
-
lines.push("");
|
|
573
|
-
}
|
|
574
|
-
}
|
|
575
|
-
if (info.target === "parent") {
|
|
576
|
-
if (processedEmitTypes.length > 0) {
|
|
577
|
-
lines.push("export interface EmitMap {");
|
|
578
|
-
processedEmitTypes.forEach((e) => {
|
|
579
|
-
lines.push(` "${e.name}": ${e.type};`);
|
|
580
|
-
});
|
|
581
|
-
lines.push("}");
|
|
582
|
-
lines.push("");
|
|
583
|
-
}
|
|
584
|
-
lines.push("export interface BridgeConnection {");
|
|
585
|
-
lines.push(" api: {");
|
|
586
|
-
lines.push(
|
|
587
|
-
...processedMethods.map(
|
|
588
|
-
(m) => (m.jsdoc ? ` ${m.jsdoc}
|
|
589
|
-
` : "") + ` ${m.name}: (${m.params}) => ${m.returnType},`
|
|
590
|
-
)
|
|
591
|
-
);
|
|
592
|
-
lines.push(" };");
|
|
593
|
-
if (processedEmitTypes.length > 0) {
|
|
594
|
-
lines.push(" onMessage<K extends keyof EmitMap>(type: K, cb: (data: EmitMap[K]) => void, once?: boolean): () => void;");
|
|
595
|
-
lines.push(" onMessage(type: string, cb: Function, once?: boolean): () => void;");
|
|
596
|
-
lines.push(" offMessage<K extends keyof EmitMap>(type: K, fn?: (data: EmitMap[K]) => void): void;");
|
|
597
|
-
lines.push(" offMessage(type: string, fn?: Function): void;");
|
|
598
|
-
} else {
|
|
599
|
-
lines.push(" onMessage(type: string, cb: Function, once?: boolean): () => void;");
|
|
600
|
-
lines.push(" offMessage(type: string, fn?: Function): void;");
|
|
601
|
-
}
|
|
602
|
-
lines.push(" isInit(): boolean;");
|
|
603
|
-
lines.push(" onInit(cb: Function): void;");
|
|
604
|
-
lines.push(" destroy(): void;");
|
|
605
|
-
lines.push("}");
|
|
606
|
-
lines.push("");
|
|
607
|
-
lines.push("export declare function create(iframe: HTMLIFrameElement, allowedOrigins?: string[]): BridgeConnection;");
|
|
608
|
-
lines.push("declare const bridge: { create: typeof create };");
|
|
609
|
-
lines.push("export default bridge;");
|
|
610
|
-
lines.push("");
|
|
611
|
-
return lines.join("\n");
|
|
612
|
-
}
|
|
613
572
|
if (processedEmitTypes.length > 0) {
|
|
614
573
|
lines.push("export interface EmitMap {");
|
|
615
574
|
processedEmitTypes.forEach((e) => {
|
|
@@ -617,18 +576,10 @@ function generateDtsContent(info, outDir, preserveModules = []) {
|
|
|
617
576
|
});
|
|
618
577
|
lines.push("}");
|
|
619
578
|
lines.push("");
|
|
620
|
-
lines.push("export declare function onMessage<K extends keyof EmitMap>(type: K, cb: (data: EmitMap[K]) => void, once?: boolean): () => void;");
|
|
621
|
-
lines.push("export declare function onMessage(type: string, cb: Function, once?: boolean): () => void;");
|
|
622
|
-
lines.push("export declare function offMessage<K extends keyof EmitMap>(type: K, fn?: (data: EmitMap[K]) => void): void;");
|
|
623
|
-
lines.push("export declare function offMessage(type: string, fn?: Function): void;");
|
|
624
|
-
} else {
|
|
625
|
-
lines.push("export declare function onMessage(type: string, cb: Function, once?: boolean): () => void;");
|
|
626
|
-
lines.push("export declare function offMessage(type: string, fn?: Function): void;");
|
|
627
579
|
}
|
|
628
|
-
lines.push("export declare function
|
|
629
|
-
lines.push("export declare function onInit(cb: Function): void;");
|
|
580
|
+
lines.push("export declare function createBridgeClient(remoteWindow: Window, allowedOrigins?: string[]): BridgeClient;");
|
|
630
581
|
lines.push("");
|
|
631
|
-
lines.push(`export
|
|
582
|
+
lines.push(`export interface BridgeApi {`);
|
|
632
583
|
lines.push(
|
|
633
584
|
...processedMethods.map(
|
|
634
585
|
(m) => (m.jsdoc ? ` ${m.jsdoc}
|
|
@@ -637,6 +588,24 @@ function generateDtsContent(info, outDir, preserveModules = []) {
|
|
|
637
588
|
);
|
|
638
589
|
lines.push("}");
|
|
639
590
|
lines.push("");
|
|
591
|
+
lines.push("export type BridgeClient = BridgeApi & {");
|
|
592
|
+
if (processedEmitTypes.length > 0) {
|
|
593
|
+
lines.push(" onMessage<K extends keyof EmitMap>(type: K, cb: (data: EmitMap[K]) => void, once?: boolean): () => void;");
|
|
594
|
+
lines.push(" onMessage(type: string, cb: Function, once?: boolean): () => void;");
|
|
595
|
+
lines.push(" offMessage<K extends keyof EmitMap>(type: K, fn?: (data: EmitMap[K]) => void): void;");
|
|
596
|
+
lines.push(" offMessage(type: string, fn?: Function): void;");
|
|
597
|
+
} else {
|
|
598
|
+
lines.push(" onMessage(type: string, cb: Function, once?: boolean): () => void;");
|
|
599
|
+
lines.push(" offMessage(type: string, fn?: Function): void;");
|
|
600
|
+
}
|
|
601
|
+
lines.push(" isInit(): boolean;");
|
|
602
|
+
lines.push(" onInit(cb: (api: BridgeClient) => void): void;");
|
|
603
|
+
lines.push(" destroy(): void;");
|
|
604
|
+
lines.push("}");
|
|
605
|
+
lines.push("");
|
|
606
|
+
lines.push("declare const createBridge: () => BridgeClient;");
|
|
607
|
+
lines.push("export default createBridge;");
|
|
608
|
+
lines.push("");
|
|
640
609
|
return lines.join("\n");
|
|
641
610
|
}
|
|
642
611
|
function writeDtsFile(info, options) {
|
|
@@ -662,7 +631,7 @@ function processFile(filePath, code, options) {
|
|
|
662
631
|
const { results: bridges, cleanup } = parseBridgeFromCode(code, filePath);
|
|
663
632
|
for (const bridge of bridges) {
|
|
664
633
|
writeDtsFile(bridge, options);
|
|
665
|
-
writeBridgeRuntime(bridge, options);
|
|
634
|
+
writeBridgeRuntime(bridge.name, options);
|
|
666
635
|
}
|
|
667
636
|
cleanup();
|
|
668
637
|
return bridges;
|
|
@@ -671,19 +640,13 @@ function processFile(filePath, code, options) {
|
|
|
671
640
|
return [];
|
|
672
641
|
}
|
|
673
642
|
}
|
|
674
|
-
function writeBridgeRuntime(
|
|
643
|
+
function writeBridgeRuntime(bridgeName, options) {
|
|
675
644
|
const isFull = options.full !== false;
|
|
676
645
|
const allowedOrigins = options.allowedOrigins || ["*"];
|
|
677
646
|
const outDir = options.outDir || "bridges";
|
|
678
647
|
const variant = isFull ? "full" : "mini";
|
|
679
|
-
const basePaths = [
|
|
680
|
-
// 1. 假设我们在 dist 目录中运行
|
|
681
|
-
path.resolve(__dirname, variant),
|
|
682
|
-
// 2. 假设我们在 src 目录中运行
|
|
683
|
-
path.resolve(__dirname, "../dist", variant)
|
|
684
|
-
];
|
|
685
648
|
let coreDir = "";
|
|
686
|
-
for (const p of
|
|
649
|
+
for (const p of getCoreDirs(variant)) {
|
|
687
650
|
if (fs.existsSync(p)) {
|
|
688
651
|
coreDir = p;
|
|
689
652
|
break;
|
|
@@ -692,15 +655,14 @@ function writeBridgeRuntime(info, options) {
|
|
|
692
655
|
if (!coreDir) {
|
|
693
656
|
return;
|
|
694
657
|
}
|
|
695
|
-
const absoluteOutDir = path.resolve(process.cwd(), outDir,
|
|
658
|
+
const absoluteOutDir = path.resolve(process.cwd(), outDir, bridgeName);
|
|
696
659
|
if (!fs.existsSync(absoluteOutDir)) {
|
|
697
660
|
fs.mkdirSync(absoluteOutDir, { recursive: true });
|
|
698
661
|
}
|
|
699
662
|
const extensions = ["js", "mjs"];
|
|
700
663
|
const replaceContent = JSON.stringify(allowedOrigins).slice(1, -1);
|
|
701
|
-
const runtimeName = info.target === "parent" ? "parent-core" : "core";
|
|
702
664
|
for (const ext of extensions) {
|
|
703
|
-
const srcFile = path.join(coreDir,
|
|
665
|
+
const srcFile = path.join(coreDir, `core.${ext}`);
|
|
704
666
|
if (fs.existsSync(srcFile)) {
|
|
705
667
|
try {
|
|
706
668
|
let content = fs.readFileSync(srcFile, "utf-8");
|