openvibers/openvibe.games Commits
Publish Games' New worlds card at /.well-known/openvibe-menu.json (#303)
Changes
@@@ -98,6 +98,7 @@ import { CASUAL_GAMES, validatePack } from '@openvibe/casual'import { CreatorWorldHost } from './worlds/worldHost.js'import { createWorldHubStarter, worldScriptsFactory } from './worlds/startWorldHub.js'import { createWorldRoutes } from './worlds/worldRoutes.js'++import { createMenuCardHandler } from './net/menuCard.js'import { createAssetRoutes } from './worlds/assetRoutes.js'import { createWorldPage } from './worlds/worldPage.js'import { createWorldSharing } from './worlds/sharing.js'@@@ -1063,6 +1064,8 @@ async function main(): Promise<void> {...(worldSearch ? { search: worldSearch } : {}),...(worldSharing ? { sharing: worldSharing } : {}),})++ // The menu's network card (frame.menu-card@1): /.well-known/openvibe-menu.json, the newest published worlds.++ const serveMenuCard = createMenuCardHandler({ store: creatorWorlds })// The uniform share API for worlds: /api/v1/world/<id>/share and the shared-with-me listing.const serveWorldShare = worldSharing? createWorldShareRoutes({@@@ -1268,6 +1271,7 @@ async function main(): Promise<void> {)return true}++ if (serveMenuCard(req, res)) return trueif (serveCasual(req, res)) return trueif (serveAiMatches(req, res)) return trueif (serveWorldShare?.(req, res)) return truennew file mode 100644@@@ -0,0 +1,157 @@++import type { IncomingMessage, ServerResponse } from 'node:http'++import { describe, expect, it } from 'vitest'++import type { CreatorWorld } from '@openvibe/persistence'++import { CARD_TTL_S, cardFrom, createMenuCardHandler, plain } from './menuCard.js'++++const NOW = Date.parse('2026-11-07T08:00:00Z')++++const world = (id: string, over: Partial<CreatorWorld> = {}): CreatorWorld => ({++ id,++ ownerSubject: `usr_${id}`,++ ownerName: 'Builder',++ title: `World ${id}`,++ summary: 'A floating island',++ status: 'published',++ revision: 'r1',++ plays: 3,++ createdAt: NOW,++ updatedAt: NOW,++ publishedAt: NOW,++ remixedFrom: null,++ remixes: 0,++ view: '3d',++ ...over,++})++++/** A ServerResponse that records the head and body and resolves when the handler ends it. */++function fakeRes() {++ const headers: Record<string, string | number | string[] | undefined> = {}++ let status = 0++ let body = ''++ let done!: () => void++ const ended = new Promise<void>((resolve) => {++ done = resolve++ })++ const res = {++ writeHead(code: number, h: Record<string, string | number | string[]> = {}) {++ status = code++ Object.assign(headers, h)++ return this++ },++ end(chunk?: string) {++ body = chunk ?? ''++ done()++ return this++ },++ } as unknown as ServerResponse++ return { res, ended, headers, status: () => status, body: () => body }++}++++const req = (url: string, method = 'GET') => ({ url, method }) as IncomingMessage++++const storeReturning = (rows: CreatorWorld[]) => {++ let calls = 0++ return {++ calls: () => calls,++ listPublished: async (limit: number, offset: number) => {++ calls++++ expect(limit).toBe(6)++ expect(offset).toBe(0)++ return rows++ },++ }++}++++describe('the menu network card (frame.menu-card@1)', () => {++ it('is the newest published worlds, newest first, linking each to its page', () => {++ const card = cardFrom([world('a'), world('b', { title: 'Moon <b>base</b>' })], NOW)++ expect(card).toMatchObject({++ id: 'new-worlds',++ site: 'games',++ title: 'New worlds',++ kind: 'rows',++ updated_at: '2026-11-07T08:00:00.000Z',++ ttl_s: CARD_TTL_S,++ })++ expect(card.more).toEqual({ label: 'All worlds', url: 'https://openvibe.games/worlds' })++ expect(card.items).toEqual([++ { title: 'World a', meta: 'by Builder', url: 'https://openvibe.games/worlds/a' },++ { title: 'Moon base', meta: 'by Builder', url: 'https://openvibe.games/worlds/b' },++ ])++ expect(card.title.length).toBeLessThanOrEqual(60)++ for (const item of card.items) {++ expect(item.title.length).toBeLessThanOrEqual(80)++ expect(item.meta.length).toBeLessThanOrEqual(120)++ expect(item.url.startsWith('https://openvibe.games/')).toBe(true)++ }++ })++++ it('sends at most six, and never a draft or a hidden world', () => {++ const many = Array.from({ length: 8 }, (_, i) => world(`w${i}`))++ expect(cardFrom(many, NOW).items).toHaveLength(6)++ expect(cardFrom([world('draft', { status: 'draft' })], NOW).items).toEqual([])++ expect(cardFrom([world('hidden', { status: 'hidden' })], NOW).items).toEqual([])++ expect(cardFrom([], NOW).items).toEqual([])++ })++++ it('strips markup and control characters from the words', () => {++ expect(plain('<i>Moon</i>\n\t base ', 80)).toBe('Moon base')++ expect(plain('x'.repeat(200), 80)).toHaveLength(80)++ expect(++ cardFrom([world('a', { title: '<script>alert(1)</script>Moon' })], NOW).items[0]!.title,++ ).toBe('alert(1) Moon')++ })++++ it('answers GET /.well-known/openvibe-menu.json with CORS * and a cache, and nothing else', async () => {++ const store = storeReturning([world('a')])++ const handler = createMenuCardHandler({ store, now: () => NOW })++ expect(handler(req('/other'), fakeRes().res)).toBe(false)++++ const first = fakeRes()++ expect(handler(req('/.well-known/openvibe-menu.json'), first.res)).toBe(true)++ await first.ended++ expect(first.status()).toBe(200)++ expect(first.headers['access-control-allow-origin']).toBe('*')++ expect(first.headers['content-type']).toContain('application/json')++ expect(first.headers['cache-control']).toBe('public, max-age=60')++ const parsed = JSON.parse(first.body())++ expect(Array.isArray(parsed) && parsed.length).toBe(1)++ expect(parsed[0].site).toBe('games')++++ const second = fakeRes()++ expect(handler(req('/.well-known/openvibe-menu.json'), second.res)).toBe(true)++ await second.ended++ expect(store.calls(), 'the second request is served from the cache').toBe(1)++ })++++ it('answers 503 when the store fails and no good card is cached, and keeps the last good one after', async () => {++ let fail = false++ let calls = 0++ const store = {++ listPublished: async () => {++ calls++++ if (fail) throw new Error('db down')++ return [world('a')]++ },++ }++ const handler = createMenuCardHandler({ store, now: () => NOW })++ const bad = fakeRes()++ fail = true++ handler(req('/.well-known/openvibe-menu.json'), bad.res)++ await bad.ended++ expect(bad.status()).toBe(503)++++ fail = false++ const good = fakeRes()++ handler(req('/.well-known/openvibe-menu.json'), good.res)++ await good.ended++ expect(good.status()).toBe(200)++ fail = true++ const kept = fakeRes()++ handler(req('/.well-known/openvibe-menu.json'), kept.res)++ await kept.ended++ expect(kept.status()).toBe(200)++ expect(JSON.parse(kept.body())[0].items[0].title).toBe('World a')++ expect(calls).toBe(2)++ })++})nnew file mode 100644@@@ -0,0 +1,113 @@++import type { IncomingMessage, ServerResponse } from 'node:http'++import type { CreatorWorld, CreatorWorldStore } from '@openvibe/persistence'++++/**++ * The menu's network card for OpenVibe.Games (frame.menu-card@1): GET /.well-known/openvibe-menu.json.++ *++ * Games publishes "New worlds": the newest published creator worlds, each linking to its own page. The file is++ * public and CORS *, cached for a minute (Network refetches every five minutes). Only fields a published world++ * already shows on /worlds are copied — never the owner's subject, a draft, a hidden world or a map.++ */++export const SITE = 'games'++export const CARD_ID = 'new-worlds'++export const CARD_TTL_S = 300++const CACHE_MS = 60_000++const BASE = 'https://openvibe.games'++++/** Plain words for a card: markup and control characters out, one line, within the schema's limit. */++export function plain(value: unknown, max: number): string {++ const visible = Array.from(String(value ?? ''), (ch) => {++ const code = ch.charCodeAt(0)++ return code < 32 || code === 127 ? ' ' : ch++ }).join('')++ return visible++ .replace(/<[^>]*>/g, ' ')++ .replace(/\s+/g, ' ')++ .trim()++ .slice(0, max)++}++++/** The card itself, newest published world first (the store's order). */++export function cardFrom(worlds: CreatorWorld[], at = Date.now()) {++ const items = (Array.isArray(worlds) ? worlds : [])++ .filter((w) => w && w.id && w.status === 'published')++ .slice(0, 6)++ .map((w) => ({++ title: plain(w.title, 80),++ meta: `by ${plain(w.ownerName, 110)}`,++ url: `${BASE}/worlds/${encodeURIComponent(w.id)}`,++ }))++ return {++ id: CARD_ID,++ site: SITE,++ title: 'New worlds',++ kind: 'rows',++ items,++ more: { label: 'All worlds', url: `${BASE}/worlds` },++ updated_at: new Date(at).toISOString(),++ ttl_s: CARD_TTL_S,++ }++}++++export interface MenuCardOptions {++ store: Pick<CreatorWorldStore, 'listPublished'>++ now?: () => number++}++++/**++ * The route. Returns true when it answered the request (the platform handle stops there), false for any other++ * path. A database failure keeps the last good card; before one exists it answers 503 and Network keeps the++ * site's previous card for its 30-minute window.++ */++export function createMenuCardHandler({ store, now = Date.now }: MenuCardOptions) {++ let cached: ReturnType<typeof cardFrom> | null = null++ let cachedAt = 0++ let pending: Promise<ReturnType<typeof cardFrom>> | null = null++++ async function card(): Promise<ReturnType<typeof cardFrom>> {++ const at = now()++ if (cached && at - cachedAt < CACHE_MS) return cached++ if (pending) return pending++ pending = (async () => {++ try {++ cached = cardFrom(await store.listPublished(6, 0), at)++ cachedAt = at++ } catch (err) {++ if (!cached) throw err++ }++ return cached as ReturnType<typeof cardFrom>++ })().finally(() => {++ pending = null++ })++ return pending++ }++++ return (req: IncomingMessage, res: ServerResponse): boolean => {++ const path = (req.url ?? '/').split('?')[0] ?? '/'++ if (path !== '/.well-known/openvibe-menu.json') return false++ if (req.method !== 'GET' && req.method !== 'HEAD') {++ res.writeHead(405, { 'content-type': 'application/json', allow: 'GET, HEAD' })++ res.end('{"error":"method_not_allowed"}')++ return true++ }++ void card()++ .then((body) => {++ res.writeHead(200, {++ 'content-type': 'application/json; charset=utf-8',++ 'cache-control': 'public, max-age=60',++ 'access-control-allow-origin': '*',++ 'cross-origin-resource-policy': 'cross-origin',++ })++ res.end(req.method === 'HEAD' ? undefined : JSON.stringify([body]))++ })++ .catch(() => {++ res.writeHead(503, {++ 'content-type': 'application/json',++ 'cache-control': 'no-store',++ 'access-control-allow-origin': '*',++ })++ res.end('{"error":"menu_unavailable"}')++ })++ return true++ }++}nnew file mode 100644@@@ -0,0 +1,3 @@++// file: 'apps/server/src/net/menuCard.test.ts'++// covers: 'apps/server/src/net'++// Generated by node test/run.js --index; do not edit.
@@ -98,6 +98,7 @@ import { CASUAL_GAMES, validatePack } from '@openvibe/casual'
@@ -98,6 +98,7 @@ import { CASUAL_GAMES, validatePack } from '@openvibe/casual'
import { CreatorWorldHost } from './worlds/worldHost.js'
import { CreatorWorldHost } from './worlds/worldHost.js'
import { createWorldHubStarter, worldScriptsFactory } from './worlds/startWorldHub.js'
import { createWorldHubStarter, worldScriptsFactory } from './worlds/startWorldHub.js'
import { createWorldRoutes } from './worlds/worldRoutes.js'
import { createWorldRoutes } from './worlds/worldRoutes.js'
+import { createMenuCardHandler } from './net/menuCard.js'
import { createAssetRoutes } from './worlds/assetRoutes.js'
import { createAssetRoutes } from './worlds/assetRoutes.js'
import { createWorldPage } from './worlds/worldPage.js'
import { createWorldPage } from './worlds/worldPage.js'
import { createWorldSharing } from './worlds/sharing.js'
import { createWorldSharing } from './worlds/sharing.js'
@@ -1063,6 +1064,8 @@ async function main(): Promise<void> {
@@ -1063,6 +1064,8 @@ async function main(): Promise<void> {
...(worldSearch ? { search: worldSearch } : {}),
...(worldSearch ? { search: worldSearch } : {}),
...(worldSharing ? { sharing: worldSharing } : {}),
...(worldSharing ? { sharing: worldSharing } : {}),
})
})
+ // The menu's network card (frame.menu-card@1): /.well-known/openvibe-menu.json, the newest published worlds.
+ const serveMenuCard = createMenuCardHandler({ store: creatorWorlds })
// The uniform share API for worlds: /api/v1/world/<id>/share and the shared-with-me listing.
// The uniform share API for worlds: /api/v1/world/<id>/share and the shared-with-me listing.
const serveWorldShare = worldSharing
const serveWorldShare = worldSharing
? createWorldShareRoutes({
? createWorldShareRoutes({
@@ -1268,6 +1271,7 @@ async function main(): Promise<void> {
@@ -1268,6 +1271,7 @@ async function main(): Promise<void> {
)
)
return true
return true
}
}
+ if (serveMenuCard(req, res)) return true
if (serveCasual(req, res)) return true
if (serveCasual(req, res)) return true
if (serveAiMatches(req, res)) return true
if (serveAiMatches(req, res)) return true
if (serveWorldShare?.(req, res)) return true
if (serveWorldShare?.(req, res)) return true
new file mode 100644
new file mode 100644
@@ -0,0 +1,157 @@
@@ -0,0 +1,157 @@
+import type { IncomingMessage, ServerResponse } from 'node:http'
+import { describe, expect, it } from 'vitest'
+import type { CreatorWorld } from '@openvibe/persistence'
+import { CARD_TTL_S, cardFrom, createMenuCardHandler, plain } from './menuCard.js'
+
+const NOW = Date.parse('2026-11-07T08:00:00Z')
+
+const world = (id: string, over: Partial<CreatorWorld> = {}): CreatorWorld => ({
+ id,
+ ownerSubject: `usr_${id}`,
+ ownerName: 'Builder',
+ title: `World ${id}`,
+ summary: 'A floating island',
+ status: 'published',
+ revision: 'r1',
+ plays: 3,
+ createdAt: NOW,
+ updatedAt: NOW,
+ publishedAt: NOW,
+ remixedFrom: null,
+ remixes: 0,
+ view: '3d',
+ ...over,
+})
+
+/** A ServerResponse that records the head and body and resolves when the handler ends it. */
+function fakeRes() {
+ const headers: Record<string, string | number | string[] | undefined> = {}
+ let status = 0
+ let body = ''
+ let done!: () => void
+ const ended = new Promise<void>((resolve) => {
+ done = resolve
+ })
+ const res = {
+ writeHead(code: number, h: Record<string, string | number | string[]> = {}) {
+ status = code
+ Object.assign(headers, h)
+ return this
+ },
+ end(chunk?: string) {
+ body = chunk ?? ''
+ done()
+ return this
+ },
+ } as unknown as ServerResponse
+ return { res, ended, headers, status: () => status, body: () => body }
+}
+
+const req = (url: string, method = 'GET') => ({ url, method }) as IncomingMessage
+
+const storeReturning = (rows: CreatorWorld[]) => {
+ let calls = 0
+ return {
+ calls: () => calls,
+ listPublished: async (limit: number, offset: number) => {
+ calls++
+ expect(limit).toBe(6)
+ expect(offset).toBe(0)
+ return rows
+ },
+ }
+}
+
+describe('the menu network card (frame.menu-card@1)', () => {
+ it('is the newest published worlds, newest first, linking each to its page', () => {
+ const card = cardFrom([world('a'), world('b', { title: 'Moon <b>base</b>' })], NOW)
+ expect(card).toMatchObject({
+ id: 'new-worlds',
+ site: 'games',
+ title: 'New worlds',
+ kind: 'rows',
+ updated_at: '2026-11-07T08:00:00.000Z',
+ ttl_s: CARD_TTL_S,
+ })
+ expect(card.more).toEqual({ label: 'All worlds', url: 'https://openvibe.games/worlds' })
+ expect(card.items).toEqual([
+ { title: 'World a', meta: 'by Builder', url: 'https://openvibe.games/worlds/a' },
+ { title: 'Moon base', meta: 'by Builder', url: 'https://openvibe.games/worlds/b' },
+ ])
+ expect(card.title.length).toBeLessThanOrEqual(60)
+ for (const item of card.items) {
+ expect(item.title.length).toBeLessThanOrEqual(80)
+ expect(item.meta.length).toBeLessThanOrEqual(120)
+ expect(item.url.startsWith('https://openvibe.games/')).toBe(true)
+ }
+ })
+
+ it('sends at most six, and never a draft or a hidden world', () => {
+ const many = Array.from({ length: 8 }, (_, i) => world(`w${i}`))
+ expect(cardFrom(many, NOW).items).toHaveLength(6)
+ expect(cardFrom([world('draft', { status: 'draft' })], NOW).items).toEqual([])
+ expect(cardFrom([world('hidden', { status: 'hidden' })], NOW).items).toEqual([])
+ expect(cardFrom([], NOW).items).toEqual([])
+ })
+
+ it('strips markup and control characters from the words', () => {
+ expect(plain('<i>Moon</i>\n\t base ', 80)).toBe('Moon base')
+ expect(plain('x'.repeat(200), 80)).toHaveLength(80)
+ expect(
+ cardFrom([world('a', { title: '<script>alert(1)</script>Moon' })], NOW).items[0]!.title,
+ ).toBe('alert(1) Moon')
+ })
+
+ it('answers GET /.well-known/openvibe-menu.json with CORS * and a cache, and nothing else', async () => {
+ const store = storeReturning([world('a')])
+ const handler = createMenuCardHandler({ store, now: () => NOW })
+ expect(handler(req('/other'), fakeRes().res)).toBe(false)
+
+ const first = fakeRes()
+ expect(handler(req('/.well-known/openvibe-menu.json'), first.res)).toBe(true)
+ await first.ended
+ expect(first.status()).toBe(200)
+ expect(first.headers['access-control-allow-origin']).toBe('*')
+ expect(first.headers['content-type']).toContain('application/json')
+ expect(first.headers['cache-control']).toBe('public, max-age=60')
+ const parsed = JSON.parse(first.body())
+ expect(Array.isArray(parsed) && parsed.length).toBe(1)
+ expect(parsed[0].site).toBe('games')
+
+ const second = fakeRes()
+ expect(handler(req('/.well-known/openvibe-menu.json'), second.res)).toBe(true)
+ await second.ended
+ expect(store.calls(), 'the second request is served from the cache').toBe(1)
+ })
+
+ it('answers 503 when the store fails and no good card is cached, and keeps the last good one after', async () => {
+ let fail = false
+ let calls = 0
+ const store = {
+ listPublished: async () => {
+ calls++
+ if (fail) throw new Error('db down')
+ return [world('a')]
+ },
+ }
+ const handler = createMenuCardHandler({ store, now: () => NOW })
+ const bad = fakeRes()
+ fail = true
+ handler(req('/.well-known/openvibe-menu.json'), bad.res)
+ await bad.ended
+ expect(bad.status()).toBe(503)
+
+ fail = false
+ const good = fakeRes()
+ handler(req('/.well-known/openvibe-menu.json'), good.res)
+ await good.ended
+ expect(good.status()).toBe(200)
+ fail = true
+ const kept = fakeRes()
+ handler(req('/.well-known/openvibe-menu.json'), kept.res)
+ await kept.ended
+ expect(kept.status()).toBe(200)
+ expect(JSON.parse(kept.body())[0].items[0].title).toBe('World a')
+ expect(calls).toBe(2)
+ })
+})
new file mode 100644
new file mode 100644
@@ -0,0 +1,113 @@
@@ -0,0 +1,113 @@
+import type { IncomingMessage, ServerResponse } from 'node:http'
+import type { CreatorWorld, CreatorWorldStore } from '@openvibe/persistence'
+
+/**
+ * The menu's network card for OpenVibe.Games (frame.menu-card@1): GET /.well-known/openvibe-menu.json.
+ *
+ * Games publishes "New worlds": the newest published creator worlds, each linking to its own page. The file is
+ * public and CORS *, cached for a minute (Network refetches every five minutes). Only fields a published world
+ * already shows on /worlds are copied — never the owner's subject, a draft, a hidden world or a map.
+ */
+export const SITE = 'games'
+export const CARD_ID = 'new-worlds'
+export const CARD_TTL_S = 300
+const CACHE_MS = 60_000
+const BASE = 'https://openvibe.games'
+
+/** Plain words for a card: markup and control characters out, one line, within the schema's limit. */
+export function plain(value: unknown, max: number): string {
+ const visible = Array.from(String(value ?? ''), (ch) => {
+ const code = ch.charCodeAt(0)
+ return code < 32 || code === 127 ? ' ' : ch
+ }).join('')
+ return visible
+ .replace(/<[^>]*>/g, ' ')
+ .replace(/\s+/g, ' ')
+ .trim()
+ .slice(0, max)
+}
+
+/** The card itself, newest published world first (the store's order). */
+export function cardFrom(worlds: CreatorWorld[], at = Date.now()) {
+ const items = (Array.isArray(worlds) ? worlds : [])
+ .filter((w) => w && w.id && w.status === 'published')
+ .slice(0, 6)
+ .map((w) => ({
+ title: plain(w.title, 80),
+ meta: `by ${plain(w.ownerName, 110)}`,
+ url: `${BASE}/worlds/${encodeURIComponent(w.id)}`,
+ }))
+ return {
+ id: CARD_ID,
+ site: SITE,
+ title: 'New worlds',
+ kind: 'rows',
+ items,
+ more: { label: 'All worlds', url: `${BASE}/worlds` },
+ updated_at: new Date(at).toISOString(),
+ ttl_s: CARD_TTL_S,
+ }
+}
+
+export interface MenuCardOptions {
+ store: Pick<CreatorWorldStore, 'listPublished'>
+ now?: () => number
+}
+
+/**
+ * The route. Returns true when it answered the request (the platform handle stops there), false for any other
+ * path. A database failure keeps the last good card; before one exists it answers 503 and Network keeps the
+ * site's previous card for its 30-minute window.
+ */
+export function createMenuCardHandler({ store, now = Date.now }: MenuCardOptions) {
+ let cached: ReturnType<typeof cardFrom> | null = null
+ let cachedAt = 0
+ let pending: Promise<ReturnType<typeof cardFrom>> | null = null
+
+ async function card(): Promise<ReturnType<typeof cardFrom>> {
+ const at = now()
+ if (cached && at - cachedAt < CACHE_MS) return cached
+ if (pending) return pending
+ pending = (async () => {
+ try {
+ cached = cardFrom(await store.listPublished(6, 0), at)
+ cachedAt = at
+ } catch (err) {
+ if (!cached) throw err
+ }
+ return cached as ReturnType<typeof cardFrom>
+ })().finally(() => {
+ pending = null
+ })
+ return pending
+ }
+
+ return (req: IncomingMessage, res: ServerResponse): boolean => {
+ const path = (req.url ?? '/').split('?')[0] ?? '/'
+ if (path !== '/.well-known/openvibe-menu.json') return false
+ if (req.method !== 'GET' && req.method !== 'HEAD') {
+ res.writeHead(405, { 'content-type': 'application/json', allow: 'GET, HEAD' })
+ res.end('{"error":"method_not_allowed"}')
+ return true
+ }
+ void card()
+ .then((body) => {
+ res.writeHead(200, {
+ 'content-type': 'application/json; charset=utf-8',
+ 'cache-control': 'public, max-age=60',
+ 'access-control-allow-origin': '*',
+ 'cross-origin-resource-policy': 'cross-origin',
+ })
+ res.end(req.method === 'HEAD' ? undefined : JSON.stringify([body]))
+ })
+ .catch(() => {
+ res.writeHead(503, {
+ 'content-type': 'application/json',
+ 'cache-control': 'no-store',
+ 'access-control-allow-origin': '*',
+ })
+ res.end('{"error":"menu_unavailable"}')
+ })
+ return true
+ }
+}
new file mode 100644
new file mode 100644
@@ -0,0 +1,3 @@
@@ -0,0 +1,3 @@
+// file: 'apps/server/src/net/menuCard.test.ts'
+// covers: 'apps/server/src/net'
+// Generated by node test/run.js --index; do not edit.