playcademy 0.11.3 → 0.11.5
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/dist/edge-play/src/constants.ts +7 -4
- package/dist/edge-play/src/entry.ts +2 -2
- package/dist/edge-play/src/index.ts +1 -0
- package/dist/edge-play/src/register-routes.ts +5 -8
- package/dist/edge-play/src/routes/index.ts +8 -6
- package/dist/edge-play/src/routes/integrations/timeback/{session-end.ts → end-activity.ts} +41 -23
- package/dist/index.js +3431 -2820
- package/dist/types.d.ts +61 -3
- package/dist/utils.d.ts +5 -1
- package/dist/utils.js +198 -194
- package/package.json +2 -2
- package/dist/edge-play/src/routes/integrations/timeback/award-xp.ts +0 -87
- package/dist/edge-play/src/routes/integrations/timeback/progress.ts +0 -89
|
@@ -1,87 +0,0 @@
|
|
|
1
|
-
import { verifyGameToken } from '@playcademy/sdk/server'
|
|
2
|
-
|
|
3
|
-
import type { Context } from 'hono'
|
|
4
|
-
import type { PlaycademyConfig, XPAwardMetadata } from '@playcademy/sdk/server'
|
|
5
|
-
import type { HonoEnv } from '../../../types'
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* TimeBack integration - Award XP to student
|
|
9
|
-
* Route: POST /api/integrations/timeback/award-xp
|
|
10
|
-
* Auto-generated when integrations.timeback is configured
|
|
11
|
-
*
|
|
12
|
-
* Flow:
|
|
13
|
-
* 1. Game frontend calls this route on deployed backend ({slug}.playcademy.gg/api/integrations/timeback/award-xp)
|
|
14
|
-
* 2. This route calls Playcademy platform API via SDK (hub.playcademy.net/api/timeback/award-xp)
|
|
15
|
-
* 3. Platform API sends Caliper events to TimeBack
|
|
16
|
-
*
|
|
17
|
-
* This acts as a secure proxy - game developers don't need TimeBack credentials or
|
|
18
|
-
* their own backend infrastructure. The SDK handles config enrichment and metadata.
|
|
19
|
-
*/
|
|
20
|
-
|
|
21
|
-
function getConfig(c: Context<HonoEnv>): PlaycademyConfig {
|
|
22
|
-
const config = c.get('config')
|
|
23
|
-
const timebackConfig = config?.integrations?.timeback
|
|
24
|
-
if (!timebackConfig) throw new Error('TimeBack integration not found')
|
|
25
|
-
return config
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
function enrichMetadata(
|
|
29
|
-
metadata: XPAwardMetadata,
|
|
30
|
-
config: PlaycademyConfig,
|
|
31
|
-
c: Context<HonoEnv>,
|
|
32
|
-
): XPAwardMetadata {
|
|
33
|
-
const appName = metadata.appName || config?.name
|
|
34
|
-
const subject =
|
|
35
|
-
metadata.subject ||
|
|
36
|
-
config?.integrations?.timeback?.course?.defaultSubject ||
|
|
37
|
-
config?.integrations?.timeback?.course?.subjects?.[0]
|
|
38
|
-
const sensorUrl = metadata.sensorUrl || new URL(c.req.url).origin
|
|
39
|
-
|
|
40
|
-
if (!appName) throw new Error('App name is required')
|
|
41
|
-
if (!subject) throw new Error('Subject is required')
|
|
42
|
-
if (!sensorUrl) throw new Error('Sensor URL is required')
|
|
43
|
-
|
|
44
|
-
return { ...metadata, appName, subject, sensorUrl }
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
export async function POST(c: Context<HonoEnv>): Promise<Response> {
|
|
48
|
-
try {
|
|
49
|
-
// 1. Verify game token from frontend (calls platform API for verification)
|
|
50
|
-
const token = c.req.header('Authorization')?.replace('Bearer ', '')
|
|
51
|
-
if (!token) return c.json({ error: 'Unauthorized' }, 401)
|
|
52
|
-
|
|
53
|
-
const { user } = await verifyGameToken(token)
|
|
54
|
-
|
|
55
|
-
// 2. Ensure user has TimeBack integration
|
|
56
|
-
if (!user.timeback_id) {
|
|
57
|
-
return c.json({ error: 'User does not have TimeBack integration' }, 400)
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
// 3. Parse request body
|
|
61
|
-
const { xpAmount, metadata } = await c.req.json()
|
|
62
|
-
|
|
63
|
-
// 4. Get config and enrich metadata with required Caliper fields
|
|
64
|
-
const config = getConfig(c)
|
|
65
|
-
|
|
66
|
-
// 5. Enrich metadata with required Caliper fields
|
|
67
|
-
const enrichedMetadata = enrichMetadata(metadata, config, c)
|
|
68
|
-
|
|
69
|
-
// 6. Get SDK client from context (initialized once per Worker, reused across requests)
|
|
70
|
-
const sdk = c.get('sdk')
|
|
71
|
-
|
|
72
|
-
// 7. Award XP to student (SDK handles enrichment & Caliper events)
|
|
73
|
-
const result = await sdk.timeback.awardXP(user.timeback_id, xpAmount, enrichedMetadata)
|
|
74
|
-
|
|
75
|
-
return c.json(result)
|
|
76
|
-
} catch (error) {
|
|
77
|
-
console.error('[TimeBack Award XP] Error:', error)
|
|
78
|
-
return c.json(
|
|
79
|
-
{
|
|
80
|
-
error: 'Failed to award XP',
|
|
81
|
-
message: error instanceof Error ? error.message : String(error),
|
|
82
|
-
stack: error instanceof Error ? error.stack : undefined,
|
|
83
|
-
},
|
|
84
|
-
500,
|
|
85
|
-
)
|
|
86
|
-
}
|
|
87
|
-
}
|
|
@@ -1,89 +0,0 @@
|
|
|
1
|
-
import { verifyGameToken } from '@playcademy/sdk/server'
|
|
2
|
-
|
|
3
|
-
import type { Context } from 'hono'
|
|
4
|
-
import type { PlaycademyConfig, ProgressData } from '@playcademy/sdk/server'
|
|
5
|
-
import type { HonoEnv } from '../../../types'
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* TimeBack integration - Record student progress
|
|
9
|
-
* Route: POST /api/integrations/timeback/progress
|
|
10
|
-
* Auto-generated when integrations.timeback is configured
|
|
11
|
-
*
|
|
12
|
-
* Flow:
|
|
13
|
-
* 1. Game frontend calls this route on deployed backend ({slug}.playcademy.gg/api/integrations/timeback/progress)
|
|
14
|
-
* 2. This route calls Playcademy platform API via SDK (hub.playcademy.net/api/timeback/progress)
|
|
15
|
-
* 3. Platform API sends Caliper events to TimeBack
|
|
16
|
-
*
|
|
17
|
-
* This acts as a secure proxy - game developers don't need TimeBack credentials or
|
|
18
|
-
* their own backend infrastructure. The SDK handles config enrichment and metadata.
|
|
19
|
-
*/
|
|
20
|
-
|
|
21
|
-
function getConfig(c: Context<HonoEnv>): PlaycademyConfig {
|
|
22
|
-
const config = c.get('config')
|
|
23
|
-
const timebackConfig = config?.integrations?.timeback
|
|
24
|
-
if (!timebackConfig) throw new Error('TimeBack integration not found')
|
|
25
|
-
return config
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
function enrichProgressData(
|
|
29
|
-
progressData: ProgressData,
|
|
30
|
-
config: PlaycademyConfig,
|
|
31
|
-
c: Context<HonoEnv>,
|
|
32
|
-
): ProgressData {
|
|
33
|
-
const appName = progressData.appName || config?.name
|
|
34
|
-
const subject =
|
|
35
|
-
progressData.subject ||
|
|
36
|
-
config?.integrations?.timeback?.course?.defaultSubject ||
|
|
37
|
-
config?.integrations?.timeback?.course?.subjects?.[0]
|
|
38
|
-
const sensorUrl = progressData.sensorUrl || new URL(c.req.url).origin
|
|
39
|
-
|
|
40
|
-
if (!appName) throw new Error('App name is required')
|
|
41
|
-
if (!subject) throw new Error('Subject is required')
|
|
42
|
-
if (!sensorUrl) throw new Error('Sensor URL is required')
|
|
43
|
-
|
|
44
|
-
return { ...progressData, appName, subject, sensorUrl }
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
export async function POST(c: Context<HonoEnv>): Promise<Response> {
|
|
48
|
-
try {
|
|
49
|
-
// 1. Verify game token from frontend (calls platform API for verification)
|
|
50
|
-
const token = c.req.header('Authorization')?.replace('Bearer ', '')
|
|
51
|
-
if (!token) {
|
|
52
|
-
return c.json({ error: 'Unauthorized' }, 401)
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
const { user } = await verifyGameToken(token)
|
|
56
|
-
|
|
57
|
-
// 2. Ensure user has TimeBack integration
|
|
58
|
-
if (!user.timeback_id) {
|
|
59
|
-
return c.json({ error: 'User does not have TimeBack integration' }, 400)
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
// 3. Parse request body
|
|
63
|
-
const { progressData } = await c.req.json()
|
|
64
|
-
|
|
65
|
-
// 4. Get config and enrich progress data with required Caliper fields
|
|
66
|
-
const config = getConfig(c)
|
|
67
|
-
|
|
68
|
-
// 5. Enrich progress data with required Caliper fields
|
|
69
|
-
const enrichedProgressData = enrichProgressData(progressData, config, c)
|
|
70
|
-
|
|
71
|
-
// 5. Get SDK client from context (initialized once per Worker, reused across requests)
|
|
72
|
-
const sdk = c.get('sdk')
|
|
73
|
-
|
|
74
|
-
// 6. Record progress to TimeBack (SDK handles enrichment & Caliper events)
|
|
75
|
-
const result = await sdk.timeback.recordProgress(user.timeback_id, enrichedProgressData)
|
|
76
|
-
|
|
77
|
-
return c.json(result)
|
|
78
|
-
} catch (error) {
|
|
79
|
-
console.error('[TimeBack Progress] Error:', error)
|
|
80
|
-
return c.json(
|
|
81
|
-
{
|
|
82
|
-
error: 'Failed to record progress',
|
|
83
|
-
message: error instanceof Error ? error.message : String(error),
|
|
84
|
-
stack: error instanceof Error ? error.stack : undefined,
|
|
85
|
-
},
|
|
86
|
-
500,
|
|
87
|
-
)
|
|
88
|
-
}
|
|
89
|
-
}
|