@epic-web/workshop-presence 5.7.1 → 5.8.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.
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"presence.server.d.ts","sourceRoot":"","sources":["../../src/presence.server.ts"],"names":[],"mappings":"AAUA,OAAO,EAAE,KAAK,OAAO,EAAE,MAAM,wCAAwC,CAAA;AAErE,OAAO,EAAmC,KAAK,IAAI,EAAE,MAAM,eAAe,CAAA;AAE1E,eAAO,MAAM,aAAa;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAAmD,CAAA;AAE7E,wBAAsB,eAAe,CAAC,EACrC,OAAO,EACP,OAAO,GACP,GAAE;IAAE,OAAO,CAAC,EAAE,OAAO,CAAC;IAAC,OAAO,CAAC,EAAE,OAAO,CAAA;CAAO,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,
|
|
1
|
+
{"version":3,"file":"presence.server.d.ts","sourceRoot":"","sources":["../../src/presence.server.ts"],"names":[],"mappings":"AAUA,OAAO,EAAE,KAAK,OAAO,EAAE,MAAM,wCAAwC,CAAA;AAErE,OAAO,EAAmC,KAAK,IAAI,EAAE,MAAM,eAAe,CAAA;AAE1E,eAAO,MAAM,aAAa;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAAmD,CAAA;AAE7E,wBAAsB,eAAe,CAAC,EACrC,OAAO,EACP,OAAO,GACP,GAAE;IAAE,OAAO,CAAC,EAAE,OAAO,CAAC;IAAC,OAAO,CAAC,EAAE,OAAO,CAAA;CAAO,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CA6FtE"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"presence.server.js","sourceRoot":"","sources":["../../src/presence.server.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n\tcachified,\n\tmakeSingletonCache,\n} from '@epic-web/workshop-utils/cache.server'\nimport { getWorkshopConfig } from '@epic-web/workshop-utils/config.server'\nimport { getAuthInfo, getPreferences } from '@epic-web/workshop-utils/db.server'\nimport {\n\tgetUserInfo,\n\tuserHasAccessToWorkshop,\n} from '@epic-web/workshop-utils/epic-api.server'\nimport { type Timings } from '@epic-web/workshop-utils/timing.server'\nimport { getUserId } from '@epic-web/workshop-utils/user.server'\nimport { PresenceSchema, partykitBaseUrl, type User } from './presence.js'\n\nexport const presenceCache = makeSingletonCache<Array<User>>('PresenceCache')\n\nexport async function getPresentUsers({\n\ttimings,\n\trequest,\n}: { timings?: Timings; request?: Request } = {}): Promise<Array<User>> {\n\tconst presence = await cachified({\n\t\tkey: 'presence',\n\t\tcache: presenceCache,\n\t\ttimings,\n\t\trequest,\n\t\tttl: 1000 * 2,\n\t\tswr: 1000 * 60 * 60 * 24,\n\t\tcheckValue: PresenceSchema,\n\t\tasync getFreshValue(context) {\n\t\t\ttry {\n\t\t\t\tconst response = await Promise.race([\n\t\t\t\t\tfetch(`${partykitBaseUrl}/presence`),\n\t\t\t\t\tnew Promise<Response>((resolve) =>\n\t\t\t\t\t\tsetTimeout(() => {\n\t\t\t\t\t\t\tresolve(new Response('Timeout', { status: 500 }))\n\t\t\t\t\t\t}, 500),\n\t\t\t\t\t),\n\t\t\t\t] as const)\n\t\t\t\tif (response.statusText === 'Timeout') {\n\t\t\t\t\tthrow new Error(`Timeout fetching partykit presence`)\n\t\t\t\t}\n\t\t\t\tif (!response.ok) {\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t`Unexpected response from partykit: ${response.status} ${response.statusText}`,\n\t\t\t\t\t)\n\t\t\t\t}\n\t\t\t\tconst presence = PresenceSchema.parse(await response.json())\n\t\t\t\treturn presence\n\t\t\t} catch {\n\t\t\t\t// console.error(err)\n\t\t\t\tcontext.metadata.ttl = 300\n\t\t\t\treturn { users: [] }\n\t\t\t}\n\t\t},\n\t})\n\tconst { users } = presence\n\n\tconst authInfo = await getAuthInfo()\n\tconst userId = request\n\t\t? (await getUserId({ request })).id\n\t\t: (authInfo?.id ?? null)\n\n\tconst preferences = await getPreferences()\n\n\tif (preferences?.presence.optOut || !userId) {\n\t\treturn uniqueUsers(users.filter((u) => u.id !== userId))\n\t} else {\n\t\tconst user: User = { id: userId }\n\t\tconst config = getWorkshopConfig()\n\t\tconst url = request ? new URL(request.url) : undefined\n\t\tuser.location = {\n\t\t\tworkshopTitle: config.title,\n\t\t\torigin: url ? url.origin : undefined,\n\t\t}\n\t\tif (url) {\n\t\t\tif (url.pathname.startsWith('/exercise/')) {\n\t\t\t\tconst [exerciseNumber, stepNumber, type] = url.pathname\n\t\t\t\t\t.split('/')\n\t\t\t\t\t.slice(2)\n\t\t\t\tuser.location.exercise = {\n\t\t\t\t\texerciseNumber: isNaN(Number(exerciseNumber))\n\t\t\t\t\t\t? null\n\t\t\t\t\t\t: Number(exerciseNumber),\n\t\t\t\t\tstepNumber: isNaN(Number(stepNumber)) ? null : Number(stepNumber),\n\t\t\t\t\ttype:\n\t\t\t\t\t\ttype === 'problem'\n\t\t\t\t\t\t\t? 'problem'\n\t\t\t\t\t\t\t: type === 'solution'\n\t\t\t\t\t\t\t\t? 'solution'\n\t\t\t\t\t\t\t\t: null,\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (authInfo) {\n\t\t\tconst [userInfo, hasAccess] = await Promise.all([\n\t\t\t\tgetUserInfo({ request, timings }),\n\t\t\t\tuserHasAccessToWorkshop({ request, timings }),\n\t\t\t])\n\n\t\t\tObject.assign(user, {\n\t\t\t\tname: userInfo?.name,\n\t\t\t\tavatarUrl: userInfo?.imageUrlLarge,\n\t\t\t\timageUrlSmall: userInfo?.imageUrlSmall,\n\t\t\t\timageUrlLarge: userInfo?.imageUrlLarge,\n\t\t\t\thasAccess,\n\t\t\t})\n\t\t}\n\n\t\treturn uniqueUsers([...users, user])\n\t}\n}\n\n// A user maybe on the same page in multiple tabs\n// so let's make sure we only show them once\nfunction uniqueUsers(users: Array<User>) {\n\tconst seen = new Set()\n\treturn users.filter(Boolean).filter((user) => {\n\t\tif (seen.has(user.id)) {\n\t\t\treturn false\n\t\t}\n\t\tseen.add(user.id)\n\t\treturn true\n\t})\n}\n"]}
|
|
1
|
+
{"version":3,"file":"presence.server.js","sourceRoot":"","sources":["../../src/presence.server.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n\tcachified,\n\tmakeSingletonCache,\n} from '@epic-web/workshop-utils/cache.server'\nimport { getWorkshopConfig } from '@epic-web/workshop-utils/config.server'\nimport { getAuthInfo, getPreferences } from '@epic-web/workshop-utils/db.server'\nimport {\n\tgetUserInfo,\n\tuserHasAccessToWorkshop,\n} from '@epic-web/workshop-utils/epic-api.server'\nimport { type Timings } from '@epic-web/workshop-utils/timing.server'\nimport { getUserId } from '@epic-web/workshop-utils/user.server'\nimport { PresenceSchema, partykitBaseUrl, type User } from './presence.js'\n\nexport const presenceCache = makeSingletonCache<Array<User>>('PresenceCache')\n\nexport async function getPresentUsers({\n\ttimings,\n\trequest,\n}: { timings?: Timings; request?: Request } = {}): Promise<Array<User>> {\n\tconst presence = await cachified({\n\t\tkey: 'presence',\n\t\tcache: presenceCache,\n\t\ttimings,\n\t\trequest,\n\t\tttl: 1000 * 2,\n\t\tswr: 1000 * 60 * 60 * 24,\n\t\tofflineFallbackValue: { users: [] },\n\t\tcheckValue: PresenceSchema,\n\t\tasync getFreshValue(context) {\n\t\t\ttry {\n\t\t\t\tconst response = await Promise.race([\n\t\t\t\t\tfetch(`${partykitBaseUrl}/presence`),\n\t\t\t\t\tnew Promise<Response>((resolve) =>\n\t\t\t\t\t\tsetTimeout(() => {\n\t\t\t\t\t\t\tresolve(new Response('Timeout', { status: 500 }))\n\t\t\t\t\t\t}, 500),\n\t\t\t\t\t),\n\t\t\t\t] as const)\n\t\t\t\tif (response.statusText === 'Timeout') {\n\t\t\t\t\tthrow new Error(`Timeout fetching partykit presence`)\n\t\t\t\t}\n\t\t\t\tif (!response.ok) {\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t`Unexpected response from partykit: ${response.status} ${response.statusText}`,\n\t\t\t\t\t)\n\t\t\t\t}\n\t\t\t\tconst presence = PresenceSchema.parse(await response.json())\n\t\t\t\treturn presence\n\t\t\t} catch {\n\t\t\t\t// console.error(err)\n\t\t\t\tcontext.metadata.ttl = 300\n\t\t\t\treturn { users: [] }\n\t\t\t}\n\t\t},\n\t})\n\tconst { users } = presence\n\n\tconst authInfo = await getAuthInfo()\n\tconst userId = request\n\t\t? (await getUserId({ request })).id\n\t\t: (authInfo?.id ?? null)\n\n\tconst preferences = await getPreferences()\n\n\tif (preferences?.presence.optOut || !userId) {\n\t\treturn uniqueUsers(users.filter((u) => u.id !== userId))\n\t} else {\n\t\tconst user: User = { id: userId }\n\t\tconst config = getWorkshopConfig()\n\t\tconst url = request ? new URL(request.url) : undefined\n\t\tuser.location = {\n\t\t\tworkshopTitle: config.title,\n\t\t\torigin: url ? url.origin : undefined,\n\t\t}\n\t\tif (url) {\n\t\t\tif (url.pathname.startsWith('/exercise/')) {\n\t\t\t\tconst [exerciseNumber, stepNumber, type] = url.pathname\n\t\t\t\t\t.split('/')\n\t\t\t\t\t.slice(2)\n\t\t\t\tuser.location.exercise = {\n\t\t\t\t\texerciseNumber: isNaN(Number(exerciseNumber))\n\t\t\t\t\t\t? null\n\t\t\t\t\t\t: Number(exerciseNumber),\n\t\t\t\t\tstepNumber: isNaN(Number(stepNumber)) ? null : Number(stepNumber),\n\t\t\t\t\ttype:\n\t\t\t\t\t\ttype === 'problem'\n\t\t\t\t\t\t\t? 'problem'\n\t\t\t\t\t\t\t: type === 'solution'\n\t\t\t\t\t\t\t\t? 'solution'\n\t\t\t\t\t\t\t\t: null,\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (authInfo) {\n\t\t\tconst [userInfo, hasAccess] = await Promise.all([\n\t\t\t\tgetUserInfo({ request, timings }),\n\t\t\t\tuserHasAccessToWorkshop({ request, timings }),\n\t\t\t])\n\n\t\t\tObject.assign(user, {\n\t\t\t\tname: userInfo?.name,\n\t\t\t\tavatarUrl: userInfo?.imageUrlLarge,\n\t\t\t\timageUrlSmall: userInfo?.imageUrlSmall,\n\t\t\t\timageUrlLarge: userInfo?.imageUrlLarge,\n\t\t\t\thasAccess,\n\t\t\t})\n\t\t}\n\n\t\treturn uniqueUsers([...users, user])\n\t}\n}\n\n// A user maybe on the same page in multiple tabs\n// so let's make sure we only show them once\nfunction uniqueUsers(users: Array<User>) {\n\tconst seen = new Set()\n\treturn users.filter(Boolean).filter((user) => {\n\t\tif (seen.has(user.id)) {\n\t\t\treturn false\n\t\t}\n\t\tseen.add(user.id)\n\t\treturn true\n\t})\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@epic-web/workshop-presence",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.8.0",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"access": "public"
|
|
6
6
|
},
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
"deploy": "partykit deploy"
|
|
12
12
|
},
|
|
13
13
|
"dependencies": {
|
|
14
|
-
"@epic-web/workshop-utils": "5.
|
|
14
|
+
"@epic-web/workshop-utils": "5.8.0",
|
|
15
15
|
"zod": "^3.23.8"
|
|
16
16
|
},
|
|
17
17
|
"devDependencies": {
|