playcademy 0.14.2 → 0.14.4-alpha.1

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.
@@ -0,0 +1,34 @@
1
+ import type { User } from '../../lib/auth'
2
+
3
+ /**
4
+ * Protected Route Example
5
+ *
6
+ * Demonstrates how to require authentication in a route.
7
+ * This endpoint will only be accessible to authenticated users.
8
+ */
9
+ export async function GET(c: Context): Promise<Response> {
10
+ // Check if user is authenticated
11
+ const user = c.get('user') as User | undefined
12
+
13
+ if (!user) {
14
+ return c.json({ error: 'Authentication required' }, 401)
15
+ }
16
+
17
+ // OPTIONAL: Require user to be from Playcademy platform
18
+ // Useful for platform-exclusive features
19
+ // if (!user.playcademyUserId) {
20
+ // return c.json({ error: 'Platform access required' }, 403)
21
+ // }
22
+
23
+ return c.json({
24
+ success: true,
25
+ message: 'Authentication working! You are signed in.',
26
+ user: {
27
+ id: user.id,
28
+ email: user.email,
29
+ name: user.name,
30
+ playcademyUserId: user.playcademyUserId,
31
+ },
32
+ })
33
+ }
34
+
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Better Auth Routes
3
+ *
4
+ * Handles all Better Auth routes (/api/auth/*)
5
+ * This is a standard catch-all route - no customization needed.
6
+ */
7
+ import { getAuth } from '../../lib/auth'
8
+
9
+ export async function GET(c: Context): Promise<Response> {
10
+ const auth = getAuth(c)
11
+ return auth.handler(c.req.raw)
12
+ }
13
+
14
+ export async function POST(c: Context): Promise<Response> {
15
+ const auth = getAuth(c)
16
+ return auth.handler(c.req.raw)
17
+ }
18
+
@@ -0,0 +1,62 @@
1
+ /**
2
+ * Better Auth Schema
3
+ *
4
+ * Database tables for Better Auth authentication system
5
+ */
6
+ import { integer, sqliteTable, text } from 'drizzle-orm/sqlite-core'
7
+
8
+ export const user = sqliteTable('user', {
9
+ id: text('id').primaryKey(),
10
+ name: text('name').notNull(),
11
+ email: text('email').notNull().unique(),
12
+ emailVerified: integer('emailVerified').notNull(),
13
+ image: text('image'),
14
+ createdAt: integer('createdAt', { mode: 'timestamp' }).notNull(),
15
+ updatedAt: integer('updatedAt', { mode: 'timestamp' }).notNull(),
16
+
17
+ // Platform linkage: Links this user to a Playcademy platform identity
18
+ // When users launch the game from Playcademy, their platform identity
19
+ // is verified and linked to a Better Auth session via this field
20
+ playcademyUserId: text('playcademy_user_id').unique(),
21
+ })
22
+
23
+ export const session = sqliteTable('session', {
24
+ id: text('id').primaryKey(),
25
+ expiresAt: integer('expiresAt', { mode: 'timestamp' }).notNull(),
26
+ token: text('token').notNull().unique(),
27
+ createdAt: integer('createdAt', { mode: 'timestamp' }).notNull(),
28
+ updatedAt: integer('updatedAt', { mode: 'timestamp' }).notNull(),
29
+ ipAddress: text('ipAddress'),
30
+ userAgent: text('userAgent'),
31
+ userId: text('userId')
32
+ .notNull()
33
+ .references(() => user.id, { onDelete: 'cascade' }),
34
+ })
35
+
36
+ export const account = sqliteTable('account', {
37
+ id: text('id').primaryKey(),
38
+ accountId: text('accountId').notNull(),
39
+ providerId: text('providerId').notNull(),
40
+ userId: text('userId')
41
+ .notNull()
42
+ .references(() => user.id, { onDelete: 'cascade' }),
43
+ accessToken: text('accessToken'),
44
+ refreshToken: text('refreshToken'),
45
+ idToken: text('idToken'),
46
+ accessTokenExpiresAt: integer('accessTokenExpiresAt', { mode: 'timestamp' }),
47
+ refreshTokenExpiresAt: integer('refreshTokenExpiresAt', { mode: 'timestamp' }),
48
+ scope: text('scope'),
49
+ password: text('password'),
50
+ createdAt: integer('createdAt', { mode: 'timestamp' }).notNull(),
51
+ updatedAt: integer('updatedAt', { mode: 'timestamp' }).notNull(),
52
+ })
53
+
54
+ export const verification = sqliteTable('verification', {
55
+ id: text('id').primaryKey(),
56
+ identifier: text('identifier').notNull(),
57
+ value: text('value').notNull(),
58
+ expiresAt: integer('expiresAt', { mode: 'timestamp' }).notNull(),
59
+ createdAt: integer('createdAt', { mode: 'timestamp' }).notNull(),
60
+ updatedAt: integer('updatedAt', { mode: 'timestamp' }).notNull(),
61
+ })
62
+
@@ -0,0 +1,55 @@
1
+ /**
2
+ * Better Auth Configuration
3
+ *
4
+ * CUSTOMIZABLE: This file is where you configure your auth providers,
5
+ * social logins, and other auth-specific settings.
6
+ */
7
+ import { betterAuth } from 'better-auth'
8
+ import { drizzleAdapter } from 'better-auth/adapters/drizzle'
9
+
10
+ import { playcademy } from '@playcademy/better-auth/server'
11
+
12
+ import { getDb } from '../../db'
13
+
14
+ import type { Context } from 'hono'
15
+
16
+ export function getAuth(c: Context) {
17
+ const db = getDb(c.env.DB)
18
+
19
+ // CUSTOMIZABLE: Configure trusted origins for CORS
20
+ // These origins are allowed to make cross-origin requests to your game's auth endpoints.
21
+ // Add your deployed game URLs here when you deploy to staging or production.
22
+ const trustedOrigins = [
23
+ 'http://localhost:5173', // Local development
24
+ // 'https://{{GAME_SLUG}}-staging.playcademy.gg', // Staging deployment
25
+ // 'https://{{GAME_SLUG}}.playcademy.gg', // Production deployment
26
+ ]
27
+
28
+ return betterAuth({
29
+ database: drizzleAdapter(db, {
30
+ provider: 'sqlite',
31
+ usePlural: false,
32
+ }),
33
+
34
+ trustedOrigins,
35
+ {{EMAIL_AND_PASSWORD}}{{SOCIAL_PROVIDERS}}
36
+ // REQUIRED: Platform integration
37
+ plugins: [
38
+ playcademy(),
39
+ ],
40
+
41
+ // CUSTOMIZABLE: Cookie settings
42
+ advanced: {
43
+ defaultCookieAttributes: {
44
+ path: '/',
45
+ secure: true,
46
+ partitioned: true, // CHIPS for Chrome/Edge
47
+ sameSite: 'none', // Ensure state + session cookies are sent on cross-site redirects
48
+ },
49
+ },
50
+ })
51
+ }
52
+
53
+ export type Auth = ReturnType<typeof getAuth>
54
+ export type Session = Auth['$Infer']['Session']
55
+ export type User = Auth['$Infer']['Session']['user']
@@ -1,7 +1,7 @@
1
1
 
2
2
 
3
3
  // External integrations
4
- // See https://docs.playcademy.com/integrations for more details
4
+ // See https://docs.playcademy.net/integrations/overview.html for more details
5
5
  integrations: {
6
6
  {{INTEGRATIONS_CONTENT}}
7
7
  },
@@ -1,15 +1,24 @@
1
+ /**
2
+ * Playcademy Environment Types
3
+ *
4
+ * Auto-generated by Playcademy CLI.
5
+ * Regenerated on: playcademy dev, playcademy init, playcademy db init, playcademy auth init
6
+ *
7
+ * Do not edit - changes will be overwritten.
8
+ */
9
+
1
10
  /// <reference types="./.playcademy/node_modules/@cloudflare/workers-types" />
2
11
 
3
- import type { Context as HonoContext } from './.playcademy/node_modules/hono'
12
+ import type { Context as HonoContext } from './.playcademy/node_modules/hono'{{AUTH_IMPORT}}
4
13
 
5
14
  declare global {
6
15
  interface PlaycademyEnv {
7
16
  PLAYCADEMY_API_KEY: string
8
17
  GAME_ID: string
9
18
  PLAYCADEMY_BASE_URL: string{{BINDINGS}}{{SECRETS}}
10
- }
19
+ }{{VARIABLES}}
11
20
 
12
- type Context = HonoContext<{ Bindings: PlaycademyEnv }>
21
+ type Context = HonoContext<{ Bindings: PlaycademyEnv{{CONTEXT_VARS}} }>
13
22
  }
