@dartsee/plugin-sdk 0.0.1 → 0.0.3
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 +0 -2
- package/dist/manifest.d.ts +1 -0
- package/dist/plugin-sdk.es.js +23 -23
- package/dist/plugin-sdk.iife.js +2 -2
- package/dist/protocol.d.ts +0 -4
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -11,8 +11,6 @@ const session = await dartsee.session.get()
|
|
|
11
11
|
const off = dartsee.on('gameEnd', (game) => { /* ... */ })
|
|
12
12
|
```
|
|
13
13
|
|
|
14
|
-
Script tag: `https://cdn.jsdelivr.net/npm/@dartsee/plugin-sdk@<version>/dist/plugin-sdk.iife.js` → global `DartseeSDK`.
|
|
15
|
-
|
|
16
14
|
## Your page runs with an opaque origin
|
|
17
15
|
|
|
18
16
|
The iframe is `sandbox="allow-scripts allow-forms"`, without `allow-same-origin`. That means:
|
package/dist/manifest.d.ts
CHANGED
package/dist/plugin-sdk.es.js
CHANGED
|
@@ -13,17 +13,17 @@ function I({ timeout: r = _ } = {}) {
|
|
|
13
13
|
if (e === window)
|
|
14
14
|
return Promise.reject(new g("HOST_ERROR", "Not inside the Dartsee host (no parent frame)"));
|
|
15
15
|
const i = /* @__PURE__ */ new Map(), t = /* @__PURE__ */ new Map();
|
|
16
|
-
let
|
|
17
|
-
const o = (n,
|
|
18
|
-
if (!
|
|
19
|
-
return Promise.reject(new g("UNSUPPORTED", `Host ${
|
|
20
|
-
const
|
|
16
|
+
let E = 0;
|
|
17
|
+
const o = (n, d, s = {}) => {
|
|
18
|
+
if (!d.capabilities.includes(n))
|
|
19
|
+
return Promise.reject(new g("UNSUPPORTED", `Host ${d.hostVersion} does not support ${n}`));
|
|
20
|
+
const u = s.timeout ?? _, c = String(++E), p = $(n, c), a = k(n, c);
|
|
21
21
|
return new Promise((T, y) => {
|
|
22
22
|
const f = () => {
|
|
23
23
|
clearTimeout(h), i.delete(p), i.delete(a);
|
|
24
24
|
}, h = setTimeout(() => {
|
|
25
|
-
f(), y(new g("TIMEOUT", `${n} timed out after ${
|
|
26
|
-
},
|
|
25
|
+
f(), y(new g("TIMEOUT", `${n} timed out after ${u} ms`));
|
|
26
|
+
}, u);
|
|
27
27
|
i.set(p, (R) => {
|
|
28
28
|
f(), T(R.data);
|
|
29
29
|
}), i.set(a, (R) => {
|
|
@@ -33,26 +33,26 @@ function I({ timeout: r = _ } = {}) {
|
|
|
33
33
|
}), e.postMessage({ id: n, nonce: c }, "*");
|
|
34
34
|
});
|
|
35
35
|
}, v = (n) => {
|
|
36
|
-
let
|
|
36
|
+
let d;
|
|
37
37
|
return {
|
|
38
38
|
context: n,
|
|
39
39
|
session: { get: (s) => o(m.SESSION_GET, n, s) },
|
|
40
40
|
game: { get: (s) => o(m.GAME_GET, n, s) },
|
|
41
41
|
auth: {
|
|
42
42
|
async getToken(s) {
|
|
43
|
-
return (!
|
|
43
|
+
return (!d || d.expiresAt - Date.now() < G) && (d = await o(m.AUTH_GET_TOKEN, n, s)), d.token;
|
|
44
44
|
}
|
|
45
45
|
},
|
|
46
|
-
on(s,
|
|
46
|
+
on(s, u) {
|
|
47
47
|
const c = t.get(s) ?? /* @__PURE__ */ new Set();
|
|
48
|
-
return t.set(s, c), c.add(
|
|
48
|
+
return t.set(s, c), c.add(u), () => c.delete(u);
|
|
49
49
|
}
|
|
50
50
|
};
|
|
51
51
|
};
|
|
52
|
-
return new Promise((n,
|
|
52
|
+
return new Promise((n, d) => {
|
|
53
53
|
let s = !1;
|
|
54
|
-
const
|
|
55
|
-
window.removeEventListener("message", c),
|
|
54
|
+
const u = setTimeout(() => {
|
|
55
|
+
window.removeEventListener("message", c), d(new g("TIMEOUT", `Host did not answer within ${r} ms`));
|
|
56
56
|
}, r);
|
|
57
57
|
function c(p) {
|
|
58
58
|
if (p.source !== e)
|
|
@@ -62,7 +62,7 @@ function I({ timeout: r = _ } = {}) {
|
|
|
62
62
|
if (!s) {
|
|
63
63
|
if (a.id !== b)
|
|
64
64
|
return;
|
|
65
|
-
s = !0, clearTimeout(
|
|
65
|
+
s = !0, clearTimeout(u), n(v(a.data));
|
|
66
66
|
return;
|
|
67
67
|
}
|
|
68
68
|
if (a.id === A) {
|
|
@@ -82,20 +82,20 @@ function I({ timeout: r = _ } = {}) {
|
|
|
82
82
|
window.addEventListener("message", c), e.postMessage({ id: N }, "*");
|
|
83
83
|
});
|
|
84
84
|
}
|
|
85
|
-
const O = ["dialog", "side", "full"],
|
|
85
|
+
const O = ["dialog", "side", "full"], l = (r) => typeof r == "string" && r.trim() !== "", w = (r) => {
|
|
86
86
|
try {
|
|
87
|
-
return
|
|
87
|
+
return l(r) && new URL(r).protocol === "https:";
|
|
88
88
|
} catch {
|
|
89
89
|
return !1;
|
|
90
90
|
}
|
|
91
|
-
}, U = (r) => Array.isArray(r) && r.every(
|
|
91
|
+
}, U = (r) => Array.isArray(r) && r.every(l);
|
|
92
92
|
function D(r) {
|
|
93
|
-
const e = r ?? {}, i = [], t = (
|
|
94
|
-
if (t(
|
|
95
|
-
const
|
|
96
|
-
(o) =>
|
|
93
|
+
const e = r ?? {}, i = [], t = (E, o) => E || i.push(o);
|
|
94
|
+
if (t(l(e.id) && /^[a-z0-9][a-z0-9-]*$/.test(e.id), "id: lowercase letters, digits and dashes"), t(l(e.name), "name: required"), t(l(e.description), "description: required"), t(w(e.icon), "icon: https URL"), t(l(e.label?.en), "label.en: required"), t(e.label == null || Object.values(e.label).every(l), "label: every value a non-empty string"), t(w(e.entryUrl), "entryUrl: https URL"), t(U(e.scopes), "scopes: array of strings"), t(e.allow === void 0 || U(e.allow), "allow: array of strings"), t(O.includes(e.size), `size: one of ${O.join(", ")}`), t(e.background === void 0 || typeof e.background == "boolean", "background: boolean"), t(e.verifyUrl === void 0 || w(e.verifyUrl), "verifyUrl: https URL"), t(l(e.support), "support: required"), t(w(e.privacyUrl), "privacyUrl: https URL"), e.config !== void 0) {
|
|
95
|
+
const E = Array.isArray(e.config) && e.config.every(
|
|
96
|
+
(o) => l(o?.key) && l(o?.label) && (o.secret === void 0 || typeof o.secret == "boolean")
|
|
97
97
|
);
|
|
98
|
-
t(
|
|
98
|
+
t(E, "config: array of { key, label, secret? }"), t(E && new Set(e.config.map((o) => o.key)).size === e.config.length, "config: duplicate key");
|
|
99
99
|
}
|
|
100
100
|
if (i.length)
|
|
101
101
|
throw new Error(`Invalid manifest:
|
package/dist/plugin-sdk.iife.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
var DartseeSDK=function(s){"use strict";class f extends Error{constructor(e,
|
|
2
|
-
- ${
|
|
1
|
+
var DartseeSDK=function(s){"use strict";class f extends Error{constructor(e,a){super(a),this.code=e,this.name="DartseeError"}}const _="CONNECT",v="READY",U="EVENT",g={SESSION_GET:"SESSION_GET",GAME_GET:"GAME_GET",AUTH_GET_TOKEN:"AUTH_GET_TOKEN"},D=Object.values(g),N=(r,e)=>`${r}_RESPONSE_${e}`,b=(r,e)=>`${r}_ERROR_${e}`,A=1e4,$=3e4;function k({timeout:r=A}={}){const e=window.parent;if(e===window)return Promise.reject(new f("HOST_ERROR","Not inside the Dartsee host (no parent frame)"));const a=new Map,t=new Map;let T=0;const i=(n,E,o={})=>{if(!E.capabilities.includes(n))return Promise.reject(new f("UNSUPPORTED",`Host ${E.hostVersion} does not support ${n}`));const u=o.timeout??A,d=String(++T),y=N(n,d),c=b(n,d);return new Promise((p,S)=>{const w=()=>{clearTimeout(h),a.delete(y),a.delete(c)},h=setTimeout(()=>{w(),S(new f("TIMEOUT",`${n} timed out after ${u} ms`))},u);a.set(y,O=>{w(),p(O.data)}),a.set(c,O=>{w();const M=O.data;S(new f(M?.code??"HOST_ERROR",M?.message??`${n} failed`))}),e.postMessage({id:n,nonce:d},"*")})},P=n=>{let E;return{context:n,session:{get:o=>i(g.SESSION_GET,n,o)},game:{get:o=>i(g.GAME_GET,n,o)},auth:{async getToken(o){return(!E||E.expiresAt-Date.now()<$)&&(E=await i(g.AUTH_GET_TOKEN,n,o)),E.token}},on(o,u){const d=t.get(o)??new Set;return t.set(o,d),d.add(u),()=>d.delete(u)}}};return new Promise((n,E)=>{let o=!1;const u=setTimeout(()=>{window.removeEventListener("message",d),E(new f("TIMEOUT",`Host did not answer within ${r} ms`))},r);function d(y){if(y.source!==e)return;const c=y.data;if(!(!c||typeof c.id!="string")){if(!o){if(c.id!==v)return;o=!0,clearTimeout(u),n(P(c.data));return}if(c.id===U){const{name:p,payload:S}=c.data??{};t.get(p)?.forEach(w=>{try{w(S)}catch(h){console.error(`[dartsee] ${p} listener threw`,h)}});return}a.get(c.id)?.(c)}}window.addEventListener("message",d),e.postMessage({id:_},"*")})}const R=["dialog","side","full"],l=r=>typeof r=="string"&&r.trim()!=="",m=r=>{try{return l(r)&&new URL(r).protocol==="https:"}catch{return!1}},I=r=>Array.isArray(r)&&r.every(l);function G(r){const e=r??{},a=[],t=(T,i)=>T||a.push(i);if(t(l(e.id)&&/^[a-z0-9][a-z0-9-]*$/.test(e.id),"id: lowercase letters, digits and dashes"),t(l(e.name),"name: required"),t(l(e.description),"description: required"),t(m(e.icon),"icon: https URL"),t(l(e.label?.en),"label.en: required"),t(e.label==null||Object.values(e.label).every(l),"label: every value a non-empty string"),t(m(e.entryUrl),"entryUrl: https URL"),t(I(e.scopes),"scopes: array of strings"),t(e.allow===void 0||I(e.allow),"allow: array of strings"),t(R.includes(e.size),`size: one of ${R.join(", ")}`),t(e.background===void 0||typeof e.background=="boolean","background: boolean"),t(e.verifyUrl===void 0||m(e.verifyUrl),"verifyUrl: https URL"),t(l(e.support),"support: required"),t(m(e.privacyUrl),"privacyUrl: https URL"),e.config!==void 0){const T=Array.isArray(e.config)&&e.config.every(i=>l(i?.key)&&l(i?.label)&&(i.secret===void 0||typeof i.secret=="boolean"));t(T,"config: array of { key, label, secret? }"),t(T&&new Set(e.config.map(i=>i.key)).size===e.config.length,"config: duplicate key")}if(a.length)throw new Error(`Invalid manifest:
|
|
2
|
+
- ${a.join(`
|
|
3
3
|
- `)}`);return e}return s.CONNECT=_,s.DartseeError=f,s.EVENT=U,s.READY=v,s.RPC=g,s.RPC_IDS=D,s.SIZES=R,s.connect=k,s.errorId=b,s.responseId=N,s.validateManifest=G,Object.defineProperty(s,Symbol.toStringTag,{value:"Module"}),s}({});
|
package/dist/protocol.d.ts
CHANGED
|
@@ -5,7 +5,6 @@ export interface Message<T = unknown> {
|
|
|
5
5
|
data?: T;
|
|
6
6
|
nonce?: string;
|
|
7
7
|
}
|
|
8
|
-
/** The host answers every CONNECT with READY, not just the first, so a late-loading plugin can't miss it. */
|
|
9
8
|
export declare const CONNECT = "CONNECT";
|
|
10
9
|
export declare const READY = "READY";
|
|
11
10
|
export declare const EVENT = "EVENT";
|
|
@@ -15,7 +14,6 @@ export declare const RPC: {
|
|
|
15
14
|
readonly AUTH_GET_TOKEN: "AUTH_GET_TOKEN";
|
|
16
15
|
};
|
|
17
16
|
export type RpcId = (typeof RPC)[keyof typeof RPC];
|
|
18
|
-
/** The host's allowlist: any other id does nothing. */
|
|
19
17
|
export declare const RPC_IDS: readonly RpcId[];
|
|
20
18
|
export declare const responseId: (id: string, nonce: string) => string;
|
|
21
19
|
export declare const errorId: (id: string, nonce: string) => string;
|
|
@@ -36,7 +34,6 @@ export interface Context {
|
|
|
36
34
|
export interface SessionInfo {
|
|
37
35
|
active: boolean;
|
|
38
36
|
controlMode: string;
|
|
39
|
-
/** epoch ms; absent for open-ended sessions */
|
|
40
37
|
endsAt?: number;
|
|
41
38
|
playerCount: number;
|
|
42
39
|
}
|
|
@@ -46,7 +43,6 @@ export interface GameInfo {
|
|
|
46
43
|
}
|
|
47
44
|
export interface TokenInfo {
|
|
48
45
|
token: string;
|
|
49
|
-
/** epoch ms */
|
|
50
46
|
expiresAt: number;
|
|
51
47
|
}
|
|
52
48
|
export interface EventMap {
|
package/package.json
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dartsee/plugin-sdk",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.3",
|
|
4
4
|
"description": "SDK for Dartsee Game Controller plugins",
|
|
5
5
|
"license": "MIT",
|
|
6
|
+
"homepage": "https://apidocs.dartsee.com",
|
|
6
7
|
"repository": {
|
|
7
8
|
"type": "git",
|
|
8
9
|
"url": "git+https://gitlab.com/dartsee/games-monorepo.git",
|