playcademy 0.13.19 → 0.13.21
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/constants.d.ts +28 -1
- package/dist/constants.js +18 -0
- package/dist/db.js +9 -2
- package/dist/edge-play/src/entry/middleware.ts +74 -0
- package/dist/edge-play/src/entry/setup.ts +52 -0
- package/dist/edge-play/src/entry/types.ts +30 -0
- package/dist/edge-play/src/entry.ts +20 -71
- package/dist/edge-play/src/routes/health.ts +56 -27
- package/dist/edge-play/src/routes/index.ts +43 -15
- package/dist/edge-play/src/types.ts +8 -1
- package/dist/index.d.ts +51 -1
- package/dist/index.js +792 -241
- package/dist/templates/gitignore.template +3 -0
- package/dist/templates/playcademy-env.d.ts.template +1 -2
- package/dist/utils.d.ts +13 -13
- package/dist/utils.js +1074 -395
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -117,7 +117,8 @@ async function loadFile(filename, options = {}) {
|
|
|
117
117
|
required = false,
|
|
118
118
|
searchUp = false,
|
|
119
119
|
maxLevels = 3,
|
|
120
|
-
parseJson = false
|
|
120
|
+
parseJson = false,
|
|
121
|
+
stripComments = false
|
|
121
122
|
} = options;
|
|
122
123
|
let fileResult;
|
|
123
124
|
if (searchUp) {
|
|
@@ -146,8 +147,11 @@ async function loadFile(filename, options = {}) {
|
|
|
146
147
|
return null;
|
|
147
148
|
}
|
|
148
149
|
try {
|
|
149
|
-
|
|
150
|
+
let content = await readFile(fileResult.path, "utf-8");
|
|
150
151
|
if (parseJson) {
|
|
152
|
+
if (stripComments) {
|
|
153
|
+
content = stripJsonComments(content);
|
|
154
|
+
}
|
|
151
155
|
return JSON.parse(content);
|
|
152
156
|
}
|
|
153
157
|
return content;
|
|
@@ -212,6 +216,11 @@ function getCurrentDirectoryName(fallback = "unknown-directory") {
|
|
|
212
216
|
function getFileExtension(path2) {
|
|
213
217
|
return path2.split(".").pop()?.toLowerCase();
|
|
214
218
|
}
|
|
219
|
+
function stripJsonComments(jsonc) {
|
|
220
|
+
let result = jsonc.replace(/\/\*[\s\S]*?\*\//g, "");
|
|
221
|
+
result = result.replace(/\/\/.*/g, "");
|
|
222
|
+
return result;
|
|
223
|
+
}
|
|
215
224
|
async function loadModule(filename, options = {}) {
|
|
216
225
|
const { cwd = process.cwd(), required = false, searchUp = false, maxLevels = 3 } = options;
|
|
217
226
|
let fileResult;
|
|
@@ -2099,6 +2108,28 @@ var init_api = __esm({
|
|
|
2099
2108
|
}
|
|
2100
2109
|
});
|
|
2101
2110
|
|
|
2111
|
+
// src/constants/config.ts
|
|
2112
|
+
var ENV_FILES, TSCONFIG_FILES;
|
|
2113
|
+
var init_config = __esm({
|
|
2114
|
+
"src/constants/config.ts"() {
|
|
2115
|
+
"use strict";
|
|
2116
|
+
ENV_FILES = [
|
|
2117
|
+
".env",
|
|
2118
|
+
// Loaded first
|
|
2119
|
+
".env.development",
|
|
2120
|
+
// Overrides .env
|
|
2121
|
+
".env.local"
|
|
2122
|
+
// Overrides all (highest priority)
|
|
2123
|
+
];
|
|
2124
|
+
TSCONFIG_FILES = [
|
|
2125
|
+
"tsconfig.app.json",
|
|
2126
|
+
// Modern tooling (try first)
|
|
2127
|
+
"tsconfig.json"
|
|
2128
|
+
// Standard (fallback)
|
|
2129
|
+
];
|
|
2130
|
+
}
|
|
2131
|
+
});
|
|
2132
|
+
|
|
2102
2133
|
// src/constants/database.ts
|
|
2103
2134
|
var init_database = __esm({
|
|
2104
2135
|
"src/constants/database.ts"() {
|
|
@@ -2311,6 +2342,7 @@ var init_constants = __esm({
|
|
|
2311
2342
|
"src/constants/index.ts"() {
|
|
2312
2343
|
"use strict";
|
|
2313
2344
|
init_api();
|
|
2345
|
+
init_config();
|
|
2314
2346
|
init_database();
|
|
2315
2347
|
init_http_server();
|
|
2316
2348
|
init_paths();
|
|
@@ -2364,6 +2396,7 @@ var init_context = __esm({
|
|
|
2364
2396
|
// src/lib/core/logger.ts
|
|
2365
2397
|
import {
|
|
2366
2398
|
blue,
|
|
2399
|
+
blueBright,
|
|
2367
2400
|
bold as bold2,
|
|
2368
2401
|
cyan,
|
|
2369
2402
|
dim as dim2,
|
|
@@ -2376,8 +2409,10 @@ import {
|
|
|
2376
2409
|
} from "colorette";
|
|
2377
2410
|
import { colorize } from "json-colorizer";
|
|
2378
2411
|
function customTransform(text5) {
|
|
2379
|
-
|
|
2380
|
-
|
|
2412
|
+
let result = text5;
|
|
2413
|
+
result = result.replace(/`([^`]+)`/g, (_, code) => greenBright(code));
|
|
2414
|
+
result = result.replace(/<([^>]+)>/g, (_, path2) => blueBright(path2));
|
|
2415
|
+
return result;
|
|
2381
2416
|
}
|
|
2382
2417
|
function formatTable(data, title) {
|
|
2383
2418
|
if (data.length === 0) return;
|
|
@@ -2545,6 +2580,10 @@ var init_logger = __esm({
|
|
|
2545
2580
|
const spaces = " ".repeat(indent);
|
|
2546
2581
|
console.log(`${spaces}${text5}`);
|
|
2547
2582
|
},
|
|
2583
|
+
customRaw: (text5, indent = 0) => {
|
|
2584
|
+
const spaces = " ".repeat(indent);
|
|
2585
|
+
console.log(`${spaces}${customTransform(text5)}`);
|
|
2586
|
+
},
|
|
2548
2587
|
/**
|
|
2549
2588
|
* Display a configuration error with helpful suggestions
|
|
2550
2589
|
*/
|
|
@@ -2625,7 +2664,7 @@ function getProfileName() {
|
|
|
2625
2664
|
function getWebBaseUrl(apiBaseUrl) {
|
|
2626
2665
|
return apiBaseUrl.replace(/\/api\/?$/, "");
|
|
2627
2666
|
}
|
|
2628
|
-
var
|
|
2667
|
+
var init_config2 = __esm({
|
|
2629
2668
|
"src/lib/core/config.ts"() {
|
|
2630
2669
|
"use strict";
|
|
2631
2670
|
init_constants2();
|
|
@@ -2757,7 +2796,7 @@ var init_storage = __esm({
|
|
|
2757
2796
|
"src/lib/auth/storage.ts"() {
|
|
2758
2797
|
"use strict";
|
|
2759
2798
|
init_constants2();
|
|
2760
|
-
|
|
2799
|
+
init_config2();
|
|
2761
2800
|
}
|
|
2762
2801
|
});
|
|
2763
2802
|
|
|
@@ -3154,7 +3193,7 @@ var init_game = __esm({
|
|
|
3154
3193
|
"use strict";
|
|
3155
3194
|
init_src();
|
|
3156
3195
|
init_slug();
|
|
3157
|
-
|
|
3196
|
+
init_config3();
|
|
3158
3197
|
}
|
|
3159
3198
|
});
|
|
3160
3199
|
|
|
@@ -3573,7 +3612,7 @@ __export(config_exports, {
|
|
|
3573
3612
|
updateConfigFile: () => updateConfigFile,
|
|
3574
3613
|
validateConfig: () => validateConfig
|
|
3575
3614
|
});
|
|
3576
|
-
var
|
|
3615
|
+
var init_config3 = __esm({
|
|
3577
3616
|
"src/lib/config/index.ts"() {
|
|
3578
3617
|
"use strict";
|
|
3579
3618
|
init_loader();
|
|
@@ -3617,7 +3656,7 @@ var init_client = __esm({
|
|
|
3617
3656
|
"use strict";
|
|
3618
3657
|
init_storage();
|
|
3619
3658
|
init_logger();
|
|
3620
|
-
|
|
3659
|
+
init_config2();
|
|
3621
3660
|
}
|
|
3622
3661
|
});
|
|
3623
3662
|
|
|
@@ -3715,7 +3754,7 @@ var init_core = __esm({
|
|
|
3715
3754
|
"src/lib/core/index.ts"() {
|
|
3716
3755
|
"use strict";
|
|
3717
3756
|
init_client();
|
|
3718
|
-
|
|
3757
|
+
init_config2();
|
|
3719
3758
|
init_context();
|
|
3720
3759
|
init_errors();
|
|
3721
3760
|
init_game();
|
|
@@ -3751,7 +3790,7 @@ import { program } from "commander";
|
|
|
3751
3790
|
|
|
3752
3791
|
// src/commands/init/index.ts
|
|
3753
3792
|
import { execSync as execSync4 } from "child_process";
|
|
3754
|
-
import { readFileSync as
|
|
3793
|
+
import { readFileSync as readFileSync7, writeFileSync as writeFileSync9 } from "fs";
|
|
3755
3794
|
import { resolve as resolve10 } from "path";
|
|
3756
3795
|
|
|
3757
3796
|
// ../../node_modules/@inquirer/core/dist/esm/lib/errors.js
|
|
@@ -4548,7 +4587,7 @@ function getCallbackUrl() {
|
|
|
4548
4587
|
}
|
|
4549
4588
|
|
|
4550
4589
|
// src/lib/index.ts
|
|
4551
|
-
|
|
4590
|
+
init_config3();
|
|
4552
4591
|
init_core();
|
|
4553
4592
|
|
|
4554
4593
|
// src/lib/db/path.ts
|
|
@@ -4639,8 +4678,8 @@ function resetDatabase() {
|
|
|
4639
4678
|
init_src();
|
|
4640
4679
|
init_constants2();
|
|
4641
4680
|
init_core();
|
|
4642
|
-
import { existsSync as
|
|
4643
|
-
import { join as
|
|
4681
|
+
import { existsSync as existsSync13 } from "node:fs";
|
|
4682
|
+
import { join as join15 } from "node:path";
|
|
4644
4683
|
|
|
4645
4684
|
// src/lib/init/bucket.ts
|
|
4646
4685
|
function hasBucketSetup(config) {
|
|
@@ -4805,7 +4844,7 @@ var timebackChangeDetector = {
|
|
|
4805
4844
|
return;
|
|
4806
4845
|
}
|
|
4807
4846
|
const currentConfig = await client.timeback.management.getConfig(gameId);
|
|
4808
|
-
const { deriveTimebackConfig: deriveTimebackConfig2 } = await Promise.resolve().then(() => (
|
|
4847
|
+
const { deriveTimebackConfig: deriveTimebackConfig2 } = await Promise.resolve().then(() => (init_config3(), config_exports));
|
|
4809
4848
|
const newConfig = await deriveTimebackConfig2(config);
|
|
4810
4849
|
const changes = this.detectChanges(currentConfig, newConfig);
|
|
4811
4850
|
if (changes.length > 0) {
|
|
@@ -4877,7 +4916,7 @@ import { existsSync as existsSync7 } from "fs";
|
|
|
4877
4916
|
import { join as join8 } from "path";
|
|
4878
4917
|
|
|
4879
4918
|
// ../edge-play/src/entry.ts
|
|
4880
|
-
var entry_default = "/**\n * Game Backend Entry Point\n *\n * This file is the main entry point for deployed game backends.\n * It creates a Hono app and registers all enabled integration routes.\n *\n * Bundled with esbuild and deployed to Cloudflare Workers (or AWS Lambda).\n * Config is injected at build time via esbuild's `define` option.\n */\n\nimport { Hono } from 'hono'\nimport {
|
|
4919
|
+
var entry_default = "/**\n * Game Backend Entry Point\n *\n * This file is the main entry point for deployed game backends.\n * It creates a Hono app and registers all enabled integration routes.\n *\n * Bundled with esbuild and deployed to Cloudflare Workers (or AWS Lambda).\n * Config is injected at build time via esbuild's `define` option.\n */\n\nimport { Hono } from 'hono'\n\nimport { registerCors, registerEnvSetup, registerSdkInit } from './entry/middleware'\nimport { setupProcessGlobal } from './entry/setup'\nimport { registerBuiltinRoutes } from './register-routes'\n\nimport type { RuntimeConfig } from './entry/types'\nimport type { HonoEnv } from './types'\n\n/**\n * Config injected at build time by esbuild\n *\n * The `declare const` tells TypeScript \"this exists at runtime, trust me.\"\n * During bundling, esbuild's `define` option does literal text replacement:\n *\n * Example bundling:\n * Source: if (PLAYCADEMY_CONFIG.integrations.timeback) { ... }\n * Define: { 'PLAYCADEMY_CONFIG': JSON.stringify({ integrations: { timeback: {...} } }) }\n * Output: if ({\"integrations\":{\"timeback\":{...}}}.integrations.timeback) { ... }\n *\n * This enables tree-shaking: if timeback is not configured, those code paths are removed.\n * The bundled Worker only includes the routes that are actually enabled.\n */\ndeclare const PLAYCADEMY_CONFIG: RuntimeConfig\n\n// Setup process global polyfill for SDK compatibility\nsetupProcessGlobal()\n\n// Create Hono app\nconst app = new Hono<HonoEnv>()\n\n// Register middleware\nregisterCors(app)\nregisterEnvSetup(app, PLAYCADEMY_CONFIG)\nregisterSdkInit(app, PLAYCADEMY_CONFIG)\n\n// Register built-in integration routes based on enabled integrations\n// This function conditionally imports and registers routes like:\n// - GET /api (always included)\n// - GET /api/health (always included)\n// - POST /api/integrations/timeback/end-activity (if timeback enabled)\n//\n// Uses dynamic imports for tree-shaking: if an integration is not enabled,\n// its route code is completely removed from the bundle.\nawait registerBuiltinRoutes(app, PLAYCADEMY_CONFIG.integrations)\n\nexport default app\n";
|
|
4881
4920
|
|
|
4882
4921
|
// ../utils/src/path.ts
|
|
4883
4922
|
import fs from "node:fs";
|
|
@@ -5219,6 +5258,7 @@ function filePathToRoutePath(filePath) {
|
|
|
5219
5258
|
routePath = routePath.replace(/\/?index$/, "");
|
|
5220
5259
|
}
|
|
5221
5260
|
let urlPath = "/" + routePath.replace(/\\/g, "/");
|
|
5261
|
+
urlPath = urlPath.replace(/\[\.\.\.([^\]]+)\]/g, ":$1{.*}");
|
|
5222
5262
|
urlPath = urlPath.replace(/\[([^\]]+)\]/g, ":$1");
|
|
5223
5263
|
urlPath = urlPath === "/" ? "/api" : `/api${urlPath}`;
|
|
5224
5264
|
return urlPath;
|
|
@@ -5380,7 +5420,7 @@ async function bundleBackend(config, options = {}) {
|
|
|
5380
5420
|
const { customRouteData, customRoutesDir } = await discoverCustomRoutes(config);
|
|
5381
5421
|
const bundleConfig = {
|
|
5382
5422
|
...config,
|
|
5383
|
-
|
|
5423
|
+
__routeMetadata: customRouteData
|
|
5384
5424
|
};
|
|
5385
5425
|
const entryCode = generateEntryCode(customRouteData, customRoutesDir);
|
|
5386
5426
|
const paths = resolveEmbeddedSourcePaths();
|
|
@@ -5429,9 +5469,9 @@ function generateEntryCode(customRoutes, customRoutesDir) {
|
|
|
5429
5469
|
|
|
5430
5470
|
// src/lib/deploy/schema.ts
|
|
5431
5471
|
init_core();
|
|
5432
|
-
import { existsSync as
|
|
5472
|
+
import { existsSync as existsSync12 } from "fs";
|
|
5433
5473
|
import { createRequire } from "module";
|
|
5434
|
-
import { join as
|
|
5474
|
+
import { join as join14 } from "path";
|
|
5435
5475
|
|
|
5436
5476
|
// src/lib/init/prompts.ts
|
|
5437
5477
|
init_constants3();
|
|
@@ -5670,7 +5710,6 @@ async function selectConfigFormat(hasPackageJson2) {
|
|
|
5670
5710
|
init_package_manager();
|
|
5671
5711
|
init_context();
|
|
5672
5712
|
init_logger();
|
|
5673
|
-
import { blueBright } from "colorette";
|
|
5674
5713
|
function displayConfigSuccess(timebackConfig) {
|
|
5675
5714
|
logger.success("Playcademy configuration created successfully!");
|
|
5676
5715
|
logger.newLine();
|
|
@@ -5698,9 +5737,9 @@ function displaySuccessMessage(context2) {
|
|
|
5698
5737
|
logger.newLine();
|
|
5699
5738
|
const nextSteps = [];
|
|
5700
5739
|
const pm = getPackageManager();
|
|
5701
|
-
nextSteps.push(`1. Review your config file:
|
|
5740
|
+
nextSteps.push(`1. Review your config file: <${context2.configFileName}>`);
|
|
5702
5741
|
if (context2.hasDatabase) {
|
|
5703
|
-
nextSteps.push(`3. Review schema:
|
|
5742
|
+
nextSteps.push(`3. Review schema: <db/schema/index.ts>`);
|
|
5704
5743
|
nextSteps.push("4. Start dev server: `playcademy dev`");
|
|
5705
5744
|
nextSteps.push(`5. Push your schema: \`${getRunCommand(pm, "db:push")}\``);
|
|
5706
5745
|
}
|
|
@@ -5712,7 +5751,7 @@ function displaySuccessMessage(context2) {
|
|
|
5712
5751
|
}
|
|
5713
5752
|
if (context2.apiDirectory) {
|
|
5714
5753
|
const stepNum = context2.hasDatabase ? "7" : "3";
|
|
5715
|
-
nextSteps.push(`${stepNum}. Customize API routes:
|
|
5754
|
+
nextSteps.push(`${stepNum}. Customize API routes: <${context2.apiDirectory}>`);
|
|
5716
5755
|
}
|
|
5717
5756
|
if (context2.timebackConfig) {
|
|
5718
5757
|
const stepNum = nextSteps.length + 1;
|
|
@@ -5727,61 +5766,256 @@ function displaySuccessMessage(context2) {
|
|
|
5727
5766
|
// src/lib/init/types.ts
|
|
5728
5767
|
init_file_loader();
|
|
5729
5768
|
init_package_manager();
|
|
5769
|
+
init_string();
|
|
5730
5770
|
init_constants2();
|
|
5731
5771
|
init_loader();
|
|
5732
5772
|
init_core();
|
|
5733
|
-
init_loader2();
|
|
5734
5773
|
import { execSync as execSync3 } from "child_process";
|
|
5735
|
-
import { writeFileSync as
|
|
5736
|
-
import { dirname as dirname4, join as
|
|
5774
|
+
import { writeFileSync as writeFileSync5 } from "fs";
|
|
5775
|
+
import { dirname as dirname4, join as join12 } from "path";
|
|
5737
5776
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
5777
|
+
|
|
5778
|
+
// src/lib/secrets/env.ts
|
|
5779
|
+
init_file_loader();
|
|
5780
|
+
init_constants2();
|
|
5781
|
+
import { existsSync as existsSync9 } from "fs";
|
|
5782
|
+
import { join as join10 } from "path";
|
|
5783
|
+
function parseEnvFile(contents) {
|
|
5784
|
+
const secrets = {};
|
|
5785
|
+
for (const line of contents.split("\n")) {
|
|
5786
|
+
const trimmed = line.trim();
|
|
5787
|
+
if (!trimmed || trimmed.startsWith("#")) {
|
|
5788
|
+
continue;
|
|
5789
|
+
}
|
|
5790
|
+
const match = trimmed.match(/^([A-Z_][A-Z0-9_]*)=(.*)$/);
|
|
5791
|
+
if (match) {
|
|
5792
|
+
const [, key, value] = match;
|
|
5793
|
+
if (!key || !value) {
|
|
5794
|
+
continue;
|
|
5795
|
+
}
|
|
5796
|
+
const unquoted = value.replace(/^["']|["']$/g, "");
|
|
5797
|
+
secrets[key] = unquoted;
|
|
5798
|
+
}
|
|
5799
|
+
}
|
|
5800
|
+
return secrets;
|
|
5801
|
+
}
|
|
5802
|
+
async function readEnvFile(workspace) {
|
|
5803
|
+
let secrets = {};
|
|
5804
|
+
for (const filename of ENV_FILES) {
|
|
5805
|
+
try {
|
|
5806
|
+
const contents = await loadFile(filename, { cwd: workspace, searchUp: false });
|
|
5807
|
+
if (contents) {
|
|
5808
|
+
const fileSecrets = parseEnvFile(contents);
|
|
5809
|
+
secrets = { ...secrets, ...fileSecrets };
|
|
5810
|
+
}
|
|
5811
|
+
} catch {
|
|
5812
|
+
continue;
|
|
5813
|
+
}
|
|
5814
|
+
}
|
|
5815
|
+
return secrets;
|
|
5816
|
+
}
|
|
5817
|
+
function getLoadedEnvFiles(workspace) {
|
|
5818
|
+
return ENV_FILES.filter((filename) => existsSync9(join10(workspace, filename)));
|
|
5819
|
+
}
|
|
5820
|
+
function hasEnvFile(workspace) {
|
|
5821
|
+
return ENV_FILES.some((filename) => existsSync9(join10(workspace, filename)));
|
|
5822
|
+
}
|
|
5823
|
+
|
|
5824
|
+
// src/lib/init/types.ts
|
|
5825
|
+
init_loader2();
|
|
5826
|
+
|
|
5827
|
+
// src/lib/init/tsconfig.ts
|
|
5828
|
+
init_file_loader();
|
|
5829
|
+
init_constants2();
|
|
5830
|
+
import { existsSync as existsSync10, readFileSync as readFileSync4, writeFileSync as writeFileSync4 } from "fs";
|
|
5831
|
+
import { join as join11 } from "path";
|
|
5832
|
+
function hasPlaycademyEnv(config) {
|
|
5833
|
+
return config.include?.includes("playcademy-env.d.ts") ?? false;
|
|
5834
|
+
}
|
|
5835
|
+
function addPlaycademyEnv(config) {
|
|
5836
|
+
if (!config.include) {
|
|
5837
|
+
config.include = [];
|
|
5838
|
+
}
|
|
5839
|
+
config.include.push("playcademy-env.d.ts");
|
|
5840
|
+
}
|
|
5841
|
+
function updateExistingIncludeArray(content) {
|
|
5842
|
+
const includeRegex = /"include"\s*:\s*\[([^\]]*)\]/;
|
|
5843
|
+
const match = content.match(includeRegex);
|
|
5844
|
+
if (!match || !match[1]) {
|
|
5845
|
+
return null;
|
|
5846
|
+
}
|
|
5847
|
+
const fullMatch = match[0];
|
|
5848
|
+
const arrayContents = match[1];
|
|
5849
|
+
if (arrayContents.includes("playcademy-env.d.ts")) {
|
|
5850
|
+
return content;
|
|
5851
|
+
}
|
|
5852
|
+
const trimmedContents = arrayContents.trim();
|
|
5853
|
+
const newEntry = '"playcademy-env.d.ts"';
|
|
5854
|
+
let newArrayContents;
|
|
5855
|
+
if (trimmedContents === "") {
|
|
5856
|
+
newArrayContents = newEntry;
|
|
5857
|
+
} else if (arrayContents.includes("\n")) {
|
|
5858
|
+
newArrayContents = `${arrayContents},
|
|
5859
|
+
${newEntry}
|
|
5860
|
+
`;
|
|
5861
|
+
} else {
|
|
5862
|
+
newArrayContents = `${trimmedContents}, ${newEntry}`;
|
|
5863
|
+
}
|
|
5864
|
+
const newIncludeArray = `"include": [${newArrayContents}]`;
|
|
5865
|
+
return content.replace(fullMatch, newIncludeArray);
|
|
5866
|
+
}
|
|
5867
|
+
function addNewIncludeProperty(content) {
|
|
5868
|
+
const closingBraceMatch = content.match(/\n(\s*)\}(\s*)$/);
|
|
5869
|
+
if (!closingBraceMatch || closingBraceMatch.index === void 0) {
|
|
5870
|
+
return null;
|
|
5871
|
+
}
|
|
5872
|
+
const propertyMatch = content.match(/\n(\s+)"/);
|
|
5873
|
+
const propertyIndent = propertyMatch ? propertyMatch[1] : " ";
|
|
5874
|
+
const insertPosition = closingBraceMatch.index;
|
|
5875
|
+
const beforeClosing = content.slice(0, insertPosition).trim();
|
|
5876
|
+
const needsComma = beforeClosing.endsWith("]") || beforeClosing.endsWith("}") || beforeClosing.endsWith('"');
|
|
5877
|
+
const comma = needsComma ? "," : "";
|
|
5878
|
+
const includeEntry = `${comma}
|
|
5879
|
+
${propertyIndent}"include": ["playcademy-env.d.ts"]`;
|
|
5880
|
+
const updatedContent = content.slice(0, insertPosition) + includeEntry + content.slice(insertPosition);
|
|
5881
|
+
return updatedContent;
|
|
5882
|
+
}
|
|
5883
|
+
function addToIncludeArrayPreservingComments(content) {
|
|
5884
|
+
return updateExistingIncludeArray(content) || addNewIncludeProperty(content);
|
|
5885
|
+
}
|
|
5886
|
+
async function ensureTsconfigIncludes(workspace) {
|
|
5887
|
+
for (const filename of TSCONFIG_FILES) {
|
|
5888
|
+
const configPath = join11(workspace, filename);
|
|
5889
|
+
if (!existsSync10(configPath)) {
|
|
5890
|
+
continue;
|
|
5891
|
+
}
|
|
5892
|
+
try {
|
|
5893
|
+
const config = await loadFile(configPath, {
|
|
5894
|
+
parseJson: true,
|
|
5895
|
+
stripComments: true
|
|
5896
|
+
});
|
|
5897
|
+
if (!config) continue;
|
|
5898
|
+
if (config.references && filename !== "tsconfig.json") {
|
|
5899
|
+
continue;
|
|
5900
|
+
}
|
|
5901
|
+
if (hasPlaycademyEnv(config)) {
|
|
5902
|
+
return filename;
|
|
5903
|
+
}
|
|
5904
|
+
try {
|
|
5905
|
+
const rawContent = readFileSync4(configPath, "utf-8");
|
|
5906
|
+
const updatedContent = addToIncludeArrayPreservingComments(rawContent);
|
|
5907
|
+
if (updatedContent && updatedContent !== rawContent) {
|
|
5908
|
+
writeFileSync4(configPath, updatedContent);
|
|
5909
|
+
return filename;
|
|
5910
|
+
}
|
|
5911
|
+
} catch {
|
|
5912
|
+
}
|
|
5913
|
+
addPlaycademyEnv(config);
|
|
5914
|
+
writeFileSync4(configPath, JSON.stringify(config, null, 4) + "\n");
|
|
5915
|
+
return filename;
|
|
5916
|
+
} catch {
|
|
5917
|
+
continue;
|
|
5918
|
+
}
|
|
5919
|
+
}
|
|
5920
|
+
return null;
|
|
5921
|
+
}
|
|
5922
|
+
|
|
5923
|
+
// src/lib/init/types.ts
|
|
5738
5924
|
var playcademyEnvTemplate = loadTemplateString("playcademy-env.d.ts");
|
|
5739
|
-
|
|
5925
|
+
function detectBackendFeatures(workspace, config) {
|
|
5926
|
+
return {
|
|
5927
|
+
hasDB: hasDatabaseSetup(),
|
|
5928
|
+
hasKV: hasKVSetup(config),
|
|
5929
|
+
hasBucket: hasBucketSetup(config),
|
|
5930
|
+
hasRoutes: hasLocalCustomRoutes(workspace, config),
|
|
5931
|
+
hasSecrets: hasEnvFile(workspace)
|
|
5932
|
+
};
|
|
5933
|
+
}
|
|
5934
|
+
function hasAnyBackend(features) {
|
|
5935
|
+
return Object.values(features).some(Boolean);
|
|
5936
|
+
}
|
|
5937
|
+
async function setupPlaycademyDependencies(workspace) {
|
|
5938
|
+
const playcademyDir = join12(workspace, CLI_DIRECTORIES.WORKSPACE);
|
|
5939
|
+
const playcademyPkgPath = join12(playcademyDir, "package.json");
|
|
5940
|
+
const __dirname2 = dirname4(fileURLToPath2(import.meta.url));
|
|
5941
|
+
const cliPkg = await loadPackageJson({ cwd: __dirname2, searchUp: true, required: true });
|
|
5942
|
+
const workersTypesVersion = cliPkg?.devDependencies?.["@cloudflare/workers-types"] || "latest";
|
|
5943
|
+
const honoVersion = cliPkg?.dependencies?.hono || "latest";
|
|
5944
|
+
const playcademyPkg = {
|
|
5945
|
+
private: true,
|
|
5946
|
+
dependencies: { hono: honoVersion },
|
|
5947
|
+
devDependencies: { "@cloudflare/workers-types": workersTypesVersion }
|
|
5948
|
+
};
|
|
5949
|
+
writeFileSync5(playcademyPkgPath, JSON.stringify(playcademyPkg, null, 4) + "\n");
|
|
5950
|
+
const pm = detectPackageManager(workspace);
|
|
5951
|
+
const installCmd = getInstallCommand(pm);
|
|
5952
|
+
execSync3(installCmd, {
|
|
5953
|
+
cwd: playcademyDir,
|
|
5954
|
+
stdio: ["ignore", "ignore", "ignore"]
|
|
5955
|
+
});
|
|
5956
|
+
}
|
|
5957
|
+
function generateBindingsTypeString(features) {
|
|
5958
|
+
const bindings = [];
|
|
5959
|
+
if (features.hasKV) bindings.push(" KV: KVNamespace");
|
|
5960
|
+
if (features.hasDB) bindings.push(" DB: D1Database");
|
|
5961
|
+
if (features.hasBucket) bindings.push(" BUCKET: R2Bucket");
|
|
5962
|
+
return bindings.length > 0 ? "\n" + bindings.join("\n") : "";
|
|
5963
|
+
}
|
|
5964
|
+
async function generateSecretsTypeString(workspace, verbose = false) {
|
|
5965
|
+
try {
|
|
5966
|
+
const envSecrets = await readEnvFile(workspace);
|
|
5967
|
+
const secretKeys = Object.keys(envSecrets);
|
|
5968
|
+
if (secretKeys.length === 0) {
|
|
5969
|
+
if (verbose) logger.success("No secrets in <.env> files");
|
|
5970
|
+
return "\n secrets: Record<string, string>";
|
|
5971
|
+
}
|
|
5972
|
+
if (verbose) {
|
|
5973
|
+
const loadedFiles = getLoadedEnvFiles(workspace);
|
|
5974
|
+
const fileList = loadedFiles.map((f) => `<${f}>`).join(", ");
|
|
5975
|
+
logger.success(
|
|
5976
|
+
`Loaded ${secretKeys.length} ${pluralize(secretKeys.length, "secret")} from ${fileList}`
|
|
5977
|
+
);
|
|
5978
|
+
}
|
|
5979
|
+
const secretTypes = secretKeys.map((key) => ` ${key}: string`).join("\n");
|
|
5980
|
+
return `
|
|
5981
|
+
secrets: {
|
|
5982
|
+
${secretTypes}
|
|
5983
|
+
[key: string]: string
|
|
5984
|
+
}`;
|
|
5985
|
+
} catch {
|
|
5986
|
+
return "\n secrets: Record<string, string>";
|
|
5987
|
+
}
|
|
5988
|
+
}
|
|
5989
|
+
async function ensurePlaycademyTypes(options = {}) {
|
|
5990
|
+
const { verbose = false } = options;
|
|
5740
5991
|
try {
|
|
5741
5992
|
const workspace = getWorkspace();
|
|
5742
5993
|
const config = await loadConfig();
|
|
5743
|
-
const
|
|
5744
|
-
|
|
5745
|
-
|
|
5746
|
-
|
|
5994
|
+
const features = detectBackendFeatures(workspace, config);
|
|
5995
|
+
if (!hasAnyBackend(features)) {
|
|
5996
|
+
if (verbose) {
|
|
5997
|
+
logger.dim("No backend functionality detected");
|
|
5998
|
+
}
|
|
5747
5999
|
return;
|
|
5748
6000
|
}
|
|
5749
|
-
|
|
5750
|
-
|
|
5751
|
-
|
|
5752
|
-
const cliPkg = await loadPackageJson({ cwd: __dirname2, searchUp: true, required: true });
|
|
5753
|
-
const workersTypesVersion = cliPkg?.devDependencies?.["@cloudflare/workers-types"] || "latest";
|
|
5754
|
-
const honoVersion = cliPkg?.dependencies?.hono || "latest";
|
|
5755
|
-
const playcademyPkg = {
|
|
5756
|
-
private: true,
|
|
5757
|
-
dependencies: {
|
|
5758
|
-
hono: honoVersion
|
|
5759
|
-
},
|
|
5760
|
-
devDependencies: {
|
|
5761
|
-
"@cloudflare/workers-types": workersTypesVersion
|
|
5762
|
-
}
|
|
5763
|
-
};
|
|
5764
|
-
writeFileSync4(playcademyPkgPath, JSON.stringify(playcademyPkg, null, 4) + "\n");
|
|
5765
|
-
const pm = detectPackageManager(workspace);
|
|
5766
|
-
const installCmd = getInstallCommand(pm);
|
|
5767
|
-
execSync3(installCmd, {
|
|
5768
|
-
cwd: playcademyDir,
|
|
5769
|
-
stdio: ["ignore", "ignore", "ignore"]
|
|
5770
|
-
});
|
|
5771
|
-
const bindings = [];
|
|
5772
|
-
if (hasKV) {
|
|
5773
|
-
bindings.push(" KV: KVNamespace");
|
|
6001
|
+
await setupPlaycademyDependencies(workspace);
|
|
6002
|
+
if (verbose) {
|
|
6003
|
+
logger.success(`Installed packages in <${CLI_DIRECTORIES.WORKSPACE}>`);
|
|
5774
6004
|
}
|
|
5775
|
-
|
|
5776
|
-
|
|
6005
|
+
const bindingsStr = generateBindingsTypeString(features);
|
|
6006
|
+
const secretsStr = await generateSecretsTypeString(workspace, verbose);
|
|
6007
|
+
let envContent = playcademyEnvTemplate.replace("{{BINDINGS}}", bindingsStr);
|
|
6008
|
+
envContent = envContent.replace("{{SECRETS}}", secretsStr);
|
|
6009
|
+
const envPath = join12(workspace, "playcademy-env.d.ts");
|
|
6010
|
+
writeFileSync5(envPath, envContent);
|
|
6011
|
+
if (verbose) {
|
|
6012
|
+
logger.success(`Generated <playcademy-env.d.ts>`);
|
|
5777
6013
|
}
|
|
5778
|
-
|
|
5779
|
-
|
|
6014
|
+
const tsConfigFilename = await ensureTsconfigIncludes(workspace);
|
|
6015
|
+
if (verbose) {
|
|
6016
|
+
logger.success(`Updated <${tsConfigFilename}>`);
|
|
5780
6017
|
}
|
|
5781
|
-
|
|
5782
|
-
const envContent = playcademyEnvTemplate.replace("{{BINDINGS}}", bindingsStr);
|
|
5783
|
-
const envPath = join10(workspace, "playcademy-env.d.ts");
|
|
5784
|
-
writeFileSync4(envPath, envContent);
|
|
6018
|
+
logger.newLine();
|
|
5785
6019
|
} catch (error) {
|
|
5786
6020
|
logger.warn(
|
|
5787
6021
|
`Failed to generate TypeScript types: ${error instanceof Error ? error.message : String(error)}`
|
|
@@ -5792,19 +6026,19 @@ async function ensurePlaycademyTypes() {
|
|
|
5792
6026
|
// src/lib/init/gitignore.ts
|
|
5793
6027
|
init_core();
|
|
5794
6028
|
init_loader2();
|
|
5795
|
-
import { existsSync as
|
|
5796
|
-
import { join as
|
|
6029
|
+
import { existsSync as existsSync11, readFileSync as readFileSync5, writeFileSync as writeFileSync6 } from "fs";
|
|
6030
|
+
import { join as join13 } from "path";
|
|
5797
6031
|
var rootGitignoreTemplate = loadTemplateString("gitignore");
|
|
5798
6032
|
function normalizeGitignoreEntry(entry) {
|
|
5799
6033
|
return entry.replace(/^\/+/, "").replace(/\/+$/, "");
|
|
5800
6034
|
}
|
|
5801
6035
|
function ensureRootGitignore(workspace = getWorkspace()) {
|
|
5802
|
-
const gitignorePath =
|
|
5803
|
-
if (!
|
|
5804
|
-
|
|
6036
|
+
const gitignorePath = join13(workspace, ".gitignore");
|
|
6037
|
+
if (!existsSync11(gitignorePath)) {
|
|
6038
|
+
writeFileSync6(gitignorePath, rootGitignoreTemplate);
|
|
5805
6039
|
return;
|
|
5806
6040
|
}
|
|
5807
|
-
const existingContent =
|
|
6041
|
+
const existingContent = readFileSync5(gitignorePath, "utf-8");
|
|
5808
6042
|
const existingNormalized = new Set(
|
|
5809
6043
|
existingContent.split("\n").map((line) => line.trim()).filter((line) => line && !line.startsWith("#")).map(normalizeGitignoreEntry)
|
|
5810
6044
|
);
|
|
@@ -5821,7 +6055,7 @@ function ensureRootGitignore(workspace = getWorkspace()) {
|
|
|
5821
6055
|
const prefix = hasTrailingNewline ? "\n" : "\n\n";
|
|
5822
6056
|
const header = "# Generated by Playcademy\n";
|
|
5823
6057
|
const newEntries = entriesToAdd.join("\n");
|
|
5824
|
-
|
|
6058
|
+
writeFileSync6(gitignorePath, existingContent + prefix + header + newEntries + "\n");
|
|
5825
6059
|
}
|
|
5826
6060
|
|
|
5827
6061
|
// src/lib/deploy/schema.ts
|
|
@@ -5839,8 +6073,8 @@ async function getSchemaInfo(previousSchemaSnapshot) {
|
|
|
5839
6073
|
if (!hasDatabaseSetup()) {
|
|
5840
6074
|
return null;
|
|
5841
6075
|
}
|
|
5842
|
-
const schemaPath =
|
|
5843
|
-
if (!
|
|
6076
|
+
const schemaPath = join14(workspace, "db/schema/index.ts");
|
|
6077
|
+
if (!existsSync12(schemaPath)) {
|
|
5844
6078
|
return null;
|
|
5845
6079
|
}
|
|
5846
6080
|
try {
|
|
@@ -5874,6 +6108,42 @@ async function getSchemaStatementCount(previousSchemaSnapshot) {
|
|
|
5874
6108
|
return schemaInfo.sql.split(";").filter((stmt) => stmt.trim()).length;
|
|
5875
6109
|
}
|
|
5876
6110
|
|
|
6111
|
+
// src/lib/deploy/secrets.ts
|
|
6112
|
+
init_core();
|
|
6113
|
+
init_logger();
|
|
6114
|
+
function compareSecrets(current, previous) {
|
|
6115
|
+
const currentKeys = Object.keys(current);
|
|
6116
|
+
const changes = [];
|
|
6117
|
+
for (const key of currentKeys) {
|
|
6118
|
+
if (!previous.includes(key)) {
|
|
6119
|
+
changes.push({ key, type: "added" });
|
|
6120
|
+
}
|
|
6121
|
+
}
|
|
6122
|
+
for (const key of previous) {
|
|
6123
|
+
if (!currentKeys.includes(key)) {
|
|
6124
|
+
changes.push({ key, type: "removed" });
|
|
6125
|
+
}
|
|
6126
|
+
}
|
|
6127
|
+
return {
|
|
6128
|
+
hasChanges: changes.length > 0,
|
|
6129
|
+
changes
|
|
6130
|
+
};
|
|
6131
|
+
}
|
|
6132
|
+
async function fetchSecretsForDeployment(slug) {
|
|
6133
|
+
try {
|
|
6134
|
+
const client = await requireAuthenticatedClient();
|
|
6135
|
+
const secrets = await client.dev.games.secrets.get(slug);
|
|
6136
|
+
const keys = Object.keys(secrets);
|
|
6137
|
+
return { secrets, keys };
|
|
6138
|
+
} catch (error) {
|
|
6139
|
+
logger.warn(
|
|
6140
|
+
`Could not fetch secrets: ${error instanceof Error ? error.message : String(error)}`
|
|
6141
|
+
);
|
|
6142
|
+
logger.debug(`[Secrets] Error details: ${error}`);
|
|
6143
|
+
return { secrets: {}, keys: [] };
|
|
6144
|
+
}
|
|
6145
|
+
}
|
|
6146
|
+
|
|
5877
6147
|
// src/lib/deploy/utils.ts
|
|
5878
6148
|
init_src2();
|
|
5879
6149
|
function getDeploymentId(gameSlug) {
|
|
@@ -5887,11 +6157,11 @@ var CUSTOM_ROUTES_EXTENSIONS_WITH_DOT = [".ts", ".js", ".mjs", ".cjs"];
|
|
|
5887
6157
|
function getCustomRoutesDirectory(projectPath, config) {
|
|
5888
6158
|
const customRoutes = config?.integrations?.customRoutes;
|
|
5889
6159
|
const customRoutesDir = typeof customRoutes === "object" && customRoutes.directory || DEFAULT_API_ROUTES_DIRECTORY;
|
|
5890
|
-
return
|
|
6160
|
+
return join15(projectPath, customRoutesDir);
|
|
5891
6161
|
}
|
|
5892
6162
|
function hasLocalCustomRoutes(projectPath, config) {
|
|
5893
6163
|
const customRoutesDir = getCustomRoutesDirectory(projectPath, config);
|
|
5894
|
-
return
|
|
6164
|
+
return existsSync13(customRoutesDir);
|
|
5895
6165
|
}
|
|
5896
6166
|
async function getCustomRoutesHash(projectPath, config) {
|
|
5897
6167
|
const customRoutesDir = getCustomRoutesDirectory(projectPath, config);
|
|
@@ -5899,16 +6169,16 @@ async function getCustomRoutesHash(projectPath, config) {
|
|
|
5899
6169
|
}
|
|
5900
6170
|
async function getCustomRoutesSize(projectPath, config) {
|
|
5901
6171
|
const { stat: stat3, readdir } = await import("node:fs/promises");
|
|
5902
|
-
const { join:
|
|
6172
|
+
const { join: join37 } = await import("node:path");
|
|
5903
6173
|
const customRoutesDir = getCustomRoutesDirectory(projectPath, config);
|
|
5904
|
-
if (!
|
|
6174
|
+
if (!existsSync13(customRoutesDir)) {
|
|
5905
6175
|
return null;
|
|
5906
6176
|
}
|
|
5907
6177
|
let totalSize = 0;
|
|
5908
6178
|
async function calculateDirSize(dir) {
|
|
5909
6179
|
const entries = await readdir(dir, { withFileTypes: true });
|
|
5910
6180
|
for (const entry of entries) {
|
|
5911
|
-
const fullPath =
|
|
6181
|
+
const fullPath = join37(dir, entry.name);
|
|
5912
6182
|
if (entry.isDirectory()) {
|
|
5913
6183
|
await calculateDirSize(fullPath);
|
|
5914
6184
|
} else if (entry.isFile()) {
|
|
@@ -5958,7 +6228,7 @@ function getBackendBindings(config, slug) {
|
|
|
5958
6228
|
}
|
|
5959
6229
|
return Object.keys(bindings).length > 0 ? bindings : void 0;
|
|
5960
6230
|
}
|
|
5961
|
-
async function deployGameBackend(client, slug, config, projectPath, previousCustomRoutesHash, fullConfig, forceBackend, previousIntegrationKeys, previousSchemaSnapshot, debug) {
|
|
6231
|
+
async function deployGameBackend(client, slug, config, projectPath, previousCustomRoutesHash, fullConfig, forceBackend, previousIntegrationKeys, previousSchemaSnapshot, debug, previousDeployedSecrets) {
|
|
5962
6232
|
try {
|
|
5963
6233
|
if (fullConfig === void 0 || fullConfig === null) {
|
|
5964
6234
|
return null;
|
|
@@ -5967,11 +6237,29 @@ async function deployGameBackend(client, slug, config, projectPath, previousCust
|
|
|
5967
6237
|
const currentIntegrationKeys = getIntegrationKeys(fullConfig?.integrations);
|
|
5968
6238
|
const hasIntegrations = currentIntegrationKeys.length > 0;
|
|
5969
6239
|
const currentIntegrationsHash = hasIntegrations ? hashContent(fullConfig.integrations) : null;
|
|
5970
|
-
|
|
6240
|
+
const { secrets, keys: currentSecretKeys } = await fetchSecretsForDeployment(slug);
|
|
6241
|
+
const hasSecrets = currentSecretKeys.length > 0;
|
|
6242
|
+
if (!hasCustomRoutes2 && !hasIntegrations && !hasSecrets) {
|
|
5971
6243
|
return null;
|
|
5972
6244
|
}
|
|
5973
6245
|
const currentCustomRoutesHash = hasCustomRoutes2 ? await getCustomRoutesHash(projectPath, fullConfig) : null;
|
|
5974
6246
|
const currentCustomRoutesSize = hasCustomRoutes2 ? await getCustomRoutesSize(projectPath, fullConfig) : null;
|
|
6247
|
+
const secretsComparison = compareSecrets(secrets, previousDeployedSecrets || []);
|
|
6248
|
+
const secretsChanged = secretsComparison.hasChanges;
|
|
6249
|
+
if (debug) {
|
|
6250
|
+
logger.highlight("Debug: Secrets Info");
|
|
6251
|
+
logger.data("Current secret keys", currentSecretKeys.join(", ") || "none", 1);
|
|
6252
|
+
logger.data(
|
|
6253
|
+
"Previous secret keys",
|
|
6254
|
+
(previousDeployedSecrets || []).join(", ") || "none",
|
|
6255
|
+
1
|
|
6256
|
+
);
|
|
6257
|
+
logger.data("Secrets changed", String(secretsChanged), 1);
|
|
6258
|
+
if (secretsChanged) {
|
|
6259
|
+
logger.data("Changes", JSON.stringify(secretsComparison.changes), 1);
|
|
6260
|
+
}
|
|
6261
|
+
logger.newLine();
|
|
6262
|
+
}
|
|
5975
6263
|
const customRoutesChanged = currentCustomRoutesHash !== previousCustomRoutesHash;
|
|
5976
6264
|
const integrationsComparison = compareIntegrationKeys(
|
|
5977
6265
|
previousIntegrationKeys,
|
|
@@ -5979,7 +6267,7 @@ async function deployGameBackend(client, slug, config, projectPath, previousCust
|
|
|
5979
6267
|
);
|
|
5980
6268
|
const integrationsChanged = integrationsComparison.hasChanges;
|
|
5981
6269
|
const schemaChanged = await hasSchemaChanged(previousSchemaSnapshot);
|
|
5982
|
-
const nothingChanged = !customRoutesChanged && !integrationsChanged && !schemaChanged;
|
|
6270
|
+
const nothingChanged = !customRoutesChanged && !integrationsChanged && !schemaChanged && !secretsChanged;
|
|
5983
6271
|
if (!forceBackend && nothingChanged) {
|
|
5984
6272
|
return null;
|
|
5985
6273
|
}
|
|
@@ -6002,7 +6290,8 @@ async function deployGameBackend(client, slug, config, projectPath, previousCust
|
|
|
6002
6290
|
async () => client.dev.games.deploy.backend(slug, {
|
|
6003
6291
|
...bundle,
|
|
6004
6292
|
bindings,
|
|
6005
|
-
schema: schemaInfo || void 0
|
|
6293
|
+
schema: schemaInfo || void 0,
|
|
6294
|
+
secrets: Object.keys(secrets).length > 0 ? secrets : void 0
|
|
6006
6295
|
}),
|
|
6007
6296
|
"Backend deployed"
|
|
6008
6297
|
);
|
|
@@ -6013,7 +6302,8 @@ async function deployGameBackend(client, slug, config, projectPath, previousCust
|
|
|
6013
6302
|
integrationKeys: currentIntegrationKeys,
|
|
6014
6303
|
integrationsHash: currentIntegrationsHash,
|
|
6015
6304
|
backendSize: bundle.code.length,
|
|
6016
|
-
schemaSnapshot: schemaInfo?.hash ? JSON.parse(schemaInfo.hash) : void 0
|
|
6305
|
+
schemaSnapshot: schemaInfo?.hash ? JSON.parse(schemaInfo.hash) : void 0,
|
|
6306
|
+
deployedSecrets: currentSecretKeys
|
|
6017
6307
|
};
|
|
6018
6308
|
} catch (error) {
|
|
6019
6309
|
logger.error("Backend deployment failed");
|
|
@@ -6211,7 +6501,7 @@ function displayDeploymentDiff(options) {
|
|
|
6211
6501
|
}
|
|
6212
6502
|
if (backendChanged || customRoutesChanged || forceBackend || schemaStatementCount && schemaStatementCount > 0) {
|
|
6213
6503
|
logger.bold("Backend", 1);
|
|
6214
|
-
if (customRoutesChanged
|
|
6504
|
+
if (customRoutesChanged) {
|
|
6215
6505
|
const previousSize = backend?.previousCustomRoutesSize;
|
|
6216
6506
|
const currentSize = backend?.currentCustomRoutesSize;
|
|
6217
6507
|
let routesInfo;
|
|
@@ -6226,7 +6516,7 @@ function displayDeploymentDiff(options) {
|
|
|
6226
6516
|
} else {
|
|
6227
6517
|
routesInfo = green2("Updated");
|
|
6228
6518
|
}
|
|
6229
|
-
logger.data("Routes
|
|
6519
|
+
logger.data("Routes", routesInfo, 2);
|
|
6230
6520
|
}
|
|
6231
6521
|
if (backendChanged || forceBackend) {
|
|
6232
6522
|
const previousSize = backend?.previousBundleSize;
|
|
@@ -6245,7 +6535,7 @@ function displayDeploymentDiff(options) {
|
|
|
6245
6535
|
} else {
|
|
6246
6536
|
bundleInfo = green2("Updated");
|
|
6247
6537
|
}
|
|
6248
|
-
logger.data("Bundle
|
|
6538
|
+
logger.data("Bundle", bundleInfo, 2);
|
|
6249
6539
|
}
|
|
6250
6540
|
if (schemaStatementCount && schemaStatementCount > 0) {
|
|
6251
6541
|
const schemaInfo = green2(
|
|
@@ -6272,6 +6562,25 @@ function displayDeploymentDiff(options) {
|
|
|
6272
6562
|
logger.newLine();
|
|
6273
6563
|
}
|
|
6274
6564
|
}
|
|
6565
|
+
const previousSecretKeys = options.secrets?.previousKeys;
|
|
6566
|
+
const currentSecretKeys = options.secrets?.currentKeys;
|
|
6567
|
+
if (previousSecretKeys !== void 0 && currentSecretKeys !== void 0) {
|
|
6568
|
+
const added = currentSecretKeys.filter((k) => !previousSecretKeys.includes(k));
|
|
6569
|
+
const removed = previousSecretKeys.filter((k) => !currentSecretKeys.includes(k));
|
|
6570
|
+
const hasSecretsChanges = added.length > 0 || removed.length > 0;
|
|
6571
|
+
if (hasSecretsChanges) {
|
|
6572
|
+
logger.bold("Secrets", 1);
|
|
6573
|
+
if (added.length > 0) {
|
|
6574
|
+
const addedList = added.map((k) => green2(k)).join(", ");
|
|
6575
|
+
logger.data("Added", addedList, 2);
|
|
6576
|
+
}
|
|
6577
|
+
if (removed.length > 0) {
|
|
6578
|
+
const removedList = removed.map((k) => red2(k)).join(", ");
|
|
6579
|
+
logger.data("Removed", removedList, 2);
|
|
6580
|
+
}
|
|
6581
|
+
logger.newLine();
|
|
6582
|
+
}
|
|
6583
|
+
}
|
|
6275
6584
|
}
|
|
6276
6585
|
|
|
6277
6586
|
// src/lib/deploy/interaction.ts
|
|
@@ -6287,10 +6596,10 @@ import { dim as dim4 } from "colorette";
|
|
|
6287
6596
|
init_file_loader();
|
|
6288
6597
|
init_constants2();
|
|
6289
6598
|
init_core();
|
|
6290
|
-
import { join as
|
|
6599
|
+
import { join as join16, relative as relative2 } from "path";
|
|
6291
6600
|
function findSingleBuildZip() {
|
|
6292
6601
|
const workspace = getWorkspace();
|
|
6293
|
-
const playcademyDir =
|
|
6602
|
+
const playcademyDir = join16(workspace, CLI_DIRECTORIES.WORKSPACE);
|
|
6294
6603
|
const zipFiles = findFilesByExtension(playcademyDir, "zip");
|
|
6295
6604
|
if (zipFiles.length === 1) {
|
|
6296
6605
|
return zipFiles[0] ? relative2(workspace, zipFiles[0]) : null;
|
|
@@ -6326,14 +6635,14 @@ function hasOptionalFieldsMissing(missing) {
|
|
|
6326
6635
|
|
|
6327
6636
|
// src/lib/deploy/validate.ts
|
|
6328
6637
|
init_logger();
|
|
6329
|
-
import { existsSync as
|
|
6638
|
+
import { existsSync as existsSync14 } from "fs";
|
|
6330
6639
|
import { resolve as resolve7 } from "path";
|
|
6331
6640
|
function validateBuildPath(path2) {
|
|
6332
6641
|
if (!path2.trim()) {
|
|
6333
6642
|
return "Build path is required";
|
|
6334
6643
|
}
|
|
6335
6644
|
const resolvedPath = resolve7(path2.trim());
|
|
6336
|
-
if (!
|
|
6645
|
+
if (!existsSync14(resolvedPath)) {
|
|
6337
6646
|
return `Build path not found: ${path2.trim()}`;
|
|
6338
6647
|
}
|
|
6339
6648
|
return true;
|
|
@@ -6552,6 +6861,10 @@ async function confirmDeploymentPlan(plan, context2) {
|
|
|
6552
6861
|
integrations: {
|
|
6553
6862
|
previousKeys: context2.previousIntegrationKeys,
|
|
6554
6863
|
currentKeys: currentIntegrationKeys
|
|
6864
|
+
},
|
|
6865
|
+
secrets: {
|
|
6866
|
+
previousKeys: context2.deployedGameInfo?.deployedSecrets,
|
|
6867
|
+
currentKeys: context2.currentSecretKeys
|
|
6555
6868
|
}
|
|
6556
6869
|
});
|
|
6557
6870
|
const shouldDeploy = await confirm2({
|
|
@@ -6565,9 +6878,9 @@ async function confirmDeploymentPlan(plan, context2) {
|
|
|
6565
6878
|
|
|
6566
6879
|
// src/lib/deploy/output.ts
|
|
6567
6880
|
init_src2();
|
|
6568
|
-
|
|
6881
|
+
init_config2();
|
|
6569
6882
|
init_logger();
|
|
6570
|
-
import {
|
|
6883
|
+
import { underline } from "colorette";
|
|
6571
6884
|
function displayCurrentConfiguration(context2) {
|
|
6572
6885
|
const { config } = context2;
|
|
6573
6886
|
logger.newLine();
|
|
@@ -6627,12 +6940,12 @@ function reportDeploymentSuccess(result, context2) {
|
|
|
6627
6940
|
logger.success(`${game.displayName} ${action} successfully!`);
|
|
6628
6941
|
logger.newLine();
|
|
6629
6942
|
const baseUrl = getWebBaseUrl(client.getBaseUrl());
|
|
6630
|
-
logger.data("Game URL", underline(
|
|
6943
|
+
logger.data("Game URL", underline(`${baseUrl}/g/${game.slug}`), 1);
|
|
6631
6944
|
if (backendDeployment || previousCustomRoutesHash) {
|
|
6632
6945
|
const env = getEnvironment();
|
|
6633
6946
|
const subdomain = env === "staging" ? `${game.slug}-staging` : game.slug;
|
|
6634
6947
|
const backendUrl = `https://${subdomain}.${GAME_WORKER_DOMAINS.production}/api`;
|
|
6635
|
-
logger.data("Backend API", underline(
|
|
6948
|
+
logger.data("Backend API", underline(`${backendUrl}`), 1);
|
|
6636
6949
|
}
|
|
6637
6950
|
if (game.version !== "external") {
|
|
6638
6951
|
logger.data("Version", game.version || "latest", 1);
|
|
@@ -6701,6 +7014,10 @@ async function reportDryRun(plan, context2) {
|
|
|
6701
7014
|
integrations: {
|
|
6702
7015
|
previousKeys: context2.previousIntegrationKeys,
|
|
6703
7016
|
currentKeys: currentIntegrationKeys
|
|
7017
|
+
},
|
|
7018
|
+
secrets: {
|
|
7019
|
+
previousKeys: context2.deployedGameInfo?.deployedSecrets,
|
|
7020
|
+
currentKeys: context2.currentSecretKeys
|
|
6704
7021
|
}
|
|
6705
7022
|
});
|
|
6706
7023
|
} else {
|
|
@@ -7126,28 +7443,28 @@ var INTERACTION_TYPE = Object.fromEntries(
|
|
|
7126
7443
|
|
|
7127
7444
|
// src/lib/deploy/preparation.ts
|
|
7128
7445
|
init_src();
|
|
7129
|
-
|
|
7446
|
+
init_config3();
|
|
7130
7447
|
init_client();
|
|
7131
7448
|
init_context();
|
|
7132
7449
|
|
|
7133
7450
|
// src/lib/games/storage.ts
|
|
7134
7451
|
init_constants2();
|
|
7135
|
-
import { existsSync as
|
|
7452
|
+
import { existsSync as existsSync15 } from "node:fs";
|
|
7136
7453
|
import { mkdir as mkdir3, readFile as readFile3, writeFile as writeFile3 } from "node:fs/promises";
|
|
7137
7454
|
import { homedir as homedir2 } from "node:os";
|
|
7138
|
-
import { join as
|
|
7455
|
+
import { join as join17 } from "node:path";
|
|
7139
7456
|
function getGamesStorePath() {
|
|
7140
|
-
return
|
|
7457
|
+
return join17(homedir2(), CLI_USER_DIRECTORIES.CONFIG, CLI_FILES.GAMES_STORE);
|
|
7141
7458
|
}
|
|
7142
7459
|
async function ensureConfigDir() {
|
|
7143
|
-
const configDir =
|
|
7460
|
+
const configDir = join17(homedir2(), CLI_USER_DIRECTORIES.CONFIG);
|
|
7144
7461
|
await mkdir3(configDir, { recursive: true });
|
|
7145
7462
|
}
|
|
7146
7463
|
async function loadGameStore() {
|
|
7147
7464
|
try {
|
|
7148
7465
|
await ensureConfigDir();
|
|
7149
7466
|
const storePath = getGamesStorePath();
|
|
7150
|
-
if (
|
|
7467
|
+
if (existsSync15(storePath)) {
|
|
7151
7468
|
const content = await readFile3(storePath, "utf-8");
|
|
7152
7469
|
return JSON.parse(content);
|
|
7153
7470
|
}
|
|
@@ -7231,6 +7548,11 @@ async function prepareDeploymentContext(options) {
|
|
|
7231
7548
|
buildHash = await hashFile(finalConfig.buildPath);
|
|
7232
7549
|
}
|
|
7233
7550
|
}
|
|
7551
|
+
let currentSecretKeys;
|
|
7552
|
+
if (finalConfig.slug && gameIsDeployed) {
|
|
7553
|
+
const { keys } = await fetchSecretsForDeployment(finalConfig.slug);
|
|
7554
|
+
currentSecretKeys = keys;
|
|
7555
|
+
}
|
|
7234
7556
|
return {
|
|
7235
7557
|
config: finalConfig,
|
|
7236
7558
|
fullConfig,
|
|
@@ -7249,6 +7571,7 @@ async function prepareDeploymentContext(options) {
|
|
|
7249
7571
|
previousBackendSize: deployedGameInfo?.backendSize,
|
|
7250
7572
|
previousIntegrationKeys: deployedGameInfo?.integrationKeys,
|
|
7251
7573
|
previousIntegrationsHash: deployedGameInfo?.integrationsHash,
|
|
7574
|
+
currentSecretKeys,
|
|
7252
7575
|
isDryRun: options.dryRun ?? false,
|
|
7253
7576
|
deployBackend: options.backend !== false,
|
|
7254
7577
|
forceBackend: options.forceBackend ?? false,
|
|
@@ -7284,11 +7607,24 @@ async function analyzeChanges(context2) {
|
|
|
7284
7607
|
let backendChanged;
|
|
7285
7608
|
let customRoutesChanged = false;
|
|
7286
7609
|
let schemaChanged = false;
|
|
7610
|
+
let secretsChanged = false;
|
|
7611
|
+
let hasSecrets = false;
|
|
7287
7612
|
if (!deployBackend) {
|
|
7288
7613
|
backendChanged = void 0;
|
|
7289
7614
|
} else {
|
|
7290
7615
|
const hasCustomRoutes2 = hasLocalCustomRoutes(projectPath, context2.fullConfig);
|
|
7291
7616
|
const hasIntegrations = !!context2.fullConfig?.integrations;
|
|
7617
|
+
if (context2.currentSecretKeys) {
|
|
7618
|
+
const currentSecretKeys = context2.currentSecretKeys;
|
|
7619
|
+
const previousSecretKeys = context2.deployedGameInfo?.deployedSecrets || [];
|
|
7620
|
+
hasSecrets = currentSecretKeys.length > 0;
|
|
7621
|
+
const secretsComparison = compareSecrets(
|
|
7622
|
+
Object.fromEntries(currentSecretKeys.map((k) => [k, ""])),
|
|
7623
|
+
// We only care about keys for change detection
|
|
7624
|
+
previousSecretKeys
|
|
7625
|
+
);
|
|
7626
|
+
secretsChanged = secretsComparison.hasChanges;
|
|
7627
|
+
}
|
|
7292
7628
|
if (hasCustomRoutes2) {
|
|
7293
7629
|
if (!context2.previousCustomRoutesHash) {
|
|
7294
7630
|
customRoutesChanged = true;
|
|
@@ -7313,10 +7649,10 @@ async function analyzeChanges(context2) {
|
|
|
7313
7649
|
if (context2.fullConfig) {
|
|
7314
7650
|
schemaChanged = await hasSchemaChanged(context2.deployedGameInfo?.schemaSnapshot);
|
|
7315
7651
|
}
|
|
7316
|
-
if (!hasCustomRoutes2 && !hasIntegrations) {
|
|
7652
|
+
if (!hasCustomRoutes2 && !hasIntegrations && !hasSecrets) {
|
|
7317
7653
|
backendChanged = void 0;
|
|
7318
7654
|
} else {
|
|
7319
|
-
backendChanged = customRoutesChanged || integrationKeysChanged || schemaChanged;
|
|
7655
|
+
backendChanged = customRoutesChanged || integrationKeysChanged || schemaChanged || secretsChanged;
|
|
7320
7656
|
}
|
|
7321
7657
|
}
|
|
7322
7658
|
let integrationsMetadataChanged;
|
|
@@ -7336,7 +7672,8 @@ async function analyzeChanges(context2) {
|
|
|
7336
7672
|
backend: backendChanged,
|
|
7337
7673
|
customRoutes: customRoutesChanged,
|
|
7338
7674
|
integrations: integrationsMetadataChanged,
|
|
7339
|
-
schema: schemaChanged
|
|
7675
|
+
schema: schemaChanged,
|
|
7676
|
+
secrets: secretsChanged
|
|
7340
7677
|
};
|
|
7341
7678
|
}
|
|
7342
7679
|
async function calculateDeploymentPlan(context2, changes) {
|
|
@@ -7379,7 +7716,8 @@ async function calculateDeploymentPlan(context2, changes) {
|
|
|
7379
7716
|
}
|
|
7380
7717
|
}
|
|
7381
7718
|
const shouldDeployFrontend = changes.build !== false || changes.config;
|
|
7382
|
-
const
|
|
7719
|
+
const hasSecretsForUpdate = (context2.currentSecretKeys?.length ?? 0) > 0;
|
|
7720
|
+
const needsBackend2 = hasLocalCustomRoutes(projectPath, context2.fullConfig) || !!context2.fullConfig?.integrations || hasSecretsForUpdate;
|
|
7383
7721
|
const shouldDeployBackend = deployBackend && (backendHasChanges || forceBackend || needsBackend2);
|
|
7384
7722
|
return {
|
|
7385
7723
|
action: "update-existing",
|
|
@@ -7395,7 +7733,7 @@ async function calculateDeploymentPlan(context2, changes) {
|
|
|
7395
7733
|
// src/lib/deploy/steps.ts
|
|
7396
7734
|
init_src();
|
|
7397
7735
|
init_logger();
|
|
7398
|
-
import { existsSync as
|
|
7736
|
+
import { existsSync as existsSync16 } from "fs";
|
|
7399
7737
|
import { readFile as readFile4 } from "fs/promises";
|
|
7400
7738
|
import { basename as basename2, resolve as resolve8 } from "path";
|
|
7401
7739
|
function prepareGameMetadata(config) {
|
|
@@ -7415,7 +7753,7 @@ function prepareGameMetadata(config) {
|
|
|
7415
7753
|
}
|
|
7416
7754
|
async function prepareBuildFile(buildPath) {
|
|
7417
7755
|
const resolvedPath = resolve8(buildPath);
|
|
7418
|
-
if (resolvedPath.endsWith(".zip") &&
|
|
7756
|
+
if (resolvedPath.endsWith(".zip") && existsSync16(resolvedPath)) {
|
|
7419
7757
|
const buffer = await readFile4(resolvedPath);
|
|
7420
7758
|
const uint8Array = new Uint8Array(buffer);
|
|
7421
7759
|
const blob = new Blob([uint8Array], { type: "application/zip" });
|
|
@@ -7576,7 +7914,8 @@ async function deployBackendIfNeeded(game, context2) {
|
|
|
7576
7914
|
forceBackend,
|
|
7577
7915
|
previousIntegrationKeys,
|
|
7578
7916
|
context2.deployedGameInfo?.schemaSnapshot,
|
|
7579
|
-
debug
|
|
7917
|
+
debug,
|
|
7918
|
+
context2.deployedGameInfo?.deployedSecrets
|
|
7580
7919
|
);
|
|
7581
7920
|
return backendDeployment;
|
|
7582
7921
|
}
|
|
@@ -7611,14 +7950,16 @@ async function saveDeploymentState(game, backendDeployment, context2) {
|
|
|
7611
7950
|
customRoutesSize: backendDeployment.customRoutesSize ?? void 0,
|
|
7612
7951
|
backendSize: backendDeployment.backendSize,
|
|
7613
7952
|
backendDeployedAt: backendDeployment.deployedAt,
|
|
7614
|
-
schemaSnapshot: backendDeployment.schemaSnapshot
|
|
7953
|
+
schemaSnapshot: backendDeployment.schemaSnapshot,
|
|
7954
|
+
deployedSecrets: backendDeployment.deployedSecrets
|
|
7615
7955
|
},
|
|
7616
7956
|
...!backendDeployment && context2.deployedGameInfo && {
|
|
7617
7957
|
customRoutesHash: context2.deployedGameInfo.customRoutesHash,
|
|
7618
7958
|
customRoutesSize: context2.deployedGameInfo.customRoutesSize,
|
|
7619
7959
|
backendSize: context2.deployedGameInfo.backendSize,
|
|
7620
7960
|
backendDeployedAt: context2.deployedGameInfo.backendDeployedAt,
|
|
7621
|
-
schemaSnapshot: context2.deployedGameInfo.schemaSnapshot
|
|
7961
|
+
schemaSnapshot: context2.deployedGameInfo.schemaSnapshot,
|
|
7962
|
+
deployedSecrets: context2.deployedGameInfo.deployedSecrets
|
|
7622
7963
|
},
|
|
7623
7964
|
integrationKeys,
|
|
7624
7965
|
// Always save (even if empty array)
|
|
@@ -7630,20 +7971,20 @@ async function saveDeploymentState(game, backendDeployment, context2) {
|
|
|
7630
7971
|
// src/lib/dev/backend.ts
|
|
7631
7972
|
init_constants2();
|
|
7632
7973
|
init_core();
|
|
7633
|
-
import { existsSync as
|
|
7634
|
-
import { join as
|
|
7974
|
+
import { existsSync as existsSync17 } from "fs";
|
|
7975
|
+
import { join as join18 } from "path";
|
|
7635
7976
|
function hasCustomRoutes(config) {
|
|
7636
7977
|
const workspace = getWorkspace();
|
|
7637
7978
|
const customRoutesConfig = config?.integrations?.customRoutes;
|
|
7638
7979
|
const customRoutesDir = typeof customRoutesConfig === "object" && customRoutesConfig.directory || DEFAULT_API_ROUTES_DIRECTORY;
|
|
7639
|
-
return
|
|
7980
|
+
return existsSync17(join18(workspace, customRoutesDir));
|
|
7640
7981
|
}
|
|
7641
7982
|
function needsBackend(config) {
|
|
7642
7983
|
return !!config?.integrations || hasCustomRoutes(config);
|
|
7643
7984
|
}
|
|
7644
7985
|
|
|
7645
7986
|
// src/lib/dev/display.ts
|
|
7646
|
-
import {
|
|
7987
|
+
import { dim as dim5 } from "colorette";
|
|
7647
7988
|
|
|
7648
7989
|
// ../edge-play/src/register-routes.ts
|
|
7649
7990
|
init_constants4();
|
|
@@ -7653,6 +7994,57 @@ init_constants4();
|
|
|
7653
7994
|
|
|
7654
7995
|
// src/lib/dev/display.ts
|
|
7655
7996
|
init_core();
|
|
7997
|
+
|
|
7998
|
+
// src/lib/dev/route-sorting.ts
|
|
7999
|
+
function getSegmentType(segment) {
|
|
8000
|
+
if (segment.startsWith(":") && segment.includes("{.*}")) {
|
|
8001
|
+
return 2 /* CatchAll */;
|
|
8002
|
+
}
|
|
8003
|
+
if (segment.startsWith(":")) {
|
|
8004
|
+
return 1 /* Dynamic */;
|
|
8005
|
+
}
|
|
8006
|
+
return 0 /* Static */;
|
|
8007
|
+
}
|
|
8008
|
+
function compareSegments(a, b) {
|
|
8009
|
+
const typeA = getSegmentType(a);
|
|
8010
|
+
const typeB = getSegmentType(b);
|
|
8011
|
+
if (typeA !== typeB) {
|
|
8012
|
+
if (typeA === 1 /* Dynamic */ && typeB === 0 /* Static */) {
|
|
8013
|
+
return -1;
|
|
8014
|
+
}
|
|
8015
|
+
if (typeA === 0 /* Static */ && typeB === 1 /* Dynamic */) {
|
|
8016
|
+
return 1;
|
|
8017
|
+
}
|
|
8018
|
+
if (typeA === 2 /* CatchAll */ && typeB === 0 /* Static */) {
|
|
8019
|
+
return -1;
|
|
8020
|
+
}
|
|
8021
|
+
if (typeA === 0 /* Static */ && typeB === 2 /* CatchAll */) {
|
|
8022
|
+
return 1;
|
|
8023
|
+
}
|
|
8024
|
+
return typeA - typeB;
|
|
8025
|
+
}
|
|
8026
|
+
return a.localeCompare(b);
|
|
8027
|
+
}
|
|
8028
|
+
function sortRoutes(routes) {
|
|
8029
|
+
return [...routes].sort((a, b) => {
|
|
8030
|
+
const segmentsA = a.path.split("/").filter(Boolean);
|
|
8031
|
+
const segmentsB = b.path.split("/").filter(Boolean);
|
|
8032
|
+
const maxLength = Math.max(segmentsA.length, segmentsB.length);
|
|
8033
|
+
for (let i = 0; i < maxLength; i++) {
|
|
8034
|
+
const segA = segmentsA[i];
|
|
8035
|
+
const segB = segmentsB[i];
|
|
8036
|
+
if (segA === void 0) return -1;
|
|
8037
|
+
if (segB === void 0) return 1;
|
|
8038
|
+
const comparison = compareSegments(segA, segB);
|
|
8039
|
+
if (comparison !== 0) {
|
|
8040
|
+
return comparison;
|
|
8041
|
+
}
|
|
8042
|
+
}
|
|
8043
|
+
return 0;
|
|
8044
|
+
});
|
|
8045
|
+
}
|
|
8046
|
+
|
|
8047
|
+
// src/lib/dev/display.ts
|
|
7656
8048
|
function displayRegisteredRoutes(integrations, customRoutes = []) {
|
|
7657
8049
|
const healthRoutes = [
|
|
7658
8050
|
{ path: ROUTES.HEALTH, method: "GET" }
|
|
@@ -7663,29 +8055,27 @@ function displayRegisteredRoutes(integrations, customRoutes = []) {
|
|
|
7663
8055
|
const method = hasSandboxCreds ? "POST" : "POST (not configured)";
|
|
7664
8056
|
timebackRoutes.push({ path: ROUTES.TIMEBACK.END_ACTIVITY, method });
|
|
7665
8057
|
}
|
|
7666
|
-
const customRoutesList = customRoutes.map((route) =>
|
|
7667
|
-
|
|
7668
|
-
|
|
7669
|
-
|
|
8058
|
+
const customRoutesList = customRoutes.map((route) => {
|
|
8059
|
+
const methods = route.methods?.join(", ") || "*";
|
|
8060
|
+
const isCatchAll = /{\.\*}/.test(route.path);
|
|
8061
|
+
return {
|
|
8062
|
+
path: route.path,
|
|
8063
|
+
method: isCatchAll ? `${methods} (catch-all)` : methods
|
|
8064
|
+
};
|
|
8065
|
+
});
|
|
7670
8066
|
const allRoutes = [...healthRoutes, ...timebackRoutes, ...customRoutesList];
|
|
7671
|
-
const
|
|
7672
|
-
const
|
|
8067
|
+
const sortedRoutes = sortRoutes(allRoutes);
|
|
8068
|
+
const maxPathLength = Math.max(...sortedRoutes.map((r) => r.path.length));
|
|
8069
|
+
sortedRoutes.forEach((route) => {
|
|
7673
8070
|
const paddedPath = route.path.padEnd(maxPathLength + 2, " ");
|
|
7674
|
-
logger.
|
|
7675
|
-
};
|
|
7676
|
-
healthRoutes.forEach(displayRoute);
|
|
7677
|
-
if (timebackRoutes.length > 0) {
|
|
7678
|
-
timebackRoutes.forEach(displayRoute);
|
|
7679
|
-
}
|
|
7680
|
-
if (customRoutesList.length > 0) {
|
|
7681
|
-
customRoutesList.forEach(displayRoute);
|
|
7682
|
-
}
|
|
8071
|
+
logger.customRaw(`<${paddedPath}> ${dim5(route.method)}`, 1);
|
|
8072
|
+
});
|
|
7683
8073
|
}
|
|
7684
8074
|
|
|
7685
8075
|
// src/lib/dev/reload.ts
|
|
7686
8076
|
init_constants2();
|
|
7687
8077
|
init_core();
|
|
7688
|
-
import { join as
|
|
8078
|
+
import { join as join19, relative as relative3 } from "path";
|
|
7689
8079
|
import chokidar from "chokidar";
|
|
7690
8080
|
import { bold as bold4, cyan as cyan3, dim as dim6, green as green3 } from "colorette";
|
|
7691
8081
|
function formatTime() {
|
|
@@ -7702,9 +8092,9 @@ function startHotReload(onReload, options = {}) {
|
|
|
7702
8092
|
const customRoutesConfig = options.config?.integrations?.customRoutes;
|
|
7703
8093
|
const customRoutesDir = typeof customRoutesConfig === "object" && customRoutesConfig.directory || DEFAULT_API_ROUTES_DIRECTORY;
|
|
7704
8094
|
const watchPaths = [
|
|
7705
|
-
|
|
7706
|
-
|
|
7707
|
-
|
|
8095
|
+
join19(workspace, customRoutesDir),
|
|
8096
|
+
join19(workspace, "playcademy.config.js"),
|
|
8097
|
+
join19(workspace, "playcademy.config.json")
|
|
7708
8098
|
];
|
|
7709
8099
|
const watcher = chokidar.watch(watchPaths, {
|
|
7710
8100
|
persistent: true,
|
|
@@ -7746,53 +8136,65 @@ function startHotReload(onReload, options = {}) {
|
|
|
7746
8136
|
// src/lib/dev/server.ts
|
|
7747
8137
|
init_src2();
|
|
7748
8138
|
import { mkdir as mkdir4 } from "fs/promises";
|
|
7749
|
-
import { join as
|
|
8139
|
+
import { join as join21 } from "path";
|
|
7750
8140
|
import { Log, LogLevel, Miniflare } from "miniflare";
|
|
7751
8141
|
|
|
7752
8142
|
// ../utils/src/port.ts
|
|
7753
|
-
import { existsSync as
|
|
8143
|
+
import { existsSync as existsSync18, mkdirSync as mkdirSync4, readFileSync as readFileSync6, writeFileSync as writeFileSync7 } from "node:fs";
|
|
7754
8144
|
import { createServer as createServer2 } from "node:net";
|
|
7755
8145
|
import { homedir as homedir3 } from "node:os";
|
|
7756
|
-
import { join as
|
|
8146
|
+
import { join as join20 } from "node:path";
|
|
7757
8147
|
async function isPortAvailableOnHost(port, host) {
|
|
7758
8148
|
return new Promise((resolve11) => {
|
|
7759
8149
|
const server = createServer2();
|
|
7760
|
-
|
|
7761
|
-
|
|
8150
|
+
let resolved = false;
|
|
8151
|
+
const cleanup = (result) => {
|
|
8152
|
+
if (resolved) return;
|
|
8153
|
+
resolved = true;
|
|
8154
|
+
try {
|
|
8155
|
+
server.close();
|
|
8156
|
+
} catch {
|
|
8157
|
+
}
|
|
8158
|
+
resolve11(result);
|
|
8159
|
+
};
|
|
8160
|
+
const timeout = setTimeout(() => cleanup(true), 100);
|
|
8161
|
+
server.once("error", (err) => {
|
|
8162
|
+
clearTimeout(timeout);
|
|
8163
|
+
if (err.code === "EAFNOSUPPORT" || err.code === "EADDRNOTAVAIL") {
|
|
8164
|
+
cleanup(true);
|
|
8165
|
+
} else {
|
|
8166
|
+
cleanup(false);
|
|
8167
|
+
}
|
|
7762
8168
|
});
|
|
7763
8169
|
server.once("listening", () => {
|
|
7764
|
-
|
|
7765
|
-
|
|
8170
|
+
clearTimeout(timeout);
|
|
8171
|
+
cleanup(true);
|
|
7766
8172
|
});
|
|
7767
|
-
server.listen(port, host);
|
|
8173
|
+
server.listen(port, host).unref();
|
|
7768
8174
|
});
|
|
7769
8175
|
}
|
|
7770
8176
|
async function findAvailablePort(startPort = 4321) {
|
|
7771
|
-
|
|
7772
|
-
isPortAvailableOnHost(startPort, "127.0.0.1"),
|
|
7773
|
-
isPortAvailableOnHost(startPort, "0.0.0.0"),
|
|
7774
|
-
isPortAvailableOnHost(startPort, "::")
|
|
7775
|
-
]);
|
|
7776
|
-
if (localhostAvailable && ipv4AllAvailable && ipv6AllAvailable) {
|
|
8177
|
+
if (await isPortAvailableOnHost(startPort, "0.0.0.0")) {
|
|
7777
8178
|
return startPort;
|
|
8179
|
+
} else {
|
|
8180
|
+
return findAvailablePort(startPort + 1);
|
|
7778
8181
|
}
|
|
7779
|
-
return findAvailablePort(startPort + 1);
|
|
7780
8182
|
}
|
|
7781
8183
|
function getRegistryPath() {
|
|
7782
8184
|
const home = homedir3();
|
|
7783
|
-
const dir =
|
|
7784
|
-
if (!
|
|
8185
|
+
const dir = join20(home, ".playcademy");
|
|
8186
|
+
if (!existsSync18(dir)) {
|
|
7785
8187
|
mkdirSync4(dir, { recursive: true });
|
|
7786
8188
|
}
|
|
7787
|
-
return
|
|
8189
|
+
return join20(dir, ".proc");
|
|
7788
8190
|
}
|
|
7789
8191
|
function readRegistry() {
|
|
7790
8192
|
const registryPath = getRegistryPath();
|
|
7791
|
-
if (!
|
|
8193
|
+
if (!existsSync18(registryPath)) {
|
|
7792
8194
|
return {};
|
|
7793
8195
|
}
|
|
7794
8196
|
try {
|
|
7795
|
-
const content =
|
|
8197
|
+
const content = readFileSync6(registryPath, "utf-8");
|
|
7796
8198
|
return JSON.parse(content);
|
|
7797
8199
|
} catch {
|
|
7798
8200
|
return {};
|
|
@@ -7800,7 +8202,7 @@ function readRegistry() {
|
|
|
7800
8202
|
}
|
|
7801
8203
|
function writeRegistry(registry) {
|
|
7802
8204
|
const registryPath = getRegistryPath();
|
|
7803
|
-
|
|
8205
|
+
writeFileSync7(registryPath, JSON.stringify(registry, null, 2), "utf-8");
|
|
7804
8206
|
}
|
|
7805
8207
|
function getServerKey(type, port) {
|
|
7806
8208
|
return `${type}-${port}`;
|
|
@@ -7900,9 +8302,19 @@ async function startDevServer(options) {
|
|
|
7900
8302
|
const kvDir = hasKV ? await ensureKvDirectory() : void 0;
|
|
7901
8303
|
const hasBucket = hasBucketSetup(config);
|
|
7902
8304
|
const bucketDir = hasBucket ? await ensureBucketDirectory() : void 0;
|
|
8305
|
+
const workspace = getWorkspace();
|
|
8306
|
+
const envSecrets = await readEnvFile(workspace);
|
|
7903
8307
|
const log2 = logger2 ? new FilteredLog(LogLevel.INFO) : new Log(LogLevel.NONE);
|
|
7904
|
-
const sandboxInfo = readServerInfo("sandbox",
|
|
8308
|
+
const sandboxInfo = readServerInfo("sandbox", workspace);
|
|
7905
8309
|
const baseUrl = platformUrl ?? sandboxInfo?.url ?? process.env.PLAYCADEMY_BASE_URL ?? `http://localhost:${DEFAULT_PORTS.SANDBOX}`;
|
|
8310
|
+
const bindings = {
|
|
8311
|
+
PLAYCADEMY_API_KEY: process.env.PLAYCADEMY_API_KEY || "dev-api-key",
|
|
8312
|
+
GAME_ID: CORE_GAME_UUIDS.PLAYGROUND,
|
|
8313
|
+
PLAYCADEMY_BASE_URL: baseUrl
|
|
8314
|
+
};
|
|
8315
|
+
for (const [key, value] of Object.entries(envSecrets)) {
|
|
8316
|
+
bindings[`secrets_${key}`] = value;
|
|
8317
|
+
}
|
|
7906
8318
|
const mf = new Miniflare({
|
|
7907
8319
|
port,
|
|
7908
8320
|
log: log2,
|
|
@@ -7913,11 +8325,7 @@ async function startDevServer(options) {
|
|
|
7913
8325
|
contents: bundle.code
|
|
7914
8326
|
}
|
|
7915
8327
|
],
|
|
7916
|
-
bindings
|
|
7917
|
-
PLAYCADEMY_API_KEY: process.env.PLAYCADEMY_API_KEY || "dev-api-key",
|
|
7918
|
-
GAME_ID: CORE_GAME_UUIDS.PLAYGROUND,
|
|
7919
|
-
PLAYCADEMY_BASE_URL: baseUrl
|
|
7920
|
-
},
|
|
8328
|
+
bindings,
|
|
7921
8329
|
d1Databases: hasDatabase ? ["DB"] : [],
|
|
7922
8330
|
d1Persist: dbDir,
|
|
7923
8331
|
kvNamespaces: hasKV ? ["KV"] : [],
|
|
@@ -7933,7 +8341,7 @@ async function startDevServer(options) {
|
|
|
7933
8341
|
return { server: mf, port };
|
|
7934
8342
|
}
|
|
7935
8343
|
async function ensureDatabaseDirectory() {
|
|
7936
|
-
const dbDir =
|
|
8344
|
+
const dbDir = join21(getWorkspace(), CLI_DIRECTORIES.DATABASE);
|
|
7937
8345
|
try {
|
|
7938
8346
|
await mkdir4(dbDir, { recursive: true });
|
|
7939
8347
|
} catch (error) {
|
|
@@ -7942,7 +8350,7 @@ async function ensureDatabaseDirectory() {
|
|
|
7942
8350
|
return dbDir;
|
|
7943
8351
|
}
|
|
7944
8352
|
async function ensureKvDirectory() {
|
|
7945
|
-
const kvDir =
|
|
8353
|
+
const kvDir = join21(getWorkspace(), CLI_DIRECTORIES.KV);
|
|
7946
8354
|
try {
|
|
7947
8355
|
await mkdir4(kvDir, { recursive: true });
|
|
7948
8356
|
} catch (error) {
|
|
@@ -7951,7 +8359,7 @@ async function ensureKvDirectory() {
|
|
|
7951
8359
|
return kvDir;
|
|
7952
8360
|
}
|
|
7953
8361
|
async function ensureBucketDirectory() {
|
|
7954
|
-
const bucketDir =
|
|
8362
|
+
const bucketDir = join21(getWorkspace(), CLI_DIRECTORIES.BUCKET);
|
|
7955
8363
|
try {
|
|
7956
8364
|
await mkdir4(bucketDir, { recursive: true });
|
|
7957
8365
|
} catch (error) {
|
|
@@ -8036,7 +8444,7 @@ function displayResourcesStatus(resources, logger2) {
|
|
|
8036
8444
|
}
|
|
8037
8445
|
|
|
8038
8446
|
// src/commands/init/config.ts
|
|
8039
|
-
import { writeFileSync as
|
|
8447
|
+
import { writeFileSync as writeFileSync8 } from "fs";
|
|
8040
8448
|
import { resolve as resolve9 } from "path";
|
|
8041
8449
|
init_file_loader();
|
|
8042
8450
|
init_constants2();
|
|
@@ -8088,7 +8496,7 @@ var configCommand = new Command("config").description("Create playcademy.config
|
|
|
8088
8496
|
emoji: gameInfo.emoji,
|
|
8089
8497
|
timeback: timebackConfig ?? void 0
|
|
8090
8498
|
});
|
|
8091
|
-
|
|
8499
|
+
writeFileSync8(resolve9(getWorkspace(), configFileName), configContent, "utf-8");
|
|
8092
8500
|
displayConfigSuccess(!!timebackConfig);
|
|
8093
8501
|
} catch (error) {
|
|
8094
8502
|
logger.newLine();
|
|
@@ -8207,7 +8615,7 @@ var initCommand = new Command2("init").description("Initialize a playcademy.conf
|
|
|
8207
8615
|
bucket: bucket ?? void 0,
|
|
8208
8616
|
timeback: timebackConfig ?? void 0
|
|
8209
8617
|
});
|
|
8210
|
-
|
|
8618
|
+
writeFileSync9(resolve10(getWorkspace(), configFileName), configContent, "utf-8");
|
|
8211
8619
|
if (database || kv || bucket) {
|
|
8212
8620
|
await ensurePlaycademyTypes();
|
|
8213
8621
|
}
|
|
@@ -8225,14 +8633,14 @@ var initCommand = new Command2("init").description("Initialize a playcademy.conf
|
|
|
8225
8633
|
});
|
|
8226
8634
|
async function addPlaycademySdk() {
|
|
8227
8635
|
const pkgPath = resolve10(getWorkspace(), "package.json");
|
|
8228
|
-
const pkg = JSON.parse(
|
|
8636
|
+
const pkg = JSON.parse(readFileSync7(pkgPath, "utf-8"));
|
|
8229
8637
|
const hasSdk = pkg.dependencies?.["@playcademy/sdk"] || pkg.devDependencies?.["@playcademy/sdk"];
|
|
8230
8638
|
if (hasSdk) {
|
|
8231
8639
|
return false;
|
|
8232
8640
|
}
|
|
8233
8641
|
if (!pkg.dependencies) pkg.dependencies = {};
|
|
8234
8642
|
pkg.dependencies["@playcademy/sdk"] = "latest";
|
|
8235
|
-
|
|
8643
|
+
writeFileSync9(pkgPath, JSON.stringify(pkg, null, 2) + "\n");
|
|
8236
8644
|
return true;
|
|
8237
8645
|
}
|
|
8238
8646
|
initCommand.addCommand(configCommand);
|
|
@@ -8823,7 +9231,7 @@ var getStatusCommand = new Command11("status").description("Check your developer
|
|
|
8823
9231
|
});
|
|
8824
9232
|
|
|
8825
9233
|
// src/commands/dev/server.ts
|
|
8826
|
-
import {
|
|
9234
|
+
import { underline as underline2 } from "colorette";
|
|
8827
9235
|
function setupCleanupHandlers(workspace, getServer) {
|
|
8828
9236
|
let isShuttingDown = false;
|
|
8829
9237
|
const cleanup = () => {
|
|
@@ -8873,7 +9281,7 @@ async function runDevServer(options) {
|
|
|
8873
9281
|
logger.warn("No backend integrations or custom routes configured");
|
|
8874
9282
|
logger.newLine();
|
|
8875
9283
|
logger.admonition("tip", "How to Add Backend", [
|
|
8876
|
-
`Add integrations to
|
|
9284
|
+
`Add integrations to <playcademy.config.js> or run \`playcademy api init\``
|
|
8877
9285
|
]);
|
|
8878
9286
|
logger.newLine();
|
|
8879
9287
|
logger.remark("Nothing to do");
|
|
@@ -8887,7 +9295,7 @@ async function runDevServer(options) {
|
|
|
8887
9295
|
logger: options.logger !== false
|
|
8888
9296
|
});
|
|
8889
9297
|
serverRef.current = server;
|
|
8890
|
-
logger.success(`Game API started: ${
|
|
9298
|
+
logger.success(`Game API started: ${underline2(`<http://localhost:${port}/api>`)}`);
|
|
8891
9299
|
logger.newLine();
|
|
8892
9300
|
const customRoutesDir = getCustomRoutesDirectory(workspace, config);
|
|
8893
9301
|
const customRoutes = await discoverRoutes(customRoutesDir);
|
|
@@ -9101,16 +9509,16 @@ async function runDbInit() {
|
|
|
9101
9509
|
init_src2();
|
|
9102
9510
|
init_src();
|
|
9103
9511
|
import { spawn } from "child_process";
|
|
9104
|
-
import { existsSync as
|
|
9105
|
-
import { join as
|
|
9512
|
+
import { existsSync as existsSync19, rmSync as rmSync2 } from "fs";
|
|
9513
|
+
import { join as join22 } from "path";
|
|
9106
9514
|
import { confirm as confirm6 } from "@inquirer/prompts";
|
|
9107
9515
|
import { Miniflare as Miniflare2 } from "miniflare";
|
|
9108
9516
|
init_constants2();
|
|
9109
9517
|
async function runDbReset() {
|
|
9110
9518
|
try {
|
|
9111
9519
|
const workspace = getWorkspace();
|
|
9112
|
-
const dbDir =
|
|
9113
|
-
if (!
|
|
9520
|
+
const dbDir = join22(workspace, CLI_DIRECTORIES.DATABASE);
|
|
9521
|
+
if (!existsSync19(dbDir)) {
|
|
9114
9522
|
logger.warn("No database found to reset");
|
|
9115
9523
|
logger.newLine();
|
|
9116
9524
|
logger.remark("Nothing to do");
|
|
@@ -9213,8 +9621,8 @@ async function runDbReset() {
|
|
|
9213
9621
|
// src/commands/db/seed.ts
|
|
9214
9622
|
init_package_manager();
|
|
9215
9623
|
import { execSync as execSync5 } from "child_process";
|
|
9216
|
-
import { existsSync as
|
|
9217
|
-
import { join as
|
|
9624
|
+
import { existsSync as existsSync20 } from "fs";
|
|
9625
|
+
import { join as join23 } from "path";
|
|
9218
9626
|
async function runDbSeed(options) {
|
|
9219
9627
|
const workspace = getWorkspace();
|
|
9220
9628
|
try {
|
|
@@ -9223,8 +9631,8 @@ async function runDbSeed(options) {
|
|
|
9223
9631
|
logger.newLine();
|
|
9224
9632
|
}
|
|
9225
9633
|
if (options.file) {
|
|
9226
|
-
const seedPath =
|
|
9227
|
-
if (!
|
|
9634
|
+
const seedPath = join23(workspace, options.file);
|
|
9635
|
+
if (!existsSync20(seedPath)) {
|
|
9228
9636
|
logger.error(`Seed file not found: ${options.file}`);
|
|
9229
9637
|
logger.newLine();
|
|
9230
9638
|
process.exit(1);
|
|
@@ -9255,7 +9663,7 @@ import { Command as Command15 } from "commander";
|
|
|
9255
9663
|
// src/commands/kv/clear.ts
|
|
9256
9664
|
init_string();
|
|
9257
9665
|
init_constants2();
|
|
9258
|
-
import { join as
|
|
9666
|
+
import { join as join24 } from "path";
|
|
9259
9667
|
import { confirm as confirm7 } from "@inquirer/prompts";
|
|
9260
9668
|
import { Miniflare as Miniflare3 } from "miniflare";
|
|
9261
9669
|
async function runKVClear(options = {}) {
|
|
@@ -9292,7 +9700,7 @@ async function runKVClear(options = {}) {
|
|
|
9292
9700
|
sourcemap: false,
|
|
9293
9701
|
minify: false
|
|
9294
9702
|
});
|
|
9295
|
-
const kvDir =
|
|
9703
|
+
const kvDir = join24(getWorkspace(), CLI_DIRECTORIES.KV);
|
|
9296
9704
|
const mf = new Miniflare3({
|
|
9297
9705
|
modules: [
|
|
9298
9706
|
{
|
|
@@ -9370,7 +9778,7 @@ async function runKVClear(options = {}) {
|
|
|
9370
9778
|
|
|
9371
9779
|
// src/commands/kv/delete.ts
|
|
9372
9780
|
init_constants2();
|
|
9373
|
-
import { join as
|
|
9781
|
+
import { join as join25 } from "path";
|
|
9374
9782
|
import { Miniflare as Miniflare4 } from "miniflare";
|
|
9375
9783
|
async function runKVDelete(key, options = {}) {
|
|
9376
9784
|
try {
|
|
@@ -9415,7 +9823,7 @@ async function runKVDelete(key, options = {}) {
|
|
|
9415
9823
|
sourcemap: false,
|
|
9416
9824
|
minify: false
|
|
9417
9825
|
});
|
|
9418
|
-
const kvDir =
|
|
9826
|
+
const kvDir = join25(getWorkspace(), CLI_DIRECTORIES.KV);
|
|
9419
9827
|
const mf = new Miniflare4({
|
|
9420
9828
|
modules: [
|
|
9421
9829
|
{
|
|
@@ -9458,7 +9866,7 @@ async function runKVDelete(key, options = {}) {
|
|
|
9458
9866
|
|
|
9459
9867
|
// src/commands/kv/get.ts
|
|
9460
9868
|
init_constants2();
|
|
9461
|
-
import { join as
|
|
9869
|
+
import { join as join26 } from "path";
|
|
9462
9870
|
import { Miniflare as Miniflare5 } from "miniflare";
|
|
9463
9871
|
async function runKVGet(key, options = {}) {
|
|
9464
9872
|
try {
|
|
@@ -9503,7 +9911,7 @@ async function runKVGet(key, options = {}) {
|
|
|
9503
9911
|
sourcemap: false,
|
|
9504
9912
|
minify: false
|
|
9505
9913
|
});
|
|
9506
|
-
const kvDir =
|
|
9914
|
+
const kvDir = join26(getWorkspace(), CLI_DIRECTORIES.KV);
|
|
9507
9915
|
const mf = new Miniflare5({
|
|
9508
9916
|
modules: [
|
|
9509
9917
|
{
|
|
@@ -9648,7 +10056,7 @@ async function runKVInit() {
|
|
|
9648
10056
|
|
|
9649
10057
|
// src/commands/kv/inspect.ts
|
|
9650
10058
|
init_constants2();
|
|
9651
|
-
import { join as
|
|
10059
|
+
import { join as join27 } from "path";
|
|
9652
10060
|
import { Miniflare as Miniflare6 } from "miniflare";
|
|
9653
10061
|
async function runKVInspect(key, options = {}) {
|
|
9654
10062
|
try {
|
|
@@ -9693,7 +10101,7 @@ async function runKVInspect(key, options = {}) {
|
|
|
9693
10101
|
sourcemap: false,
|
|
9694
10102
|
minify: false
|
|
9695
10103
|
});
|
|
9696
|
-
const kvDir =
|
|
10104
|
+
const kvDir = join27(getWorkspace(), CLI_DIRECTORIES.KV);
|
|
9697
10105
|
const mf = new Miniflare6({
|
|
9698
10106
|
modules: [
|
|
9699
10107
|
{
|
|
@@ -9787,7 +10195,7 @@ async function runKVInspect(key, options = {}) {
|
|
|
9787
10195
|
// src/commands/kv/list.ts
|
|
9788
10196
|
init_string();
|
|
9789
10197
|
init_constants2();
|
|
9790
|
-
import { join as
|
|
10198
|
+
import { join as join28 } from "path";
|
|
9791
10199
|
import { Miniflare as Miniflare7 } from "miniflare";
|
|
9792
10200
|
async function runKVList(options = {}) {
|
|
9793
10201
|
try {
|
|
@@ -9823,7 +10231,7 @@ async function runKVList(options = {}) {
|
|
|
9823
10231
|
sourcemap: false,
|
|
9824
10232
|
minify: false
|
|
9825
10233
|
});
|
|
9826
|
-
const kvDir =
|
|
10234
|
+
const kvDir = join28(getWorkspace(), CLI_DIRECTORIES.KV);
|
|
9827
10235
|
const mf = new Miniflare7({
|
|
9828
10236
|
modules: [
|
|
9829
10237
|
{
|
|
@@ -9878,7 +10286,7 @@ async function runKVList(options = {}) {
|
|
|
9878
10286
|
init_file_loader();
|
|
9879
10287
|
init_string();
|
|
9880
10288
|
init_constants2();
|
|
9881
|
-
import { join as
|
|
10289
|
+
import { join as join29 } from "path";
|
|
9882
10290
|
import { confirm as confirm8 } from "@inquirer/prompts";
|
|
9883
10291
|
import { Miniflare as Miniflare8 } from "miniflare";
|
|
9884
10292
|
async function runKVSeed(seedFile, options = {}) {
|
|
@@ -9948,7 +10356,7 @@ async function runKVSeed(seedFile, options = {}) {
|
|
|
9948
10356
|
sourcemap: false,
|
|
9949
10357
|
minify: false
|
|
9950
10358
|
});
|
|
9951
|
-
const kvDir =
|
|
10359
|
+
const kvDir = join29(workspace, CLI_DIRECTORIES.KV);
|
|
9952
10360
|
const mf = new Miniflare8({
|
|
9953
10361
|
modules: [
|
|
9954
10362
|
{
|
|
@@ -10035,7 +10443,7 @@ async function runKVSeed(seedFile, options = {}) {
|
|
|
10035
10443
|
// src/commands/kv/set.ts
|
|
10036
10444
|
init_file_loader();
|
|
10037
10445
|
init_constants2();
|
|
10038
|
-
import { join as
|
|
10446
|
+
import { join as join30 } from "path";
|
|
10039
10447
|
import { Miniflare as Miniflare9 } from "miniflare";
|
|
10040
10448
|
async function runKVSet(key, value, options = {}) {
|
|
10041
10449
|
try {
|
|
@@ -10109,7 +10517,7 @@ async function runKVSet(key, value, options = {}) {
|
|
|
10109
10517
|
sourcemap: false,
|
|
10110
10518
|
minify: false
|
|
10111
10519
|
});
|
|
10112
|
-
const kvDir =
|
|
10520
|
+
const kvDir = join30(getWorkspace(), CLI_DIRECTORIES.KV);
|
|
10113
10521
|
const mf = new Miniflare9({
|
|
10114
10522
|
modules: [
|
|
10115
10523
|
{
|
|
@@ -10153,7 +10561,7 @@ async function runKVSet(key, value, options = {}) {
|
|
|
10153
10561
|
// src/commands/kv/stats.ts
|
|
10154
10562
|
init_string();
|
|
10155
10563
|
init_constants2();
|
|
10156
|
-
import { join as
|
|
10564
|
+
import { join as join31 } from "path";
|
|
10157
10565
|
import { Miniflare as Miniflare10 } from "miniflare";
|
|
10158
10566
|
async function runKVStats(options = {}) {
|
|
10159
10567
|
try {
|
|
@@ -10189,7 +10597,7 @@ async function runKVStats(options = {}) {
|
|
|
10189
10597
|
sourcemap: false,
|
|
10190
10598
|
minify: false
|
|
10191
10599
|
});
|
|
10192
|
-
const kvDir =
|
|
10600
|
+
const kvDir = join31(getWorkspace(), CLI_DIRECTORIES.KV);
|
|
10193
10601
|
const mf = new Miniflare10({
|
|
10194
10602
|
modules: [
|
|
10195
10603
|
{
|
|
@@ -10312,7 +10720,7 @@ import { Command as Command16 } from "commander";
|
|
|
10312
10720
|
|
|
10313
10721
|
// src/commands/bucket/delete.ts
|
|
10314
10722
|
init_constants2();
|
|
10315
|
-
import { join as
|
|
10723
|
+
import { join as join32 } from "path";
|
|
10316
10724
|
import { Miniflare as Miniflare11 } from "miniflare";
|
|
10317
10725
|
async function runBucketDelete(key, options = {}) {
|
|
10318
10726
|
try {
|
|
@@ -10357,7 +10765,7 @@ async function runBucketDelete(key, options = {}) {
|
|
|
10357
10765
|
sourcemap: false,
|
|
10358
10766
|
minify: false
|
|
10359
10767
|
});
|
|
10360
|
-
const bucketDir =
|
|
10768
|
+
const bucketDir = join32(getWorkspace(), CLI_DIRECTORIES.BUCKET);
|
|
10361
10769
|
const mf = new Miniflare11({
|
|
10362
10770
|
modules: [
|
|
10363
10771
|
{
|
|
@@ -10415,8 +10823,8 @@ async function runBucketDelete(key, options = {}) {
|
|
|
10415
10823
|
|
|
10416
10824
|
// src/commands/bucket/get.ts
|
|
10417
10825
|
init_constants2();
|
|
10418
|
-
import { writeFileSync as
|
|
10419
|
-
import { join as
|
|
10826
|
+
import { writeFileSync as writeFileSync10 } from "fs";
|
|
10827
|
+
import { join as join33 } from "path";
|
|
10420
10828
|
import { Miniflare as Miniflare12 } from "miniflare";
|
|
10421
10829
|
async function runBucketGet(key, options = {}) {
|
|
10422
10830
|
try {
|
|
@@ -10461,7 +10869,7 @@ async function runBucketGet(key, options = {}) {
|
|
|
10461
10869
|
sourcemap: false,
|
|
10462
10870
|
minify: false
|
|
10463
10871
|
});
|
|
10464
|
-
const bucketDir =
|
|
10872
|
+
const bucketDir = join33(getWorkspace(), CLI_DIRECTORIES.BUCKET);
|
|
10465
10873
|
const mf = new Miniflare12({
|
|
10466
10874
|
modules: [
|
|
10467
10875
|
{
|
|
@@ -10501,7 +10909,7 @@ async function runBucketGet(key, options = {}) {
|
|
|
10501
10909
|
}
|
|
10502
10910
|
if (options.output) {
|
|
10503
10911
|
const buffer = await object.arrayBuffer();
|
|
10504
|
-
|
|
10912
|
+
writeFileSync10(options.output, Buffer.from(buffer));
|
|
10505
10913
|
if (!options.raw) {
|
|
10506
10914
|
logger.success(`Downloaded '${key}' to '${options.output}'`);
|
|
10507
10915
|
logger.newLine();
|
|
@@ -10616,7 +11024,7 @@ async function runBucketInit() {
|
|
|
10616
11024
|
|
|
10617
11025
|
// src/commands/bucket/list.ts
|
|
10618
11026
|
init_constants2();
|
|
10619
|
-
import { join as
|
|
11027
|
+
import { join as join34 } from "path";
|
|
10620
11028
|
import { Miniflare as Miniflare13 } from "miniflare";
|
|
10621
11029
|
async function runBucketList(options = {}) {
|
|
10622
11030
|
try {
|
|
@@ -10652,7 +11060,7 @@ async function runBucketList(options = {}) {
|
|
|
10652
11060
|
sourcemap: false,
|
|
10653
11061
|
minify: false
|
|
10654
11062
|
});
|
|
10655
|
-
const bucketDir =
|
|
11063
|
+
const bucketDir = join34(getWorkspace(), CLI_DIRECTORIES.BUCKET);
|
|
10656
11064
|
const mf = new Miniflare13({
|
|
10657
11065
|
modules: [
|
|
10658
11066
|
{
|
|
@@ -10735,8 +11143,8 @@ function formatBytes(bytes) {
|
|
|
10735
11143
|
|
|
10736
11144
|
// src/commands/bucket/put.ts
|
|
10737
11145
|
init_constants2();
|
|
10738
|
-
import { readFileSync as
|
|
10739
|
-
import { join as
|
|
11146
|
+
import { readFileSync as readFileSync8, statSync as statSync2 } from "fs";
|
|
11147
|
+
import { join as join35 } from "path";
|
|
10740
11148
|
import { Miniflare as Miniflare14 } from "miniflare";
|
|
10741
11149
|
async function runBucketPut(key, filePath, options = {}) {
|
|
10742
11150
|
try {
|
|
@@ -10780,7 +11188,7 @@ async function runBucketPut(key, filePath, options = {}) {
|
|
|
10780
11188
|
let fileBuffer;
|
|
10781
11189
|
let fileSize;
|
|
10782
11190
|
try {
|
|
10783
|
-
fileBuffer =
|
|
11191
|
+
fileBuffer = readFileSync8(filePath);
|
|
10784
11192
|
fileSize = statSync2(filePath).size;
|
|
10785
11193
|
} catch {
|
|
10786
11194
|
if (!options.raw && !options.json) {
|
|
@@ -10793,7 +11201,7 @@ async function runBucketPut(key, filePath, options = {}) {
|
|
|
10793
11201
|
sourcemap: false,
|
|
10794
11202
|
minify: false
|
|
10795
11203
|
});
|
|
10796
|
-
const bucketDir =
|
|
11204
|
+
const bucketDir = join35(getWorkspace(), CLI_DIRECTORIES.BUCKET);
|
|
10797
11205
|
const mf = new Miniflare14({
|
|
10798
11206
|
modules: [
|
|
10799
11207
|
{
|
|
@@ -10891,12 +11299,153 @@ bucketCommand.command("delete <key>").alias("del").alias("rm").description("Dele
|
|
|
10891
11299
|
"Environment to use with --remote: staging (default) or production"
|
|
10892
11300
|
).action(runBucketDelete);
|
|
10893
11301
|
|
|
10894
|
-
// src/commands/
|
|
11302
|
+
// src/commands/secret/index.ts
|
|
10895
11303
|
import { Command as Command20 } from "commander";
|
|
10896
11304
|
|
|
11305
|
+
// src/commands/secret/delete.ts
|
|
11306
|
+
init_src();
|
|
11307
|
+
import { confirm as confirm9 } from "@inquirer/prompts";
|
|
11308
|
+
import { Command as Command17 } from "commander";
|
|
11309
|
+
var deleteCommand2 = new Command17("delete").description("Delete a game secret").argument("<key>", "Secret key to delete").option("--env <environment>", "Environment (staging or production)").option("-f, --force", "Skip confirmation").action(async (key, options) => {
|
|
11310
|
+
const { env } = options;
|
|
11311
|
+
try {
|
|
11312
|
+
const environment = ensureEnvironment(env);
|
|
11313
|
+
const client = await requireAuthenticatedClient();
|
|
11314
|
+
logger.newLine();
|
|
11315
|
+
const workspace = getWorkspace();
|
|
11316
|
+
const deployedGame = await getDeployedGame(workspace);
|
|
11317
|
+
if (!deployedGame) {
|
|
11318
|
+
logger.admonition("warning", "Deploy First", [
|
|
11319
|
+
`Deploy your game before managing secrets: \`playcademy deploy\``,
|
|
11320
|
+
`For local development, use an \`.env\` file in your project root`
|
|
11321
|
+
]);
|
|
11322
|
+
logger.newLine();
|
|
11323
|
+
process.exit(1);
|
|
11324
|
+
}
|
|
11325
|
+
const game = await client.games.fetch(deployedGame.gameId);
|
|
11326
|
+
if (!options.force) {
|
|
11327
|
+
const confirmed = await confirm9({
|
|
11328
|
+
message: `Delete secret "${key}" from "${game.slug}" in ${environment}?`,
|
|
11329
|
+
default: false
|
|
11330
|
+
});
|
|
11331
|
+
if (!confirmed) {
|
|
11332
|
+
logger.newLine();
|
|
11333
|
+
logger.remark("Nothing to do");
|
|
11334
|
+
logger.newLine();
|
|
11335
|
+
return;
|
|
11336
|
+
}
|
|
11337
|
+
}
|
|
11338
|
+
await runStep(
|
|
11339
|
+
`Deleting secret from ${environment}`,
|
|
11340
|
+
() => client.dev.games.secrets.delete(game.slug, key),
|
|
11341
|
+
`Secret deleted successfully from ${environment}`
|
|
11342
|
+
);
|
|
11343
|
+
logger.newLine();
|
|
11344
|
+
} catch (error) {
|
|
11345
|
+
logAndExit(error, logger, { prefix: "Failed to delete secret" });
|
|
11346
|
+
}
|
|
11347
|
+
});
|
|
11348
|
+
|
|
11349
|
+
// src/commands/secret/list.ts
|
|
11350
|
+
init_src();
|
|
11351
|
+
init_string();
|
|
11352
|
+
import { Command as Command18 } from "commander";
|
|
11353
|
+
var listCommand2 = new Command18("list").description("List game secret keys").option("--env <environment>", "Environment (staging or production)").action(async (options) => {
|
|
11354
|
+
const { env } = options;
|
|
11355
|
+
try {
|
|
11356
|
+
const environment = ensureEnvironment(env);
|
|
11357
|
+
const client = await requireAuthenticatedClient();
|
|
11358
|
+
logger.newLine();
|
|
11359
|
+
const workspace = getWorkspace();
|
|
11360
|
+
const deployedGame = await getDeployedGame(workspace);
|
|
11361
|
+
if (!deployedGame) {
|
|
11362
|
+
logger.admonition("warning", "Deploy First", [
|
|
11363
|
+
`Deploy your game before managing secrets: \`playcademy deploy\``,
|
|
11364
|
+
`For local development, use an \`.env\` file in your project root`
|
|
11365
|
+
]);
|
|
11366
|
+
logger.newLine();
|
|
11367
|
+
process.exit(1);
|
|
11368
|
+
}
|
|
11369
|
+
const game = await client.games.fetch(deployedGame.gameId);
|
|
11370
|
+
const keys = await runStep(
|
|
11371
|
+
`Fetching secrets from ${environment}`,
|
|
11372
|
+
() => client.dev.games.secrets.list(game.slug),
|
|
11373
|
+
(keys2) => `Found ${keys2.length} ${pluralize(keys2.length, "secret")}`
|
|
11374
|
+
);
|
|
11375
|
+
if (keys.length === 0) {
|
|
11376
|
+
logger.newLine();
|
|
11377
|
+
logger.remark("No secrets configured");
|
|
11378
|
+
logger.newLine();
|
|
11379
|
+
return;
|
|
11380
|
+
}
|
|
11381
|
+
logger.newLine();
|
|
11382
|
+
keys.forEach((key) => {
|
|
11383
|
+
logger.highlight(key, 1);
|
|
11384
|
+
logger.dim("(value hidden)", 2);
|
|
11385
|
+
});
|
|
11386
|
+
logger.newLine();
|
|
11387
|
+
} catch (error) {
|
|
11388
|
+
logAndExit(error, logger, { prefix: "Failed to list secrets" });
|
|
11389
|
+
}
|
|
11390
|
+
});
|
|
11391
|
+
|
|
11392
|
+
// src/commands/secret/set.ts
|
|
11393
|
+
init_src();
|
|
11394
|
+
import { Command as Command19 } from "commander";
|
|
11395
|
+
var setCommand = new Command19("set").description("Set or update a game secret").argument("<key>", "Secret key (e.g., STRIPE_KEY)").argument("<value>", "Secret value").option("--env <environment>", "Environment (staging or production)").action(async (key, value, options) => {
|
|
11396
|
+
const { env } = options;
|
|
11397
|
+
try {
|
|
11398
|
+
const environment = ensureEnvironment(env);
|
|
11399
|
+
const client = await requireAuthenticatedClient();
|
|
11400
|
+
logger.newLine();
|
|
11401
|
+
const workspace = getWorkspace();
|
|
11402
|
+
const deployedGame = await getDeployedGame(workspace);
|
|
11403
|
+
if (!deployedGame) {
|
|
11404
|
+
logger.admonition("warning", "Deploy First", [
|
|
11405
|
+
`Deploy your game before managing secrets: \`playcademy deploy\``,
|
|
11406
|
+
`For local development, use an \`.env\` file in your project root`
|
|
11407
|
+
]);
|
|
11408
|
+
logger.newLine();
|
|
11409
|
+
process.exit(1);
|
|
11410
|
+
}
|
|
11411
|
+
const game = await client.games.fetch(deployedGame.gameId);
|
|
11412
|
+
await runStep(
|
|
11413
|
+
`Setting secret "${key}" in ${environment}`,
|
|
11414
|
+
() => client.dev.games.secrets.set(game.slug, { [key]: value }),
|
|
11415
|
+
`Secret "${key}" set successfully in ${environment}`
|
|
11416
|
+
);
|
|
11417
|
+
logger.newLine();
|
|
11418
|
+
} catch (error) {
|
|
11419
|
+
logAndExit(error, logger, { prefix: "Failed to set secret" });
|
|
11420
|
+
}
|
|
11421
|
+
});
|
|
11422
|
+
|
|
11423
|
+
// src/commands/secret/index.ts
|
|
11424
|
+
var secretCommand = new Command20("secrets").description("Manage game secrets").addCommand(setCommand).addCommand(listCommand2).addCommand(deleteCommand2);
|
|
11425
|
+
|
|
11426
|
+
// src/commands/types.ts
|
|
11427
|
+
init_src();
|
|
11428
|
+
import { Command as Command21 } from "commander";
|
|
11429
|
+
var typesCommand = new Command21("types").description("Generate TypeScript type definitions").action(async () => {
|
|
11430
|
+
try {
|
|
11431
|
+
logger.newLine();
|
|
11432
|
+
await runStep(
|
|
11433
|
+
"Generating TypeScript types",
|
|
11434
|
+
() => ensurePlaycademyTypes({ verbose: true }),
|
|
11435
|
+
"Types generated successfully"
|
|
11436
|
+
);
|
|
11437
|
+
logger.newLine();
|
|
11438
|
+
} catch (error) {
|
|
11439
|
+
logAndExit(error, logger, { prefix: "Failed to generate types" });
|
|
11440
|
+
}
|
|
11441
|
+
});
|
|
11442
|
+
|
|
11443
|
+
// src/commands/profiles/index.ts
|
|
11444
|
+
import { Command as Command25 } from "commander";
|
|
11445
|
+
|
|
10897
11446
|
// src/commands/profiles/list.ts
|
|
10898
11447
|
init_string();
|
|
10899
|
-
import { Command as
|
|
11448
|
+
import { Command as Command22 } from "commander";
|
|
10900
11449
|
async function listProfilesAction() {
|
|
10901
11450
|
try {
|
|
10902
11451
|
const profilesMap = await listProfiles();
|
|
@@ -10938,12 +11487,12 @@ async function listProfilesAction() {
|
|
|
10938
11487
|
process.exit(1);
|
|
10939
11488
|
}
|
|
10940
11489
|
}
|
|
10941
|
-
var
|
|
11490
|
+
var listCommand3 = new Command22("list").alias("ls").description("List all stored authentication profiles").action(listProfilesAction);
|
|
10942
11491
|
|
|
10943
11492
|
// src/commands/profiles/remove.ts
|
|
10944
11493
|
import { bold as bold6 } from "colorette";
|
|
10945
|
-
import { Command as
|
|
10946
|
-
var removeCommand = new
|
|
11494
|
+
import { Command as Command23 } from "commander";
|
|
11495
|
+
var removeCommand = new Command23("remove").alias("rm").description('Remove an authentication profile (defaults to "default")').argument("[name]", "Profile name to remove", "default").option("--env <environment>", "Environment to remove profile from (staging or production)").action(async (name, options) => {
|
|
10947
11496
|
const { env } = options;
|
|
10948
11497
|
const environment = ensureEnvironment(env);
|
|
10949
11498
|
try {
|
|
@@ -10968,9 +11517,9 @@ var removeCommand = new Command18("remove").alias("rm").description('Remove an a
|
|
|
10968
11517
|
|
|
10969
11518
|
// src/commands/profiles/reset.ts
|
|
10970
11519
|
init_string();
|
|
10971
|
-
import { confirm as
|
|
10972
|
-
import { Command as
|
|
10973
|
-
var resetCommand = new
|
|
11520
|
+
import { confirm as confirm10 } from "@inquirer/prompts";
|
|
11521
|
+
import { Command as Command24 } from "commander";
|
|
11522
|
+
var resetCommand = new Command24("reset").description(
|
|
10974
11523
|
"Remove all authentication profiles across all environments (requires confirmation)"
|
|
10975
11524
|
).alias("clear").action(async () => {
|
|
10976
11525
|
try {
|
|
@@ -11006,7 +11555,7 @@ var resetCommand = new Command19("reset").description(
|
|
|
11006
11555
|
logger.newLine();
|
|
11007
11556
|
}
|
|
11008
11557
|
}
|
|
11009
|
-
const confirmed = await
|
|
11558
|
+
const confirmed = await confirm10({
|
|
11010
11559
|
message: "Are you sure you want to remove all profiles?",
|
|
11011
11560
|
default: false
|
|
11012
11561
|
});
|
|
@@ -11046,19 +11595,19 @@ var resetCommand = new Command19("reset").description(
|
|
|
11046
11595
|
});
|
|
11047
11596
|
|
|
11048
11597
|
// src/commands/profiles/index.ts
|
|
11049
|
-
var profilesCommand = new
|
|
11050
|
-
profilesCommand.addCommand(
|
|
11598
|
+
var profilesCommand = new Command25("profiles").description("Manage authentication profiles").action(listProfilesAction);
|
|
11599
|
+
profilesCommand.addCommand(listCommand3);
|
|
11051
11600
|
profilesCommand.addCommand(removeCommand);
|
|
11052
11601
|
profilesCommand.addCommand(resetCommand);
|
|
11053
11602
|
|
|
11054
11603
|
// src/commands/timeback/index.ts
|
|
11055
|
-
import { Command as
|
|
11604
|
+
import { Command as Command31 } from "commander";
|
|
11056
11605
|
|
|
11057
11606
|
// src/commands/timeback/cleanup.ts
|
|
11058
11607
|
init_src();
|
|
11059
|
-
import { confirm as
|
|
11060
|
-
import { Command as
|
|
11061
|
-
var cleanupCommand = new
|
|
11608
|
+
import { confirm as confirm11 } from "@inquirer/prompts";
|
|
11609
|
+
import { Command as Command26 } from "commander";
|
|
11610
|
+
var cleanupCommand = new Command26("cleanup").description("Remove TimeBack integration for your game").option(
|
|
11062
11611
|
"--env <environment>",
|
|
11063
11612
|
"Environment to remove TimeBack integration from (staging or production)"
|
|
11064
11613
|
).action(async (options) => {
|
|
@@ -11080,7 +11629,7 @@ var cleanupCommand = new Command21("cleanup").description("Remove TimeBack integ
|
|
|
11080
11629
|
return;
|
|
11081
11630
|
}
|
|
11082
11631
|
displayCleanupWarning(integration, game.displayName, logger);
|
|
11083
|
-
const confirmed = await
|
|
11632
|
+
const confirmed = await confirm11({
|
|
11084
11633
|
message: "Are you sure you want to remove TimeBack integration?",
|
|
11085
11634
|
default: false
|
|
11086
11635
|
});
|
|
@@ -11109,8 +11658,8 @@ var cleanupCommand = new Command21("cleanup").description("Remove TimeBack integ
|
|
|
11109
11658
|
});
|
|
11110
11659
|
|
|
11111
11660
|
// src/commands/timeback/init.ts
|
|
11112
|
-
import { Command as
|
|
11113
|
-
var initCommand2 = new
|
|
11661
|
+
import { Command as Command27 } from "commander";
|
|
11662
|
+
var initCommand2 = new Command27("init").description("Add TimeBack integration to your project").action(async () => {
|
|
11114
11663
|
try {
|
|
11115
11664
|
logger.newLine();
|
|
11116
11665
|
const configPath = await findConfigPath().catch(() => {
|
|
@@ -11163,8 +11712,8 @@ var initCommand2 = new Command22("init").description("Add TimeBack integration t
|
|
|
11163
11712
|
|
|
11164
11713
|
// src/commands/timeback/setup.ts
|
|
11165
11714
|
init_src();
|
|
11166
|
-
import { Command as
|
|
11167
|
-
var setupCommand = new
|
|
11715
|
+
import { Command as Command28 } from "commander";
|
|
11716
|
+
var setupCommand = new Command28("setup").description("Set up TimeBack integration for your game").option("--dry-run", "Validate configuration without creating resources").option("--verbose, -v", "Output detailed information").option(
|
|
11168
11717
|
"--env <environment>",
|
|
11169
11718
|
"Environment to set up TimeBack integration in (staging or production)"
|
|
11170
11719
|
).action(async (options) => {
|
|
@@ -11256,10 +11805,10 @@ var setupCommand = new Command23("setup").description("Set up TimeBack integrati
|
|
|
11256
11805
|
// src/commands/timeback/update.ts
|
|
11257
11806
|
init_src();
|
|
11258
11807
|
init_string();
|
|
11259
|
-
import { confirm as
|
|
11808
|
+
import { confirm as confirm12 } from "@inquirer/prompts";
|
|
11260
11809
|
import { green as green4, red as red3 } from "colorette";
|
|
11261
|
-
import { Command as
|
|
11262
|
-
var updateCommand = new
|
|
11810
|
+
import { Command as Command29 } from "commander";
|
|
11811
|
+
var updateCommand = new Command29("update").description("Update TimeBack integration configuration for your game").option("--verbose, -v", "Output detailed information").option(
|
|
11263
11812
|
"--env <environment>",
|
|
11264
11813
|
"Environment to update TimeBack integration in (staging or production)"
|
|
11265
11814
|
).action(async (options) => {
|
|
@@ -11337,7 +11886,7 @@ var updateCommand = new Command24("update").description("Update TimeBack integra
|
|
|
11337
11886
|
logger.data(change.label, `${red3(change.current)} \u2192 ${green4(change.next)}`, 1);
|
|
11338
11887
|
}
|
|
11339
11888
|
logger.newLine();
|
|
11340
|
-
const confirmed = await
|
|
11889
|
+
const confirmed = await confirm12({
|
|
11341
11890
|
message: `Update ${changeDetails.length} ${pluralize(changeDetails.length, "field")} in TimeBack?`,
|
|
11342
11891
|
default: false
|
|
11343
11892
|
});
|
|
@@ -11377,8 +11926,8 @@ var updateCommand = new Command24("update").description("Update TimeBack integra
|
|
|
11377
11926
|
|
|
11378
11927
|
// src/commands/timeback/verify.ts
|
|
11379
11928
|
init_src();
|
|
11380
|
-
import { Command as
|
|
11381
|
-
var verifyCommand = new
|
|
11929
|
+
import { Command as Command30 } from "commander";
|
|
11930
|
+
var verifyCommand = new Command30("verify").description("Verify TimeBack integration for your game").option("--verbose, -v", "Output detailed resource information").option(
|
|
11382
11931
|
"--env <environment>",
|
|
11383
11932
|
"Environment to verify TimeBack integration in (staging or production)"
|
|
11384
11933
|
).action(async (options) => {
|
|
@@ -11428,7 +11977,7 @@ var verifyCommand = new Command25("verify").description("Verify TimeBack integra
|
|
|
11428
11977
|
});
|
|
11429
11978
|
|
|
11430
11979
|
// src/commands/timeback/index.ts
|
|
11431
|
-
var timebackCommand = new
|
|
11980
|
+
var timebackCommand = new Command31("timeback").description(
|
|
11432
11981
|
"TimeBack integration management"
|
|
11433
11982
|
);
|
|
11434
11983
|
timebackCommand.addCommand(initCommand2);
|
|
@@ -11438,15 +11987,15 @@ timebackCommand.addCommand(verifyCommand);
|
|
|
11438
11987
|
timebackCommand.addCommand(cleanupCommand);
|
|
11439
11988
|
|
|
11440
11989
|
// src/commands/debug/index.ts
|
|
11441
|
-
import { Command as
|
|
11990
|
+
import { Command as Command33 } from "commander";
|
|
11442
11991
|
|
|
11443
11992
|
// src/commands/debug/bundle.ts
|
|
11444
11993
|
init_src();
|
|
11445
11994
|
init_constants2();
|
|
11446
|
-
import { writeFileSync as
|
|
11447
|
-
import { join as
|
|
11448
|
-
import { Command as
|
|
11449
|
-
var bundleCommand = new
|
|
11995
|
+
import { writeFileSync as writeFileSync11 } from "fs";
|
|
11996
|
+
import { join as join36 } from "path";
|
|
11997
|
+
import { Command as Command32 } from "commander";
|
|
11998
|
+
var bundleCommand = new Command32("bundle").description("Bundle and inspect the game backend worker code (for debugging)").option("-o, --output <path>", "Output file path", CLI_DEFAULT_OUTPUTS.WORKER_BUNDLE).option("--minify", "Minify the output").option("--sourcemap", "Include source maps").action(async (options) => {
|
|
11450
11999
|
try {
|
|
11451
12000
|
const workspace = getWorkspace();
|
|
11452
12001
|
logger.newLine();
|
|
@@ -11474,8 +12023,8 @@ var bundleCommand = new Command27("bundle").description("Bundle and inspect the
|
|
|
11474
12023
|
}),
|
|
11475
12024
|
(result) => `Bundled ${formatSize(result.code.length)}`
|
|
11476
12025
|
);
|
|
11477
|
-
const outputPath =
|
|
11478
|
-
|
|
12026
|
+
const outputPath = join36(workspace, options.output);
|
|
12027
|
+
writeFileSync11(outputPath, bundle.code, "utf-8");
|
|
11479
12028
|
logger.success(`Bundle saved to ${options.output}`);
|
|
11480
12029
|
logger.newLine();
|
|
11481
12030
|
logger.highlight("Bundle Analysis");
|
|
@@ -11515,7 +12064,7 @@ var bundleCommand = new Command27("bundle").description("Bundle and inspect the
|
|
|
11515
12064
|
});
|
|
11516
12065
|
|
|
11517
12066
|
// src/commands/debug/index.ts
|
|
11518
|
-
var debugCommand = new
|
|
12067
|
+
var debugCommand = new Command33("debug").description("Debug and inspect game builds").addCommand(bundleCommand);
|
|
11519
12068
|
|
|
11520
12069
|
// src/index.ts
|
|
11521
12070
|
var __dirname = dirname5(fileURLToPath3(import.meta.url));
|
|
@@ -11534,6 +12083,8 @@ program.addCommand(apiCommand);
|
|
|
11534
12083
|
program.addCommand(dbCommand);
|
|
11535
12084
|
program.addCommand(kvCommand);
|
|
11536
12085
|
program.addCommand(bucketCommand);
|
|
12086
|
+
program.addCommand(secretCommand);
|
|
12087
|
+
program.addCommand(typesCommand);
|
|
11537
12088
|
program.addCommand(gamesCommand);
|
|
11538
12089
|
program.addCommand(deployCommand);
|
|
11539
12090
|
program.addCommand(timebackCommand);
|