Skip to content

Commit 6bb07e6

Browse files
committed
code
0 parents  commit 6bb07e6

File tree

8 files changed

+318
-0
lines changed

8 files changed

+318
-0
lines changed

.gitignore

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
dist
2+
.DS_Store
3+
node_modules

.npmignore

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
/docs
2+
/test
3+
/.github

.npmrc

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
registry=https://registry.npmjs.org/

LICENSE

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2023 facing-dev
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

package-lock.json

+133
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
{
2+
"name": "post-messager",
3+
"version": "1.0.0",
4+
"description": "",
5+
"main": "dist/index.js",
6+
"module": "dist/esm/index.js",
7+
"scripts": {
8+
"test": "./node_modules/.bin/ts-node ./test/test.ts",
9+
"build": "npm run build:cjs && npm run build:esm",
10+
"build:cjs": "./node_modules/.bin/tsc",
11+
"build:esm": "./node_modules/.bin/tsc -outDir dist/esm -module ES6",
12+
"watch":"./node_modules/.bin/tsc --watch -outDir dist/esm -module ES6"
13+
},
14+
"author": "",
15+
"license": "MIT",
16+
"dependencies": {
17+
"@types/node": "^20.10.4",
18+
"ts-node": "^10.9.2",
19+
"typescript": "^5.3.3"
20+
}
21+
}

src/index.ts

+109
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
interface RawMessage<T> {
2+
type: "Message"
3+
data: T
4+
}
5+
interface RawDown {
6+
type: "Done"
7+
doneId: string
8+
}
9+
type Raw<T> = (RawMessage<T> | RawDown) & {
10+
__byPM: true
11+
timestamp: number
12+
id: string
13+
}
14+
15+
function generateId() {
16+
return `${Date.now()}-${Math.random()}`
17+
}
18+
19+
export default class PostMessager<T> {
20+
#listenerHandler: ((event: MessageEvent) => void) | null = null
21+
#targetOrigin = '*'
22+
#target: Window
23+
#doneMap: Map<string, {
24+
res: Function
25+
rej: Function
26+
}> = new Map
27+
#doneTimeout: number
28+
get doneMapSize(){
29+
return this.#doneMap.size
30+
}
31+
constructor(opt: {
32+
targetOrigin?: string
33+
target: Window
34+
doneTimeout?: number
35+
handler: (data: T, done: Function) => void
36+
rawHandler?: (data: Raw<T>, done: Function) => void
37+
}) {
38+
this.#target = opt.target
39+
this.#targetOrigin = opt?.targetOrigin ?? '*'
40+
this.#doneTimeout = opt.doneTimeout ?? 5000
41+
this.#listenerHandler = (event) => {
42+
43+
if (event.origin !== this.#targetOrigin && this.#targetOrigin !== '*') {
44+
return
45+
}
46+
if (event.data.__byPM !== true) {
47+
return
48+
}
49+
50+
const rawData = event.data as Raw<T>
51+
// const rawData = JSON.parse(event.data) as Raw<T>
52+
if (rawData.type === 'Message') {
53+
const doneCb = () => {
54+
this.#post({
55+
type: 'Done',
56+
doneId: rawData.id,
57+
})
58+
}
59+
opt.rawHandler?.(rawData, doneCb)
60+
opt.handler(rawData.data, doneCb)
61+
}
62+
if (rawData.type === 'Done') {
63+
this.#doneMap.get(rawData.doneId)?.res()
64+
}
65+
}
66+
window.addEventListener('message', this.#listenerHandler)
67+
}
68+
#post(raw: RawMessage<T> | RawDown, id = generateId(), timestamp = Date.now()) {
69+
const message: Raw<T> = {
70+
...raw,
71+
id,
72+
timestamp,
73+
__byPM: true
74+
}
75+
this.#target.postMessage(message, this.#targetOrigin)
76+
}
77+
post(data: T, promise?: false): void
78+
post(data: T, promise: true): Promise<void>
79+
post(data: T, promise?: boolean): Promise<void> | void {
80+
const id = generateId()
81+
const timestamp = Date.now()
82+
const p = promise ? new Promise<void>((res, rej) => {
83+
const timeout = setTimeout(() => {
84+
this.#doneMap.get(id)?.rej()
85+
}, this.#doneTimeout);
86+
this.#doneMap.set(id, {
87+
res: () => {
88+
clearTimeout(timeout)
89+
this.#doneMap.delete(id)
90+
res()
91+
},
92+
rej: () => {
93+
this.#doneMap.delete(id)
94+
rej(`message timeout id: ${id}`)
95+
}
96+
})
97+
}) : undefined
98+
this.#post({
99+
type: 'Message',
100+
data: data
101+
}, id, timestamp)
102+
return p
103+
}
104+
release() {
105+
if (this.#listenerHandler) {
106+
window.removeEventListener('message', this.#listenerHandler)
107+
}
108+
}
109+
}

tsconfig.json

+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
{
2+
"compilerOptions": {
3+
"outDir": "./dist",
4+
"baseUrl": ".",
5+
"rootDir": "./src",
6+
"moduleResolution": "node",
7+
"module": "CommonJS",
8+
"target": "ES6",
9+
"strict": true,
10+
"sourceMap": true,
11+
"lib": [
12+
"esnext",
13+
"DOM",
14+
"DOM.Iterable"
15+
],
16+
"esModuleInterop": true,
17+
"isolatedModules": true,
18+
"emitDeclarationOnly": false,
19+
"composite": false,
20+
"declaration": true,
21+
"declarationMap": true,
22+
"noUnusedLocals": false
23+
},
24+
"include": [
25+
"./src/index.ts",
26+
],
27+
}

0 commit comments

Comments
 (0)