@colyseus/playground 0.17.12 → 0.18.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/build/assets/index-CWU1hZTF.css +6 -0
- package/build/assets/index-hvVeOuTE.js +2165 -0
- package/build/assets/index-hvVeOuTE.js.map +1 -0
- package/build/colyseus.ext.cjs +5 -0
- package/build/colyseus.ext.cjs.map +2 -2
- package/build/colyseus.ext.mjs +5 -0
- package/build/colyseus.ext.mjs.map +2 -2
- package/build/index.cjs +256 -42
- package/build/index.cjs.map +3 -3
- package/build/index.d.ts +8 -2
- package/build/index.html +2 -2
- package/build/index.mjs +241 -37
- package/build/index.mjs.map +3 -3
- package/build/serve-static.cjs +108 -0
- package/build/serve-static.cjs.map +7 -0
- package/build/serve-static.d.ts +1 -0
- package/build/serve-static.mjs +72 -0
- package/build/serve-static.mjs.map +7 -0
- package/package.json +13 -6
- package/src-backend/colyseus.ext.ts +8 -0
- package/src-backend/index.ts +270 -44
- package/src-backend/serve-static.ts +76 -0
- package/build/assets/index-BS3RJoKX.css +0 -6
- package/build/assets/index-D6rlB4zv.js +0 -2161
- package/build/assets/index-D6rlB4zv.js.map +0 -1
package/build/colyseus.ext.cjs
CHANGED
|
@@ -34,7 +34,12 @@ __export(colyseus_ext_exports, {
|
|
|
34
34
|
});
|
|
35
35
|
module.exports = __toCommonJS(colyseus_ext_exports);
|
|
36
36
|
var import_core = require("@colyseus/core");
|
|
37
|
+
var __patched = false;
|
|
37
38
|
async function applyMonkeyPatch() {
|
|
39
|
+
if (__patched) {
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
__patched = true;
|
|
38
43
|
let z = void 0;
|
|
39
44
|
try {
|
|
40
45
|
z = await import("zod");
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src-backend/colyseus.ext.ts"],
|
|
4
|
-
"sourcesContent": ["import { Room, Client, ClientState, ClientPrivate, AuthContext } from '@colyseus/core';\n\nexport async function applyMonkeyPatch() {\n /**\n * Optional: if zod is available, we can use toJSONSchema() for body and query types\n */\n let z: any = undefined;\n try { z = await import(\"zod\"); } catch (e: any) { /* zod not installed */ }\n\n const _onJoin = Room.prototype['_onJoin'];\n Room.prototype['_onJoin'] = async function (this: Room, client: Client & ClientPrivate) {\n const result = await _onJoin.apply(this, arguments as any);\n\n if (client.state === ClientState.JOINING) {\n\n const messages: any = {};\n Object.keys(this['onMessageEvents'].events).sort().forEach((type) => {\n if (type.indexOf(\"__\") === 0 || type === \"*\") { return; }\n\n const messageValidator = this['onMessageValidators'][type];\n messages[type] = z && messageValidator && z.toJSONSchema(messageValidator) || null;\n });\n\n client.send(\"__playground_message_types\", messages);\n }\n\n return result;\n }\n}"],
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,kBAAsE;AAEtE,eAAsB,mBAAmB;AAIvC,MAAI,IAAS;AACb,MAAI;AAAE,QAAI,MAAM,OAAO,KAAK;AAAA,EAAG,SAAS,GAAP;AAAA,EAA0C;AAE3E,QAAM,UAAU,iBAAK,UAAU,SAAS;AACxC,mBAAK,UAAU,SAAS,IAAI,eAA4B,QAAgC;AACtF,UAAM,SAAS,MAAM,QAAQ,MAAM,MAAM,SAAgB;AAEzD,QAAI,OAAO,UAAU,wBAAY,SAAS;AAExC,YAAM,WAAgB,CAAC;AACvB,aAAO,KAAK,KAAK,iBAAiB,EAAE,MAAM,EAAE,KAAK,EAAE,QAAQ,CAAC,SAAS;AACnE,YAAI,KAAK,QAAQ,IAAI,MAAM,KAAK,SAAS,KAAK;AAAE;AAAA,QAAQ;AAExD,cAAM,mBAAmB,KAAK,qBAAqB,EAAE,IAAI;AACzD,iBAAS,IAAI,IAAI,KAAK,oBAAoB,EAAE,aAAa,gBAAgB,KAAK;AAAA,MAChF,CAAC;AAED,aAAO,KAAK,8BAA8B,QAAQ;AAAA,IACpD;AAEA,WAAO;AAAA,EACT;AACF;",
|
|
4
|
+
"sourcesContent": ["import { Room, Client, ClientState, ClientPrivate, AuthContext } from '@colyseus/core';\n\nlet __patched = false;\n\nexport async function applyMonkeyPatch() {\n // Idempotent: playground() may be invoked multiple times (e.g. once for\n // createRouter spread, once for the express middleware) \u2014 stacking\n // _onJoin wrappers would leak.\n if (__patched) { return; }\n __patched = true;\n\n /**\n * Optional: if zod is available, we can use toJSONSchema() for body and query types\n */\n let z: any = undefined;\n try { z = await import(\"zod\"); } catch (e: any) { /* zod not installed */ }\n\n const _onJoin = Room.prototype['_onJoin'];\n Room.prototype['_onJoin'] = async function (this: Room, client: Client & ClientPrivate) {\n const result = await _onJoin.apply(this, arguments as any);\n\n if (client.state === ClientState.JOINING) {\n\n const messages: any = {};\n Object.keys(this['onMessageEvents'].events).sort().forEach((type) => {\n if (type.indexOf(\"__\") === 0 || type === \"*\") { return; }\n\n const messageValidator = this['onMessageValidators'][type];\n messages[type] = z && messageValidator && z.toJSONSchema(messageValidator) || null;\n });\n\n client.send(\"__playground_message_types\", messages);\n }\n\n return result;\n }\n}"],
|
|
5
|
+
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,kBAAsE;AAEtE,IAAI,YAAY;AAEhB,eAAsB,mBAAmB;AAIvC,MAAI,WAAW;AAAE;AAAA,EAAQ;AACzB,cAAY;AAKZ,MAAI,IAAS;AACb,MAAI;AAAE,QAAI,MAAM,OAAO,KAAK;AAAA,EAAG,SAAS,GAAP;AAAA,EAA0C;AAE3E,QAAM,UAAU,iBAAK,UAAU,SAAS;AACxC,mBAAK,UAAU,SAAS,IAAI,eAA4B,QAAgC;AACtF,UAAM,SAAS,MAAM,QAAQ,MAAM,MAAM,SAAgB;AAEzD,QAAI,OAAO,UAAU,wBAAY,SAAS;AAExC,YAAM,WAAgB,CAAC;AACvB,aAAO,KAAK,KAAK,iBAAiB,EAAE,MAAM,EAAE,KAAK,EAAE,QAAQ,CAAC,SAAS;AACnE,YAAI,KAAK,QAAQ,IAAI,MAAM,KAAK,SAAS,KAAK;AAAE;AAAA,QAAQ;AAExD,cAAM,mBAAmB,KAAK,qBAAqB,EAAE,IAAI;AACzD,iBAAS,IAAI,IAAI,KAAK,oBAAoB,EAAE,aAAa,gBAAgB,KAAK;AAAA,MAChF,CAAC;AAED,aAAO,KAAK,8BAA8B,QAAQ;AAAA,IACpD;AAEA,WAAO;AAAA,EACT;AACF;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/build/colyseus.ext.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src-backend/colyseus.ext.ts"],
|
|
4
|
-
"sourcesContent": ["import { Room, Client, ClientState, ClientPrivate, AuthContext } from '@colyseus/core';\n\nexport async function applyMonkeyPatch() {\n /**\n * Optional: if zod is available, we can use toJSONSchema() for body and query types\n */\n let z: any = undefined;\n try { z = await import(\"zod\"); } catch (e: any) { /* zod not installed */ }\n\n const _onJoin = Room.prototype['_onJoin'];\n Room.prototype['_onJoin'] = async function (this: Room, client: Client & ClientPrivate) {\n const result = await _onJoin.apply(this, arguments as any);\n\n if (client.state === ClientState.JOINING) {\n\n const messages: any = {};\n Object.keys(this['onMessageEvents'].events).sort().forEach((type) => {\n if (type.indexOf(\"__\") === 0 || type === \"*\") { return; }\n\n const messageValidator = this['onMessageValidators'][type];\n messages[type] = z && messageValidator && z.toJSONSchema(messageValidator) || null;\n });\n\n client.send(\"__playground_message_types\", messages);\n }\n\n return result;\n }\n}"],
|
|
5
|
-
"mappings": ";AAAA,SAAS,MAAc,mBAA+C;AAEtE,eAAsB,mBAAmB;AAIvC,MAAI,IAAS;AACb,MAAI;AAAE,QAAI,MAAM,OAAO,KAAK;AAAA,EAAG,SAAS,GAAP;AAAA,EAA0C;AAE3E,QAAM,UAAU,KAAK,UAAU,SAAS;AACxC,OAAK,UAAU,SAAS,IAAI,eAA4B,QAAgC;AACtF,UAAM,SAAS,MAAM,QAAQ,MAAM,MAAM,SAAgB;AAEzD,QAAI,OAAO,UAAU,YAAY,SAAS;AAExC,YAAM,WAAgB,CAAC;AACvB,aAAO,KAAK,KAAK,iBAAiB,EAAE,MAAM,EAAE,KAAK,EAAE,QAAQ,CAAC,SAAS;AACnE,YAAI,KAAK,QAAQ,IAAI,MAAM,KAAK,SAAS,KAAK;AAAE;AAAA,QAAQ;AAExD,cAAM,mBAAmB,KAAK,qBAAqB,EAAE,IAAI;AACzD,iBAAS,IAAI,IAAI,KAAK,oBAAoB,EAAE,aAAa,gBAAgB,KAAK;AAAA,MAChF,CAAC;AAED,aAAO,KAAK,8BAA8B,QAAQ;AAAA,IACpD;AAEA,WAAO;AAAA,EACT;AACF;",
|
|
4
|
+
"sourcesContent": ["import { Room, Client, ClientState, ClientPrivate, AuthContext } from '@colyseus/core';\n\nlet __patched = false;\n\nexport async function applyMonkeyPatch() {\n // Idempotent: playground() may be invoked multiple times (e.g. once for\n // createRouter spread, once for the express middleware) \u2014 stacking\n // _onJoin wrappers would leak.\n if (__patched) { return; }\n __patched = true;\n\n /**\n * Optional: if zod is available, we can use toJSONSchema() for body and query types\n */\n let z: any = undefined;\n try { z = await import(\"zod\"); } catch (e: any) { /* zod not installed */ }\n\n const _onJoin = Room.prototype['_onJoin'];\n Room.prototype['_onJoin'] = async function (this: Room, client: Client & ClientPrivate) {\n const result = await _onJoin.apply(this, arguments as any);\n\n if (client.state === ClientState.JOINING) {\n\n const messages: any = {};\n Object.keys(this['onMessageEvents'].events).sort().forEach((type) => {\n if (type.indexOf(\"__\") === 0 || type === \"*\") { return; }\n\n const messageValidator = this['onMessageValidators'][type];\n messages[type] = z && messageValidator && z.toJSONSchema(messageValidator) || null;\n });\n\n client.send(\"__playground_message_types\", messages);\n }\n\n return result;\n }\n}"],
|
|
5
|
+
"mappings": ";AAAA,SAAS,MAAc,mBAA+C;AAEtE,IAAI,YAAY;AAEhB,eAAsB,mBAAmB;AAIvC,MAAI,WAAW;AAAE;AAAA,EAAQ;AACzB,cAAY;AAKZ,MAAI,IAAS;AACb,MAAI;AAAE,QAAI,MAAM,OAAO,KAAK;AAAA,EAAG,SAAS,GAAP;AAAA,EAA0C;AAE3E,QAAM,UAAU,KAAK,UAAU,SAAS;AACxC,OAAK,UAAU,SAAS,IAAI,eAA4B,QAAgC;AACtF,UAAM,SAAS,MAAM,QAAQ,MAAM,MAAM,SAAgB;AAEzD,QAAI,OAAO,UAAU,YAAY,SAAS;AAExC,YAAM,WAAgB,CAAC;AACvB,aAAO,KAAK,KAAK,iBAAiB,EAAE,MAAM,EAAE,KAAK,EAAE,QAAQ,CAAC,SAAS;AACnE,YAAI,KAAK,QAAQ,IAAI,MAAM,KAAK,SAAS,KAAK;AAAE;AAAA,QAAQ;AAExD,cAAM,mBAAmB,KAAK,qBAAqB,EAAE,IAAI;AACzD,iBAAS,IAAI,IAAI,KAAK,oBAAoB,EAAE,aAAa,gBAAgB,KAAK;AAAA,MAChF,CAAC;AAED,aAAO,KAAK,8BAA8B,QAAQ;AAAA,IACpD;AAEA,WAAO;AAAA,EACT;AACF;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/build/index.cjs
CHANGED
|
@@ -33,57 +33,271 @@ __export(src_backend_exports, {
|
|
|
33
33
|
playground: () => playground
|
|
34
34
|
});
|
|
35
35
|
module.exports = __toCommonJS(src_backend_exports);
|
|
36
|
+
var import_promises = __toESM(require("fs/promises"));
|
|
36
37
|
var import_path = __toESM(require("path"));
|
|
37
|
-
var
|
|
38
|
-
var
|
|
38
|
+
var import_url = require("url");
|
|
39
|
+
var import_promises2 = __toESM(require("node:inspector/promises"));
|
|
40
|
+
var import_node_child_process = require("node:child_process");
|
|
41
|
+
var import_node_os = __toESM(require("node:os"));
|
|
42
|
+
var import_node_module = require("node:module");
|
|
39
43
|
var import_core = require("@colyseus/core");
|
|
44
|
+
var import_auth = require("@colyseus/auth");
|
|
40
45
|
var import_colyseus_ext = require("./colyseus.ext.cjs");
|
|
41
|
-
|
|
46
|
+
var import_serve_static = require("./serve-static.cjs");
|
|
47
|
+
var import_meta = {};
|
|
48
|
+
var SPA_DIST = import_path.default.resolve(import_path.default.dirname((0, import_url.fileURLToPath)(import_meta.url)), "..", "build");
|
|
49
|
+
var profilingSession = null;
|
|
50
|
+
var profilingStartedAt = 0;
|
|
51
|
+
var lastProfile = null;
|
|
52
|
+
var lastReportHtml = null;
|
|
53
|
+
var lastProfilingError = null;
|
|
54
|
+
function resolveCpuproBin() {
|
|
55
|
+
try {
|
|
56
|
+
const require2 = (0, import_node_module.createRequire)(import_meta.url);
|
|
57
|
+
return import_path.default.join(import_path.default.dirname(require2.resolve("cpupro/package.json")), "bin", "cpupro");
|
|
58
|
+
} catch (e) {
|
|
59
|
+
return null;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
async function generateCpuproReport(profileJson) {
|
|
63
|
+
const bin = resolveCpuproBin();
|
|
64
|
+
if (!bin) {
|
|
65
|
+
throw new Error("cpupro is not installed \u2014 run `npm install cpupro` to render reports in the playground. The .cpuprofile is still available to download.");
|
|
66
|
+
}
|
|
67
|
+
const stamp = Date.now();
|
|
68
|
+
const profilePath = import_path.default.join(import_node_os.default.tmpdir(), `colyseus-profile-${stamp}.cpuprofile`);
|
|
69
|
+
const reportName = `colyseus-report-${stamp}.html`;
|
|
70
|
+
const reportPath = import_path.default.join(import_node_os.default.tmpdir(), reportName);
|
|
71
|
+
await import_promises.default.writeFile(profilePath, profileJson);
|
|
72
|
+
try {
|
|
73
|
+
await new Promise((resolve, reject) => {
|
|
74
|
+
const child = (0, import_node_child_process.spawn)(process.execPath, [bin, profilePath, "-n", "-o", import_node_os.default.tmpdir(), "-f", reportName], { stdio: "ignore" });
|
|
75
|
+
child.on("error", reject);
|
|
76
|
+
child.on("exit", (code) => code === 0 ? resolve() : reject(new Error(`cpupro exited with code ${code}`)));
|
|
77
|
+
});
|
|
78
|
+
return patchCpuproReport(await import_promises.default.readFile(reportPath, "utf8"));
|
|
79
|
+
} finally {
|
|
80
|
+
await import_promises.default.rm(profilePath, { force: true }).catch(() => {
|
|
81
|
+
});
|
|
82
|
+
await import_promises.default.rm(reportPath, { force: true }).catch(() => {
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
function patchCpuproReport(html) {
|
|
87
|
+
return html.replace(/dataSource:"url",data:[A-Za-z_$][\w$]*\.model\.data/, 'dataSource:"push",data:1');
|
|
88
|
+
}
|
|
89
|
+
function playground(opts = {}) {
|
|
90
|
+
var _a, _b;
|
|
42
91
|
(0, import_colyseus_ext.applyMonkeyPatch)();
|
|
43
|
-
const
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
92
|
+
const prefix = (_a = opts.prefix) != null ? _a : "";
|
|
93
|
+
const use = (_b = opts.use) != null ? _b : [];
|
|
94
|
+
const profilingDenied = () => !import_core.isDevMode && use.length === 0 ? new Response("Not found", { status: 404 }) : null;
|
|
95
|
+
const endpoints = {
|
|
96
|
+
"playground-rooms": (0, import_core.createEndpoint)(`${prefix}/rooms`, { method: "GET", use }, async () => {
|
|
97
|
+
const rooms = await import_core.matchMaker.driver.query({});
|
|
98
|
+
const roomsByType = {};
|
|
99
|
+
const roomsById = {};
|
|
100
|
+
rooms.forEach((room) => {
|
|
101
|
+
var _a2;
|
|
102
|
+
roomsByType[room.name] = ((_a2 = roomsByType[room.name]) != null ? _a2 : 0) + 1;
|
|
103
|
+
roomsById[room.roomId] = room;
|
|
104
|
+
});
|
|
105
|
+
return {
|
|
106
|
+
rooms: Object.keys(import_core.matchMaker.getAllHandlers()),
|
|
107
|
+
roomsByType,
|
|
108
|
+
roomsById,
|
|
109
|
+
auth: {
|
|
110
|
+
oauth: Object.keys(import_auth.auth.oauth.providers),
|
|
111
|
+
register: typeof import_auth.auth.settings.onRegisterWithEmailAndPassword === "function",
|
|
112
|
+
anonymous: typeof import_auth.JWT.settings.secret === "string"
|
|
113
|
+
}
|
|
114
|
+
};
|
|
115
|
+
}),
|
|
116
|
+
"playground-apidocs": (0, import_core.createEndpoint)(`${prefix}/__apidocs`, { method: "GET", use }, async () => {
|
|
117
|
+
var _a2, _b2, _c;
|
|
118
|
+
if (!import_core.isDevMode && use.length === 0) {
|
|
119
|
+
return new Response("Not found", { status: 404 });
|
|
52
120
|
}
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
121
|
+
let z;
|
|
122
|
+
try {
|
|
123
|
+
z = await import("zod");
|
|
124
|
+
} catch (e) {
|
|
125
|
+
}
|
|
126
|
+
const routerEndpoints = (_c = (_b2 = (_a2 = import_core.Server.current) == null ? void 0 : _a2.router) == null ? void 0 : _b2.endpoints) != null ? _c : {};
|
|
127
|
+
return Object.values(routerEndpoints).map((endpoint) => {
|
|
128
|
+
var _a3, _b3;
|
|
129
|
+
return {
|
|
130
|
+
method: endpoint.options.method,
|
|
131
|
+
path: endpoint.path,
|
|
132
|
+
body: z && endpoint.options.body && z.toJSONSchema(endpoint.options.body),
|
|
133
|
+
query: z && endpoint.options.query && z.toJSONSchema(endpoint.options.query),
|
|
134
|
+
metadata: endpoint.options.metadata,
|
|
135
|
+
description: (_b3 = (_a3 = endpoint.options.metadata) == null ? void 0 : _a3.openapi) == null ? void 0 : _b3.description
|
|
136
|
+
};
|
|
137
|
+
});
|
|
138
|
+
}),
|
|
139
|
+
"profiling-start": (0, import_core.createEndpoint)(`${prefix}/profiling/start`, { method: "POST", use }, async (ctx) => {
|
|
140
|
+
var _a2;
|
|
141
|
+
const denied = profilingDenied();
|
|
142
|
+
if (denied) {
|
|
143
|
+
return denied;
|
|
144
|
+
}
|
|
145
|
+
if (profilingSession) {
|
|
146
|
+
return { status: "running", startedAt: profilingStartedAt, error: "already running" };
|
|
147
|
+
}
|
|
148
|
+
const interval = Number((_a2 = ctx.query) == null ? void 0 : _a2.interval) || 100;
|
|
149
|
+
const session = new import_promises2.default.Session();
|
|
150
|
+
session.connect();
|
|
151
|
+
await session.post("Profiler.enable");
|
|
152
|
+
await session.post("Profiler.setSamplingInterval", { interval });
|
|
153
|
+
await session.post("Profiler.start");
|
|
154
|
+
profilingSession = session;
|
|
155
|
+
profilingStartedAt = Date.now();
|
|
156
|
+
lastProfile = null;
|
|
157
|
+
lastReportHtml = null;
|
|
158
|
+
lastProfilingError = null;
|
|
159
|
+
return { status: "started", startedAt: profilingStartedAt, interval };
|
|
160
|
+
}),
|
|
161
|
+
"profiling-stop": (0, import_core.createEndpoint)(`${prefix}/profiling/stop`, { method: "POST", use }, async () => {
|
|
162
|
+
var _a2;
|
|
163
|
+
const denied = profilingDenied();
|
|
164
|
+
if (denied) {
|
|
165
|
+
return denied;
|
|
166
|
+
}
|
|
167
|
+
if (!profilingSession) {
|
|
168
|
+
return { status: "idle", error: "not running" };
|
|
169
|
+
}
|
|
170
|
+
const session = profilingSession;
|
|
171
|
+
profilingSession = null;
|
|
172
|
+
const durationMs = Date.now() - profilingStartedAt;
|
|
173
|
+
const { profile } = await session.post("Profiler.stop");
|
|
174
|
+
session.disconnect();
|
|
175
|
+
lastProfile = JSON.stringify(profile);
|
|
176
|
+
lastReportHtml = null;
|
|
177
|
+
lastProfilingError = null;
|
|
178
|
+
try {
|
|
179
|
+
lastReportHtml = await generateCpuproReport(lastProfile);
|
|
180
|
+
} catch (e) {
|
|
181
|
+
lastProfilingError = (_a2 = e == null ? void 0 : e.message) != null ? _a2 : String(e);
|
|
182
|
+
}
|
|
183
|
+
return {
|
|
184
|
+
status: "stopped",
|
|
185
|
+
durationMs,
|
|
186
|
+
profileBytes: lastProfile.length,
|
|
187
|
+
reportReady: !!lastReportHtml,
|
|
188
|
+
error: lastProfilingError
|
|
189
|
+
};
|
|
190
|
+
}),
|
|
191
|
+
"profiling-status": (0, import_core.createEndpoint)(`${prefix}/profiling/status`, { method: "GET", use }, async () => {
|
|
192
|
+
const denied = profilingDenied();
|
|
193
|
+
if (denied) {
|
|
194
|
+
return denied;
|
|
65
195
|
}
|
|
66
|
-
});
|
|
67
|
-
});
|
|
68
|
-
router.get("/__apidocs", async (_, res) => {
|
|
69
|
-
let z = void 0;
|
|
70
|
-
try {
|
|
71
|
-
z = await import("zod");
|
|
72
|
-
} catch (e) {
|
|
73
|
-
}
|
|
74
|
-
res.json(Object.values(import_core.__globalEndpoints).map((endpoint) => {
|
|
75
|
-
var _a, _b;
|
|
76
196
|
return {
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
197
|
+
running: !!profilingSession,
|
|
198
|
+
startedAt: profilingSession ? profilingStartedAt : 0,
|
|
199
|
+
hasProfile: !!lastProfile,
|
|
200
|
+
hasReport: !!lastReportHtml,
|
|
201
|
+
// false when the optional `cpupro` peer dep isn't installed — the UI
|
|
202
|
+
// uses this to warn up front that captures are download-only.
|
|
203
|
+
reportSupported: !!resolveCpuproBin(),
|
|
204
|
+
error: lastProfilingError
|
|
205
|
+
};
|
|
206
|
+
}),
|
|
207
|
+
"profiling-profile": (0, import_core.createEndpoint)(`${prefix}/profiling/profile.cpuprofile`, { method: "GET", use }, async () => {
|
|
208
|
+
const denied = profilingDenied();
|
|
209
|
+
if (denied) {
|
|
210
|
+
return denied;
|
|
211
|
+
}
|
|
212
|
+
if (!lastProfile) {
|
|
213
|
+
return new Response("No profile captured", { status: 404 });
|
|
214
|
+
}
|
|
215
|
+
const buf = Buffer.from(lastProfile, "utf8");
|
|
216
|
+
return new Response(new Uint8Array(buf), {
|
|
217
|
+
status: 200,
|
|
218
|
+
headers: {
|
|
219
|
+
"content-type": "application/json",
|
|
220
|
+
"content-length": String(buf.length),
|
|
221
|
+
"content-disposition": 'attachment; filename="profile.cpuprofile"',
|
|
222
|
+
"cache-control": "no-cache",
|
|
223
|
+
// serve-static.ts sets this for the same reason: better-call's node
|
|
224
|
+
// adapter doesn't call res.end() on a backpressured single-chunk
|
|
225
|
+
// body, so a keep-alive response is left unterminated and browsers
|
|
226
|
+
// spin. Closing the connection terminates it cleanly.
|
|
227
|
+
"connection": "close"
|
|
228
|
+
}
|
|
229
|
+
});
|
|
230
|
+
}),
|
|
231
|
+
"profiling-report": (0, import_core.createEndpoint)(`${prefix}/profiling/report.html`, { method: "GET", use }, async () => {
|
|
232
|
+
const denied = profilingDenied();
|
|
233
|
+
if (denied) {
|
|
234
|
+
return denied;
|
|
235
|
+
}
|
|
236
|
+
if (!lastReportHtml) {
|
|
237
|
+
return new Response("No report available", { status: 404 });
|
|
238
|
+
}
|
|
239
|
+
const buf = Buffer.from(lastReportHtml, "utf8");
|
|
240
|
+
return new Response(new Uint8Array(buf), {
|
|
241
|
+
status: 200,
|
|
242
|
+
headers: {
|
|
243
|
+
"content-type": "text/html; charset=utf-8",
|
|
244
|
+
"content-length": String(buf.length),
|
|
245
|
+
"cache-control": "no-cache",
|
|
246
|
+
// see profiling-profile above — `connection: close` so the browser
|
|
247
|
+
// doesn't spin on better-call's unterminated keep-alive response.
|
|
248
|
+
"connection": "close"
|
|
249
|
+
}
|
|
250
|
+
});
|
|
251
|
+
}),
|
|
252
|
+
"playground-index": (0, import_core.createEndpoint)(`${prefix}/`, { method: "GET", use }, async () => {
|
|
253
|
+
return (0, import_serve_static.serveStatic)(SPA_DIST, "");
|
|
254
|
+
}),
|
|
255
|
+
"playground-static": (0, import_core.createEndpoint)(`${prefix}/**:splat`, { method: "GET", use }, async (ctx) => {
|
|
256
|
+
return (0, import_serve_static.serveStatic)(SPA_DIST, ctx.params.splat);
|
|
257
|
+
})
|
|
258
|
+
};
|
|
259
|
+
const SPA_DIST_RESOLVED = import_path.default.resolve(SPA_DIST);
|
|
260
|
+
return (0, import_core.dualModeEndpoints)(endpoints, {
|
|
261
|
+
catchAllKey: "playground-static",
|
|
262
|
+
buildMiddleware: ({ fullHandler }) => {
|
|
263
|
+
const dispatch = (req, res, next) => {
|
|
264
|
+
const stripped = Object.create(req, {
|
|
265
|
+
baseUrl: { value: "", enumerable: true, configurable: true },
|
|
266
|
+
originalUrl: { value: req.url, enumerable: true, configurable: true }
|
|
267
|
+
});
|
|
268
|
+
fullHandler(stripped, res).catch(next);
|
|
83
269
|
};
|
|
84
|
-
|
|
270
|
+
return (req, res, next) => {
|
|
271
|
+
var _a2;
|
|
272
|
+
const url = ((_a2 = req.url) != null ? _a2 : "").split("?")[0];
|
|
273
|
+
const isProfiling = url.startsWith("/profiling");
|
|
274
|
+
if (req.method === "POST") {
|
|
275
|
+
return isProfiling ? dispatch(req, res, next) : next();
|
|
276
|
+
}
|
|
277
|
+
if (req.method !== "GET") {
|
|
278
|
+
return next();
|
|
279
|
+
}
|
|
280
|
+
if (url === "/" || url === "/rooms" || url === "/__apidocs" || isProfiling) {
|
|
281
|
+
return dispatch(req, res, next);
|
|
282
|
+
}
|
|
283
|
+
const rel = url.replace(/^\/+/, "");
|
|
284
|
+
if (!rel || rel.includes("..")) {
|
|
285
|
+
return next();
|
|
286
|
+
}
|
|
287
|
+
const filePath = import_path.default.resolve(SPA_DIST_RESOLVED, rel);
|
|
288
|
+
if (!filePath.startsWith(SPA_DIST_RESOLVED + import_path.default.sep)) {
|
|
289
|
+
return next();
|
|
290
|
+
}
|
|
291
|
+
import_promises.default.stat(filePath).then((stat) => {
|
|
292
|
+
if (stat.isFile()) {
|
|
293
|
+
dispatch(req, res, next);
|
|
294
|
+
} else {
|
|
295
|
+
next();
|
|
296
|
+
}
|
|
297
|
+
}).catch(() => next());
|
|
298
|
+
};
|
|
299
|
+
}
|
|
85
300
|
});
|
|
86
|
-
return router;
|
|
87
301
|
}
|
|
88
302
|
// Annotate the CommonJS export names for ESM import in node:
|
|
89
303
|
0 && (module.exports = {
|
package/build/index.cjs.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src-backend/index.ts"],
|
|
4
|
-
"sourcesContent": ["import path from 'path';\nimport express, { Router } from 'express';\nimport { auth, JWT } from '@colyseus/auth';\nimport { matchMaker, IRoomCache, __globalEndpoints } from '@colyseus/core';\nimport type { Endpoint } from \"@colyseus/better-call\";\nimport { applyMonkeyPatch } from './colyseus.ext.js';\n\nimport { fileURLToPath } from 'url'; // required for ESM build (see build.mjs)\n\nexport type AuthConfig = {\n oauth: string[],\n register: boolean,\n anonymous: boolean,\n};\n\nexport function playground(): Router {\n applyMonkeyPatch();\n\n const router = express.Router();\n\n // serve static frontend\n router.use(\"/\", express.static(path.resolve(__dirname, \"..\", \"build\")));\n\n // expose matchmaking stats\n router.get(\"/rooms\", async (req, res) => {\n const rooms = await matchMaker.driver.query({});\n\n const roomsByType: { [roomName: string]: number } = {};\n const roomsById: { [roomName: string]: IRoomCache } = {};\n\n rooms.forEach((room) => {\n if (!roomsByType[room.name]) { roomsByType[room.name] = 0; }\n roomsByType[room.name]++;\n roomsById[room.roomId] = room;\n });\n\n res.json({\n rooms: Object.keys(matchMaker.getAllHandlers()),\n\n roomsByType,\n roomsById,\n\n auth: {\n // list of OAuth providers\n oauth: Object.keys(auth.oauth.providers),\n register: typeof(auth.settings.onRegisterWithEmailAndPassword) === \"function\",\n anonymous: typeof(JWT.settings.secret) === \"string\",\n } as AuthConfig\n });\n });\n\n // serve API docs for playground\n // (workaround to use better-call route inside express.Router)\n router.get(\"/__apidocs\", async (_, res) => {\n /**\n * Optional: if zod is available, we can use toJSONSchema() for body and query types\n */\n let z: any = undefined;\n try { z = await import(\"zod\"); } catch (e: any) { /* zod not installed */ }\n\n res.json(Object.values(__globalEndpoints).map((endpoint: Endpoint) => {\n return {\n method: endpoint.options.method,\n path: endpoint.path,\n body: z && endpoint.options.body && z.toJSONSchema(endpoint.options.body),\n query: z && endpoint.options.query && z.toJSONSchema(endpoint.options.query),\n metadata: endpoint.options.metadata,\n description: endpoint.options.metadata?.openapi?.description,\n };\n }));\n });\n\n return router;\n}\n"],
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,kBAAiB;AACjB,
|
|
6
|
-
"names": ["
|
|
4
|
+
"sourcesContent": ["import fs from 'fs/promises';\nimport path from 'path';\nimport { fileURLToPath } from 'url';\nimport inspector from 'node:inspector/promises';\nimport { spawn } from 'node:child_process';\nimport os from 'node:os';\nimport { createRequire } from 'node:module';\nimport type { IncomingMessage, ServerResponse } from 'http';\nimport { createEndpoint, dualModeEndpoints, isDevMode, matchMaker, Server, type IRoomCache, type Endpoint } from '@colyseus/core';\nimport { auth, JWT } from '@colyseus/auth';\nimport { applyMonkeyPatch } from './colyseus.ext.js';\nimport { serveStatic } from './serve-static.js';\n\nexport type AuthConfig = {\n oauth: string[],\n register: boolean,\n anonymous: boolean,\n};\n\nexport interface PlaygroundOptions {\n /** Mount prefix used when spread into `createRouter`. Ignored in express-middleware mode (express strips its mount path). Defaults to `''`. */\n prefix?: string;\n /** Better-call middleware applied to every playground endpoint \u2014 use for auth gating. */\n use?: any[];\n}\n\nconst SPA_DIST = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..', 'build');\n\n// CPU profiling state \u2014 single process, single active session. The captured\n// `.cpuprofile` and the cpupro-generated standalone HTML report are kept in\n// memory (latest only); a process restart clears them, which is fine for a\n// dev tool. See the `/profiling/*` endpoints below.\nlet profilingSession: inspector.Session | null = null;\nlet profilingStartedAt = 0;\nlet lastProfile: string | null = null;\nlet lastReportHtml: string | null = null;\nlet lastProfilingError: string | null = null;\n\n// cpupro is an OPTIONAL peer dependency \u2014 it pulls in a native addon\n// (v8-profiler-next) we don't use, so it's opt-in. Resolve its CLI bin if\n// installed, else null. cpupro's `exports` map hides `bin/cpupro`, so resolve\n// the package dir via its (exported) package.json and join the bin path.\nfunction resolveCpuproBin(): string | null {\n try {\n const require = createRequire(import.meta.url);\n return path.join(path.dirname(require.resolve('cpupro/package.json')), 'bin', 'cpupro');\n } catch {\n return null;\n }\n}\n\n// Render an existing `.cpuprofile` (JSON string) into a standalone,\n// self-contained cpupro HTML report by shelling out to the cpupro CLI. The\n// CLI is the documented, format-stable path and is agnostic to our cjs/esm\n// dual build.\nasync function generateCpuproReport(profileJson: string): Promise<string> {\n const bin = resolveCpuproBin();\n if (!bin) {\n throw new Error(\"cpupro is not installed \u2014 run `npm install cpupro` to render reports in the playground. The .cpuprofile is still available to download.\");\n }\n const stamp = Date.now();\n const profilePath = path.join(os.tmpdir(), `colyseus-profile-${stamp}.cpuprofile`);\n const reportName = `colyseus-report-${stamp}.html`;\n const reportPath = path.join(os.tmpdir(), reportName);\n await fs.writeFile(profilePath, profileJson);\n try {\n await new Promise<void>((resolve, reject) => {\n const child = spawn(process.execPath, [bin, profilePath, '-n', '-o', os.tmpdir(), '-f', reportName], { stdio: 'ignore' });\n child.on('error', reject);\n child.on('exit', (code) => code === 0 ? resolve() : reject(new Error(`cpupro exited with code ${code}`)));\n });\n return patchCpuproReport(await fs.readFile(reportPath, 'utf8'));\n } finally {\n await fs.rm(profilePath, { force: true }).catch(() => {});\n await fs.rm(reportPath, { force: true }).catch(() => {});\n }\n}\n\n// cpupro@0.7.0 ships a `build/report.html` template configured to fetch its\n// data from a sibling `model.data` URL (`dataSource:\"url\"`), yet `report.js`\n// appends the actual profile inline as `discoveryLoader.push()` chunks \u2014 a\n// mechanism only wired up when `dataSource===\"push\"`. As shipped the file is\n// therefore not self-contained: it requests `model.data` (404s through our\n// SPA) and throws `discoveryLoader is not defined`. Flip the data source to\n// `push` so the embedded chunks are consumed and the report stands alone.\nfunction patchCpuproReport(html: string): string {\n return html.replace(/dataSource:\"url\",data:[A-Za-z_$][\\w$]*\\.model\\.data/, 'dataSource:\"push\",data:1');\n}\n\nexport function playground(opts: PlaygroundOptions = {}) {\n applyMonkeyPatch();\n\n const prefix = opts.prefix ?? '';\n const use = opts.use ?? [];\n\n // Same opt-in rule as `playground-apidocs`: profiling adds runtime overhead\n // and leaks internal stack frames, so refuse outside devMode unless an\n // explicit `use:` auth guard is configured. 404 hides the route's existence.\n const profilingDenied = () =>\n (!isDevMode && use.length === 0) ? new Response('Not found', { status: 404 }) : null;\n\n const endpoints: Record<string, Endpoint> = {\n 'playground-rooms': createEndpoint(`${prefix}/rooms`, { method: 'GET', use }, async () => {\n const rooms = await matchMaker.driver.query({});\n const roomsByType: Record<string, number> = {};\n const roomsById: Record<string, IRoomCache> = {};\n rooms.forEach((room) => {\n roomsByType[room.name] = (roomsByType[room.name] ?? 0) + 1;\n roomsById[room.roomId] = room;\n });\n return {\n rooms: Object.keys(matchMaker.getAllHandlers()),\n roomsByType,\n roomsById,\n auth: {\n oauth: Object.keys(auth.oauth.providers),\n register: typeof auth.settings.onRegisterWithEmailAndPassword === 'function',\n anonymous: typeof JWT.settings.secret === 'string',\n } as AuthConfig,\n };\n }),\n\n 'playground-apidocs': createEndpoint(`${prefix}/__apidocs`, { method: 'GET', use }, async () => {\n // Dumps every route + Zod schema, so an unguarded public mount leaks\n // the whole API surface. Refuse only the accidental case: not devMode\n // AND no `use:` guard. A guard is the opt-in for prod use. 404 hides\n // the route's existence.\n if (!isDevMode && use.length === 0) {\n return new Response('Not found', { status: 404 });\n }\n\n let z: any;\n try { z = await import('zod'); } catch { /* zod is an optional peer */ }\n const routerEndpoints: Record<string, any> = (Server.current?.router as any)?.endpoints ?? {};\n return Object.values(routerEndpoints).map((endpoint: any) => ({\n method: endpoint.options.method,\n path: endpoint.path,\n body: z && endpoint.options.body && z.toJSONSchema(endpoint.options.body),\n query: z && endpoint.options.query && z.toJSONSchema(endpoint.options.query),\n metadata: endpoint.options.metadata,\n description: endpoint.options.metadata?.openapi?.description,\n }));\n }),\n\n 'profiling-start': createEndpoint(`${prefix}/profiling/start`, { method: 'POST', use }, async (ctx) => {\n const denied = profilingDenied(); if (denied) { return denied; }\n if (profilingSession) {\n return { status: 'running', startedAt: profilingStartedAt, error: 'already running' };\n }\n const interval = Number((ctx.query as any)?.interval) || 100;\n const session = new inspector.Session();\n session.connect();\n await session.post('Profiler.enable');\n await session.post('Profiler.setSamplingInterval', { interval });\n await session.post('Profiler.start');\n profilingSession = session;\n profilingStartedAt = Date.now();\n lastProfile = null;\n lastReportHtml = null;\n lastProfilingError = null;\n return { status: 'started', startedAt: profilingStartedAt, interval };\n }),\n\n 'profiling-stop': createEndpoint(`${prefix}/profiling/stop`, { method: 'POST', use }, async () => {\n const denied = profilingDenied(); if (denied) { return denied; }\n if (!profilingSession) {\n return { status: 'idle', error: 'not running' };\n }\n const session = profilingSession;\n profilingSession = null;\n const durationMs = Date.now() - profilingStartedAt;\n const { profile } = await session.post('Profiler.stop');\n session.disconnect();\n lastProfile = JSON.stringify(profile);\n lastReportHtml = null;\n lastProfilingError = null;\n try {\n lastReportHtml = await generateCpuproReport(lastProfile);\n } catch (e: any) {\n lastProfilingError = e?.message ?? String(e);\n }\n return {\n status: 'stopped',\n durationMs,\n profileBytes: lastProfile.length,\n reportReady: !!lastReportHtml,\n error: lastProfilingError,\n };\n }),\n\n 'profiling-status': createEndpoint(`${prefix}/profiling/status`, { method: 'GET', use }, async () => {\n const denied = profilingDenied(); if (denied) { return denied; }\n return {\n running: !!profilingSession,\n startedAt: profilingSession ? profilingStartedAt : 0,\n hasProfile: !!lastProfile,\n hasReport: !!lastReportHtml,\n // false when the optional `cpupro` peer dep isn't installed \u2014 the UI\n // uses this to warn up front that captures are download-only.\n reportSupported: !!resolveCpuproBin(),\n error: lastProfilingError,\n };\n }),\n\n 'profiling-profile': createEndpoint(`${prefix}/profiling/profile.cpuprofile`, { method: 'GET', use }, async () => {\n const denied = profilingDenied(); if (denied) { return denied; }\n if (!lastProfile) { return new Response('No profile captured', { status: 404 }); }\n const buf = Buffer.from(lastProfile, 'utf8');\n return new Response(new Uint8Array(buf) as any, {\n status: 200,\n headers: {\n 'content-type': 'application/json',\n 'content-length': String(buf.length),\n 'content-disposition': 'attachment; filename=\"profile.cpuprofile\"',\n 'cache-control': 'no-cache',\n // serve-static.ts sets this for the same reason: better-call's node\n // adapter doesn't call res.end() on a backpressured single-chunk\n // body, so a keep-alive response is left unterminated and browsers\n // spin. Closing the connection terminates it cleanly.\n 'connection': 'close',\n },\n });\n }),\n\n 'profiling-report': createEndpoint(`${prefix}/profiling/report.html`, { method: 'GET', use }, async () => {\n const denied = profilingDenied(); if (denied) { return denied; }\n if (!lastReportHtml) { return new Response('No report available', { status: 404 }); }\n const buf = Buffer.from(lastReportHtml, 'utf8');\n return new Response(new Uint8Array(buf) as any, {\n status: 200,\n headers: {\n 'content-type': 'text/html; charset=utf-8',\n 'content-length': String(buf.length),\n 'cache-control': 'no-cache',\n // see profiling-profile above \u2014 `connection: close` so the browser\n // doesn't spin on better-call's unterminated keep-alive response.\n 'connection': 'close',\n },\n });\n }),\n\n 'playground-index': createEndpoint(`${prefix}/`, { method: 'GET', use }, async () => {\n return serveStatic(SPA_DIST, '');\n }),\n\n 'playground-static': createEndpoint(`${prefix}/**:splat`, { method: 'GET', use }, async (ctx) => {\n return serveStatic(SPA_DIST, (ctx.params as any).splat);\n }),\n };\n\n const SPA_DIST_RESOLVED = path.resolve(SPA_DIST);\n\n return dualModeEndpoints(endpoints, {\n catchAllKey: 'playground-static',\n buildMiddleware: ({ fullHandler }) => {\n // Strip express's `baseUrl` so the inner router sees the request\n // relative to its mount point \u2014 playground's endpoint paths assume\n // a `''` prefix, so a sub-mount like `app.use(\"/foo\", playground())`\n // needs the leading `/foo` stripped before dispatch.\n const dispatch = (req: IncomingMessage, res: ServerResponse, next: (e?: any) => void) => {\n const stripped = Object.create(req, {\n baseUrl: { value: '', enumerable: true, configurable: true },\n originalUrl: { value: req.url, enumerable: true, configurable: true },\n });\n fullHandler(stripped as any, res as any).catch(next);\n };\n\n return (req, res, next) => {\n const url = (req.url ?? '').split('?')[0]!;\n const isProfiling = url.startsWith('/profiling');\n\n // Profiling start/stop are POSTs; everything else here is GET-only.\n if (req.method === 'POST') {\n return isProfiling ? dispatch(req, res, next) : next();\n }\n if (req.method !== 'GET') { return next(); }\n\n if (url === '/' || url === '/rooms' || url === '/__apidocs' || isProfiling) {\n return dispatch(req, res, next);\n }\n\n // Asset request \u2014 only delegate if the file actually exists on\n // disk. Avoids the catch-all's SPA fallback (which would serve\n // index.html for unknown paths, masking sibling express routes).\n const rel = url.replace(/^\\/+/, '');\n if (!rel || rel.includes('..')) { return next(); }\n const filePath = path.resolve(SPA_DIST_RESOLVED, rel);\n if (!filePath.startsWith(SPA_DIST_RESOLVED + path.sep)) { return next(); }\n\n fs.stat(filePath).then((stat) => {\n if (stat.isFile()) {\n dispatch(req, res, next);\n } else {\n next();\n }\n }).catch(() => next());\n };\n },\n });\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["import_promises", "path", "require", "os", "fs", "_a", "_b", "inspector"]
|
|
7
7
|
}
|
package/build/index.d.ts
CHANGED
|
@@ -1,7 +1,13 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { type Endpoint } from '@colyseus/core';
|
|
2
2
|
export type AuthConfig = {
|
|
3
3
|
oauth: string[];
|
|
4
4
|
register: boolean;
|
|
5
5
|
anonymous: boolean;
|
|
6
6
|
};
|
|
7
|
-
export
|
|
7
|
+
export interface PlaygroundOptions {
|
|
8
|
+
/** Mount prefix used when spread into `createRouter`. Ignored in express-middleware mode (express strips its mount path). Defaults to `''`. */
|
|
9
|
+
prefix?: string;
|
|
10
|
+
/** Better-call middleware applied to every playground endpoint — use for auth gating. */
|
|
11
|
+
use?: any[];
|
|
12
|
+
}
|
|
13
|
+
export declare function playground(opts?: PlaygroundOptions): import("@colyseus/core").ExpressMiddleware & Record<string, Endpoint>;
|
package/build/index.html
CHANGED
|
@@ -12,8 +12,8 @@
|
|
|
12
12
|
<link rel="apple-touch-icon" href="./logo192.png" />
|
|
13
13
|
<link rel="manifest" href="./manifest.json" crossorigin="use-credentials" />
|
|
14
14
|
<title>[Colyseus Playground]</title>
|
|
15
|
-
<script type="module" crossorigin src="./assets/index-
|
|
16
|
-
<link rel="stylesheet" crossorigin href="./assets/index-
|
|
15
|
+
<script type="module" crossorigin src="./assets/index-hvVeOuTE.js"></script>
|
|
16
|
+
<link rel="stylesheet" crossorigin href="./assets/index-CWU1hZTF.css">
|
|
17
17
|
</head>
|
|
18
18
|
<body>
|
|
19
19
|
<noscript>You need to enable JavaScript to run this app.</noscript>
|