@memizy/protocol 1.0.0-rc.5 → 1.0.0-rc.7
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/CHANGELOG.md +30 -0
- package/LICENSE +21 -0
- package/README.md +6 -4
- package/SPEC.md +90 -54
- package/dist/errors.cjs +1 -1
- package/dist/errors.js +5 -2
- package/dist/index.cjs +1 -1
- package/dist/index.js +11 -12
- package/dist/internal.cjs +1 -0
- package/dist/internal.js +8 -0
- package/dist/items.cjs +1 -1
- package/dist/items.js +107 -44
- package/dist/limits.cjs +1 -1
- package/dist/limits.js +9 -1
- package/dist/manifestSchema.cjs +1 -1
- package/dist/manifestSchema.js +1 -1
- package/dist/pluginRuntime.cjs +1 -1
- package/dist/pluginRuntime.js +26 -24
- package/dist/relay.cjs +1 -1
- package/dist/relay.js +2 -1
- package/dist/schemas.cjs +1 -1
- package/dist/schemas.js +34 -36
- package/dist/settings.cjs +1 -1
- package/dist/settings.js +24 -14
- package/dist/settingsSchema.cjs +1 -1
- package/dist/settingsSchema.js +55 -39
- package/dist/src/errors.d.ts +1 -1
- package/dist/src/index.d.ts +16 -13
- package/dist/src/internal.d.ts +12 -0
- package/dist/src/items.d.ts +6 -3
- package/dist/src/limits.d.ts +17 -1
- package/dist/src/manifestSchema.d.ts +43 -50
- package/dist/src/pluginRuntime.d.ts +8 -2
- package/dist/src/relay.d.ts +23 -5
- package/dist/src/schemas.d.ts +3 -10
- package/dist/src/security.d.ts +1 -1
- package/dist/src/settings.d.ts +24 -3
- package/dist/src/settingsSchema.d.ts +63 -0
- package/dist/src/types.d.ts +33 -31
- package/dist/types.cjs +1 -1
- package/dist/types.js +3 -7
- package/package.json +13 -5
package/dist/internal.js
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { RateLimiter as e, assertJsonWithin as t, findNonJson as n, jsonByteSize as r } from "./limits.js";
|
|
2
|
+
import { toRuntime as i } from "./pluginRuntime.js";
|
|
3
|
+
import { HOST_API_ARGS as a, parseHostCall as o } from "./schemas.js";
|
|
4
|
+
import { RELAY_LIMITS as s, isPin as c, normalizePlayerName as l } from "./relay.js";
|
|
5
|
+
import { displayItem as u, publicItem as d, seededRandom as f } from "./items.js";
|
|
6
|
+
import { LIBRARY_ORIGINS as p, injectContentPolicy as m, pluginAllowAttribute as h, pluginContentPolicy as g } from "./security.js";
|
|
7
|
+
import { ensureConnectionPolyfills as _ } from "./polyfills.js";
|
|
8
|
+
export { a as HOST_API_ARGS, p as LIBRARY_ORIGINS, s as RELAY_LIMITS, e as RateLimiter, t as assertJsonWithin, u as displayItem, _ as ensureConnectionPolyfills, n as findNonJson, m as injectContentPolicy, c as isPin, r as jsonByteSize, l as normalizePlayerName, o as parseHostCall, h as pluginAllowAttribute, g as pluginContentPolicy, d as publicItem, f as seededRandom, i as toRuntime };
|
package/dist/items.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
let e=require("@memizy/oqse");function t(e){let t=2166136261;for(let n=0;n<e.length;n++)t=Math.imul(t^e.charCodeAt(n),16777619);let n=t>>>0;return()=>{n=n+1831565813>>>0;let e=n;return e=Math.imul(e^e>>>15,e|1),e^=e+Math.imul(e^e>>>7,e|61),((e^e>>>14)>>>0)/4294967296}}function n(e,t,n){for(let r=0;r<6;r++){let r=[...e];for(let e=r.length-1;e>0;e--){let n=Math.floor(t()*(e+1));[r[e],r[n]]=[r[n],r[e]]}if(!n||r.length<2||!n(r))return r}return[...e.slice(1),e[0]]}var r=e=>t=>t.every((t,n)=>t.id===e[n]);function i(t,i){let a=structuredClone(t);switch(a.type){case`mcq-single`:case`mcq-multi`:return a.shuffle!==!1&&(a.options=n(a.options,i)),a;case`fill-in-select`:for(let e of Object.values(a.blanks??{}))e.shuffle!==!1&&(e.options=n(e.options,i));return a;case`sort-items`:return a.items=n(a.items,i,r(a.correctOrder)),a;case`match-pairs`:return a.prompts=n(a.prompts,i),a.matches=n(a.matches,i),a;case`match-complex`:return a.
|
|
1
|
+
let e=require("@memizy/oqse");function t(e){let t=2166136261;for(let n=0;n<e.length;n++)t=Math.imul(t^e.charCodeAt(n),16777619);let n=t>>>0;return()=>{n=n+1831565813>>>0;let e=n;return e=Math.imul(e^e>>>15,e|1),e^=e+Math.imul(e^e>>>7,e|61),((e^e>>>14)>>>0)/4294967296}}function n(e,t,n){for(let r=0;r<6;r++){let r=[...e];for(let e=r.length-1;e>0;e--){let n=Math.floor(t()*(e+1));[r[e],r[n]]=[r[n],r[e]]}if(!n||r.length<2||!n(r))return r}return[...e.slice(1),e[0]]}var r=e=>t=>t.every((t,n)=>t.id===e[n]);function i(t,i){let a=structuredClone(t);switch(a.type){case`mcq-single`:case`mcq-multi`:return a.shuffle!==!1&&(a.options=n(a.options,i)),a;case`fill-in-select`:for(let e of Object.values(a.blanks??{}))e.shuffle!==!1&&(e.options=n(e.options,i));return a;case`sort-items`:return a.items=n(a.items,i,r(a.correctOrder)),a;case`match-pairs`:return a.prompts=n(a.prompts,i),a.matches=n(a.matches,i),a;case`match-complex`:return a.prompts=n(a.prompts,i),a.matches=n(a.matches,i),a;case`timeline`:return a.shuffle!==!1&&(a.events=n(a.events,i,t=>(0,e.isTimelineOrderCorrect)(t))),a;case`categorize`:return a.items=n(a.items,i),a;case`diagram-label`:return a.requireTyping||(a.labels=n(a.labels,i)),a;default:return a}}var a=e=>typeof e==`object`&&!!e&&!Array.isArray(e);function o(e,t){return e.find(e=>{let n=e._zod.def.shape?.type;return n?._zod.def.type===`literal`&&n._zod.def.values.includes(t.type)})}function s(e,t){let n=t._zod.def;switch(n.type){case`optional`:case`nullable`:case`default`:case`prefault`:case`nonoptional`:case`readonly`:case`catch`:return e==null?e:s(e,n.innerType);case`pipe`:return s(e,n.in);case`lazy`:return s(e,n.getter());case`object`:{if(!a(e))return e;let t={};for(let[r,i]of Object.entries(n.shape)){if(!(r in e))continue;let n=s(e[r],i);n!==void 0&&(t[r]=n)}return t}case`array`:return Array.isArray(e)?e.map(e=>s(e,n.element)):e;case`record`:return a(e)?[`unknown`,`any`].includes(n.valueType._zod.def.type)?void 0:Object.fromEntries(Object.entries(e).map(([e,t])=>[e,s(t,n.valueType)])):e;case`intersection`:return a(e)?{...s(e,n.left),...s(e,n.right)}:e;case`union`:{if(!a(e)&&!Array.isArray(e))return e;let t=n.options,r=a(e)&&o(t,e)||t.find(t=>t.safeParse(e).success);return r?s(e,r):Array.isArray(e)?[]:{}}case`unknown`:case`any`:return;default:return e}}var c=[`explanation`,`incorrectFeedback`],l={note:[`hiddenContent`],flashcard:[`back`],"true-false":[`correctAnswer`],"mcq-single":[`correctId`],"mcq-multi":[`correctIds`],"short-answer":[`correctAnswers`],"sort-items":[`correctOrder`],"match-pairs":[`pairs`],"match-complex":[`connections`],slider:[`correctAnswer`],"numeric-input":[`correctAnswer`],"math-input":[`correctAnswers`],matrix:[`correctCells`],"open-ended":[`sampleAnswer`,`rubric`],"chess-puzzle":[`correctAnswers`]},u=[`options`,`items`,`prompts`,`matches`,`categories`,`rows`,`columns`,`labels`];function d(t){let n=t.type,r=n.startsWith(`x-`)?structuredClone(t):s(structuredClone(t),e.OQSEItemSchema);for(let e of c)delete r[e];if(Array.isArray(r.sources))for(let e of r.sources)e&&typeof e==`object`&&delete e.quote;if(n.startsWith(`x-`))return delete r.solution,r.answerHidden=!0,r;for(let e of l[n]??[])delete r[e];for(let e of u)if(Array.isArray(r[e]))for(let t of r[e])t&&typeof t==`object`&&delete t.explanation;switch(n){case`fill-in-blanks`:r.blanks=Object.fromEntries(Object.keys(r.blanks??{}).map(e=>[e,[]]));break;case`fill-in-select`:for(let e of Object.values(r.blanks??{})){delete e.correctId;for(let t of e.options??[])delete t.explanation}break;case`categorize`:for(let e of r.items??[])delete e.correctCategoryId;break;case`timeline`:for(let e of r.events??[])delete e.date,delete e.precision;break;case`diagram-label`:for(let e of r.zones??[])delete e.correctLabelId;r.requireTyping&&(r.labels=[]);break;case`pin-on-image`:case`pin-on-model`:r.hotspots=[]}if(r.assets&&typeof r.assets==`object`){let e=f(r);r.assets=Object.fromEntries(Object.entries(r.assets).filter(([t])=>e.has(t.toLowerCase())))}return r.answerHidden=!0,r}function f(t){let n=new Set;for(let[r,i]of(0,e.itemRichText)(t))if(r[0]!==`assets`)for(let t of(0,e.findAssetKeys)(i))n.add(t);let r=t.targetAsset;return typeof r==`string`&&n.add(r.toLowerCase()),n}function p(t,n){if(!t.assets)return t;let r=new Set;for(let e of n)for(let t of f(e))r.add(t);for(let[n,i]of(0,e.metaRichText)(t))if(n[1]!==`assets`)for(let t of(0,e.findAssetKeys)(i))r.add(t);return t.thumbnail&&r.add(t.thumbnail.toLowerCase()),{...t,assets:Object.fromEntries(Object.entries(t.assets).filter(([e])=>r.has(e.toLowerCase())))}}function m(e,n){let r=e.items.map(e=>n===void 0?structuredClone(e):i(e,t(`${n}:${e.id}`))),a=r.map(d);return{set:{meta:e.meta,items:r},publicSet:{meta:p(e.meta,a),items:a}}}exports.displayItem=i,exports.prepareDisplaySet=m,exports.publicItem=d,exports.seededRandom=t;
|
package/dist/items.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { OQSEItemSchema as e, findAssetKeys as t, isTimelineOrderCorrect as n, itemRichText as r, metaRichText as i } from "@memizy/oqse";
|
|
2
2
|
//#region src/items.ts
|
|
3
|
-
function
|
|
3
|
+
function a(e) {
|
|
4
4
|
let t = 2166136261;
|
|
5
5
|
for (let n = 0; n < e.length; n++) t = Math.imul(t ^ e.charCodeAt(n), 16777619);
|
|
6
6
|
let n = t >>> 0;
|
|
@@ -10,7 +10,7 @@ function t(e) {
|
|
|
10
10
|
return e = Math.imul(e ^ e >>> 15, e | 1), e ^= e + Math.imul(e ^ e >>> 7, e | 61), ((e ^ e >>> 14) >>> 0) / 4294967296;
|
|
11
11
|
};
|
|
12
12
|
}
|
|
13
|
-
function
|
|
13
|
+
function o(e, t, n) {
|
|
14
14
|
for (let r = 0; r < 6; r++) {
|
|
15
15
|
let r = [...e];
|
|
16
16
|
for (let e = r.length - 1; e > 0; e--) {
|
|
@@ -21,25 +21,70 @@ function n(e, t, n) {
|
|
|
21
21
|
}
|
|
22
22
|
return [...e.slice(1), e[0]];
|
|
23
23
|
}
|
|
24
|
-
var
|
|
25
|
-
function
|
|
26
|
-
let
|
|
27
|
-
switch (
|
|
24
|
+
var s = (e) => (t) => t.every((t, n) => t.id === e[n]);
|
|
25
|
+
function c(e, t) {
|
|
26
|
+
let r = structuredClone(e);
|
|
27
|
+
switch (r.type) {
|
|
28
28
|
case "mcq-single":
|
|
29
|
-
case "mcq-multi": return
|
|
29
|
+
case "mcq-multi": return r.shuffle !== !1 && (r.options = o(r.options, t)), r;
|
|
30
30
|
case "fill-in-select":
|
|
31
|
-
for (let e of Object.values(
|
|
32
|
-
return
|
|
33
|
-
case "sort-items": return
|
|
34
|
-
case "match-pairs": return
|
|
35
|
-
case "match-complex": return
|
|
36
|
-
case "timeline": return
|
|
37
|
-
case "categorize": return
|
|
38
|
-
case "diagram-label": return
|
|
39
|
-
default: return
|
|
31
|
+
for (let e of Object.values(r.blanks ?? {})) e.shuffle !== !1 && (e.options = o(e.options, t));
|
|
32
|
+
return r;
|
|
33
|
+
case "sort-items": return r.items = o(r.items, t, s(r.correctOrder)), r;
|
|
34
|
+
case "match-pairs": return r.prompts = o(r.prompts, t), r.matches = o(r.matches, t), r;
|
|
35
|
+
case "match-complex": return r.prompts = o(r.prompts, t), r.matches = o(r.matches, t), r;
|
|
36
|
+
case "timeline": return r.shuffle !== !1 && (r.events = o(r.events, t, (e) => n(e))), r;
|
|
37
|
+
case "categorize": return r.items = o(r.items, t), r;
|
|
38
|
+
case "diagram-label": return r.requireTyping || (r.labels = o(r.labels, t)), r;
|
|
39
|
+
default: return r;
|
|
40
40
|
}
|
|
41
41
|
}
|
|
42
|
-
var
|
|
42
|
+
var l = (e) => typeof e == "object" && !!e && !Array.isArray(e);
|
|
43
|
+
function u(e, t) {
|
|
44
|
+
return e.find((e) => {
|
|
45
|
+
let n = e._zod.def.shape?.type;
|
|
46
|
+
return n?._zod.def.type === "literal" && n._zod.def.values.includes(t.type);
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
function d(e, t) {
|
|
50
|
+
let n = t._zod.def;
|
|
51
|
+
switch (n.type) {
|
|
52
|
+
case "optional":
|
|
53
|
+
case "nullable":
|
|
54
|
+
case "default":
|
|
55
|
+
case "prefault":
|
|
56
|
+
case "nonoptional":
|
|
57
|
+
case "readonly":
|
|
58
|
+
case "catch": return e == null ? e : d(e, n.innerType);
|
|
59
|
+
case "pipe": return d(e, n.in);
|
|
60
|
+
case "lazy": return d(e, n.getter());
|
|
61
|
+
case "object": {
|
|
62
|
+
if (!l(e)) return e;
|
|
63
|
+
let t = {};
|
|
64
|
+
for (let [r, i] of Object.entries(n.shape)) {
|
|
65
|
+
if (!(r in e)) continue;
|
|
66
|
+
let n = d(e[r], i);
|
|
67
|
+
n !== void 0 && (t[r] = n);
|
|
68
|
+
}
|
|
69
|
+
return t;
|
|
70
|
+
}
|
|
71
|
+
case "array": return Array.isArray(e) ? e.map((e) => d(e, n.element)) : e;
|
|
72
|
+
case "record": return l(e) ? ["unknown", "any"].includes(n.valueType._zod.def.type) ? void 0 : Object.fromEntries(Object.entries(e).map(([e, t]) => [e, d(t, n.valueType)])) : e;
|
|
73
|
+
case "intersection": return l(e) ? {
|
|
74
|
+
...d(e, n.left),
|
|
75
|
+
...d(e, n.right)
|
|
76
|
+
} : e;
|
|
77
|
+
case "union": {
|
|
78
|
+
if (!l(e) && !Array.isArray(e)) return e;
|
|
79
|
+
let t = n.options, r = l(e) && u(t, e) || t.find((t) => t.safeParse(e).success);
|
|
80
|
+
return r ? d(e, r) : Array.isArray(e) ? [] : {};
|
|
81
|
+
}
|
|
82
|
+
case "unknown":
|
|
83
|
+
case "any": return;
|
|
84
|
+
default: return e;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
var f = ["explanation", "incorrectFeedback"], p = {
|
|
43
88
|
note: ["hiddenContent"],
|
|
44
89
|
flashcard: ["back"],
|
|
45
90
|
"true-false": ["correctAnswer"],
|
|
@@ -51,66 +96,84 @@ var a = ["explanation", "incorrectFeedback"], o = {
|
|
|
51
96
|
"match-complex": ["connections"],
|
|
52
97
|
slider: ["correctAnswer"],
|
|
53
98
|
"numeric-input": ["correctAnswer"],
|
|
54
|
-
"math-input": ["
|
|
99
|
+
"math-input": ["correctAnswers"],
|
|
55
100
|
matrix: ["correctCells"],
|
|
56
101
|
"open-ended": ["sampleAnswer", "rubric"],
|
|
57
102
|
"chess-puzzle": ["correctAnswers"]
|
|
58
|
-
},
|
|
103
|
+
}, m = [
|
|
59
104
|
"options",
|
|
60
105
|
"items",
|
|
61
106
|
"prompts",
|
|
62
107
|
"matches",
|
|
63
|
-
"leftItems",
|
|
64
|
-
"rightItems",
|
|
65
108
|
"categories",
|
|
66
109
|
"rows",
|
|
67
110
|
"columns",
|
|
68
111
|
"labels"
|
|
69
112
|
];
|
|
70
|
-
function
|
|
71
|
-
let
|
|
72
|
-
for (let e of
|
|
73
|
-
if (Array.isArray(
|
|
74
|
-
if (
|
|
75
|
-
for (let e of
|
|
76
|
-
for (let e of
|
|
77
|
-
switch (
|
|
113
|
+
function h(t) {
|
|
114
|
+
let n = t.type, r = n.startsWith("x-") ? structuredClone(t) : d(structuredClone(t), e);
|
|
115
|
+
for (let e of f) delete r[e];
|
|
116
|
+
if (Array.isArray(r.sources)) for (let e of r.sources) e && typeof e == "object" && delete e.quote;
|
|
117
|
+
if (n.startsWith("x-")) return delete r.solution, r.answerHidden = !0, r;
|
|
118
|
+
for (let e of p[n] ?? []) delete r[e];
|
|
119
|
+
for (let e of m) if (Array.isArray(r[e])) for (let t of r[e]) t && typeof t == "object" && delete t.explanation;
|
|
120
|
+
switch (n) {
|
|
78
121
|
case "fill-in-blanks":
|
|
79
|
-
|
|
122
|
+
r.blanks = Object.fromEntries(Object.keys(r.blanks ?? {}).map((e) => [e, []]));
|
|
80
123
|
break;
|
|
81
124
|
case "fill-in-select":
|
|
82
|
-
for (let e of Object.values(
|
|
125
|
+
for (let e of Object.values(r.blanks ?? {})) {
|
|
83
126
|
delete e.correctId;
|
|
84
127
|
for (let t of e.options ?? []) delete t.explanation;
|
|
85
128
|
}
|
|
86
129
|
break;
|
|
87
130
|
case "categorize":
|
|
88
|
-
for (let e of
|
|
131
|
+
for (let e of r.items ?? []) delete e.correctCategoryId;
|
|
89
132
|
break;
|
|
90
133
|
case "timeline":
|
|
91
|
-
for (let e of
|
|
134
|
+
for (let e of r.events ?? []) delete e.date, delete e.precision;
|
|
92
135
|
break;
|
|
93
136
|
case "diagram-label":
|
|
94
|
-
for (let e of
|
|
95
|
-
|
|
137
|
+
for (let e of r.zones ?? []) delete e.correctLabelId;
|
|
138
|
+
r.requireTyping && (r.labels = []);
|
|
96
139
|
break;
|
|
97
140
|
case "pin-on-image":
|
|
98
|
-
case "pin-on-model":
|
|
141
|
+
case "pin-on-model": r.hotspots = [];
|
|
99
142
|
}
|
|
100
|
-
|
|
143
|
+
if (r.assets && typeof r.assets == "object") {
|
|
144
|
+
let e = g(r);
|
|
145
|
+
r.assets = Object.fromEntries(Object.entries(r.assets).filter(([t]) => e.has(t.toLowerCase())));
|
|
146
|
+
}
|
|
147
|
+
return r.answerHidden = !0, r;
|
|
148
|
+
}
|
|
149
|
+
function g(e) {
|
|
150
|
+
let n = /* @__PURE__ */ new Set();
|
|
151
|
+
for (let [i, a] of r(e)) if (i[0] !== "assets") for (let e of t(a)) n.add(e);
|
|
152
|
+
let i = e.targetAsset;
|
|
153
|
+
return typeof i == "string" && n.add(i.toLowerCase()), n;
|
|
101
154
|
}
|
|
102
|
-
function
|
|
103
|
-
|
|
155
|
+
function _(e, n) {
|
|
156
|
+
if (!e.assets) return e;
|
|
157
|
+
let r = /* @__PURE__ */ new Set();
|
|
158
|
+
for (let e of n) for (let t of g(e)) r.add(t);
|
|
159
|
+
for (let [n, a] of i(e)) if (n[1] !== "assets") for (let e of t(a)) r.add(e);
|
|
160
|
+
return e.thumbnail && r.add(e.thumbnail.toLowerCase()), {
|
|
161
|
+
...e,
|
|
162
|
+
assets: Object.fromEntries(Object.entries(e.assets).filter(([e]) => r.has(e.toLowerCase())))
|
|
163
|
+
};
|
|
164
|
+
}
|
|
165
|
+
function v(e, t) {
|
|
166
|
+
let n = e.items.map((e) => t === void 0 ? structuredClone(e) : c(e, a(`${t}:${e.id}`))), r = n.map(h);
|
|
104
167
|
return {
|
|
105
168
|
set: {
|
|
106
169
|
meta: e.meta,
|
|
107
|
-
items:
|
|
170
|
+
items: n
|
|
108
171
|
},
|
|
109
172
|
publicSet: {
|
|
110
|
-
meta: e.meta,
|
|
111
|
-
items:
|
|
173
|
+
meta: _(e.meta, r),
|
|
174
|
+
items: r
|
|
112
175
|
}
|
|
113
176
|
};
|
|
114
177
|
}
|
|
115
178
|
//#endregion
|
|
116
|
-
export {
|
|
179
|
+
export { c as displayItem, v as prepareDisplaySet, h as publicItem, a as seededRandom };
|
package/dist/limits.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
const e=require("./errors.cjs");var t={messageBytes:65536,messagesPerSecond:30,messageBurst:60,snapshotBytes:1048576,snapshotsPerSecond:2,dataBytes:262144,dataWritesPerSecond:1,helloTimeoutMs:1e4,answerBytes:4096,generatedItemBytes:32768,serviceBytes:65536,servicesPerMinute:30},n=64;function r(e,t=`$`,i=0,a=new Set){if(e===null||typeof e==`string`||typeof e==`boolean`)return null;if(typeof e==`number`)return Number.isFinite(e)?null:`${t} is not a finite number`;if(typeof e!=`object`)return`${t} is a ${typeof e}`;if(i>=n)return`${t} is nested deeper than ${n} levels`;if(a.has(e))return`${t} contains a circular reference`;if(Array.isArray(e)){a.add(e);for(let n=0;n<e.length;n++){let o=r(e[n],`${t}[${n}]`,i+1,a);if(o)return o}return a.delete(e),null}let o=Object.getPrototypeOf(e);if(o!==Object.prototype&&o!==null)return`${t} is not a plain object`;a.add(e);for(let[n,o]of Object.entries(e)){let e=r(o,`${t}.${n}`,i+1,a);if(e)return e}return a.delete(e),null}function i(e){return new TextEncoder().encode(JSON.stringify(e)).length}function a(t,n,a,o){let s=r(t);if(s)throw new e.ProtocolError(`INVALID_ARGUMENT`,`${o} must be plain JSON: ${s}.`);let c=i(t);if(c>n)throw new e.ProtocolError(a,`${o} is ${c} bytes; the limit is ${n} bytes.`);return c}var o=class{rate;burst;now;tokens;last;constructor(e,t,n=()=>Date.now()){this.rate=e,this.burst=t,this.now=n,this.tokens=t,this.last=n()}tryTake(e=1){let t=this.now();return this.tokens=Math.min(this.burst,this.tokens+(t-this.last)/1e3*this.rate),this.last=t,this.tokens<e?!1:(this.tokens-=e,!0)}};exports.LIMITS=t,exports.RateLimiter=o,exports.assertJsonWithin=a,exports.findNonJson=r,exports.jsonByteSize=i;
|
|
1
|
+
const e=require("./errors.cjs");var t={messageBytes:65536,messagesPerSecond:30,messageBurst:60,snapshotBytes:1048576,snapshotsPerSecond:2,dataBytes:262144,dataWritesPerSecond:1,helloTimeoutMs:1e4,answerBytes:4096,generatedItemBytes:32768,answersPerSecond:10,answerBurst:20,serviceBytes:65536,serviceResultBytes:262144,servicesPerMinute:30,assetsPerSecond:10,assetBurst:20,assetBytes:2097152,errorReportsPerSecond:5,errorReportBurst:10},n=64;function r(e,t=`$`,i=0,a=new Set){if(e===null||typeof e==`string`||typeof e==`boolean`)return null;if(typeof e==`number`)return Number.isFinite(e)?null:`${t} is not a finite number`;if(typeof e!=`object`)return`${t} is a ${typeof e}`;if(i>=n)return`${t} is nested deeper than ${n} levels`;if(a.has(e))return`${t} contains a circular reference`;if(Array.isArray(e)){a.add(e);for(let n=0;n<e.length;n++){let o=r(e[n],`${t}[${n}]`,i+1,a);if(o)return o}return a.delete(e),null}let o=Object.getPrototypeOf(e);if(o!==Object.prototype&&o!==null)return`${t} is not a plain object`;a.add(e);for(let[n,o]of Object.entries(e)){let e=r(o,`${t}.${n}`,i+1,a);if(e)return e}return a.delete(e),null}function i(e){return new TextEncoder().encode(JSON.stringify(e)).length}function a(t,n,a,o){let s=r(t);if(s)throw new e.ProtocolError(`INVALID_ARGUMENT`,`${o} must be plain JSON: ${s}.`);let c=i(t);if(c>n)throw new e.ProtocolError(a,`${o} is ${c} bytes; the limit is ${n} bytes.`);return c}var o=class{rate;burst;now;tokens;last;constructor(e,t,n=()=>Date.now()){this.rate=e,this.burst=t,this.now=n,this.tokens=t,this.last=n()}tryTake(e=1){let t=this.now();return this.tokens=Math.min(this.burst,this.tokens+(t-this.last)/1e3*this.rate),this.last=t,this.tokens<e?!1:(this.tokens-=e,!0)}};exports.LIMITS=t,exports.RateLimiter=o,exports.assertJsonWithin=a,exports.findNonJson=r,exports.jsonByteSize=i;
|
package/dist/limits.js
CHANGED
|
@@ -11,8 +11,16 @@ var t = {
|
|
|
11
11
|
helloTimeoutMs: 1e4,
|
|
12
12
|
answerBytes: 4096,
|
|
13
13
|
generatedItemBytes: 32768,
|
|
14
|
+
answersPerSecond: 10,
|
|
15
|
+
answerBurst: 20,
|
|
14
16
|
serviceBytes: 65536,
|
|
15
|
-
|
|
17
|
+
serviceResultBytes: 262144,
|
|
18
|
+
servicesPerMinute: 30,
|
|
19
|
+
assetsPerSecond: 10,
|
|
20
|
+
assetBurst: 20,
|
|
21
|
+
assetBytes: 2097152,
|
|
22
|
+
errorReportsPerSecond: 5,
|
|
23
|
+
errorReportBurst: 10
|
|
16
24
|
}, n = 64;
|
|
17
25
|
function r(e, t = "$", i = 0, a = /* @__PURE__ */ new Set()) {
|
|
18
26
|
if (e === null || typeof e == "string" || typeof e == "boolean") return null;
|
package/dist/manifestSchema.cjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
const e=require("./settingsSchema.cjs"),t=require("./pluginRuntime.cjs");let n=require("zod"),r=require("@memizy/oqse");var i=n.z.string().regex(/^\d+\.\d+$/,`Protocol version must be in MAJOR.MINOR format (e.g. "1.0")`),a=n.z.enum([`presenter`,`player`]),o=n.z.looseObject({players:n.z.looseObject({min:n.z.number().int().min(1,`players.min must be at least 1`),max:n.z.number().int().max(200,`players.max must be at most 200`),recommended:n.z.number().int().positive().optional()}).refine(e=>e.min<=e.max,{message:`players.min must not be greater than players.max`,path:[`min`]}).refine(e=>e.recommended===void 0||e.recommended>=e.min&&e.recommended<=e.max,{message:`players.recommended must be between min and max`,path:[`recommended`]}),hostAs:n.z.array(a).min(1,`hostAs must contain "presenter" and/or "player"`).refine(e=>new Set(e).size===e.length,`hostAs must not contain duplicates`),lateJoin:n.z.boolean().optional()}),s=n.z.string().regex(/^(https|wss):\/\/[a-z0-9.-]+(:\d{1,5})?$/i,`A network origin is "https://host" or "wss://host" (no path)`),c=n.z.string().max(100).regex(/^[a-z][a-z0-9-]*(\.[a-z0-9][a-z0-9-]*)*$/,`A service name is lowercase segments joined by dots (e.g. "chess.puzzles")`),l=n.z.looseObject({network:n.z.array(s).max(20).optional(),devices:n.z.array(n.z.enum([`camera`,`microphone`,`geolocation`,`serial`,`bluetooth`])).max(5).optional()}),u=n.z.looseObject({protocol:i,set:n.z.enum([`required`,`optional`,`none`]).optional(),modes:n.z.looseObject({solo:n.z.looseObject({}).optional(),multiplayer:o.optional()}),settings:n.z.array(e.
|
|
1
|
+
const e=require("./settingsSchema.cjs"),t=require("./pluginRuntime.cjs");let n=require("zod"),r=require("@memizy/oqse");var i=n.z.string().regex(/^\d+\.\d+$/,`Protocol version must be in MAJOR.MINOR format (e.g. "1.0")`),a=n.z.enum([`presenter`,`player`]),o=n.z.looseObject({players:n.z.looseObject({min:n.z.number().int().min(1,`players.min must be at least 1`),max:n.z.number().int().max(200,`players.max must be at most 200`),recommended:n.z.number().int().positive().optional()}).refine(e=>e.min<=e.max,{message:`players.min must not be greater than players.max`,path:[`min`]}).refine(e=>e.recommended===void 0||e.recommended>=e.min&&e.recommended<=e.max,{message:`players.recommended must be between min and max`,path:[`recommended`]}),hostAs:n.z.array(a).min(1,`hostAs must contain "presenter" and/or "player"`).refine(e=>new Set(e).size===e.length,`hostAs must not contain duplicates`),lateJoin:n.z.boolean().optional()}),s=n.z.string().regex(/^(https|wss):\/\/[a-z0-9.-]+(:\d{1,5})?$/i,`A network origin is "https://host" or "wss://host" (no path)`),c=n.z.string().max(100).regex(/^[a-z][a-z0-9-]*(\.[a-z0-9][a-z0-9-]*)*$/,`A service name is lowercase segments joined by dots (e.g. "chess.puzzles")`),l=n.z.looseObject({network:n.z.array(s).max(20).optional(),devices:n.z.array(n.z.enum([`camera`,`microphone`,`geolocation`,`serial`,`bluetooth`])).max(5).optional()}),u=n.z.looseObject({protocol:i,set:n.z.enum([`required`,`optional`,`none`]).optional(),modes:n.z.looseObject({solo:n.z.looseObject({}).optional(),multiplayer:o.optional()}),settings:n.z.array(e.SettingEntrySchema).optional(),settingsScreen:n.z.looseObject({size:n.z.enum([`compact`,`large`])}).optional(),display:n.z.looseObject({orientation:n.z.enum([`any`,`portrait`,`landscape`]).optional()}).optional(),permissions:l.optional(),services:n.z.array(c).max(20).optional()}).refine(e=>e.modes.solo!==void 0||e.modes.multiplayer!==void 0,{message:`modes must declare "solo" and/or "multiplayer"`,path:[`modes`]}).refine(e=>e.settingsScreen===void 0||e.modes.multiplayer!==void 0,{message:`settingsScreen is only used in the multiplayer lobby; declare modes.multiplayer or remove it`,path:[`settingsScreen`]}).refine(e=>{let t=(e.settings??[]).map(e=>e.id);return new Set(t).size===t.length},{message:`Setting ids must be unique`,path:[`settings`]});function d(e){let n=[],i=r.OQSEManifestSchema.safeParse(e);i.success||n.push(...(0,r.formatOQSEErrors)(i.error));let a=e?.appSpecific?.memizy;if(a===void 0)n.push(`appSpecific.memizy: Missing the Memizy runtime block (protocol, modes, …)`);else{let e=u.safeParse(a);e.success||n.push(...(0,r.formatOQSEErrors)(e.error).map(e=>`appSpecific.memizy.${e}`))}if(n.length>0)return{success:!1,errors:n};let o=(0,r.withManifestDefaults)(e),s=t.toRuntime(o.appSpecific.memizy),c=o.capabilities.types;return s.set!==`none`&&(!Array.isArray(c)||c.length===0)?{success:!1,errors:[`capabilities.types: Declare the item types the game shows, or "set": "none" in appSpecific.memizy for a game without questions.`]}:{success:!0,manifest:o,runtime:s}}var f=class extends Error{errors;constructor(e){super(`Invalid plugin manifest:\n${e.join(`
|
|
2
2
|
`)}`),this.name=`PluginManifestError`,this.errors=e}};function p(e){let t=d(e);if(!t.success)throw new f(t.errors);return{manifest:t.manifest,runtime:t.runtime}}function m(e){let n=t.extractManifestFromHtml(e);return n.success?d(n.data):{success:!1,errors:[n.error]}}exports.HostAsSchema=a,exports.MemizyRuntimeSchema=u,exports.MultiplayerModeSchema=o,exports.PluginManifestError=f,exports.PluginPermissionsSchema=l,exports.ServiceNameSchema=c,exports.parsePluginManifest=p,exports.readPluginManifestFromHtml=m,exports.safeParsePluginManifest=d;
|
package/dist/manifestSchema.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { SettingEntrySchema as e } from "./settingsSchema.js";
|
|
2
2
|
import { extractManifestFromHtml as t, toRuntime as n } from "./pluginRuntime.js";
|
|
3
3
|
import { z as r } from "zod";
|
|
4
4
|
import { OQSEManifestSchema as i, formatOQSEErrors as a, withManifestDefaults as o } from "@memizy/oqse";
|
package/dist/pluginRuntime.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
var
|
|
1
|
+
const e=require("./settings.cjs");var t=/<script\b[^>]*\btype\s*=\s*["']application\/oqse-manifest\+json["'][^>]*>([\s\S]*?)<\/script\s*>/i;function n(e){let n=t.exec(e);if(!n)return{success:!1,error:`No <script type="application/oqse-manifest+json"> data island found.`};try{return{success:!0,data:JSON.parse(n[1])}}catch(e){return{success:!1,error:`The manifest data island is not valid JSON: ${e.message}`}}}function r(t){let n=t.modes.multiplayer,r=n?{players:{min:n.players.min,max:n.players.max,...n.players.recommended!==void 0&&{recommended:n.players.recommended}},hostAs:[...n.hostAs],lateJoin:n.lateJoin??!0}:null,i=[];return t.modes.solo&&i.push(`solo`),r?.hostAs.includes(`presenter`)&&i.push(`board`),r&&i.push(`controller`),r&&t.settingsScreen&&i.push(`settings`),{protocol:t.protocol,set:t.set??`required`,solo:t.modes.solo!==void 0,multiplayer:r,settings:(t.settings??[]).filter(e.isKnownSetting),unknownSettings:(t.settings??[]).filter(t=>!e.isKnownSetting(t)),settingsScreen:t.settingsScreen?{size:t.settingsScreen.size}:null,orientation:t.display?.orientation??`any`,views:i,permissions:{network:[...new Set(t.permissions?.network??[])],devices:[...new Set(t.permissions?.devices??[])]},services:[...new Set(t.services??[])]}}exports.extractManifestFromHtml=n,exports.toRuntime=r;
|
package/dist/pluginRuntime.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
+
import { isKnownSetting as e } from "./settings.js";
|
|
1
2
|
//#region src/pluginRuntime.ts
|
|
2
|
-
var
|
|
3
|
-
function
|
|
4
|
-
let n =
|
|
3
|
+
var t = /<script\b[^>]*\btype\s*=\s*["']application\/oqse-manifest\+json["'][^>]*>([\s\S]*?)<\/script\s*>/i;
|
|
4
|
+
function n(e) {
|
|
5
|
+
let n = t.exec(e);
|
|
5
6
|
if (!n) return {
|
|
6
7
|
success: !1,
|
|
7
8
|
error: "No <script type=\"application/oqse-manifest+json\"> data island found."
|
|
@@ -18,31 +19,32 @@ function t(t) {
|
|
|
18
19
|
};
|
|
19
20
|
}
|
|
20
21
|
}
|
|
21
|
-
function
|
|
22
|
-
let
|
|
22
|
+
function r(t) {
|
|
23
|
+
let n = t.modes.multiplayer, r = n ? {
|
|
23
24
|
players: {
|
|
24
|
-
min:
|
|
25
|
-
max:
|
|
26
|
-
...
|
|
25
|
+
min: n.players.min,
|
|
26
|
+
max: n.players.max,
|
|
27
|
+
...n.players.recommended !== void 0 && { recommended: n.players.recommended }
|
|
27
28
|
},
|
|
28
|
-
hostAs: [...
|
|
29
|
-
lateJoin:
|
|
30
|
-
} : null,
|
|
31
|
-
return
|
|
32
|
-
protocol:
|
|
33
|
-
set:
|
|
34
|
-
solo:
|
|
35
|
-
multiplayer:
|
|
36
|
-
settings:
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
29
|
+
hostAs: [...n.hostAs],
|
|
30
|
+
lateJoin: n.lateJoin ?? !0
|
|
31
|
+
} : null, i = [];
|
|
32
|
+
return t.modes.solo && i.push("solo"), r?.hostAs.includes("presenter") && i.push("board"), r && i.push("controller"), r && t.settingsScreen && i.push("settings"), {
|
|
33
|
+
protocol: t.protocol,
|
|
34
|
+
set: t.set ?? "required",
|
|
35
|
+
solo: t.modes.solo !== void 0,
|
|
36
|
+
multiplayer: r,
|
|
37
|
+
settings: (t.settings ?? []).filter(e),
|
|
38
|
+
unknownSettings: (t.settings ?? []).filter((t) => !e(t)),
|
|
39
|
+
settingsScreen: t.settingsScreen ? { size: t.settingsScreen.size } : null,
|
|
40
|
+
orientation: t.display?.orientation ?? "any",
|
|
41
|
+
views: i,
|
|
40
42
|
permissions: {
|
|
41
|
-
network: [...new Set(
|
|
42
|
-
devices: [...new Set(
|
|
43
|
+
network: [...new Set(t.permissions?.network ?? [])],
|
|
44
|
+
devices: [...new Set(t.permissions?.devices ?? [])]
|
|
43
45
|
},
|
|
44
|
-
services: [...new Set(
|
|
46
|
+
services: [...new Set(t.services ?? [])]
|
|
45
47
|
};
|
|
46
48
|
}
|
|
47
49
|
//#endregion
|
|
48
|
-
export {
|
|
50
|
+
export { n as extractManifestFromHtml, r as toRuntime };
|
package/dist/relay.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
var e=1,t={frameBytes:
|
|
1
|
+
var e=1,t={frameBytes:3145728,bundleBytes:8388608,playersPerRoom:100,playerFramesPerSecond:60,playerFrameBurst:120,hostFramesPerSecond:3e3,hostFrameBurst:6e3,nameLength:32,authLength:4096,hostAwayMs:6e5,roomTtlMs:216e5};function n(e){return typeof e==`string`?e.replace(/\s+/g,` `).trim().slice(0,t.nameLength):``}function r(e){return typeof e==`string`&&/^\d{6}$/.test(e)}exports.RELAY_LIMITS=t,exports.RELAY_PROTOCOL=e,exports.isPin=r,exports.normalizePlayerName=n;
|
package/dist/relay.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
//#region src/relay.ts
|
|
2
2
|
var e = 1, t = {
|
|
3
|
-
frameBytes:
|
|
3
|
+
frameBytes: 3145728,
|
|
4
4
|
bundleBytes: 8388608,
|
|
5
5
|
playersPerRoom: 100,
|
|
6
6
|
playerFramesPerSecond: 60,
|
|
@@ -8,6 +8,7 @@ var e = 1, t = {
|
|
|
8
8
|
hostFramesPerSecond: 3e3,
|
|
9
9
|
hostFrameBurst: 6e3,
|
|
10
10
|
nameLength: 32,
|
|
11
|
+
authLength: 4096,
|
|
11
12
|
hostAwayMs: 6e5,
|
|
12
13
|
roomTtlMs: 216e5
|
|
13
14
|
};
|
package/dist/schemas.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
const e=require("./errors.cjs");let t=require("zod"),n=require("@memizy/oqse");var r=e=>t.z.string().min(1).max(e),i=t.z.string().min(1).max(128),a=t.z.looseObject({protocol:t.z.string().regex(/^\d+\.\d+$/,`protocol must be in MAJOR.MINOR format`),sdk:t.z.looseObject({name:r(200),version:r(100)}),plugin:t.z.looseObject({id:r(500),version:r(100)}),features:t.z.array(r(100)).max(100)}),o=t.z.looseObject({to:t.z.union([t.z.literal(`authority`),t.z.literal(`all`),t.z.array(i).min(1).max(500)]),data:t.z.unknown()}),s=t.z.looseObject({playerId:i.optional(),itemId:r(128),isCorrect:t.z.boolean(),confidence:t.z.union([t.z.literal(1),t.z.literal(2),t.z.literal(3),t.z.literal(4)]).optional(),timeSpentMs:t.z.number().int().nonnegative().optional(),hintsUsed:t.z.number().int().nonnegative().optional(),isSkipped:t.z.boolean().optional(),answer:t.z.unknown().optional(),item:t.z.looseObject({id:r(128),type:r(64)}).optional()}).refine(e=>!e.item||e.item.id===e.itemId,{message:`item.id must equal itemId`,path:[`item`,`id`]}),c=t.z.
|
|
1
|
+
const e=require("./errors.cjs");let t=require("zod"),n=require("@memizy/oqse");var r=e=>t.z.string().min(1).max(e),i=t.z.string().min(1).max(128),a=t.z.looseObject({protocol:t.z.string().regex(/^\d+\.\d+$/,`protocol must be in MAJOR.MINOR format`),sdk:t.z.looseObject({name:r(200),version:r(100)}),plugin:t.z.looseObject({id:r(500),version:r(100)}),features:t.z.array(r(100)).max(100)}),o=t.z.looseObject({to:t.z.union([t.z.literal(`authority`),t.z.literal(`all`),t.z.array(i).min(1).max(500)]),data:t.z.unknown()}),s=t.z.looseObject({playerId:i.optional(),itemId:r(128),isCorrect:t.z.boolean(),confidence:t.z.union([t.z.literal(1),t.z.literal(2),t.z.literal(3),t.z.literal(4)]).optional(),timeSpentMs:t.z.number().int().nonnegative().optional(),hintsUsed:t.z.number().int().nonnegative().optional(),isSkipped:t.z.boolean().optional(),score:t.z.number().min(0).max(1).optional(),answer:t.z.unknown().optional(),item:t.z.looseObject({id:r(128),type:r(64)}).optional()}).refine(e=>!e.item||e.item.id===e.itemId,{message:`item.id must equal itemId`,path:[`item`,`id`]}),c=t.z.enum([`plugin`,`set`]),l=t.z.looseObject({values:t.z.record(t.z.string(),t.z.unknown()),valid:t.z.boolean(),message:t.z.string().max(500).optional()}),u=t.z.looseObject({scores:t.z.record(i,t.z.number().finite()).optional(),summary:t.z.string().max(1e3).optional()}),d=t.z.looseObject({code:r(100),message:t.z.string().max(2e3),context:t.z.record(t.z.string(),t.z.unknown()).optional()}),f={hello:t.z.tuple([a]),ready:t.z.tuple([]),send:t.z.tuple([o]),saveSnapshot:t.z.tuple([t.z.unknown()]),recordAnswer:t.z.tuple([s]),saveData:t.z.tuple([c,t.z.unknown()]),updateSettings:t.z.tuple([l]),getAsset:t.z.tuple([r(200),r(128).optional()]),end:t.z.tuple([u]),reportError:t.z.tuple([d]),service:t.z.tuple([r(100),t.z.unknown()])};function p(t,r){let i=f[t].safeParse(r);if(!i.success)throw new e.ProtocolError(`INVALID_ARGUMENT`,`${t}: ${(0,n.formatOQSEErrors)(i.error).join(`; `)}`);return i.data}exports.AddressSchema=i,exports.AnswerRecordSchema=s,exports.DataScopeSchema=c,exports.ErrorReportSchema=d,exports.HOST_API_ARGS=f,exports.HandshakeSchema=a,exports.OutgoingMessageSchema=o,exports.SessionResultSchema=u,exports.SettingsUpdateSchema=l,exports.parseHostCall=p;
|
package/dist/schemas.js
CHANGED
|
@@ -1,28 +1,28 @@
|
|
|
1
1
|
import { ProtocolError as e } from "./errors.js";
|
|
2
2
|
import { z as t } from "zod";
|
|
3
|
-
import {
|
|
3
|
+
import { formatOQSEErrors as n } from "@memizy/oqse";
|
|
4
4
|
//#region src/schemas.ts
|
|
5
|
-
var
|
|
5
|
+
var r = (e) => t.string().min(1).max(e), i = t.string().min(1).max(128), a = t.looseObject({
|
|
6
6
|
protocol: t.string().regex(/^\d+\.\d+$/, "protocol must be in MAJOR.MINOR format"),
|
|
7
7
|
sdk: t.looseObject({
|
|
8
|
-
name:
|
|
9
|
-
version:
|
|
8
|
+
name: r(200),
|
|
9
|
+
version: r(100)
|
|
10
10
|
}),
|
|
11
11
|
plugin: t.looseObject({
|
|
12
|
-
id:
|
|
13
|
-
version:
|
|
12
|
+
id: r(500),
|
|
13
|
+
version: r(100)
|
|
14
14
|
}),
|
|
15
|
-
features: t.array(
|
|
16
|
-
}),
|
|
15
|
+
features: t.array(r(100)).max(100)
|
|
16
|
+
}), o = t.looseObject({
|
|
17
17
|
to: t.union([
|
|
18
18
|
t.literal("authority"),
|
|
19
19
|
t.literal("all"),
|
|
20
|
-
t.array(
|
|
20
|
+
t.array(i).min(1).max(500)
|
|
21
21
|
]),
|
|
22
22
|
data: t.unknown()
|
|
23
|
-
}),
|
|
24
|
-
playerId:
|
|
25
|
-
itemId:
|
|
23
|
+
}), s = t.looseObject({
|
|
24
|
+
playerId: i.optional(),
|
|
25
|
+
itemId: r(128),
|
|
26
26
|
isCorrect: t.boolean(),
|
|
27
27
|
confidence: t.union([
|
|
28
28
|
t.literal(1),
|
|
@@ -33,45 +33,43 @@ var i = (e) => t.string().min(1).max(e), a = t.string().min(1).max(128), o = t.l
|
|
|
33
33
|
timeSpentMs: t.number().int().nonnegative().optional(),
|
|
34
34
|
hintsUsed: t.number().int().nonnegative().optional(),
|
|
35
35
|
isSkipped: t.boolean().optional(),
|
|
36
|
+
score: t.number().min(0).max(1).optional(),
|
|
36
37
|
answer: t.unknown().optional(),
|
|
37
38
|
item: t.looseObject({
|
|
38
|
-
id:
|
|
39
|
-
type:
|
|
39
|
+
id: r(128),
|
|
40
|
+
type: r(64)
|
|
40
41
|
}).optional()
|
|
41
42
|
}).refine((e) => !e.item || e.item.id === e.itemId, {
|
|
42
43
|
message: "item.id must equal itemId",
|
|
43
44
|
path: ["item", "id"]
|
|
44
|
-
}),
|
|
45
|
+
}), c = t.enum(["plugin", "set"]), l = t.looseObject({
|
|
45
46
|
values: t.record(t.string(), t.unknown()),
|
|
46
47
|
valid: t.boolean(),
|
|
47
48
|
message: t.string().max(500).optional()
|
|
48
|
-
}),
|
|
49
|
-
scores: t.record(
|
|
49
|
+
}), u = t.looseObject({
|
|
50
|
+
scores: t.record(i, t.number().finite()).optional(),
|
|
50
51
|
summary: t.string().max(1e3).optional()
|
|
51
|
-
}),
|
|
52
|
-
code:
|
|
52
|
+
}), d = t.looseObject({
|
|
53
|
+
code: r(100),
|
|
53
54
|
message: t.string().max(2e3),
|
|
54
55
|
context: t.record(t.string(), t.unknown()).optional()
|
|
55
|
-
}),
|
|
56
|
-
hello: t.tuple([
|
|
56
|
+
}), f = {
|
|
57
|
+
hello: t.tuple([a]),
|
|
57
58
|
ready: t.tuple([]),
|
|
58
|
-
send: t.tuple([
|
|
59
|
+
send: t.tuple([o]),
|
|
59
60
|
saveSnapshot: t.tuple([t.unknown()]),
|
|
60
|
-
recordAnswer: t.tuple([
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
reportError: t.tuple([m]),
|
|
68
|
-
exit: t.tuple([]),
|
|
69
|
-
service: t.tuple([i(100), t.unknown()])
|
|
61
|
+
recordAnswer: t.tuple([s]),
|
|
62
|
+
saveData: t.tuple([c, t.unknown()]),
|
|
63
|
+
updateSettings: t.tuple([l]),
|
|
64
|
+
getAsset: t.tuple([r(200), r(128).optional()]),
|
|
65
|
+
end: t.tuple([u]),
|
|
66
|
+
reportError: t.tuple([d]),
|
|
67
|
+
service: t.tuple([r(100), t.unknown()])
|
|
70
68
|
};
|
|
71
|
-
function
|
|
72
|
-
let i =
|
|
73
|
-
if (!i.success) throw new e("INVALID_ARGUMENT", `${t}: ${
|
|
69
|
+
function p(t, r) {
|
|
70
|
+
let i = f[t].safeParse(r);
|
|
71
|
+
if (!i.success) throw new e("INVALID_ARGUMENT", `${t}: ${n(i.error).join("; ")}`);
|
|
74
72
|
return i.data;
|
|
75
73
|
}
|
|
76
74
|
//#endregion
|
|
77
|
-
export {
|
|
75
|
+
export { i as AddressSchema, s as AnswerRecordSchema, c as DataScopeSchema, d as ErrorReportSchema, f as HOST_API_ARGS, a as HandshakeSchema, o as OutgoingMessageSchema, u as SessionResultSchema, l as SettingsUpdateSchema, p as parseHostCall };
|
package/dist/settings.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
function e(e,t){switch(e.type){case`number`:return typeof t!=`number`||!Number.isFinite(t)?`must be a number`:e.min!==void 0&&t<e.min?`must be at least ${e.min}`:e.max!==void 0&&t>e.max?`must be at most ${e.max}`:null;case`boolean`:return typeof t==`boolean`?null:`must be true or false`;case`select`:return e.options.some(e=>e.value===t)?null:`must be one of the options`;case`text`:return typeof t==`string`?e.maxLength!==void 0&&t.length>e.maxLength?`must be at most ${e.maxLength} characters`:null:`must be text`}}function
|
|
1
|
+
var e=[`number`,`boolean`,`select`,`text`];function t(t){return e.includes(t.type)}function n(e,t){switch(e.type){case`number`:return typeof t!=`number`||!Number.isFinite(t)?`must be a number`:e.min!==void 0&&t<e.min?`must be at least ${e.min}`:e.max!==void 0&&t>e.max?`must be at most ${e.max}`:null;case`boolean`:return typeof t==`boolean`?null:`must be true or false`;case`select`:return e.options.some(e=>e.value===t)?null:`must be one of the options`;case`text`:return typeof t==`string`?e.maxLength!==void 0&&t.length>e.maxLength?`must be at most ${e.maxLength} characters`:null:`must be text`}}function r(e,t={},r=[]){let i={},a=[];for(let r of e){if(!(r.id in t)){i[r.id]=r.default;continue}let e=n(r,t[r.id]);e?(a.push(`${r.id}: ${e}`),i[r.id]=r.default):i[r.id]=t[r.id]}for(let e of r)i[e.id]=structuredClone(e.default);for(let n of Object.keys(t))!e.some(e=>e.id===n)&&!r.some(e=>e.id===n)&&a.push(`${n}: unknown setting`);return{values:i,errors:a}}function i(e,t){return e.filter(e=>!e.modes||e.modes.includes(t))}function a(e,t){if(typeof e==`string`)return e;let n=t.split(`-`)[0];return e[t]??e[n]??e.en??Object.values(e)[0]}exports.SETTING_TYPES=e,exports.isKnownSetting=t,exports.localize=a,exports.resolveSettings=r,exports.settingsForMode=i,exports.validateSettingValue=n;
|
package/dist/settings.js
CHANGED
|
@@ -1,5 +1,14 @@
|
|
|
1
1
|
//#region src/settings.ts
|
|
2
|
-
|
|
2
|
+
var e = [
|
|
3
|
+
"number",
|
|
4
|
+
"boolean",
|
|
5
|
+
"select",
|
|
6
|
+
"text"
|
|
7
|
+
];
|
|
8
|
+
function t(t) {
|
|
9
|
+
return e.includes(t.type);
|
|
10
|
+
}
|
|
11
|
+
function n(e, t) {
|
|
3
12
|
switch (e.type) {
|
|
4
13
|
case "number": return typeof t != "number" || !Number.isFinite(t) ? "must be a number" : e.min !== void 0 && t < e.min ? `must be at least ${e.min}` : e.max !== void 0 && t > e.max ? `must be at most ${e.max}` : null;
|
|
5
14
|
case "boolean": return typeof t == "boolean" ? null : "must be true or false";
|
|
@@ -7,29 +16,30 @@ function e(e, t) {
|
|
|
7
16
|
case "text": return typeof t == "string" ? e.maxLength !== void 0 && t.length > e.maxLength ? `must be at most ${e.maxLength} characters` : null : "must be text";
|
|
8
17
|
}
|
|
9
18
|
}
|
|
10
|
-
function
|
|
11
|
-
let
|
|
12
|
-
for (let
|
|
13
|
-
if (!(
|
|
14
|
-
r
|
|
19
|
+
function r(e, t = {}, r = []) {
|
|
20
|
+
let i = {}, a = [];
|
|
21
|
+
for (let r of e) {
|
|
22
|
+
if (!(r.id in t)) {
|
|
23
|
+
i[r.id] = r.default;
|
|
15
24
|
continue;
|
|
16
25
|
}
|
|
17
|
-
let
|
|
18
|
-
|
|
26
|
+
let e = n(r, t[r.id]);
|
|
27
|
+
e ? (a.push(`${r.id}: ${e}`), i[r.id] = r.default) : i[r.id] = t[r.id];
|
|
19
28
|
}
|
|
20
|
-
for (let e of
|
|
29
|
+
for (let e of r) i[e.id] = structuredClone(e.default);
|
|
30
|
+
for (let n of Object.keys(t)) !e.some((e) => e.id === n) && !r.some((e) => e.id === n) && a.push(`${n}: unknown setting`);
|
|
21
31
|
return {
|
|
22
|
-
values:
|
|
23
|
-
errors:
|
|
32
|
+
values: i,
|
|
33
|
+
errors: a
|
|
24
34
|
};
|
|
25
35
|
}
|
|
26
|
-
function
|
|
36
|
+
function i(e, t) {
|
|
27
37
|
return e.filter((e) => !e.modes || e.modes.includes(t));
|
|
28
38
|
}
|
|
29
|
-
function
|
|
39
|
+
function a(e, t) {
|
|
30
40
|
if (typeof e == "string") return e;
|
|
31
41
|
let n = t.split("-")[0];
|
|
32
42
|
return e[t] ?? e[n] ?? e.en ?? Object.values(e)[0];
|
|
33
43
|
}
|
|
34
44
|
//#endregion
|
|
35
|
-
export {
|
|
45
|
+
export { e as SETTING_TYPES, t as isKnownSetting, a as localize, r as resolveSettings, i as settingsForMode, n as validateSettingValue };
|
package/dist/settingsSchema.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
const e=require("./settings.cjs");let t=require("zod");var n=t.z.union([t.z.string().min(1,`Text must not be empty`),t.z.record(t.z.string().min(2),t.z.string().min(1)).refine(e=>Object.keys(e).length>0,`Localized text needs at least one language`)]),r={id:t.z.string().regex(/^[a-zA-Z][a-zA-Z0-9_-]{0,63}$/,`Setting id must start with a letter and contain only letters, digits, "_" and "-"`),label:n,description:n.optional(),modes:t.z.array(t.z.enum([`solo`,`multiplayer`])).min(1,`modes needs at least one mode`).optional()},i=t.z.looseObject({...r,type:t.z.literal(`number`),default:t.z.number().finite(),min:t.z.number().finite().optional(),max:t.z.number().finite().optional(),step:t.z.number().positive().optional()}).refine(e=>e.min===void 0||e.max===void 0||e.min<=e.max,{message:`min must not be greater than max`,path:[`min`]}).refine(e=>(e.min===void 0||e.default>=e.min)&&(e.max===void 0||e.default<=e.max),{message:`default is outside min/max`,path:[`default`]}),a=t.z.looseObject({...r,type:t.z.literal(`boolean`),default:t.z.boolean()}),o=t.z.union([t.z.string(),t.z.number().finite(),t.z.boolean()]),s=t.z.looseObject({...r,type:t.z.literal(`select`),options:t.z.array(t.z.looseObject({value:o,label:n})).min(1,`A select setting needs at least one option`),default:o}).refine(e=>new Set(e.options.map(e=>e.value)).size===e.options.length,{message:`Option values must be unique`,path:[`options`]}).refine(e=>e.options.some(t=>t.value===e.default),{message:`default must be one of the option values`,path:[`default`]}),c=t.z.looseObject({...r,type:t.z.literal(`text`),default:t.z.string(),maxLength:t.z.number().int().positive().optional()}).refine(e=>e.maxLength===void 0||e.default.length<=e.maxLength,{message:`default is longer than maxLength`,path:[`default`]}),l=t.z.discriminatedUnion(`type`,[i,a,s,c]),u=t.z.looseObject({...r,type:t.z.string().regex(/^[a-z][a-z0-9-]*$/,`A setting type is a lowercase name`).refine(t=>!e.SETTING_TYPES.includes(t),`A known setting type`),default:t.z.unknown().refine(e=>e!==void 0,`A setting needs a default`)}),d=t.z.unknown().transform((n,r)=>{let i=typeof n==`object`&&n?n.type:void 0,a=(typeof i==`string`&&e.SETTING_TYPES.includes(i)?l:u).safeParse(n);if(!a.success){for(let e of a.error.issues)r.addIssue({code:`custom`,message:e.message,path:e.path});return t.z.NEVER}return a.data});exports.LocalizedTextSchema=n,exports.SettingDefinitionSchema=l,exports.SettingEntrySchema=d,exports.UnknownSettingSchema=u;
|