playcademy 0.12.3 → 0.12.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/routes/root.html +127 -43
- package/dist/index.d.ts +65 -1
- package/dist/index.js +76 -50
- package/dist/utils.js +74 -49
- package/package.json +1 -1
- /package/dist/{vendor/constants → constants/src}/auth.ts +0 -0
- /package/dist/{vendor/constants → constants/src}/domains.ts +0 -0
- /package/dist/{vendor/constants → constants/src}/env-vars.ts +0 -0
- /package/dist/{vendor/constants → constants/src}/index.ts +0 -0
- /package/dist/{vendor/constants → constants/src}/overworld.ts +0 -0
- /package/dist/{vendor/constants → constants/src}/system.ts +0 -0
- /package/dist/{vendor/constants → constants/src}/timeback.ts +0 -0
- /package/dist/{vendor/constants → constants/src}/workers.ts +0 -0
|
@@ -20,9 +20,28 @@
|
|
|
20
20
|
<body
|
|
21
21
|
class="min-h-screen flex items-center justify-center bg-black dark:bg-white transition-colors relative overflow-hidden"
|
|
22
22
|
>
|
|
23
|
+
<!-- Top left badges -->
|
|
24
|
+
<a
|
|
25
|
+
href="{{PLAYCADEMY_HUB_URL}}"
|
|
26
|
+
target="_blank"
|
|
27
|
+
rel="noopener noreferrer"
|
|
28
|
+
class="fixed top-5 left-5 px-2 py-1 rounded bg-[rgba(23,23,23,0.9)] hover:bg-[rgba(23,23,23,1)] dark:bg-[rgba(255,255,255,0.9)] dark:hover:bg-[rgba(255,255,255,1)] text-white dark:text-black border border-white/20 dark:border-black/20 backdrop-blur-lg transition-colors z-[9999] no-underline"
|
|
29
|
+
style="font-family: 'VT323', monospace; font-size: 1rem; letter-spacing: 0.05em"
|
|
30
|
+
>
|
|
31
|
+
PLAYCADEMY
|
|
32
|
+
</a>
|
|
33
|
+
<a
|
|
34
|
+
href="/api"
|
|
35
|
+
class="fixed top-5 left-[7.5rem] px-2 py-1 rounded bg-[rgba(23,23,23,0.9)] hover:bg-[rgba(23,23,23,1)] dark:bg-[rgba(255,255,255,0.9)] dark:hover:bg-[rgba(255,255,255,1)] text-white dark:text-black border border-white/20 dark:border-black/20 backdrop-blur-lg transition-colors z-[9999] no-underline"
|
|
36
|
+
style="font-family: 'VT323', monospace; font-size: 1rem; letter-spacing: 0.05em"
|
|
37
|
+
>
|
|
38
|
+
VIEW ROUTES
|
|
39
|
+
</a>
|
|
40
|
+
|
|
41
|
+
<!-- Theme toggle -->
|
|
23
42
|
<button
|
|
24
43
|
id="themeToggle"
|
|
25
|
-
class="fixed top-5 right-5 w-8 h-8 flex items-center justify-center cursor-pointer opacity-40 hover:opacity-100 transition-opacity"
|
|
44
|
+
class="fixed top-5 right-5 w-8 h-8 flex items-center justify-center cursor-pointer opacity-40 hover:opacity-100 transition-opacity z-[9999]"
|
|
26
45
|
>
|
|
27
46
|
<svg
|
|
28
47
|
id="sunIcon"
|
|
@@ -47,6 +66,9 @@
|
|
|
47
66
|
</svg>
|
|
48
67
|
</button>
|
|
49
68
|
|
|
69
|
+
<!-- Pixel trail container -->
|
|
70
|
+
<div id="pixelTrail" class="absolute inset-0 z-0"></div>
|
|
71
|
+
|
|
50
72
|
<!-- Subtle background enhancements: vignette + grid (theme-aware) -->
|
|
51
73
|
<div class="pointer-events-none absolute inset-0 z-0">
|
|
52
74
|
<!-- Light mode vignette (white on black) -->
|
|
@@ -93,45 +115,14 @@
|
|
|
93
115
|
></div>
|
|
94
116
|
</div>
|
|
95
117
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
</h1>
|
|
105
|
-
<p
|
|
106
|
-
class="text-lg text-gray-500 dark:text-gray-500"
|
|
107
|
-
style="font-family: 'VT323', monospace; letter-spacing: 0.1em"
|
|
108
|
-
>
|
|
109
|
-
GAME BACKEND API
|
|
110
|
-
</p>
|
|
111
|
-
</div>
|
|
112
|
-
|
|
113
|
-
<a
|
|
114
|
-
href="/api"
|
|
115
|
-
class="inline-block px-8 py-2.5 bg-white dark:bg-black text-black dark:text-white rounded border-2 border-white dark:border-black hover:bg-gray-200 dark:hover:bg-gray-800 transition-colors"
|
|
116
|
-
style="font-family: 'VT323', monospace; letter-spacing: 0.05em; font-size: 1rem"
|
|
117
|
-
>
|
|
118
|
-
VIEW ROUTES →
|
|
119
|
-
</a>
|
|
120
|
-
|
|
121
|
-
<div
|
|
122
|
-
class="pt-8 text-xs text-gray-600 dark:text-gray-500"
|
|
123
|
-
style="font-family: 'VT323', monospace; letter-spacing: 0.05em"
|
|
124
|
-
>
|
|
125
|
-
POWERED BY
|
|
126
|
-
<a
|
|
127
|
-
href="{{PLAYCADEMY_HUB_URL}}"
|
|
128
|
-
target="_blank"
|
|
129
|
-
rel="noopener noreferrer"
|
|
130
|
-
class="font-bold hover:text-gray-500 dark:hover:text-gray-600 transition-colors underline decoration-dotted underline-offset-2"
|
|
131
|
-
>PLAYCADEMY</a
|
|
132
|
-
>
|
|
133
|
-
</div>
|
|
134
|
-
</div>
|
|
118
|
+
<!-- Center content -->
|
|
119
|
+
<div class="relative z-10">
|
|
120
|
+
<h1
|
|
121
|
+
class="text-6xl md:text-7xl lg:text-6xl font-bold text-white dark:text-black text-center"
|
|
122
|
+
style="font-family: 'Tomorrow', sans-serif; letter-spacing: -0.02em"
|
|
123
|
+
>
|
|
124
|
+
{{GAME_NAME}}
|
|
125
|
+
</h1>
|
|
135
126
|
</div>
|
|
136
127
|
|
|
137
128
|
<script>
|
|
@@ -152,10 +143,9 @@
|
|
|
152
143
|
}
|
|
153
144
|
}
|
|
154
145
|
|
|
155
|
-
// Initialize theme from localStorage
|
|
146
|
+
// Initialize theme from localStorage, defaulting to dark mode
|
|
156
147
|
const savedTheme = localStorage.getItem('theme')
|
|
157
|
-
const
|
|
158
|
-
const isDark = savedTheme === 'dark' || (!savedTheme && prefersDark)
|
|
148
|
+
const isDark = savedTheme !== 'light' // Default to dark unless explicitly set to light
|
|
159
149
|
setTheme(isDark)
|
|
160
150
|
|
|
161
151
|
// Toggle on click
|
|
@@ -165,5 +155,99 @@
|
|
|
165
155
|
localStorage.setItem('theme', willBeDark ? 'dark' : 'light')
|
|
166
156
|
})
|
|
167
157
|
</script>
|
|
158
|
+
|
|
159
|
+
<script>
|
|
160
|
+
// Pixel Trail Effect
|
|
161
|
+
const pixelTrail = document.getElementById('pixelTrail')
|
|
162
|
+
const PIXEL_SIZE = 20 // px
|
|
163
|
+
const FADE_DURATION = 300 // ms
|
|
164
|
+
|
|
165
|
+
// Arcade color palette - vibrant neon colors
|
|
166
|
+
const ARCADE_COLORS = [
|
|
167
|
+
'rgba(255, 0, 255, 0.8)', // Neon Pink/Magenta
|
|
168
|
+
'rgba(0, 255, 255, 0.8)', // Neon Cyan
|
|
169
|
+
'rgba(255, 255, 0, 0.8)', // Neon Yellow
|
|
170
|
+
'rgba(0, 255, 0, 0.8)', // Neon Green
|
|
171
|
+
'rgba(255, 105, 180, 0.8)', // Hot Pink
|
|
172
|
+
'rgba(138, 43, 226, 0.8)', // Blue Violet
|
|
173
|
+
'rgba(50, 205, 50, 0.8)', // Lime Green
|
|
174
|
+
]
|
|
175
|
+
|
|
176
|
+
let pixelGrid = {}
|
|
177
|
+
let columns = 0
|
|
178
|
+
let rows = 0
|
|
179
|
+
|
|
180
|
+
function getRandomArcadeColor() {
|
|
181
|
+
return ARCADE_COLORS[Math.floor(Math.random() * ARCADE_COLORS.length)]
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
function initPixelGrid() {
|
|
185
|
+
const width = window.innerWidth
|
|
186
|
+
const height = window.innerHeight
|
|
187
|
+
columns = Math.ceil(width / PIXEL_SIZE)
|
|
188
|
+
rows = Math.ceil(height / PIXEL_SIZE)
|
|
189
|
+
|
|
190
|
+
// Clear existing grid
|
|
191
|
+
pixelTrail.innerHTML = ''
|
|
192
|
+
pixelGrid = {}
|
|
193
|
+
|
|
194
|
+
// Create pixel grid
|
|
195
|
+
for (let row = 0; row < rows; row++) {
|
|
196
|
+
for (let col = 0; col < columns; col++) {
|
|
197
|
+
const pixel = document.createElement('div')
|
|
198
|
+
pixel.className = 'absolute pointer-events-none transition-opacity'
|
|
199
|
+
pixel.style.width = `${PIXEL_SIZE}px`
|
|
200
|
+
pixel.style.height = `${PIXEL_SIZE}px`
|
|
201
|
+
pixel.style.left = `${col * PIXEL_SIZE}px`
|
|
202
|
+
pixel.style.top = `${row * PIXEL_SIZE}px`
|
|
203
|
+
pixel.style.opacity = '0'
|
|
204
|
+
pixel.style.transitionDuration = `${FADE_DURATION}ms`
|
|
205
|
+
pixel.style.borderRadius = '2px' // Slight rounding for arcade feel
|
|
206
|
+
|
|
207
|
+
pixelTrail.appendChild(pixel)
|
|
208
|
+
pixelGrid[`${col}-${row}`] = pixel
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
function animatePixel(col, row) {
|
|
214
|
+
const key = `${col}-${row}`
|
|
215
|
+
const pixel = pixelGrid[key]
|
|
216
|
+
if (!pixel) return
|
|
217
|
+
|
|
218
|
+
// Cancel any ongoing animation
|
|
219
|
+
clearTimeout(pixel.fadeTimeout)
|
|
220
|
+
|
|
221
|
+
// Assign random arcade color
|
|
222
|
+
pixel.style.backgroundColor = getRandomArcadeColor()
|
|
223
|
+
|
|
224
|
+
// Show pixel
|
|
225
|
+
pixel.style.opacity = '1'
|
|
226
|
+
|
|
227
|
+
// Fade out after duration
|
|
228
|
+
pixel.fadeTimeout = setTimeout(() => {
|
|
229
|
+
pixel.style.opacity = '0'
|
|
230
|
+
}, FADE_DURATION)
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
function handleMouseMove(e) {
|
|
234
|
+
const col = Math.floor(e.clientX / PIXEL_SIZE)
|
|
235
|
+
const row = Math.floor(e.clientY / PIXEL_SIZE)
|
|
236
|
+
animatePixel(col, row)
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
// Initialize on load
|
|
240
|
+
initPixelGrid()
|
|
241
|
+
|
|
242
|
+
// Add event listeners
|
|
243
|
+
document.body.addEventListener('mousemove', handleMouseMove)
|
|
244
|
+
|
|
245
|
+
// Reinitialize on window resize
|
|
246
|
+
let resizeTimeout
|
|
247
|
+
window.addEventListener('resize', () => {
|
|
248
|
+
clearTimeout(resizeTimeout)
|
|
249
|
+
resizeTimeout = setTimeout(initPixelGrid, 200)
|
|
250
|
+
})
|
|
251
|
+
</script>
|
|
168
252
|
</body>
|
|
169
253
|
</html>
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { UserInfo, ApiKey, BackendDeploymentResponse } from '@playcademy/data/types';
|
|
2
|
+
import { SchemaInfo } from '@playcademy/cloudflare';
|
|
2
3
|
import { OrganizationConfig, CourseConfig, ComponentConfig, ResourceConfig, ComponentResourceConfig } from '@playcademy/timeback/types';
|
|
3
4
|
export { ComponentConfig, ComponentResourceConfig, CourseConfig, DerivedComponentConfig, DerivedComponentResourceConfig, DerivedCourseConfig, DerivedOrganizationConfig, DerivedResourceConfig, DerivedTimebackConfig, OrganizationConfig, ResourceConfig, TimebackGrade, TimebackSourcedIds, TimebackSubject } from '@playcademy/timeback/types';
|
|
4
5
|
import { PlaycademyClient } from '@playcademy/sdk';
|
|
@@ -222,6 +223,32 @@ interface PlaycademyConfig {
|
|
|
222
223
|
integrations?: IntegrationsConfig;
|
|
223
224
|
}
|
|
224
225
|
|
|
226
|
+
/**
|
|
227
|
+
* Resource bindings for backend deployment
|
|
228
|
+
* Provider-agnostic abstraction for cloud resources
|
|
229
|
+
*/
|
|
230
|
+
interface BackendResourceBindings {
|
|
231
|
+
/** SQL database instances to create and bind (maps to D1 on Cloudflare) */
|
|
232
|
+
database?: string[];
|
|
233
|
+
/** Key-value store namespaces to create and bind (maps to KV on Cloudflare) */
|
|
234
|
+
keyValue?: string[];
|
|
235
|
+
/** Object storage buckets to bind (maps to R2 on Cloudflare) */
|
|
236
|
+
bucket?: string[];
|
|
237
|
+
}
|
|
238
|
+
/**
|
|
239
|
+
* Backend deployment bundle for uploading to Playcademy platform
|
|
240
|
+
*/
|
|
241
|
+
interface BackendDeploymentBundle {
|
|
242
|
+
/** Bundled JavaScript code ready for deployment */
|
|
243
|
+
code: string;
|
|
244
|
+
/** Game configuration */
|
|
245
|
+
config: PlaycademyConfig;
|
|
246
|
+
/** Optional resource bindings (database, storage, etc.) */
|
|
247
|
+
bindings?: BackendResourceBindings;
|
|
248
|
+
/** Optional schema information for database setup */
|
|
249
|
+
schema?: SchemaInfo;
|
|
250
|
+
}
|
|
251
|
+
|
|
225
252
|
type GameMetadata = {
|
|
226
253
|
description?: string;
|
|
227
254
|
emoji?: string;
|
|
@@ -620,6 +647,43 @@ interface UpdateExistingGameOptions {
|
|
|
620
647
|
previousBackendSize?: number;
|
|
621
648
|
verbose?: boolean;
|
|
622
649
|
}
|
|
650
|
+
/**
|
|
651
|
+
* Backend bundle with CLI-specific metadata
|
|
652
|
+
* Extends SDK's BackendDeploymentBundle with route discovery metadata
|
|
653
|
+
*/
|
|
654
|
+
interface BackendBundle extends BackendDeploymentBundle {
|
|
655
|
+
/** Discovered custom routes (for CLI display and tracking) */
|
|
656
|
+
customRoutes: Array<{
|
|
657
|
+
path: string;
|
|
658
|
+
file: string;
|
|
659
|
+
methods?: string[];
|
|
660
|
+
}>;
|
|
661
|
+
}
|
|
662
|
+
/**
|
|
663
|
+
* Bundle configuration options
|
|
664
|
+
*/
|
|
665
|
+
interface BundleOptions {
|
|
666
|
+
/** Include source map for debugging (default: false) */
|
|
667
|
+
sourcemap?: boolean;
|
|
668
|
+
/** Minify output (default: false) */
|
|
669
|
+
minify?: boolean;
|
|
670
|
+
}
|
|
671
|
+
/**
|
|
672
|
+
* Resolved paths for bundling embedded sources
|
|
673
|
+
* Used to support both monorepo development and published package scenarios
|
|
674
|
+
*/
|
|
675
|
+
interface EmbeddedSourcePaths {
|
|
676
|
+
/** Whether we're running from a published package (vs monorepo dev) */
|
|
677
|
+
isBuiltPackage: boolean;
|
|
678
|
+
/** Path to edge-play sources (embedded or monorepo) */
|
|
679
|
+
edgePlaySrc: string;
|
|
680
|
+
/** Path to constants entry point (embedded or monorepo) */
|
|
681
|
+
constantsEntry: string;
|
|
682
|
+
/** User's workspace node_modules */
|
|
683
|
+
workspaceNodeModules: string;
|
|
684
|
+
/** CLI's node_modules (monorepo root in dev, same as workspace in published) */
|
|
685
|
+
cliNodeModules: string;
|
|
686
|
+
}
|
|
623
687
|
|
|
624
688
|
/**
|
|
625
689
|
* Types for the CLI local HTTP server that handles OAuth callbacks
|
|
@@ -801,4 +865,4 @@ interface DeploymentDiffOptions {
|
|
|
801
865
|
integrations?: IntegrationsDiff;
|
|
802
866
|
}
|
|
803
867
|
|
|
804
|
-
export type { ApiConfig, ApiErrorResponse, ApiKeyListItem, ApiKeyWithSecret, ApiRequestOptions, AuthProfile, AuthStore, BackendDeploymentWithHash, BackendDiff, BuildDiff, CallbackServerResult, ConfigDiff, CreateApiKeyResponse, CustomRoutesIntegrationOptions, DatabaseIntegrationOptions, DeployConfig, DeployNewGameOptions, DeployedGameInfo, DeploymentChanges, DeploymentContext, DeploymentDiffOptions, DeploymentPlan, DeploymentResult, EnvironmentAuthProfiles, GameStore, IntegrationChangeDetector, IntegrationChangeDetectors, IntegrationConfigChange, IntegrationsConfig, IntegrationsDiff, LoginCredentials, LoginResponse, PlaycademyConfig, PreviewOptions, PreviewResponse, SignInResponse, SsoCallbackData, TimebackIntegrationConfig, TokenType, UpdateExistingGameOptions };
|
|
868
|
+
export type { ApiConfig, ApiErrorResponse, ApiKeyListItem, ApiKeyWithSecret, ApiRequestOptions, AuthProfile, AuthStore, BackendBundle, BackendDeploymentWithHash, BackendDiff, BuildDiff, BundleOptions, CallbackServerResult, ConfigDiff, CreateApiKeyResponse, CustomRoutesIntegrationOptions, DatabaseIntegrationOptions, DeployConfig, DeployNewGameOptions, DeployedGameInfo, DeploymentChanges, DeploymentContext, DeploymentDiffOptions, DeploymentPlan, DeploymentResult, EmbeddedSourcePaths, EnvironmentAuthProfiles, GameStore, IntegrationChangeDetector, IntegrationChangeDetectors, IntegrationConfigChange, IntegrationsConfig, IntegrationsDiff, LoginCredentials, LoginResponse, PlaycademyConfig, PreviewOptions, PreviewResponse, SignInResponse, SsoCallbackData, TimebackIntegrationConfig, TokenType, UpdateExistingGameOptions };
|
package/dist/index.js
CHANGED
|
@@ -5222,9 +5222,8 @@ async function registerCustomRoutes(app, routes) {
|
|
|
5222
5222
|
}
|
|
5223
5223
|
|
|
5224
5224
|
// src/lib/deploy/bundle.ts
|
|
5225
|
-
var entryTemplate = entry_default;
|
|
5226
|
-
async function
|
|
5227
|
-
const esbuild = await import("esbuild");
|
|
5225
|
+
var entryTemplate = entry_default.toString();
|
|
5226
|
+
async function discoverCustomRoutes(config) {
|
|
5228
5227
|
const workspace = getWorkspace();
|
|
5229
5228
|
const customRoutesConfig = config.integrations?.customRoutes;
|
|
5230
5229
|
const customRoutesDir = typeof customRoutesConfig === "object" && customRoutesConfig.directory || DEFAULT_API_ROUTES_DIRECTORY;
|
|
@@ -5235,89 +5234,115 @@ async function bundleBackend(config, options = {}) {
|
|
|
5235
5234
|
// Use relative path (e.g., 'server/api/test.ts'), not absolute
|
|
5236
5235
|
methods: r.methods
|
|
5237
5236
|
}));
|
|
5238
|
-
|
|
5239
|
-
|
|
5240
|
-
|
|
5241
|
-
|
|
5242
|
-
const entryCode = generateEntryCode(customRouteData, customRoutesDir);
|
|
5237
|
+
return { customRouteData, customRoutesDir };
|
|
5238
|
+
}
|
|
5239
|
+
function resolveEmbeddedSourcePaths() {
|
|
5240
|
+
const workspace = getWorkspace();
|
|
5243
5241
|
const distDir = new URL(".", import.meta.url).pathname;
|
|
5244
5242
|
const embeddedEdgeSrc = join6(distDir, "edge-play", "src");
|
|
5243
|
+
const isBuiltPackage = existsSync7(embeddedEdgeSrc);
|
|
5245
5244
|
const monorepoRoot = getMonorepoRoot();
|
|
5246
5245
|
const monorepoEdgeSrc = join6(monorepoRoot, "packages/edge-play/src");
|
|
5247
|
-
const isBuiltPackage = existsSync7(embeddedEdgeSrc);
|
|
5248
5246
|
const edgePlaySrc = isBuiltPackage ? embeddedEdgeSrc : monorepoEdgeSrc;
|
|
5249
5247
|
const cliPackageRoot = isBuiltPackage ? join6(distDir, "../../..") : join6(monorepoRoot, "packages/cli");
|
|
5250
5248
|
const cliNodeModules = isBuiltPackage ? join6(cliPackageRoot, "node_modules") : monorepoRoot;
|
|
5251
5249
|
const workspaceNodeModules = join6(workspace, "node_modules");
|
|
5252
|
-
const constantsEntry = isBuiltPackage ? (
|
|
5253
|
-
|
|
5254
|
-
join6(embeddedEdgeSrc, "..", "..", "vendor", "constants", "index.ts")
|
|
5255
|
-
) : join6(monorepoRoot, "packages", "constants", "src", "index.ts");
|
|
5256
|
-
console.log({
|
|
5250
|
+
const constantsEntry = isBuiltPackage ? join6(embeddedEdgeSrc, "..", "..", "constants", "src", "index.ts") : join6(monorepoRoot, "packages", "constants", "src", "index.ts");
|
|
5251
|
+
return {
|
|
5257
5252
|
isBuiltPackage,
|
|
5258
|
-
distDir,
|
|
5259
|
-
constantsEntry,
|
|
5260
|
-
embeddedEdgeSrc,
|
|
5261
5253
|
edgePlaySrc,
|
|
5262
|
-
|
|
5263
|
-
|
|
5264
|
-
|
|
5265
|
-
}
|
|
5266
|
-
|
|
5254
|
+
constantsEntry,
|
|
5255
|
+
workspaceNodeModules,
|
|
5256
|
+
cliNodeModules
|
|
5257
|
+
};
|
|
5258
|
+
}
|
|
5259
|
+
function createEsbuildConfig(entryCode, paths, bundleConfig, customRoutesDir, options) {
|
|
5260
|
+
const workspace = getWorkspace();
|
|
5261
|
+
const { isBuiltPackage, edgePlaySrc, constantsEntry, workspaceNodeModules, cliNodeModules } = paths;
|
|
5262
|
+
return {
|
|
5263
|
+
// ──── Input Configuration ────
|
|
5267
5264
|
stdin: {
|
|
5268
5265
|
contents: entryCode,
|
|
5266
|
+
// Generated entry code with custom route imports
|
|
5269
5267
|
resolveDir: edgePlaySrc,
|
|
5270
|
-
//
|
|
5268
|
+
// Resolve relative imports from edge-play/src
|
|
5271
5269
|
loader: "ts"
|
|
5270
|
+
// Treat input as TypeScript
|
|
5272
5271
|
},
|
|
5272
|
+
// ──── Output Configuration ────
|
|
5273
5273
|
bundle: true,
|
|
5274
|
+
// Bundle all dependencies into single file
|
|
5274
5275
|
format: "esm",
|
|
5276
|
+
// Output ES modules (required for Cloudflare Workers)
|
|
5275
5277
|
platform: "browser",
|
|
5278
|
+
// Workers use browser APIs, not Node.js
|
|
5276
5279
|
target: "es2022",
|
|
5280
|
+
// Modern JavaScript for Workers runtime
|
|
5277
5281
|
write: false,
|
|
5282
|
+
// Return code as string (don't write to disk)
|
|
5278
5283
|
sourcemap: options.sourcemap ? "inline" : false,
|
|
5279
5284
|
minify: options.minify || false,
|
|
5280
5285
|
logLevel: "error",
|
|
5281
|
-
|
|
5282
|
-
//
|
|
5283
|
-
|
|
5284
|
-
|
|
5285
|
-
|
|
5286
|
+
// Only show errors (suppress warnings)
|
|
5287
|
+
// ──── Module Resolution ────
|
|
5288
|
+
// Tell esbuild where to find node_modules for bare imports
|
|
5289
|
+
// In dev: Need both workspace and monorepo root (hoisted deps)
|
|
5290
|
+
// In published: Both point to same location (/user-project/node_modules)
|
|
5291
|
+
nodePaths: isBuiltPackage ? [workspaceNodeModules] : [workspaceNodeModules, cliNodeModules],
|
|
5292
|
+
// ──── Build-time Constants ────
|
|
5293
|
+
// Inject the Playcademy config as a global constant
|
|
5294
|
+
// Code can access it via: const config = PLAYCADEMY_CONFIG
|
|
5286
5295
|
define: {
|
|
5287
5296
|
PLAYCADEMY_CONFIG: JSON.stringify(bundleConfig)
|
|
5288
5297
|
},
|
|
5298
|
+
// ──── Import Aliases ────
|
|
5289
5299
|
alias: {
|
|
5290
|
-
//
|
|
5300
|
+
// ┌─ Workspace-only package resolution ─────────────────────────────┐
|
|
5301
|
+
// │ @playcademy/constants is a workspace package that users don't │
|
|
5302
|
+
// │ install. We embed it in dist/ and alias imports to point there. │
|
|
5303
|
+
// └─────────────────────────────────────────────────────────────────┘
|
|
5291
5304
|
"@playcademy/constants": constantsEntry,
|
|
5292
|
-
|
|
5293
|
-
|
|
5294
|
-
|
|
5295
|
-
|
|
5296
|
-
|
|
5297
|
-
*
|
|
5298
|
-
* The alias resolves to the absolute path of the custom routes directory in the
|
|
5299
|
-
* user's game project (configured via integrations.customRoutes.directory), enabling esbuild
|
|
5300
|
-
* to bundle custom routes into the worker.
|
|
5301
|
-
*/
|
|
5305
|
+
// ┌─ User's custom routes ──────────────────────────────────────────┐
|
|
5306
|
+
// │ @game-api is a virtual module that maps to the user's API dir. │
|
|
5307
|
+
// │ Example: import * as route from '@game-api/hello.ts' │
|
|
5308
|
+
// │ Resolves to: /user-project/server/api/hello.ts │
|
|
5309
|
+
// └─────────────────────────────────────────────────────────────────┘
|
|
5302
5310
|
"@game-api": join6(workspace, customRoutesDir),
|
|
5303
|
-
|
|
5304
|
-
|
|
5305
|
-
|
|
5306
|
-
|
|
5307
|
-
* These aliases redirect Node.js imports to a polyfill that throws helpful errors.
|
|
5308
|
-
*
|
|
5309
|
-
* This prevents bundling errors and provides clear runtime messages if
|
|
5310
|
-
* user code accidentally imports Node.js modules that won't work in Workers.
|
|
5311
|
-
*/
|
|
5311
|
+
// ┌─ Node.js polyfills for Cloudflare Workers ──────────────────────┐
|
|
5312
|
+
// │ Workers don't have fs, path, os, etc. Redirect to polyfills │
|
|
5313
|
+
// │ that throw helpful errors if user code tries to use them. │
|
|
5314
|
+
// └─────────────────────────────────────────────────────────────────┘
|
|
5312
5315
|
fs: join6(edgePlaySrc, "polyfills.js"),
|
|
5313
5316
|
"fs/promises": join6(edgePlaySrc, "polyfills.js"),
|
|
5314
5317
|
path: join6(edgePlaySrc, "polyfills.js"),
|
|
5315
5318
|
os: join6(edgePlaySrc, "polyfills.js"),
|
|
5316
5319
|
process: join6(edgePlaySrc, "polyfills.js")
|
|
5317
5320
|
},
|
|
5321
|
+
// ──── Build Plugins ────
|
|
5318
5322
|
plugins: [textLoaderPlugin()],
|
|
5323
|
+
// Support Bun's 'with { type: "text" }' imports
|
|
5324
|
+
// ──── External Dependencies ────
|
|
5319
5325
|
external: []
|
|
5320
|
-
|
|
5326
|
+
// Bundle everything (no externals for Workers)
|
|
5327
|
+
};
|
|
5328
|
+
}
|
|
5329
|
+
async function bundleBackend(config, options = {}) {
|
|
5330
|
+
const esbuild = await import("esbuild");
|
|
5331
|
+
const { customRouteData, customRoutesDir } = await discoverCustomRoutes(config);
|
|
5332
|
+
const bundleConfig = {
|
|
5333
|
+
...config,
|
|
5334
|
+
customRoutes: customRouteData
|
|
5335
|
+
};
|
|
5336
|
+
const entryCode = generateEntryCode(customRouteData, customRoutesDir);
|
|
5337
|
+
const paths = resolveEmbeddedSourcePaths();
|
|
5338
|
+
const buildConfig = createEsbuildConfig(
|
|
5339
|
+
entryCode,
|
|
5340
|
+
paths,
|
|
5341
|
+
bundleConfig,
|
|
5342
|
+
customRoutesDir,
|
|
5343
|
+
options
|
|
5344
|
+
);
|
|
5345
|
+
const result = await esbuild.build(buildConfig);
|
|
5321
5346
|
if (!result.outputFiles?.[0]) {
|
|
5322
5347
|
throw new Error("Backend bundling failed: no output");
|
|
5323
5348
|
}
|
|
@@ -5616,7 +5641,8 @@ async function getSchemaInfo(previousSchemaSnapshot) {
|
|
|
5616
5641
|
return null;
|
|
5617
5642
|
}
|
|
5618
5643
|
try {
|
|
5619
|
-
const
|
|
5644
|
+
const drizzleKitApi = await import("drizzle-kit/api");
|
|
5645
|
+
const { generateSQLiteDrizzleJson, generateSQLiteMigration } = drizzleKitApi;
|
|
5620
5646
|
const schemaModule = await import(schemaPath);
|
|
5621
5647
|
const currentSchema = schemaModule.default || schemaModule;
|
|
5622
5648
|
const nextJson = await generateSQLiteDrizzleJson(currentSchema);
|
package/dist/utils.js
CHANGED
|
@@ -1162,9 +1162,8 @@ async function transpileRoute(filePath) {
|
|
|
1162
1162
|
}
|
|
1163
1163
|
|
|
1164
1164
|
// src/lib/deploy/bundle.ts
|
|
1165
|
-
var entryTemplate = entry_default;
|
|
1166
|
-
async function
|
|
1167
|
-
const esbuild = await import("esbuild");
|
|
1165
|
+
var entryTemplate = entry_default.toString();
|
|
1166
|
+
async function discoverCustomRoutes(config) {
|
|
1168
1167
|
const workspace = getWorkspace();
|
|
1169
1168
|
const customRoutesConfig = config.integrations?.customRoutes;
|
|
1170
1169
|
const customRoutesDir = typeof customRoutesConfig === "object" && customRoutesConfig.directory || DEFAULT_API_ROUTES_DIRECTORY;
|
|
@@ -1175,89 +1174,115 @@ async function bundleBackend(config, options = {}) {
|
|
|
1175
1174
|
// Use relative path (e.g., 'server/api/test.ts'), not absolute
|
|
1176
1175
|
methods: r.methods
|
|
1177
1176
|
}));
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
const entryCode = generateEntryCode(customRouteData, customRoutesDir);
|
|
1177
|
+
return { customRouteData, customRoutesDir };
|
|
1178
|
+
}
|
|
1179
|
+
function resolveEmbeddedSourcePaths() {
|
|
1180
|
+
const workspace = getWorkspace();
|
|
1183
1181
|
const distDir = new URL(".", import.meta.url).pathname;
|
|
1184
1182
|
const embeddedEdgeSrc = join2(distDir, "edge-play", "src");
|
|
1183
|
+
const isBuiltPackage = existsSync2(embeddedEdgeSrc);
|
|
1185
1184
|
const monorepoRoot = getMonorepoRoot();
|
|
1186
1185
|
const monorepoEdgeSrc = join2(monorepoRoot, "packages/edge-play/src");
|
|
1187
|
-
const isBuiltPackage = existsSync2(embeddedEdgeSrc);
|
|
1188
1186
|
const edgePlaySrc = isBuiltPackage ? embeddedEdgeSrc : monorepoEdgeSrc;
|
|
1189
1187
|
const cliPackageRoot = isBuiltPackage ? join2(distDir, "../../..") : join2(monorepoRoot, "packages/cli");
|
|
1190
1188
|
const cliNodeModules = isBuiltPackage ? join2(cliPackageRoot, "node_modules") : monorepoRoot;
|
|
1191
1189
|
const workspaceNodeModules = join2(workspace, "node_modules");
|
|
1192
|
-
const constantsEntry = isBuiltPackage ? (
|
|
1193
|
-
|
|
1194
|
-
join2(embeddedEdgeSrc, "..", "..", "vendor", "constants", "index.ts")
|
|
1195
|
-
) : join2(monorepoRoot, "packages", "constants", "src", "index.ts");
|
|
1196
|
-
console.log({
|
|
1190
|
+
const constantsEntry = isBuiltPackage ? join2(embeddedEdgeSrc, "..", "..", "constants", "src", "index.ts") : join2(monorepoRoot, "packages", "constants", "src", "index.ts");
|
|
1191
|
+
return {
|
|
1197
1192
|
isBuiltPackage,
|
|
1198
|
-
distDir,
|
|
1199
|
-
constantsEntry,
|
|
1200
|
-
embeddedEdgeSrc,
|
|
1201
1193
|
edgePlaySrc,
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
}
|
|
1206
|
-
|
|
1194
|
+
constantsEntry,
|
|
1195
|
+
workspaceNodeModules,
|
|
1196
|
+
cliNodeModules
|
|
1197
|
+
};
|
|
1198
|
+
}
|
|
1199
|
+
function createEsbuildConfig(entryCode, paths, bundleConfig, customRoutesDir, options) {
|
|
1200
|
+
const workspace = getWorkspace();
|
|
1201
|
+
const { isBuiltPackage, edgePlaySrc, constantsEntry, workspaceNodeModules, cliNodeModules } = paths;
|
|
1202
|
+
return {
|
|
1203
|
+
// ──── Input Configuration ────
|
|
1207
1204
|
stdin: {
|
|
1208
1205
|
contents: entryCode,
|
|
1206
|
+
// Generated entry code with custom route imports
|
|
1209
1207
|
resolveDir: edgePlaySrc,
|
|
1210
|
-
//
|
|
1208
|
+
// Resolve relative imports from edge-play/src
|
|
1211
1209
|
loader: "ts"
|
|
1210
|
+
// Treat input as TypeScript
|
|
1212
1211
|
},
|
|
1212
|
+
// ──── Output Configuration ────
|
|
1213
1213
|
bundle: true,
|
|
1214
|
+
// Bundle all dependencies into single file
|
|
1214
1215
|
format: "esm",
|
|
1216
|
+
// Output ES modules (required for Cloudflare Workers)
|
|
1215
1217
|
platform: "browser",
|
|
1218
|
+
// Workers use browser APIs, not Node.js
|
|
1216
1219
|
target: "es2022",
|
|
1220
|
+
// Modern JavaScript for Workers runtime
|
|
1217
1221
|
write: false,
|
|
1222
|
+
// Return code as string (don't write to disk)
|
|
1218
1223
|
sourcemap: options.sourcemap ? "inline" : false,
|
|
1219
1224
|
minify: options.minify || false,
|
|
1220
1225
|
logLevel: "error",
|
|
1221
|
-
|
|
1222
|
-
//
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
+
// Only show errors (suppress warnings)
|
|
1227
|
+
// ──── Module Resolution ────
|
|
1228
|
+
// Tell esbuild where to find node_modules for bare imports
|
|
1229
|
+
// In dev: Need both workspace and monorepo root (hoisted deps)
|
|
1230
|
+
// In published: Both point to same location (/user-project/node_modules)
|
|
1231
|
+
nodePaths: isBuiltPackage ? [workspaceNodeModules] : [workspaceNodeModules, cliNodeModules],
|
|
1232
|
+
// ──── Build-time Constants ────
|
|
1233
|
+
// Inject the Playcademy config as a global constant
|
|
1234
|
+
// Code can access it via: const config = PLAYCADEMY_CONFIG
|
|
1226
1235
|
define: {
|
|
1227
1236
|
PLAYCADEMY_CONFIG: JSON.stringify(bundleConfig)
|
|
1228
1237
|
},
|
|
1238
|
+
// ──── Import Aliases ────
|
|
1229
1239
|
alias: {
|
|
1230
|
-
//
|
|
1240
|
+
// ┌─ Workspace-only package resolution ─────────────────────────────┐
|
|
1241
|
+
// │ @playcademy/constants is a workspace package that users don't │
|
|
1242
|
+
// │ install. We embed it in dist/ and alias imports to point there. │
|
|
1243
|
+
// └─────────────────────────────────────────────────────────────────┘
|
|
1231
1244
|
"@playcademy/constants": constantsEntry,
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
*
|
|
1238
|
-
* The alias resolves to the absolute path of the custom routes directory in the
|
|
1239
|
-
* user's game project (configured via integrations.customRoutes.directory), enabling esbuild
|
|
1240
|
-
* to bundle custom routes into the worker.
|
|
1241
|
-
*/
|
|
1245
|
+
// ┌─ User's custom routes ──────────────────────────────────────────┐
|
|
1246
|
+
// │ @game-api is a virtual module that maps to the user's API dir. │
|
|
1247
|
+
// │ Example: import * as route from '@game-api/hello.ts' │
|
|
1248
|
+
// │ Resolves to: /user-project/server/api/hello.ts │
|
|
1249
|
+
// └─────────────────────────────────────────────────────────────────┘
|
|
1242
1250
|
"@game-api": join2(workspace, customRoutesDir),
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
* These aliases redirect Node.js imports to a polyfill that throws helpful errors.
|
|
1248
|
-
*
|
|
1249
|
-
* This prevents bundling errors and provides clear runtime messages if
|
|
1250
|
-
* user code accidentally imports Node.js modules that won't work in Workers.
|
|
1251
|
-
*/
|
|
1251
|
+
// ┌─ Node.js polyfills for Cloudflare Workers ──────────────────────┐
|
|
1252
|
+
// │ Workers don't have fs, path, os, etc. Redirect to polyfills │
|
|
1253
|
+
// │ that throw helpful errors if user code tries to use them. │
|
|
1254
|
+
// └─────────────────────────────────────────────────────────────────┘
|
|
1252
1255
|
fs: join2(edgePlaySrc, "polyfills.js"),
|
|
1253
1256
|
"fs/promises": join2(edgePlaySrc, "polyfills.js"),
|
|
1254
1257
|
path: join2(edgePlaySrc, "polyfills.js"),
|
|
1255
1258
|
os: join2(edgePlaySrc, "polyfills.js"),
|
|
1256
1259
|
process: join2(edgePlaySrc, "polyfills.js")
|
|
1257
1260
|
},
|
|
1261
|
+
// ──── Build Plugins ────
|
|
1258
1262
|
plugins: [textLoaderPlugin()],
|
|
1263
|
+
// Support Bun's 'with { type: "text" }' imports
|
|
1264
|
+
// ──── External Dependencies ────
|
|
1259
1265
|
external: []
|
|
1260
|
-
|
|
1266
|
+
// Bundle everything (no externals for Workers)
|
|
1267
|
+
};
|
|
1268
|
+
}
|
|
1269
|
+
async function bundleBackend(config, options = {}) {
|
|
1270
|
+
const esbuild = await import("esbuild");
|
|
1271
|
+
const { customRouteData, customRoutesDir } = await discoverCustomRoutes(config);
|
|
1272
|
+
const bundleConfig = {
|
|
1273
|
+
...config,
|
|
1274
|
+
customRoutes: customRouteData
|
|
1275
|
+
};
|
|
1276
|
+
const entryCode = generateEntryCode(customRouteData, customRoutesDir);
|
|
1277
|
+
const paths = resolveEmbeddedSourcePaths();
|
|
1278
|
+
const buildConfig = createEsbuildConfig(
|
|
1279
|
+
entryCode,
|
|
1280
|
+
paths,
|
|
1281
|
+
bundleConfig,
|
|
1282
|
+
customRoutesDir,
|
|
1283
|
+
options
|
|
1284
|
+
);
|
|
1285
|
+
const result = await esbuild.build(buildConfig);
|
|
1261
1286
|
if (!result.outputFiles?.[0]) {
|
|
1262
1287
|
throw new Error("Backend bundling failed: no output");
|
|
1263
1288
|
}
|
package/package.json
CHANGED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|