14
23
 
15
24
  export {}
package/dist/utils.d.ts CHANGED
@@ -54,6 +54,8 @@ interface IntegrationsConfig {
54
54
  kv?: boolean;
55
55
  /** Bucket storage (optional) */
56
56
  bucket?: boolean;
57
+ /** Authentication (optional) */
58
+ auth?: boolean;
57
59
  }
58
60
  /**
59
61
  * Unified Playcademy configuration
@@ -80,6 +82,14 @@ interface PlaycademyConfig {
80
82
  integrations?: IntegrationsConfig;
81
83
  }
82
84
 
85
+ /**
86
+ * Logger interface for embedding in other tools (e.g., vite plugin)
87
+ */
88
+ interface PluginLogger {
89
+ info: (msg: string) => void;
90
+ warn: (msg: string) => void;
91
+ error: (msg: string) => void;
92
+ }
83
93
  interface DevServerOptions {
84
94
  port: number;
85
95
  /** Playcademy config. If not provided, will attempt to load from playcademy.config.js */
@@ -94,6 +104,8 @@ interface DevServerOptions {
94
104
  onReload?: (restart: () => Promise<void>) => void;
95
105
  /** URL for Playcademy platform/sandbox API (defaults to localhost:5174 platform) */
96
106
  platformUrl?: string;
107
+ /** Custom logger for embedding (e.g., from vite plugin) */
108
+ customLogger?: PluginLogger;
97
109
  }
98
110
 
99
111
  /**