playcademy 0.6.0 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +566 -376
- package/dist/types.d.ts +19 -6
- package/dist/utils.js +77 -66
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -64,6 +64,7 @@ var init_package_json = __esm({
|
|
|
64
64
|
var file_loader_exports = {};
|
|
65
65
|
__export(file_loader_exports, {
|
|
66
66
|
findFile: () => findFile,
|
|
67
|
+
getCurrentDirectoryName: () => getCurrentDirectoryName,
|
|
67
68
|
getFileExtension: () => getFileExtension,
|
|
68
69
|
getPackageField: () => getPackageField,
|
|
69
70
|
getPackageName: () => getPackageName,
|
|
@@ -202,6 +203,11 @@ async function getPackageNameVersion(options) {
|
|
|
202
203
|
}
|
|
203
204
|
return getPackageNameVersionFromData(pkg);
|
|
204
205
|
}
|
|
206
|
+
function getCurrentDirectoryName(fallback = "unknown-directory") {
|
|
207
|
+
const cwd = process.cwd();
|
|
208
|
+
const dirName = cwd.split("/").pop();
|
|
209
|
+
return dirName || fallback;
|
|
210
|
+
}
|
|
205
211
|
function getFileExtension(path) {
|
|
206
212
|
return path.split(".").pop()?.toLowerCase();
|
|
207
213
|
}
|
|
@@ -2507,6 +2513,16 @@ var CONFIG_FILE_NAMES = [
|
|
|
2507
2513
|
"playcademy.config.mjs"
|
|
2508
2514
|
];
|
|
2509
2515
|
|
|
2516
|
+
// src/constants/urls.ts
|
|
2517
|
+
var PLAYCADEMY_BASE_URLS = {
|
|
2518
|
+
staging: "https://hub.dev.playcademy.net",
|
|
2519
|
+
production: "https://hub.playcademy.com"
|
|
2520
|
+
};
|
|
2521
|
+
var GAME_BACKEND_DOMAINS = {
|
|
2522
|
+
staging: "staging.playcademy.gg",
|
|
2523
|
+
production: "playcademy.gg"
|
|
2524
|
+
};
|
|
2525
|
+
|
|
2510
2526
|
// src/lib/auth/storage.ts
|
|
2511
2527
|
import { access, mkdir, readFile as readFile2, writeFile } from "node:fs/promises";
|
|
2512
2528
|
import { homedir } from "node:os";
|
|
@@ -2515,7 +2531,7 @@ import { join } from "node:path";
|
|
|
2515
2531
|
// src/lib/core/context.ts
|
|
2516
2532
|
var context = {};
|
|
2517
2533
|
function setCliContext(ctx) {
|
|
2518
|
-
context = ctx;
|
|
2534
|
+
context = { ...context, ...ctx };
|
|
2519
2535
|
}
|
|
2520
2536
|
function getCliContext() {
|
|
2521
2537
|
return context;
|
|
@@ -2525,26 +2541,47 @@ function getWorkspace() {
|
|
|
2525
2541
|
}
|
|
2526
2542
|
|
|
2527
2543
|
// src/lib/core/config.ts
|
|
2544
|
+
function normalizeEnvironment(env) {
|
|
2545
|
+
if (!env) return null;
|
|
2546
|
+
const normalized = env.toLowerCase().trim();
|
|
2547
|
+
if (normalized === "staging" || normalized === "stage") {
|
|
2548
|
+
return "staging";
|
|
2549
|
+
}
|
|
2550
|
+
if (normalized === "production" || normalized === "prod") {
|
|
2551
|
+
return "production";
|
|
2552
|
+
}
|
|
2553
|
+
return null;
|
|
2554
|
+
}
|
|
2555
|
+
function ensureEnvironment(env, logger2) {
|
|
2556
|
+
if (env) {
|
|
2557
|
+
const normalized = normalizeEnvironment(env);
|
|
2558
|
+
if (!normalized) {
|
|
2559
|
+
logger2.newLine();
|
|
2560
|
+
logger2.error(`Invalid environment: "${env}"`);
|
|
2561
|
+
logger2.newLine();
|
|
2562
|
+
logger2.info("Valid environments: staging, production");
|
|
2563
|
+
logger2.newLine();
|
|
2564
|
+
process.exit(1);
|
|
2565
|
+
}
|
|
2566
|
+
setCliContext({ environment: normalized });
|
|
2567
|
+
}
|
|
2568
|
+
return getEnvironment();
|
|
2569
|
+
}
|
|
2528
2570
|
function getEnvironment() {
|
|
2529
2571
|
const context2 = getCliContext();
|
|
2530
2572
|
if (context2.environment) {
|
|
2531
2573
|
return context2.environment;
|
|
2532
2574
|
}
|
|
2533
2575
|
const env = process.env.PLAYCADEMY_ENV?.toLowerCase();
|
|
2534
|
-
if (env === "staging") {
|
|
2535
|
-
return
|
|
2576
|
+
if (env === "staging" || env === "production") {
|
|
2577
|
+
return env;
|
|
2536
2578
|
}
|
|
2537
|
-
return "
|
|
2579
|
+
return "staging";
|
|
2538
2580
|
}
|
|
2539
2581
|
function getBaseUrl() {
|
|
2540
2582
|
const explicitUrl = process.env.PLAYCADEMY_BASE_URL;
|
|
2541
|
-
if (explicitUrl)
|
|
2542
|
-
|
|
2543
|
-
}
|
|
2544
|
-
if (getEnvironment() === "staging") {
|
|
2545
|
-
return "https://hub.dev.playcademy.net";
|
|
2546
|
-
}
|
|
2547
|
-
return "https://hub.playcademy.com";
|
|
2583
|
+
if (explicitUrl) return explicitUrl;
|
|
2584
|
+
return PLAYCADEMY_BASE_URLS[getEnvironment()];
|
|
2548
2585
|
}
|
|
2549
2586
|
function getApiUrl(path) {
|
|
2550
2587
|
const baseUrl = getBaseUrl();
|
|
@@ -2567,6 +2604,12 @@ async function ensureAuthDir() {
|
|
|
2567
2604
|
const authDir = join(homedir(), ".playcademy");
|
|
2568
2605
|
await mkdir(authDir, { recursive: true });
|
|
2569
2606
|
}
|
|
2607
|
+
function createEmptyEnvironmentProfiles() {
|
|
2608
|
+
return {
|
|
2609
|
+
default: null,
|
|
2610
|
+
profiles: {}
|
|
2611
|
+
};
|
|
2612
|
+
}
|
|
2570
2613
|
async function loadAuthStore() {
|
|
2571
2614
|
try {
|
|
2572
2615
|
await ensureAuthDir();
|
|
@@ -2577,8 +2620,8 @@ async function loadAuthStore() {
|
|
|
2577
2620
|
} catch {
|
|
2578
2621
|
}
|
|
2579
2622
|
return {
|
|
2580
|
-
|
|
2581
|
-
|
|
2623
|
+
staging: createEmptyEnvironmentProfiles(),
|
|
2624
|
+
production: createEmptyEnvironmentProfiles()
|
|
2582
2625
|
};
|
|
2583
2626
|
}
|
|
2584
2627
|
async function saveAuthStore(store) {
|
|
@@ -2595,45 +2638,79 @@ async function getCurrentProfile() {
|
|
|
2595
2638
|
};
|
|
2596
2639
|
}
|
|
2597
2640
|
const store = await loadAuthStore();
|
|
2641
|
+
const environment = getEnvironment();
|
|
2598
2642
|
const profileName = getProfileName();
|
|
2643
|
+
const envProfiles = store[environment];
|
|
2644
|
+
if (!envProfiles) {
|
|
2645
|
+
return null;
|
|
2646
|
+
}
|
|
2599
2647
|
if (profileName === "default") {
|
|
2600
|
-
return
|
|
2648
|
+
return envProfiles.default;
|
|
2601
2649
|
}
|
|
2602
|
-
return
|
|
2650
|
+
return envProfiles.profiles[profileName] || null;
|
|
2603
2651
|
}
|
|
2604
|
-
async function saveProfile(profileName, profile) {
|
|
2652
|
+
async function saveProfile(environment, profileName, profile) {
|
|
2605
2653
|
const store = await loadAuthStore();
|
|
2654
|
+
if (!store[environment]) {
|
|
2655
|
+
store[environment] = createEmptyEnvironmentProfiles();
|
|
2656
|
+
}
|
|
2657
|
+
const envProfiles = store[environment];
|
|
2606
2658
|
if (profileName === "default") {
|
|
2607
|
-
|
|
2659
|
+
envProfiles.default = profile;
|
|
2608
2660
|
} else {
|
|
2609
|
-
|
|
2661
|
+
envProfiles.profiles[profileName] = profile;
|
|
2610
2662
|
}
|
|
2611
2663
|
await saveAuthStore(store);
|
|
2612
2664
|
}
|
|
2613
|
-
async function removeProfile(profileName) {
|
|
2665
|
+
async function removeProfile(environment, profileName) {
|
|
2614
2666
|
const store = await loadAuthStore();
|
|
2667
|
+
if (!store[environment]) {
|
|
2668
|
+
return;
|
|
2669
|
+
}
|
|
2670
|
+
const envProfiles = store[environment];
|
|
2615
2671
|
if (profileName === "default") {
|
|
2616
|
-
|
|
2672
|
+
envProfiles.default = null;
|
|
2617
2673
|
} else {
|
|
2618
|
-
delete
|
|
2674
|
+
delete envProfiles.profiles[profileName];
|
|
2619
2675
|
}
|
|
2620
2676
|
await saveAuthStore(store);
|
|
2621
2677
|
}
|
|
2622
|
-
async function getProfile(profileName) {
|
|
2678
|
+
async function getProfile(environment, profileName) {
|
|
2623
2679
|
const store = await loadAuthStore();
|
|
2680
|
+
const envProfiles = store[environment];
|
|
2681
|
+
if (!envProfiles) {
|
|
2682
|
+
return null;
|
|
2683
|
+
}
|
|
2624
2684
|
if (profileName === "default") {
|
|
2625
|
-
return
|
|
2685
|
+
return envProfiles.default;
|
|
2626
2686
|
}
|
|
2627
|
-
return
|
|
2687
|
+
return envProfiles.profiles[profileName] || null;
|
|
2628
2688
|
}
|
|
2629
2689
|
async function listProfiles() {
|
|
2630
2690
|
const store = await loadAuthStore();
|
|
2631
|
-
const
|
|
2632
|
-
|
|
2633
|
-
|
|
2634
|
-
|
|
2635
|
-
|
|
2636
|
-
|
|
2691
|
+
const profileMap = /* @__PURE__ */ new Map();
|
|
2692
|
+
const stagingProfiles = [];
|
|
2693
|
+
if (store.staging.default) {
|
|
2694
|
+
stagingProfiles.push("default");
|
|
2695
|
+
}
|
|
2696
|
+
stagingProfiles.push(...Object.keys(store.staging.profiles));
|
|
2697
|
+
profileMap.set("staging", stagingProfiles);
|
|
2698
|
+
const productionProfiles = [];
|
|
2699
|
+
if (store.production.default) {
|
|
2700
|
+
productionProfiles.push("default");
|
|
2701
|
+
}
|
|
2702
|
+
productionProfiles.push(...Object.keys(store.production.profiles));
|
|
2703
|
+
profileMap.set("production", productionProfiles);
|
|
2704
|
+
return profileMap;
|
|
2705
|
+
}
|
|
2706
|
+
async function getAuthenticatedEnvironments() {
|
|
2707
|
+
const store = await loadAuthStore();
|
|
2708
|
+
const environments = [];
|
|
2709
|
+
const hasStaging = store.staging.default !== null || Object.keys(store.staging.profiles).length > 0;
|
|
2710
|
+
const hasProduction = store.production.default !== null || Object.keys(store.production.profiles).length > 0;
|
|
2711
|
+
if (hasStaging) environments.push("staging");
|
|
2712
|
+
if (hasProduction) environments.push("production");
|
|
2713
|
+
return environments;
|
|
2637
2714
|
}
|
|
2638
2715
|
|
|
2639
2716
|
// src/lib/auth/http-server/server.ts
|
|
@@ -7254,15 +7331,7 @@ function createDevNamespace(client) {
|
|
|
7254
7331
|
throw new Error(`File upload failed: ${uploadResponse.status} ${uploadResponse.statusText}`);
|
|
7255
7332
|
}
|
|
7256
7333
|
}
|
|
7257
|
-
const
|
|
7258
|
-
const anyClient = client;
|
|
7259
|
-
try {
|
|
7260
|
-
return typeof anyClient.getBaseUrl === "function" ? anyClient.getBaseUrl() : "/api";
|
|
7261
|
-
} catch {
|
|
7262
|
-
return "/api";
|
|
7263
|
-
}
|
|
7264
|
-
})();
|
|
7265
|
-
const finalizeUrl = baseUrl.replace(/\/$/, "") + "/games/uploads/finalize/";
|
|
7334
|
+
const finalizeUrl = `${client.baseUrl}/games/uploads/finalize/`;
|
|
7266
7335
|
const authToken = client.getToken();
|
|
7267
7336
|
const tokenType = client.getTokenType();
|
|
7268
7337
|
const headers = {
|
|
@@ -8740,13 +8809,13 @@ var init_achievements = () => {
|
|
|
8740
8809
|
function createTimebackNamespace(client) {
|
|
8741
8810
|
return {
|
|
8742
8811
|
recordProgress: (progressData) => {
|
|
8743
|
-
return client["
|
|
8812
|
+
return client["requestGameBackend"]("/api/integrations/timeback/progress", "POST", { progressData });
|
|
8744
8813
|
},
|
|
8745
8814
|
recordSessionEnd: (sessionData) => {
|
|
8746
|
-
return client["
|
|
8815
|
+
return client["requestGameBackend"]("/api/integrations/timeback/session-end", "POST", { sessionData });
|
|
8747
8816
|
},
|
|
8748
8817
|
awardXP: (xpAmount, metadata) => {
|
|
8749
|
-
return client["
|
|
8818
|
+
return client["requestGameBackend"]("/api/integrations/timeback/award-xp", "POST", { xpAmount, metadata });
|
|
8750
8819
|
},
|
|
8751
8820
|
management: {
|
|
8752
8821
|
setup: (request2) => {
|
|
@@ -9055,7 +9124,7 @@ var init_client = __esm2(() => {
|
|
|
9055
9124
|
authContext;
|
|
9056
9125
|
initPayload;
|
|
9057
9126
|
constructor(config) {
|
|
9058
|
-
this.baseUrl = config?.baseUrl
|
|
9127
|
+
this.baseUrl = config?.baseUrl?.endsWith("/api") ? config.baseUrl : `${config?.baseUrl}/api`;
|
|
9059
9128
|
this.gameUrl = config?.gameUrl;
|
|
9060
9129
|
this.gameId = config?.gameId;
|
|
9061
9130
|
this.config = config || {};
|
|
@@ -9071,8 +9140,9 @@ var init_client = __esm2(() => {
|
|
|
9071
9140
|
return `${effectiveBaseUrl}/api`;
|
|
9072
9141
|
}
|
|
9073
9142
|
getGameBackendUrl() {
|
|
9074
|
-
if (!this.gameUrl)
|
|
9075
|
-
|
|
9143
|
+
if (!this.gameUrl) {
|
|
9144
|
+
throw new PlaycademyError("Game backend URL not configured. gameUrl must be set to use game backend features.");
|
|
9145
|
+
}
|
|
9076
9146
|
const isRelative = this.gameUrl.startsWith("/");
|
|
9077
9147
|
const isBrowser2 = typeof window !== "undefined";
|
|
9078
9148
|
const effectiveGameUrl = isRelative && isBrowser2 ? `${window.location.origin}${this.gameUrl}` : this.gameUrl;
|
|
@@ -9109,17 +9179,29 @@ var init_client = __esm2(() => {
|
|
|
9109
9179
|
listener(payload);
|
|
9110
9180
|
});
|
|
9111
9181
|
}
|
|
9112
|
-
async request(path, method, body, headers
|
|
9182
|
+
async request(path, method, body, headers) {
|
|
9113
9183
|
const effectiveHeaders = {
|
|
9114
9184
|
...headers,
|
|
9115
9185
|
...this.authStrategy.getHeaders()
|
|
9116
9186
|
};
|
|
9117
|
-
const targetBaseUrl = useGameBackend ? this.getGameBackendUrl() : this.baseUrl;
|
|
9118
9187
|
return request({
|
|
9119
9188
|
path,
|
|
9120
9189
|
method,
|
|
9121
9190
|
body,
|
|
9122
|
-
baseUrl:
|
|
9191
|
+
baseUrl: this.baseUrl,
|
|
9192
|
+
extraHeaders: effectiveHeaders
|
|
9193
|
+
});
|
|
9194
|
+
}
|
|
9195
|
+
async requestGameBackend(path, method, body, headers) {
|
|
9196
|
+
const effectiveHeaders = {
|
|
9197
|
+
...headers,
|
|
9198
|
+
...this.authStrategy.getHeaders()
|
|
9199
|
+
};
|
|
9200
|
+
return request({
|
|
9201
|
+
path,
|
|
9202
|
+
method,
|
|
9203
|
+
body,
|
|
9204
|
+
baseUrl: this.getGameBackendUrl(),
|
|
9123
9205
|
extraHeaders: effectiveHeaders
|
|
9124
9206
|
});
|
|
9125
9207
|
}
|
|
@@ -9180,13 +9262,184 @@ var init_client = __esm2(() => {
|
|
|
9180
9262
|
init_client();
|
|
9181
9263
|
init_messaging();
|
|
9182
9264
|
|
|
9265
|
+
// src/lib/core/logger.ts
|
|
9266
|
+
import {
|
|
9267
|
+
blue,
|
|
9268
|
+
bold,
|
|
9269
|
+
cyan,
|
|
9270
|
+
dim,
|
|
9271
|
+
gray,
|
|
9272
|
+
green,
|
|
9273
|
+
greenBright,
|
|
9274
|
+
red,
|
|
9275
|
+
yellow,
|
|
9276
|
+
yellowBright
|
|
9277
|
+
} from "colorette";
|
|
9278
|
+
import { colorize } from "json-colorizer";
|
|
9279
|
+
function customTransform(text2) {
|
|
9280
|
+
const highlightCode = (text3) => text3.replace(/`([^`]+)`/g, (_, code) => greenBright(code));
|
|
9281
|
+
return highlightCode(text2);
|
|
9282
|
+
}
|
|
9283
|
+
var logger = {
|
|
9284
|
+
table: (data) => {
|
|
9285
|
+
console.table(data);
|
|
9286
|
+
},
|
|
9287
|
+
/**
|
|
9288
|
+
* Info message - general information
|
|
9289
|
+
*/
|
|
9290
|
+
info: (message, indent = 0) => {
|
|
9291
|
+
const spaces = " ".repeat(indent);
|
|
9292
|
+
console.log(`${spaces}${blue("\u2139")} ${bold(customTransform(message))}`);
|
|
9293
|
+
},
|
|
9294
|
+
/**
|
|
9295
|
+
* Admonition - highlighted note/tip/warning box (Docusaurus-style)
|
|
9296
|
+
*/
|
|
9297
|
+
admonition: (type, title, lines, indent = 0) => {
|
|
9298
|
+
const spaces = " ".repeat(indent);
|
|
9299
|
+
const configs = {
|
|
9300
|
+
note: { color: green },
|
|
9301
|
+
tip: { color: cyan },
|
|
9302
|
+
info: { color: blue },
|
|
9303
|
+
warning: { color: yellow }
|
|
9304
|
+
};
|
|
9305
|
+
const { color: color2 } = configs[type];
|
|
9306
|
+
console.log(`${spaces}${color2("\u250C\u2500")} ${bold(color2(title.toUpperCase()))}`);
|
|
9307
|
+
if (lines && lines.length > 0) {
|
|
9308
|
+
lines.forEach((line2) => {
|
|
9309
|
+
console.log(`${spaces}${color2("\u2502")} ${customTransform(line2)}`);
|
|
9310
|
+
});
|
|
9311
|
+
}
|
|
9312
|
+
console.log(`${spaces}${color2("\u2514\u2500")}`);
|
|
9313
|
+
},
|
|
9314
|
+
/**
|
|
9315
|
+
* Dim message - less important information
|
|
9316
|
+
*/
|
|
9317
|
+
dim: (message, indent = 0) => {
|
|
9318
|
+
const spaces = " ".repeat(indent);
|
|
9319
|
+
console.log(`${spaces}${dim(customTransform(message))}`);
|
|
9320
|
+
},
|
|
9321
|
+
/**
|
|
9322
|
+
* Success message - operation completed successfully
|
|
9323
|
+
*/
|
|
9324
|
+
success: (message, indent = 0) => {
|
|
9325
|
+
const spaces = " ".repeat(indent);
|
|
9326
|
+
console.log(`${spaces}${green("\u2714")} ${bold(customTransform(message))}`);
|
|
9327
|
+
},
|
|
9328
|
+
remark: (message, indent = 0) => {
|
|
9329
|
+
const spaces = " ".repeat(indent);
|
|
9330
|
+
console.log(`${spaces}${bold(yellowBright("\u2726"))} ${bold(customTransform(message))}`);
|
|
9331
|
+
},
|
|
9332
|
+
/**
|
|
9333
|
+
* Error message - operation failed
|
|
9334
|
+
*/
|
|
9335
|
+
error: (message, indent = 0) => {
|
|
9336
|
+
const spaces = " ".repeat(indent);
|
|
9337
|
+
console.error(`${spaces}${red("\u2716")} ${customTransform(message)}`);
|
|
9338
|
+
},
|
|
9339
|
+
bold: (message, indent = 0) => {
|
|
9340
|
+
const spaces = " ".repeat(indent);
|
|
9341
|
+
console.log(`${spaces}${bold(customTransform(message))}`);
|
|
9342
|
+
},
|
|
9343
|
+
/**
|
|
9344
|
+
* Warning message - something to be aware of
|
|
9345
|
+
*/
|
|
9346
|
+
warn: (message, indent = 0) => {
|
|
9347
|
+
const spaces = " ".repeat(indent);
|
|
9348
|
+
console.warn(`${spaces}${yellow("\u26A0")} ${bold(customTransform(message))}`);
|
|
9349
|
+
},
|
|
9350
|
+
/**
|
|
9351
|
+
* Debug message - only shown when DEBUG env var is set
|
|
9352
|
+
*/
|
|
9353
|
+
debug: (message, indent = 0) => {
|
|
9354
|
+
const spaces = " ".repeat(indent);
|
|
9355
|
+
if (process.env.DEBUG) {
|
|
9356
|
+
console.log(gray("[DEBUG]"), `${spaces}${message}`);
|
|
9357
|
+
}
|
|
9358
|
+
},
|
|
9359
|
+
/**
|
|
9360
|
+
* Step message - shows progress through a process
|
|
9361
|
+
*/
|
|
9362
|
+
step: (step, total, message, indent = 0) => {
|
|
9363
|
+
const spaces = " ".repeat(indent);
|
|
9364
|
+
console.log(spaces + cyan(`[${step}/${total}]`), customTransform(message));
|
|
9365
|
+
},
|
|
9366
|
+
/**
|
|
9367
|
+
* Highlighted message - draws attention
|
|
9368
|
+
*/
|
|
9369
|
+
highlight: (message, indent = 0) => {
|
|
9370
|
+
const spaces = " ".repeat(indent);
|
|
9371
|
+
console.log(bold(`${spaces}${cyan(customTransform(message))}`));
|
|
9372
|
+
},
|
|
9373
|
+
/**
|
|
9374
|
+
* Aside message - for side information
|
|
9375
|
+
*/
|
|
9376
|
+
aside: (message, indent = 0) => {
|
|
9377
|
+
const spaces = " ".repeat(indent);
|
|
9378
|
+
console.log(`${spaces}${bold(customTransform(message))}`);
|
|
9379
|
+
},
|
|
9380
|
+
/**
|
|
9381
|
+
* Data display - for structured data output
|
|
9382
|
+
*/
|
|
9383
|
+
data: (label, value, indent = 0) => {
|
|
9384
|
+
const spaces = " ".repeat(indent);
|
|
9385
|
+
if (value !== void 0) {
|
|
9386
|
+
console.log(`${spaces}${dim(label + ":")} ${bold(value)}`);
|
|
9387
|
+
} else {
|
|
9388
|
+
console.log(`${spaces}${dim(label)}`);
|
|
9389
|
+
}
|
|
9390
|
+
},
|
|
9391
|
+
/**
|
|
9392
|
+
* JSON output - pretty-printed JSON
|
|
9393
|
+
*/
|
|
9394
|
+
json: (data, indent = 0) => {
|
|
9395
|
+
const spaces = " ".repeat(indent);
|
|
9396
|
+
const jsonString = colorize(JSON.stringify(data, null, 2));
|
|
9397
|
+
jsonString.split("\n").forEach((line2) => {
|
|
9398
|
+
console.log(`${spaces}${line2}`);
|
|
9399
|
+
});
|
|
9400
|
+
},
|
|
9401
|
+
/**
|
|
9402
|
+
* New line
|
|
9403
|
+
*/
|
|
9404
|
+
newLine: () => {
|
|
9405
|
+
console.log();
|
|
9406
|
+
},
|
|
9407
|
+
/**
|
|
9408
|
+
* Raw output - no formatting, useful for ASCII art or pre-formatted text
|
|
9409
|
+
*/
|
|
9410
|
+
raw: (text2, indent = 0) => {
|
|
9411
|
+
const spaces = " ".repeat(indent);
|
|
9412
|
+
console.log(`${spaces}${text2}`);
|
|
9413
|
+
},
|
|
9414
|
+
/**
|
|
9415
|
+
* Display a configuration error with helpful suggestions
|
|
9416
|
+
*/
|
|
9417
|
+
configError: (error, indent = 0) => {
|
|
9418
|
+
const spaces = " ".repeat(indent);
|
|
9419
|
+
const isConfigError = error && typeof error === "object" && "name" in error && error.name === "ConfigError";
|
|
9420
|
+
if (isConfigError && "message" in error && "field" in error && "suggestion" in error) {
|
|
9421
|
+
const configErr = error;
|
|
9422
|
+
console.error(`${spaces}${red("\u2716")} ${bold(configErr.message)}`);
|
|
9423
|
+
if (configErr.field) {
|
|
9424
|
+
console.error(`${spaces} ${dim("Field:")} ${configErr.field}`);
|
|
9425
|
+
}
|
|
9426
|
+
if (configErr.suggestion) {
|
|
9427
|
+
console.error(`${spaces} ${dim("Fix:")} ${configErr.suggestion}`);
|
|
9428
|
+
}
|
|
9429
|
+
} else if (error instanceof Error) {
|
|
9430
|
+
console.error(`${spaces}${red("\u2716")} ${bold(error.message)}`);
|
|
9431
|
+
} else {
|
|
9432
|
+
console.error(`${spaces}${red("\u2716")} ${bold(String(error))}`);
|
|
9433
|
+
}
|
|
9434
|
+
}
|
|
9435
|
+
};
|
|
9436
|
+
|
|
9183
9437
|
// src/lib/core/client.ts
|
|
9184
9438
|
async function createClient() {
|
|
9185
9439
|
const profile = await getCurrentProfile();
|
|
9186
9440
|
const baseUrl = getBaseUrl();
|
|
9187
|
-
const apiBaseUrl = `${baseUrl}/api`;
|
|
9188
9441
|
const client = new PlaycademyClient({
|
|
9189
|
-
baseUrl
|
|
9442
|
+
baseUrl,
|
|
9190
9443
|
token: profile?.token
|
|
9191
9444
|
});
|
|
9192
9445
|
if (profile?.token && profile?.tokenType) {
|
|
@@ -9196,8 +9449,15 @@ async function createClient() {
|
|
|
9196
9449
|
}
|
|
9197
9450
|
async function requireAuthenticatedClient() {
|
|
9198
9451
|
const profile = await getCurrentProfile();
|
|
9452
|
+
const environment = getEnvironment();
|
|
9199
9453
|
if (!profile) {
|
|
9200
|
-
|
|
9454
|
+
logger.newLine();
|
|
9455
|
+
logger.admonition("warning", "Login Required", [
|
|
9456
|
+
`You are not logged into ${environment}.`,
|
|
9457
|
+
environment === "production" ? `Run \`playcademy login --env ${environment}\` to authenticate.` : "Run `playcademy login` to authenticate."
|
|
9458
|
+
]);
|
|
9459
|
+
logger.newLine();
|
|
9460
|
+
process.exit(1);
|
|
9201
9461
|
}
|
|
9202
9462
|
const client = await createClient();
|
|
9203
9463
|
return client;
|
|
@@ -9236,10 +9496,10 @@ var cursor = {
|
|
|
9236
9496
|
function color(text2, colorCode) {
|
|
9237
9497
|
return `${colorCode}${text2}${styles.reset}`;
|
|
9238
9498
|
}
|
|
9239
|
-
function
|
|
9499
|
+
function dim2(text2) {
|
|
9240
9500
|
return color(text2, styles.dim);
|
|
9241
9501
|
}
|
|
9242
|
-
function
|
|
9502
|
+
function bold2(text2) {
|
|
9243
9503
|
return color(text2, styles.bold);
|
|
9244
9504
|
}
|
|
9245
9505
|
var isInteractive = typeof process !== "undefined" && process.stdout?.isTTY && !process.env.CI && process.env.TERM !== "dumb";
|
|
@@ -9369,7 +9629,7 @@ var Spinner = class {
|
|
|
9369
9629
|
// ../utils/src/log.ts
|
|
9370
9630
|
function formatDuration(ms) {
|
|
9371
9631
|
const duration = ms < 1e3 ? `${Math.round(ms)}ms` : `${(ms / 1e3).toFixed(2)}s`;
|
|
9372
|
-
return
|
|
9632
|
+
return bold2(dim2(`[${duration}]`));
|
|
9373
9633
|
}
|
|
9374
9634
|
async function runStep(text2, action, successText, options) {
|
|
9375
9635
|
const effectiveAction = action ?? (async () => void 0);
|
|
@@ -9393,7 +9653,7 @@ async function runStep(text2, action, successText, options) {
|
|
|
9393
9653
|
} else {
|
|
9394
9654
|
finalSuccessText = successText ?? text2;
|
|
9395
9655
|
}
|
|
9396
|
-
finalSuccessText =
|
|
9656
|
+
finalSuccessText = bold2(finalSuccessText);
|
|
9397
9657
|
if (hasAction) {
|
|
9398
9658
|
const durationText = formatDuration(duration);
|
|
9399
9659
|
finalSuccessText = `${finalSuccessText} ${durationText}`;
|
|
@@ -9478,178 +9738,6 @@ async function getGameFromConfig(client) {
|
|
|
9478
9738
|
return { game, config };
|
|
9479
9739
|
}
|
|
9480
9740
|
|
|
9481
|
-
// src/lib/core/logger.ts
|
|
9482
|
-
import {
|
|
9483
|
-
blue,
|
|
9484
|
-
bold as bold2,
|
|
9485
|
-
cyan,
|
|
9486
|
-
dim as dim2,
|
|
9487
|
-
gray,
|
|
9488
|
-
green,
|
|
9489
|
-
greenBright,
|
|
9490
|
-
red,
|
|
9491
|
-
yellow,
|
|
9492
|
-
yellowBright
|
|
9493
|
-
} from "colorette";
|
|
9494
|
-
import { colorize } from "json-colorizer";
|
|
9495
|
-
function customTransform(text2) {
|
|
9496
|
-
const highlightCode = (text3) => text3.replace(/`([^`]+)`/g, (_, code) => greenBright(code));
|
|
9497
|
-
return highlightCode(text2);
|
|
9498
|
-
}
|
|
9499
|
-
var logger = {
|
|
9500
|
-
table: (data) => {
|
|
9501
|
-
console.table(data);
|
|
9502
|
-
},
|
|
9503
|
-
/**
|
|
9504
|
-
* Info message - general information
|
|
9505
|
-
*/
|
|
9506
|
-
info: (message, indent = 0) => {
|
|
9507
|
-
const spaces = " ".repeat(indent);
|
|
9508
|
-
console.log(`${spaces}${blue("\u2139")} ${bold2(customTransform(message))}`);
|
|
9509
|
-
},
|
|
9510
|
-
/**
|
|
9511
|
-
* Admonition - highlighted note/tip/warning box (Docusaurus-style)
|
|
9512
|
-
*/
|
|
9513
|
-
admonition: (type, title, lines, indent = 0) => {
|
|
9514
|
-
const spaces = " ".repeat(indent);
|
|
9515
|
-
const configs = {
|
|
9516
|
-
note: { color: green },
|
|
9517
|
-
tip: { color: cyan },
|
|
9518
|
-
info: { color: blue },
|
|
9519
|
-
warning: { color: yellow }
|
|
9520
|
-
};
|
|
9521
|
-
const { color: color2 } = configs[type];
|
|
9522
|
-
console.log(`${spaces}${color2("\u250C\u2500")} ${bold2(color2(title.toUpperCase()))}`);
|
|
9523
|
-
if (lines && lines.length > 0) {
|
|
9524
|
-
lines.forEach((line2) => {
|
|
9525
|
-
console.log(`${spaces}${color2("\u2502")} ${customTransform(line2)}`);
|
|
9526
|
-
});
|
|
9527
|
-
}
|
|
9528
|
-
console.log(`${spaces}${color2("\u2514\u2500")}`);
|
|
9529
|
-
},
|
|
9530
|
-
/**
|
|
9531
|
-
* Dim message - less important information
|
|
9532
|
-
*/
|
|
9533
|
-
dim: (message, indent = 0) => {
|
|
9534
|
-
const spaces = " ".repeat(indent);
|
|
9535
|
-
console.log(`${spaces}${dim2(customTransform(message))}`);
|
|
9536
|
-
},
|
|
9537
|
-
/**
|
|
9538
|
-
* Success message - operation completed successfully
|
|
9539
|
-
*/
|
|
9540
|
-
success: (message, indent = 0) => {
|
|
9541
|
-
const spaces = " ".repeat(indent);
|
|
9542
|
-
console.log(`${spaces}${green("\u2714")} ${bold2(customTransform(message))}`);
|
|
9543
|
-
},
|
|
9544
|
-
remark: (message, indent = 0) => {
|
|
9545
|
-
const spaces = " ".repeat(indent);
|
|
9546
|
-
console.log(`${spaces}${bold2(yellowBright("\u2726"))} ${bold2(customTransform(message))}`);
|
|
9547
|
-
},
|
|
9548
|
-
/**
|
|
9549
|
-
* Error message - operation failed
|
|
9550
|
-
*/
|
|
9551
|
-
error: (message, indent = 0) => {
|
|
9552
|
-
const spaces = " ".repeat(indent);
|
|
9553
|
-
console.error(`${spaces}${red("\u2716")} ${customTransform(message)}`);
|
|
9554
|
-
},
|
|
9555
|
-
bold: (message, indent = 0) => {
|
|
9556
|
-
const spaces = " ".repeat(indent);
|
|
9557
|
-
console.log(`${spaces}${bold2(customTransform(message))}`);
|
|
9558
|
-
},
|
|
9559
|
-
/**
|
|
9560
|
-
* Warning message - something to be aware of
|
|
9561
|
-
*/
|
|
9562
|
-
warn: (message, indent = 0) => {
|
|
9563
|
-
const spaces = " ".repeat(indent);
|
|
9564
|
-
console.warn(`${spaces}${yellow("\u26A0")} ${bold2(customTransform(message))}`);
|
|
9565
|
-
},
|
|
9566
|
-
/**
|
|
9567
|
-
* Debug message - only shown when DEBUG env var is set
|
|
9568
|
-
*/
|
|
9569
|
-
debug: (message, indent = 0) => {
|
|
9570
|
-
const spaces = " ".repeat(indent);
|
|
9571
|
-
if (process.env.DEBUG) {
|
|
9572
|
-
console.log(gray("[DEBUG]"), `${spaces}${message}`);
|
|
9573
|
-
}
|
|
9574
|
-
},
|
|
9575
|
-
/**
|
|
9576
|
-
* Step message - shows progress through a process
|
|
9577
|
-
*/
|
|
9578
|
-
step: (step, total, message, indent = 0) => {
|
|
9579
|
-
const spaces = " ".repeat(indent);
|
|
9580
|
-
console.log(spaces + cyan(`[${step}/${total}]`), customTransform(message));
|
|
9581
|
-
},
|
|
9582
|
-
/**
|
|
9583
|
-
* Highlighted message - draws attention
|
|
9584
|
-
*/
|
|
9585
|
-
highlight: (message, indent = 0) => {
|
|
9586
|
-
const spaces = " ".repeat(indent);
|
|
9587
|
-
console.log(bold2(`${spaces}${cyan(customTransform(message))}`));
|
|
9588
|
-
},
|
|
9589
|
-
/**
|
|
9590
|
-
* Aside message - for side information
|
|
9591
|
-
*/
|
|
9592
|
-
aside: (message, indent = 0) => {
|
|
9593
|
-
const spaces = " ".repeat(indent);
|
|
9594
|
-
console.log(`${spaces}${bold2(customTransform(message))}`);
|
|
9595
|
-
},
|
|
9596
|
-
/**
|
|
9597
|
-
* Data display - for structured data output
|
|
9598
|
-
*/
|
|
9599
|
-
data: (label, value, indent = 0) => {
|
|
9600
|
-
const spaces = " ".repeat(indent);
|
|
9601
|
-
if (value !== void 0) {
|
|
9602
|
-
console.log(`${spaces}${dim2(label + ":")} ${bold2(value)}`);
|
|
9603
|
-
} else {
|
|
9604
|
-
console.log(`${spaces}${dim2(label)}`);
|
|
9605
|
-
}
|
|
9606
|
-
},
|
|
9607
|
-
/**
|
|
9608
|
-
* JSON output - pretty-printed JSON
|
|
9609
|
-
*/
|
|
9610
|
-
json: (data, indent = 0) => {
|
|
9611
|
-
const spaces = " ".repeat(indent);
|
|
9612
|
-
const jsonString = colorize(JSON.stringify(data, null, 2));
|
|
9613
|
-
jsonString.split("\n").forEach((line2) => {
|
|
9614
|
-
console.log(`${spaces}${line2}`);
|
|
9615
|
-
});
|
|
9616
|
-
},
|
|
9617
|
-
/**
|
|
9618
|
-
* New line
|
|
9619
|
-
*/
|
|
9620
|
-
newLine: () => {
|
|
9621
|
-
console.log();
|
|
9622
|
-
},
|
|
9623
|
-
/**
|
|
9624
|
-
* Raw output - no formatting, useful for ASCII art or pre-formatted text
|
|
9625
|
-
*/
|
|
9626
|
-
raw: (text2, indent = 0) => {
|
|
9627
|
-
const spaces = " ".repeat(indent);
|
|
9628
|
-
console.log(`${spaces}${text2}`);
|
|
9629
|
-
},
|
|
9630
|
-
/**
|
|
9631
|
-
* Display a configuration error with helpful suggestions
|
|
9632
|
-
*/
|
|
9633
|
-
configError: (error, indent = 0) => {
|
|
9634
|
-
const spaces = " ".repeat(indent);
|
|
9635
|
-
const isConfigError = error && typeof error === "object" && "name" in error && error.name === "ConfigError";
|
|
9636
|
-
if (isConfigError && "message" in error && "field" in error && "suggestion" in error) {
|
|
9637
|
-
const configErr = error;
|
|
9638
|
-
console.error(`${spaces}${red("\u2716")} ${bold2(configErr.message)}`);
|
|
9639
|
-
if (configErr.field) {
|
|
9640
|
-
console.error(`${spaces} ${dim2("Field:")} ${configErr.field}`);
|
|
9641
|
-
}
|
|
9642
|
-
if (configErr.suggestion) {
|
|
9643
|
-
console.error(`${spaces} ${dim2("Fix:")} ${configErr.suggestion}`);
|
|
9644
|
-
}
|
|
9645
|
-
} else if (error instanceof Error) {
|
|
9646
|
-
console.error(`${spaces}${red("\u2716")} ${bold2(error.message)}`);
|
|
9647
|
-
} else {
|
|
9648
|
-
console.error(`${spaces}${red("\u2716")} ${bold2(String(error))}`);
|
|
9649
|
-
}
|
|
9650
|
-
}
|
|
9651
|
-
};
|
|
9652
|
-
|
|
9653
9741
|
// src/lib/deploy/backend.ts
|
|
9654
9742
|
import { createHash as createHash2 } from "node:crypto";
|
|
9655
9743
|
import { existsSync as existsSync3 } from "node:fs";
|
|
@@ -10226,16 +10314,25 @@ async function validateDeployConfig(config) {
|
|
|
10226
10314
|
// src/lib/deploy/interaction.ts
|
|
10227
10315
|
async function selectEnvironment(options) {
|
|
10228
10316
|
let environment = options.env;
|
|
10229
|
-
|
|
10230
|
-
|
|
10317
|
+
if (environment || process.env.PLAYCADEMY_ENV || process.env.PLAYCADEMY_BASE_URL) {
|
|
10318
|
+
if (environment) {
|
|
10319
|
+
setCliContext({ environment });
|
|
10320
|
+
}
|
|
10321
|
+
return;
|
|
10322
|
+
}
|
|
10323
|
+
const authenticatedEnvs = await getAuthenticatedEnvironments();
|
|
10324
|
+
if (authenticatedEnvs.length === 1) {
|
|
10325
|
+
environment = authenticatedEnvs[0];
|
|
10326
|
+
logger.info(`Deploying to ${environment}`, 1);
|
|
10327
|
+
} else if (authenticatedEnvs.length === 2 && !options.dryRun) {
|
|
10231
10328
|
logger.newLine();
|
|
10232
10329
|
environment = await select({
|
|
10233
10330
|
message: "Select deployment environment:",
|
|
10234
10331
|
choices: [
|
|
10235
|
-
{ value: "
|
|
10236
|
-
{ value: "
|
|
10332
|
+
{ value: "staging", name: "Staging (hub.dev.playcademy.net)" },
|
|
10333
|
+
{ value: "production", name: "Production (hub.playcademy.com)" }
|
|
10237
10334
|
],
|
|
10238
|
-
default: "
|
|
10335
|
+
default: "staging"
|
|
10239
10336
|
});
|
|
10240
10337
|
}
|
|
10241
10338
|
if (environment) {
|
|
@@ -10383,10 +10480,12 @@ function displayCurrentConfiguration(context2) {
|
|
|
10383
10480
|
} else if (config.externalUrl) {
|
|
10384
10481
|
logger.data("URL", config.externalUrl, 1);
|
|
10385
10482
|
}
|
|
10386
|
-
if (
|
|
10483
|
+
if (context2.isGameDeployed) {
|
|
10387
10484
|
logger.data("Status", "Deployed", 1);
|
|
10388
|
-
} else {
|
|
10485
|
+
} else if (existingGame) {
|
|
10389
10486
|
logger.data("Status", "Not deployed", 1);
|
|
10487
|
+
} else {
|
|
10488
|
+
logger.data("Status", "New deployment", 1);
|
|
10390
10489
|
}
|
|
10391
10490
|
logger.newLine();
|
|
10392
10491
|
}
|
|
@@ -10415,14 +10514,15 @@ async function reportNoChanges(context2) {
|
|
|
10415
10514
|
function reportDeploymentSuccess(result, context2) {
|
|
10416
10515
|
const { game, backendDeployment } = result;
|
|
10417
10516
|
const { client, previousBackendHash } = context2;
|
|
10418
|
-
const action = context2.
|
|
10517
|
+
const action = context2.isGameDeployed ? "updated" : "deployed";
|
|
10419
10518
|
logger.newLine();
|
|
10420
10519
|
logger.success(`${game.displayName} ${action} successfully!`);
|
|
10421
10520
|
logger.newLine();
|
|
10422
10521
|
const baseUrl = getWebBaseUrl(client.getBaseUrl());
|
|
10423
10522
|
logger.data("Game URL", underline(blueBright(`${baseUrl}/g/${game.slug}`)), 1);
|
|
10424
10523
|
if (backendDeployment || previousBackendHash) {
|
|
10425
|
-
const
|
|
10524
|
+
const gameDomain = GAME_BACKEND_DOMAINS[getEnvironment()];
|
|
10525
|
+
const backendUrl = `https://${game.slug}.${gameDomain}/api`;
|
|
10426
10526
|
logger.data("Backend API", underline(blueBright(backendUrl)), 1);
|
|
10427
10527
|
}
|
|
10428
10528
|
if (game.version !== "external") {
|
|
@@ -10446,10 +10546,10 @@ import { stat as stat2 } from "node:fs/promises";
|
|
|
10446
10546
|
|
|
10447
10547
|
// ../data/src/domains/game/helpers.ts
|
|
10448
10548
|
var isHostedGame = (game) => {
|
|
10449
|
-
return game.gameType === "hosted" && game.assetBundleBase
|
|
10549
|
+
return game.gameType === "hosted" && !!game.assetBundleBase;
|
|
10450
10550
|
};
|
|
10451
10551
|
var isExternalGame = (game) => {
|
|
10452
|
-
return game.gameType === "external" && game.externalUrl
|
|
10552
|
+
return game.gameType === "external" && !!game.externalUrl;
|
|
10453
10553
|
};
|
|
10454
10554
|
function isGameDeployed(game) {
|
|
10455
10555
|
return isHostedGame(game) || isExternalGame(game);
|
|
@@ -10515,9 +10615,9 @@ async function prepareDeploymentContext(options) {
|
|
|
10515
10615
|
configFileName,
|
|
10516
10616
|
client,
|
|
10517
10617
|
projectPath,
|
|
10518
|
-
existingGame
|
|
10618
|
+
existingGame,
|
|
10519
10619
|
deployedGameInfo: deployedGameInfo ?? void 0,
|
|
10520
|
-
|
|
10620
|
+
isGameDeployed: gameIsDeployed,
|
|
10521
10621
|
buildHash,
|
|
10522
10622
|
buildSize,
|
|
10523
10623
|
previousBuildHash: deployedGameInfo?.buildHash,
|
|
@@ -10567,8 +10667,8 @@ async function analyzeChanges(context2) {
|
|
|
10567
10667
|
};
|
|
10568
10668
|
}
|
|
10569
10669
|
async function calculateDeploymentPlan(context2, changes) {
|
|
10570
|
-
const { config,
|
|
10571
|
-
if (
|
|
10670
|
+
const { config, isGameDeployed: isGameDeployed2, projectPath, deployBackend } = context2;
|
|
10671
|
+
if (!isGameDeployed2) {
|
|
10572
10672
|
const needsBackend3 = hasLocalBackend(projectPath) || !!context2.fullConfig?.integrations;
|
|
10573
10673
|
const shouldDeployBackend2 = deployBackend && needsBackend3;
|
|
10574
10674
|
return {
|
|
@@ -11423,19 +11523,28 @@ initCommand.addCommand(configCommand);
|
|
|
11423
11523
|
|
|
11424
11524
|
// src/commands/login.ts
|
|
11425
11525
|
import { input as input4, password, select as select3 } from "@inquirer/prompts";
|
|
11526
|
+
import { bold as bold4, dim as dim6, whiteBright } from "colorette";
|
|
11426
11527
|
import { Command as Command4 } from "commander";
|
|
11427
11528
|
import open from "open";
|
|
11428
11529
|
init_file_loader();
|
|
11429
|
-
var loginCommand = new Command4("login").description("Authenticate with Playcademy").option("-e, --email <email>", "Email address (for email/password auth)").option("-p, --password <password>", "Password (for email/password auth)").option("--sso", "Use Timeback SSO authentication").action(async (options) => {
|
|
11430
|
-
const { email, password: password2, sso } = options;
|
|
11431
|
-
logger
|
|
11530
|
+
var loginCommand = new Command4("login").description("Authenticate with Playcademy").option("-e, --email <email>", "Email address (for email/password auth)").option("-p, --password <password>", "Password (for email/password auth)").option("--sso", "Use Timeback SSO authentication").option("--env <environment>", "Environment to login to (staging or production)").action(async (options) => {
|
|
11531
|
+
const { email, password: password2, sso, env } = options;
|
|
11532
|
+
const environment = ensureEnvironment(env, logger);
|
|
11432
11533
|
const profileName = getProfileName();
|
|
11433
|
-
|
|
11534
|
+
logger.newLine();
|
|
11535
|
+
const existingProfile = await getProfile(environment, profileName);
|
|
11434
11536
|
if (existingProfile) {
|
|
11435
|
-
const email2 = existingProfile.email;
|
|
11436
|
-
|
|
11437
|
-
|
|
11438
|
-
|
|
11537
|
+
const email2 = existingProfile.email || "unknown user";
|
|
11538
|
+
const otherEnv = environment === "staging" ? "production" : "staging";
|
|
11539
|
+
const otherProfile = await getProfile(otherEnv, profileName);
|
|
11540
|
+
logger.admonition("note", "I know you!", [
|
|
11541
|
+
"You are already logged in",
|
|
11542
|
+
"",
|
|
11543
|
+
dim6("Email: ") + bold4(email2),
|
|
11544
|
+
dim6("Environment: ") + bold4(environment),
|
|
11545
|
+
dim6("Profile: ") + bold4(profileName),
|
|
11546
|
+
...otherProfile ? [dim6("Other Profile: ") + bold4(otherEnv)] : []
|
|
11547
|
+
]);
|
|
11439
11548
|
logger.newLine();
|
|
11440
11549
|
return;
|
|
11441
11550
|
}
|
|
@@ -11450,7 +11559,7 @@ var loginCommand = new Command4("login").description("Authenticate with Playcade
|
|
|
11450
11559
|
});
|
|
11451
11560
|
logger.newLine();
|
|
11452
11561
|
if (authMethod === "sso") {
|
|
11453
|
-
await handleSsoLogin(profileName);
|
|
11562
|
+
await handleSsoLogin(environment, profileName);
|
|
11454
11563
|
return;
|
|
11455
11564
|
}
|
|
11456
11565
|
const finalEmail = email || await promptForEmail();
|
|
@@ -11474,7 +11583,8 @@ var loginCommand = new Command4("login").description("Authenticate with Playcade
|
|
|
11474
11583
|
const apiKeyResult = await runStep(
|
|
11475
11584
|
"Creating API key for CLI usage",
|
|
11476
11585
|
async () => {
|
|
11477
|
-
const
|
|
11586
|
+
const pkg = await loadPackageJson({ required: false });
|
|
11587
|
+
const nameVersion = pkg ? getPackageNameVersionFromData(pkg) : `${getCurrentDirectoryName("playcademy-cli")}@0.0.0`;
|
|
11478
11588
|
const result = await client.auth.apiKeys.create({
|
|
11479
11589
|
name: nameVersion,
|
|
11480
11590
|
expiresIn: null,
|
|
@@ -11502,14 +11612,17 @@ var loginCommand = new Command4("login").description("Authenticate with Playcade
|
|
|
11502
11612
|
logger.newLine();
|
|
11503
11613
|
await runStep(
|
|
11504
11614
|
`Saving credentials to profile "${profileName}"`,
|
|
11505
|
-
() => saveProfile(profileName, authProfile),
|
|
11615
|
+
() => saveProfile(environment, profileName, authProfile),
|
|
11506
11616
|
"Credentials saved successfully"
|
|
11507
11617
|
);
|
|
11508
|
-
logger.
|
|
11509
|
-
|
|
11510
|
-
|
|
11511
|
-
|
|
11512
|
-
|
|
11618
|
+
logger.newLine();
|
|
11619
|
+
logger.admonition("tip", "Logged In Successfully!", [
|
|
11620
|
+
`Email: ${authProfile.email}`,
|
|
11621
|
+
`Environment: ${environment}`,
|
|
11622
|
+
...profileName !== "default" ? [`Profile: ${profileName}`] : [],
|
|
11623
|
+
"",
|
|
11624
|
+
...profileName !== "default" ? [`Use \`--profile ${profileName}\` with commands to use this profile`] : []
|
|
11625
|
+
]);
|
|
11513
11626
|
logger.newLine();
|
|
11514
11627
|
} catch (error) {
|
|
11515
11628
|
logger.newLine();
|
|
@@ -11520,7 +11633,7 @@ var loginCommand = new Command4("login").description("Authenticate with Playcade
|
|
|
11520
11633
|
process.exit(1);
|
|
11521
11634
|
}
|
|
11522
11635
|
});
|
|
11523
|
-
async function handleSsoLogin(profileName) {
|
|
11636
|
+
async function handleSsoLogin(environment, profileName) {
|
|
11524
11637
|
try {
|
|
11525
11638
|
const serverPromise = startCallbackServer(SSO_AUTH_TIMEOUT_MS);
|
|
11526
11639
|
const baseUrl = getBaseUrl();
|
|
@@ -11543,7 +11656,8 @@ async function handleSsoLogin(profileName) {
|
|
|
11543
11656
|
const apiKeyResult = await runStep(
|
|
11544
11657
|
"Creating API key for CLI usage",
|
|
11545
11658
|
async () => {
|
|
11546
|
-
const
|
|
11659
|
+
const pkg = await loadPackageJson({ required: false });
|
|
11660
|
+
const nameVersion = pkg ? getPackageNameVersionFromData(pkg) : `${getCurrentDirectoryName("playcademy-cli")}@0.0.0`;
|
|
11547
11661
|
const response = await client.auth.apiKeys.create({
|
|
11548
11662
|
name: nameVersion,
|
|
11549
11663
|
expiresIn: null,
|
|
@@ -11564,21 +11678,20 @@ async function handleSsoLogin(profileName) {
|
|
|
11564
11678
|
email: result.data.email
|
|
11565
11679
|
};
|
|
11566
11680
|
logger.newLine();
|
|
11567
|
-
logger.admonition("warning", "Your API Key", [
|
|
11568
|
-
|
|
11681
|
+
logger.admonition("warning", "Your API Key", [
|
|
11682
|
+
"",
|
|
11683
|
+
whiteBright(bold4(apiKeyResult.apiKey)),
|
|
11684
|
+
"",
|
|
11685
|
+
"Save this key securely - it will not be shown again!"
|
|
11686
|
+
]);
|
|
11569
11687
|
logger.newLine();
|
|
11570
11688
|
await runStep(
|
|
11571
11689
|
`Saving credentials to profile "${profileName}"`,
|
|
11572
|
-
() => saveProfile(profileName, authProfile),
|
|
11573
|
-
"Credentials saved successfully"
|
|
11690
|
+
() => saveProfile(environment, profileName, authProfile),
|
|
11691
|
+
"Credentials saved successfully",
|
|
11692
|
+
{ silent: true }
|
|
11574
11693
|
);
|
|
11575
|
-
logger.success(`Logged in as ${authProfile.email}`);
|
|
11576
|
-
if (profileName !== "default") {
|
|
11577
|
-
logger.newLine();
|
|
11578
|
-
logger.info(`Profile saved as "${profileName}"`);
|
|
11579
|
-
logger.newLine();
|
|
11580
|
-
logger.aside(`Use \`--profile ${profileName}\` with commands to use this profile`, 1);
|
|
11581
|
-
}
|
|
11694
|
+
logger.success(`Logged in to ${environment} as ${authProfile.email}`);
|
|
11582
11695
|
logger.newLine();
|
|
11583
11696
|
} catch (error) {
|
|
11584
11697
|
logger.newLine();
|
|
@@ -11617,27 +11730,23 @@ async function promptForPassword() {
|
|
|
11617
11730
|
|
|
11618
11731
|
// src/commands/logout.ts
|
|
11619
11732
|
import { Command as Command5 } from "commander";
|
|
11620
|
-
var logoutCommand = new Command5("logout").description("Log out from Playcademy").
|
|
11621
|
-
const {
|
|
11733
|
+
var logoutCommand = new Command5("logout").description("Log out from Playcademy").argument("[profile]", "Profile name to logout from", "default").option("--env <environment>", "Environment to logout from (staging or production)").action(async (profileName, options) => {
|
|
11734
|
+
const { env } = options;
|
|
11735
|
+
const environment = ensureEnvironment(env, logger);
|
|
11622
11736
|
try {
|
|
11623
11737
|
logger.newLine();
|
|
11624
|
-
const profile = await getProfile(profileName);
|
|
11738
|
+
const profile = await getProfile(environment, profileName);
|
|
11625
11739
|
if (!profile) {
|
|
11626
|
-
logger.error(`Profile "${profileName}" not found`);
|
|
11740
|
+
logger.error(`Profile "${profileName}" not found in ${environment}`);
|
|
11741
|
+
logger.newLine();
|
|
11627
11742
|
logger.info("Use `playcademy profiles list` to see available profiles");
|
|
11628
11743
|
logger.newLine();
|
|
11629
11744
|
process.exit(1);
|
|
11630
11745
|
}
|
|
11631
|
-
await removeProfile(profileName);
|
|
11632
|
-
logger.success(
|
|
11633
|
-
|
|
11634
|
-
|
|
11635
|
-
}
|
|
11636
|
-
if (profileName === "default") {
|
|
11637
|
-
logger.info("To log in again: playcademy login");
|
|
11638
|
-
} else {
|
|
11639
|
-
logger.info(`To log in again: playcademy login --profile ${profileName}`);
|
|
11640
|
-
}
|
|
11746
|
+
await removeProfile(environment, profileName);
|
|
11747
|
+
logger.success(
|
|
11748
|
+
`Logged out from ${environment} profile "${profileName}" (${profile.email})`
|
|
11749
|
+
);
|
|
11641
11750
|
logger.newLine();
|
|
11642
11751
|
} catch (error) {
|
|
11643
11752
|
logger.newLine();
|
|
@@ -11651,18 +11760,24 @@ var logoutCommand = new Command5("logout").description("Log out from Playcademy"
|
|
|
11651
11760
|
|
|
11652
11761
|
// src/commands/me.ts
|
|
11653
11762
|
import { Command as Command6 } from "commander";
|
|
11654
|
-
var meCommand = new Command6("me").description("Display current user information").
|
|
11763
|
+
var meCommand = new Command6("me").description("Display current user information").option(
|
|
11764
|
+
"--env <environment>",
|
|
11765
|
+
"Environment to check user information from (staging or production)"
|
|
11766
|
+
).action(async (options) => {
|
|
11767
|
+
const { env } = options;
|
|
11655
11768
|
try {
|
|
11769
|
+
const environment = ensureEnvironment(env, logger);
|
|
11656
11770
|
const client = await requireAuthenticatedClient();
|
|
11657
11771
|
logger.newLine();
|
|
11658
11772
|
const user = await runStep(
|
|
11659
|
-
|
|
11773
|
+
`Fetching user information from ${environment}`,
|
|
11660
11774
|
client.users.me,
|
|
11661
11775
|
"User information retrieved"
|
|
11662
11776
|
);
|
|
11663
11777
|
logger.newLine();
|
|
11664
11778
|
logger.data("ID", user.id, 1);
|
|
11665
11779
|
logger.data("Email", user.email, 1);
|
|
11780
|
+
logger.data("Environment", environment, 1);
|
|
11666
11781
|
if (user.username) {
|
|
11667
11782
|
logger.data("Username", user.username, 1);
|
|
11668
11783
|
}
|
|
@@ -11710,7 +11825,8 @@ async function executeDeployment(plan, context2) {
|
|
|
11710
11825
|
return { game, backendDeployment };
|
|
11711
11826
|
}
|
|
11712
11827
|
async function runDeployment(options) {
|
|
11713
|
-
|
|
11828
|
+
const environment = ensureEnvironment(options.env, logger);
|
|
11829
|
+
await selectEnvironment({ env: environment, dryRun: options.dryRun });
|
|
11714
11830
|
const context2 = await prepareDeploymentContext(options);
|
|
11715
11831
|
displayCurrentConfiguration(context2);
|
|
11716
11832
|
const didPrompt = await promptForMissingConfig(context2);
|
|
@@ -11775,17 +11891,19 @@ import { Command as Command10 } from "commander";
|
|
|
11775
11891
|
// src/commands/games/delete.ts
|
|
11776
11892
|
import { confirm as confirm5, input as input5, select as select4 } from "@inquirer/prompts";
|
|
11777
11893
|
import { Command as Command8 } from "commander";
|
|
11778
|
-
var deleteCommand = new Command8("delete").alias("rm").alias("remove").description("Delete a game").argument("[slug]", "Game slug to delete").option("-f, --force", "Skip confirmation prompt").action(async (slug, options) => {
|
|
11894
|
+
var deleteCommand = new Command8("delete").alias("rm").alias("remove").description("Delete a game").argument("[slug]", "Game slug to delete").option("-f, --force", "Skip confirmation prompt").option("--env <environment>", "Environment to delete game from (staging or production)").action(async (slug, options) => {
|
|
11895
|
+
const { env } = options;
|
|
11779
11896
|
try {
|
|
11780
|
-
logger
|
|
11897
|
+
const environment = ensureEnvironment(env, logger);
|
|
11781
11898
|
const client = await requireAuthenticatedClient();
|
|
11899
|
+
logger.newLine();
|
|
11782
11900
|
const games2 = await runStep(
|
|
11783
|
-
|
|
11901
|
+
`Fetching games from ${environment}`,
|
|
11784
11902
|
client.games.list,
|
|
11785
|
-
(games3) => `Found ${games3.length} game${games3.length === 1 ? "" : "s"}`
|
|
11903
|
+
(games3) => `Found ${games3.length} game${games3.length === 1 ? "" : "s"} in ${environment}`
|
|
11786
11904
|
);
|
|
11787
11905
|
if (games2.length === 0) {
|
|
11788
|
-
logger.info(
|
|
11906
|
+
logger.info(`No games found in ${environment}`);
|
|
11789
11907
|
return;
|
|
11790
11908
|
}
|
|
11791
11909
|
logger.newLine();
|
|
@@ -11833,11 +11951,11 @@ var deleteCommand = new Command8("delete").alias("rm").alias("remove").descripti
|
|
|
11833
11951
|
logger.newLine();
|
|
11834
11952
|
}
|
|
11835
11953
|
await runStep(
|
|
11836
|
-
|
|
11954
|
+
`Deleting game from ${environment}`,
|
|
11837
11955
|
async () => {
|
|
11838
11956
|
await client.dev.games.delete(game.id);
|
|
11839
11957
|
},
|
|
11840
|
-
|
|
11958
|
+
`Game deleted successfully from ${environment}`
|
|
11841
11959
|
);
|
|
11842
11960
|
const deployedGame = await getDeployedGame(getWorkspace());
|
|
11843
11961
|
if (deployedGame && deployedGame.gameId === game.id) {
|
|
@@ -11856,14 +11974,16 @@ var deleteCommand = new Command8("delete").alias("rm").alias("remove").descripti
|
|
|
11856
11974
|
|
|
11857
11975
|
// src/commands/games/list.ts
|
|
11858
11976
|
import { Command as Command9 } from "commander";
|
|
11859
|
-
var listCommand = new Command9("list").alias("ls").description("List all games").action(async () => {
|
|
11977
|
+
var listCommand = new Command9("list").alias("ls").description("List all games").option("--env <environment>", "Environment to list games from (staging or production)").action(async (options) => {
|
|
11978
|
+
const { env } = options;
|
|
11860
11979
|
try {
|
|
11980
|
+
const environment = ensureEnvironment(env, logger);
|
|
11861
11981
|
const client = await requireAuthenticatedClient();
|
|
11862
11982
|
logger.newLine();
|
|
11863
11983
|
const games2 = await runStep(
|
|
11864
|
-
|
|
11984
|
+
`Fetching games from ${environment}`,
|
|
11865
11985
|
client.games.list,
|
|
11866
|
-
(games3) => `Found ${games3.length} game${games3.length === 1 ? "" : "s"}`
|
|
11986
|
+
(games3) => `Found ${games3.length} game${games3.length === 1 ? "" : "s"} in ${environment}`
|
|
11867
11987
|
);
|
|
11868
11988
|
if (games2.length === 0) {
|
|
11869
11989
|
logger.info("No games found");
|
|
@@ -11902,22 +12022,30 @@ import { Command as Command13 } from "commander";
|
|
|
11902
12022
|
|
|
11903
12023
|
// src/commands/dev/apply.ts
|
|
11904
12024
|
import { Command as Command11 } from "commander";
|
|
11905
|
-
var applyCommand = new Command11("apply").description("Apply for developer status").
|
|
12025
|
+
var applyCommand = new Command11("apply").description("Apply for developer status").option(
|
|
12026
|
+
"--env <environment>",
|
|
12027
|
+
"Environment to apply for developer status in (staging or production)"
|
|
12028
|
+
).action(async (options) => {
|
|
12029
|
+
const { env } = options;
|
|
11906
12030
|
try {
|
|
11907
|
-
logger
|
|
12031
|
+
const environment = ensureEnvironment(env, logger);
|
|
11908
12032
|
const client = await requireAuthenticatedClient();
|
|
12033
|
+
logger.newLine();
|
|
11909
12034
|
const currentStatus = await runStep(
|
|
11910
|
-
|
|
12035
|
+
`Checking current developer status in ${environment}`,
|
|
11911
12036
|
client.dev.status.get,
|
|
11912
|
-
|
|
12037
|
+
`Current status retrieved from ${environment}`
|
|
11913
12038
|
);
|
|
12039
|
+
logger.newLine();
|
|
11914
12040
|
if (currentStatus === "approved") {
|
|
11915
|
-
logger.
|
|
12041
|
+
logger.admonition("note", "Approved!", ["You are already an approved developer!"]);
|
|
11916
12042
|
logger.newLine();
|
|
11917
12043
|
return;
|
|
11918
12044
|
}
|
|
11919
12045
|
if (currentStatus === "pending") {
|
|
11920
|
-
logger.
|
|
12046
|
+
logger.admonition("warning", "Developer Status", [
|
|
12047
|
+
"Your developer application is pending review"
|
|
12048
|
+
]);
|
|
11921
12049
|
logger.newLine();
|
|
11922
12050
|
return;
|
|
11923
12051
|
}
|
|
@@ -11927,14 +12055,15 @@ var applyCommand = new Command11("apply").description("Apply for developer statu
|
|
|
11927
12055
|
"Developer application submitted successfully"
|
|
11928
12056
|
);
|
|
11929
12057
|
logger.newLine();
|
|
11930
|
-
logger.
|
|
11931
|
-
|
|
11932
|
-
|
|
11933
|
-
|
|
11934
|
-
|
|
12058
|
+
logger.admonition("tip", "Application Submitted!", [
|
|
12059
|
+
"Your developer application has been submitted.",
|
|
12060
|
+
"",
|
|
12061
|
+
"What happens next:",
|
|
12062
|
+
" \u2022 We will review your application shortly",
|
|
12063
|
+
" \u2022 Once approved, you can create and deploy games"
|
|
12064
|
+
]);
|
|
11935
12065
|
logger.newLine();
|
|
11936
12066
|
} catch (error) {
|
|
11937
|
-
logger.newLine();
|
|
11938
12067
|
logger.error(
|
|
11939
12068
|
`Failed to apply for developer status: ${error instanceof Error ? error.message : "Unknown error"}`
|
|
11940
12069
|
);
|
|
@@ -11945,31 +12074,37 @@ var applyCommand = new Command11("apply").description("Apply for developer statu
|
|
|
11945
12074
|
|
|
11946
12075
|
// src/commands/dev/get-status.ts
|
|
11947
12076
|
import { Command as Command12 } from "commander";
|
|
11948
|
-
var getStatusCommand = new Command12("status").description("Check your developer status").
|
|
12077
|
+
var getStatusCommand = new Command12("status").description("Check your developer status").option(
|
|
12078
|
+
"--env <environment>",
|
|
12079
|
+
"Environment to check developer status from (staging or production)"
|
|
12080
|
+
).action(async (options) => {
|
|
12081
|
+
const { env } = options;
|
|
11949
12082
|
try {
|
|
11950
|
-
logger
|
|
12083
|
+
const environment = ensureEnvironment(env, logger);
|
|
11951
12084
|
const client = await requireAuthenticatedClient();
|
|
12085
|
+
logger.newLine();
|
|
11952
12086
|
const status = await runStep(
|
|
11953
|
-
|
|
12087
|
+
`Fetching developer status from ${environment}`,
|
|
11954
12088
|
() => client.dev.status.get(),
|
|
11955
|
-
|
|
12089
|
+
`Developer status retrieved from ${environment}`
|
|
11956
12090
|
);
|
|
11957
|
-
logger.newLine();
|
|
11958
|
-
logger.highlight("Developer Status");
|
|
11959
|
-
logger.data("Status", status, 1);
|
|
11960
12091
|
switch (status) {
|
|
11961
12092
|
case "none":
|
|
11962
12093
|
logger.newLine();
|
|
11963
|
-
logger.
|
|
11964
|
-
|
|
12094
|
+
logger.admonition("warning", "Become a Developer", [
|
|
12095
|
+
"Want to create and deploy games?",
|
|
12096
|
+
"Run `playcademy dev apply` to apply for developer status"
|
|
12097
|
+
]);
|
|
11965
12098
|
break;
|
|
11966
12099
|
case "pending":
|
|
11967
12100
|
logger.newLine();
|
|
11968
|
-
logger.
|
|
12101
|
+
logger.admonition("warning", "Developer Status", [
|
|
12102
|
+
"Your application is pending review."
|
|
12103
|
+
]);
|
|
11969
12104
|
break;
|
|
11970
12105
|
case "approved":
|
|
11971
12106
|
logger.newLine();
|
|
11972
|
-
logger.
|
|
12107
|
+
logger.admonition("note", "Approved!", ["You are an approved developer!"]);
|
|
11973
12108
|
break;
|
|
11974
12109
|
default:
|
|
11975
12110
|
logger.newLine();
|
|
@@ -12012,7 +12147,7 @@ async function runDevServer(options) {
|
|
|
12012
12147
|
});
|
|
12013
12148
|
const hotReload = options.reload !== false;
|
|
12014
12149
|
let startMessage = `Game API started: ${blueBright4(underline2(`http://localhost:${port}/api`))}`;
|
|
12015
|
-
if (hotReload) startMessage += hotReload ?
|
|
12150
|
+
if (hotReload) startMessage += hotReload ? dim2(" (hot reload enabled)") : "";
|
|
12016
12151
|
logger.success(startMessage);
|
|
12017
12152
|
logger.newLine();
|
|
12018
12153
|
let customRoutes = await discoverRoutes(join12(getWorkspace(), "api"));
|
|
@@ -12055,26 +12190,39 @@ import { Command as Command17 } from "commander";
|
|
|
12055
12190
|
import { Command as Command14 } from "commander";
|
|
12056
12191
|
async function listProfilesAction() {
|
|
12057
12192
|
try {
|
|
12058
|
-
const
|
|
12193
|
+
const profilesMap = await listProfiles();
|
|
12059
12194
|
logger.newLine();
|
|
12060
|
-
|
|
12195
|
+
let hasAnyProfiles = false;
|
|
12196
|
+
for (const [, profiles] of profilesMap.entries()) {
|
|
12197
|
+
if (profiles.length > 0) {
|
|
12198
|
+
hasAnyProfiles = true;
|
|
12199
|
+
break;
|
|
12200
|
+
}
|
|
12201
|
+
}
|
|
12202
|
+
if (!hasAnyProfiles) {
|
|
12061
12203
|
logger.warn("No authentication profiles found");
|
|
12062
12204
|
logger.newLine();
|
|
12063
12205
|
logger.admonition("tip", "Getting Started", [
|
|
12064
12206
|
"Run `playcademy login` to create your first profile"
|
|
12065
12207
|
]);
|
|
12208
|
+
logger.newLine();
|
|
12066
12209
|
return;
|
|
12067
12210
|
}
|
|
12068
|
-
const
|
|
12069
|
-
|
|
12070
|
-
|
|
12071
|
-
tableData
|
|
12072
|
-
|
|
12073
|
-
|
|
12074
|
-
|
|
12075
|
-
|
|
12076
|
-
|
|
12077
|
-
|
|
12211
|
+
for (const [environment, profiles] of profilesMap.entries()) {
|
|
12212
|
+
if (profiles.length === 0) continue;
|
|
12213
|
+
logger.highlight(`${environment.charAt(0).toUpperCase() + environment.slice(1)}:`);
|
|
12214
|
+
const tableData = [];
|
|
12215
|
+
for (const profileName of profiles) {
|
|
12216
|
+
const profile = await getProfile(environment, profileName);
|
|
12217
|
+
tableData.push({
|
|
12218
|
+
Profile: profileName,
|
|
12219
|
+
Email: profile?.email ?? ""
|
|
12220
|
+
});
|
|
12221
|
+
}
|
|
12222
|
+
if (tableData.length > 0) {
|
|
12223
|
+
logger.table(tableData);
|
|
12224
|
+
logger.newLine();
|
|
12225
|
+
}
|
|
12078
12226
|
}
|
|
12079
12227
|
} catch (error) {
|
|
12080
12228
|
logger.error(
|
|
@@ -12082,28 +12230,29 @@ async function listProfilesAction() {
|
|
|
12082
12230
|
);
|
|
12083
12231
|
process.exit(1);
|
|
12084
12232
|
}
|
|
12085
|
-
logger.newLine();
|
|
12086
12233
|
}
|
|
12087
12234
|
var listCommand2 = new Command14("list").alias("ls").description("List all stored authentication profiles").action(listProfilesAction);
|
|
12088
12235
|
|
|
12089
12236
|
// src/commands/profiles/remove.ts
|
|
12237
|
+
import { bold as bold5 } from "colorette";
|
|
12090
12238
|
import { Command as Command15 } from "commander";
|
|
12091
|
-
var removeCommand = new Command15("remove
|
|
12239
|
+
var removeCommand = new Command15("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) => {
|
|
12240
|
+
const { env } = options;
|
|
12241
|
+
const environment = ensureEnvironment(env, logger);
|
|
12092
12242
|
try {
|
|
12093
12243
|
logger.newLine();
|
|
12094
|
-
const
|
|
12095
|
-
|
|
12096
|
-
|
|
12244
|
+
const profilesMap = await listProfiles();
|
|
12245
|
+
const envProfiles = profilesMap.get(environment) || [];
|
|
12246
|
+
if (!envProfiles.includes(name)) {
|
|
12247
|
+
logger.error(`Profile "${name}" not found in ${environment}`);
|
|
12097
12248
|
logger.newLine();
|
|
12098
12249
|
process.exit(1);
|
|
12099
12250
|
}
|
|
12100
|
-
await removeProfile(name);
|
|
12101
|
-
logger.
|
|
12102
|
-
|
|
12103
|
-
|
|
12104
|
-
|
|
12105
|
-
logger.info("To re-authenticate: playcademy login");
|
|
12106
|
-
}
|
|
12251
|
+
await removeProfile(environment, name);
|
|
12252
|
+
logger.admonition("note", "Removed!", [
|
|
12253
|
+
`Profile ${bold5(name)} removed from ${environment}`,
|
|
12254
|
+
environment === "production" ? `To re-authenticate run \`playcademy login --env ${environment}\`` : "To re-authenticate run `playcademy login`"
|
|
12255
|
+
]);
|
|
12107
12256
|
logger.newLine();
|
|
12108
12257
|
} catch (error) {
|
|
12109
12258
|
logger.newLine();
|
|
@@ -12118,10 +12267,16 @@ var removeCommand = new Command15("remove <name>").alias("rm").description("Remo
|
|
|
12118
12267
|
// src/commands/profiles/reset.ts
|
|
12119
12268
|
import { confirm as confirm6 } from "@inquirer/prompts";
|
|
12120
12269
|
import { Command as Command16 } from "commander";
|
|
12121
|
-
var resetCommand = new Command16("reset").description(
|
|
12270
|
+
var resetCommand = new Command16("reset").description(
|
|
12271
|
+
"Remove all authentication profiles across all environments (requires confirmation)"
|
|
12272
|
+
).alias("clear").action(async () => {
|
|
12122
12273
|
try {
|
|
12123
|
-
const
|
|
12124
|
-
|
|
12274
|
+
const profilesMap = await listProfiles();
|
|
12275
|
+
let totalProfiles = 0;
|
|
12276
|
+
for (const profiles of profilesMap.values()) {
|
|
12277
|
+
totalProfiles += profiles.length;
|
|
12278
|
+
}
|
|
12279
|
+
if (totalProfiles === 0) {
|
|
12125
12280
|
logger.newLine();
|
|
12126
12281
|
logger.warn("No authentication profiles found");
|
|
12127
12282
|
logger.newLine();
|
|
@@ -12129,14 +12284,21 @@ var resetCommand = new Command16("reset").description("Remove all authentication
|
|
|
12129
12284
|
}
|
|
12130
12285
|
logger.newLine();
|
|
12131
12286
|
logger.warn(
|
|
12132
|
-
`This will remove ${
|
|
12287
|
+
`This will remove ${totalProfiles} authentication profile${totalProfiles > 1 ? "s" : ""} across all environments:`
|
|
12133
12288
|
);
|
|
12134
12289
|
logger.newLine();
|
|
12135
|
-
for (const
|
|
12136
|
-
|
|
12137
|
-
logger.
|
|
12290
|
+
for (const [environment, profiles] of profilesMap.entries()) {
|
|
12291
|
+
if (profiles.length === 0) continue;
|
|
12292
|
+
logger.highlight(
|
|
12293
|
+
`${environment.charAt(0).toUpperCase() + environment.slice(1)}:`,
|
|
12294
|
+
1
|
|
12295
|
+
);
|
|
12296
|
+
for (const profileName of profiles) {
|
|
12297
|
+
const profile = await getProfile(environment, profileName);
|
|
12298
|
+
logger.data(profileName, profile?.email || "", 2);
|
|
12299
|
+
}
|
|
12300
|
+
logger.newLine();
|
|
12138
12301
|
}
|
|
12139
|
-
logger.newLine();
|
|
12140
12302
|
const confirmed = await confirm6({
|
|
12141
12303
|
message: "Are you sure you want to remove all profiles?",
|
|
12142
12304
|
default: false
|
|
@@ -12146,23 +12308,27 @@ var resetCommand = new Command16("reset").description("Remove all authentication
|
|
|
12146
12308
|
return;
|
|
12147
12309
|
}
|
|
12148
12310
|
let removedCount = 0;
|
|
12149
|
-
for (const
|
|
12150
|
-
|
|
12151
|
-
|
|
12152
|
-
|
|
12153
|
-
|
|
12154
|
-
|
|
12155
|
-
|
|
12156
|
-
|
|
12157
|
-
|
|
12311
|
+
for (const [environment, profiles] of profilesMap.entries()) {
|
|
12312
|
+
for (const profileName of profiles) {
|
|
12313
|
+
try {
|
|
12314
|
+
await removeProfile(environment, profileName);
|
|
12315
|
+
removedCount++;
|
|
12316
|
+
} catch (error) {
|
|
12317
|
+
logger.newLine();
|
|
12318
|
+
logger.error(
|
|
12319
|
+
`Failed to remove profile "${profileName}" from ${environment}`
|
|
12320
|
+
);
|
|
12321
|
+
logger.error(error instanceof Error ? error.message : "Unknown error");
|
|
12322
|
+
logger.newLine();
|
|
12323
|
+
}
|
|
12158
12324
|
}
|
|
12159
12325
|
}
|
|
12160
|
-
if (removedCount ===
|
|
12326
|
+
if (removedCount === totalProfiles) {
|
|
12161
12327
|
logger.success(
|
|
12162
12328
|
`${removedCount > 1 ? "All " : ""}${removedCount} profile${removedCount > 1 ? "s" : ""} removed successfully`
|
|
12163
12329
|
);
|
|
12164
12330
|
} else {
|
|
12165
|
-
logger.warn(`Removed ${removedCount} of ${
|
|
12331
|
+
logger.warn(`Removed ${removedCount} of ${totalProfiles} profiles`);
|
|
12166
12332
|
}
|
|
12167
12333
|
logger.newLine();
|
|
12168
12334
|
} catch (error) {
|
|
@@ -12187,13 +12353,18 @@ import { Command as Command22 } from "commander";
|
|
|
12187
12353
|
// src/commands/timeback/cleanup.ts
|
|
12188
12354
|
import { confirm as confirm7 } from "@inquirer/prompts";
|
|
12189
12355
|
import { Command as Command18 } from "commander";
|
|
12190
|
-
var cleanupCommand = new Command18("cleanup").description("Remove TimeBack integration for your game").
|
|
12356
|
+
var cleanupCommand = new Command18("cleanup").description("Remove TimeBack integration for your game").option(
|
|
12357
|
+
"--env <environment>",
|
|
12358
|
+
"Environment to remove TimeBack integration from (staging or production)"
|
|
12359
|
+
).action(async (options) => {
|
|
12360
|
+
const { env } = options;
|
|
12191
12361
|
try {
|
|
12192
|
-
logger
|
|
12362
|
+
const environment = ensureEnvironment(env, logger);
|
|
12193
12363
|
const client = await requireAuthenticatedClient();
|
|
12364
|
+
logger.newLine();
|
|
12194
12365
|
const { game } = await getGameFromConfig(client);
|
|
12195
12366
|
const integration = await runStep(
|
|
12196
|
-
|
|
12367
|
+
`Checking for TimeBack integration in ${environment}`,
|
|
12197
12368
|
() => client.timeback.management.get(game.id),
|
|
12198
12369
|
"Integration status checked"
|
|
12199
12370
|
);
|
|
@@ -12216,9 +12387,9 @@ var cleanupCommand = new Command18("cleanup").description("Remove TimeBack integ
|
|
|
12216
12387
|
}
|
|
12217
12388
|
logger.newLine();
|
|
12218
12389
|
await runStep(
|
|
12219
|
-
|
|
12390
|
+
`Removing TimeBack integration from ${environment}`,
|
|
12220
12391
|
() => client.timeback.management.cleanup(game.id),
|
|
12221
|
-
|
|
12392
|
+
`TimeBack integration removed from ${environment}`
|
|
12222
12393
|
);
|
|
12223
12394
|
logger.newLine();
|
|
12224
12395
|
logger.admonition("note", "Note", [
|
|
@@ -12237,8 +12408,13 @@ var cleanupCommand = new Command18("cleanup").description("Remove TimeBack integ
|
|
|
12237
12408
|
// src/commands/timeback/setup.ts
|
|
12238
12409
|
import { Command as Command19 } from "commander";
|
|
12239
12410
|
import dedent from "dedent";
|
|
12240
|
-
var setupCommand = new Command19("setup").description("Set up TimeBack integration for your game").option("--dry-run", "Validate configuration without creating resources").option("--verbose, -v", "Output detailed information").
|
|
12411
|
+
var setupCommand = new Command19("setup").description("Set up TimeBack integration for your game").option("--dry-run", "Validate configuration without creating resources").option("--verbose, -v", "Output detailed information").option(
|
|
12412
|
+
"--env <environment>",
|
|
12413
|
+
"Environment to set up TimeBack integration in (staging or production)"
|
|
12414
|
+
).action(async (options) => {
|
|
12415
|
+
const { env } = options;
|
|
12241
12416
|
try {
|
|
12417
|
+
ensureEnvironment(env, logger);
|
|
12242
12418
|
logger.newLine();
|
|
12243
12419
|
const config = await runStep(
|
|
12244
12420
|
"Loading configuration",
|
|
@@ -12340,8 +12516,13 @@ var setupCommand = new Command19("setup").description("Set up TimeBack integrati
|
|
|
12340
12516
|
import { confirm as confirm8 } from "@inquirer/prompts";
|
|
12341
12517
|
import { green as green3, red as red3 } from "colorette";
|
|
12342
12518
|
import { Command as Command20 } from "commander";
|
|
12343
|
-
var updateCommand = new Command20("update").description("Update TimeBack integration configuration for your game").option("--verbose, -v", "Output detailed information").
|
|
12519
|
+
var updateCommand = new Command20("update").description("Update TimeBack integration configuration for your game").option("--verbose, -v", "Output detailed information").option(
|
|
12520
|
+
"--env <environment>",
|
|
12521
|
+
"Environment to update TimeBack integration in (staging or production)"
|
|
12522
|
+
).action(async (options) => {
|
|
12523
|
+
const { env } = options;
|
|
12344
12524
|
try {
|
|
12525
|
+
ensureEnvironment(env, logger);
|
|
12345
12526
|
logger.newLine();
|
|
12346
12527
|
const config = await runStep(
|
|
12347
12528
|
"Loading configuration",
|
|
@@ -12447,13 +12628,18 @@ var updateCommand = new Command20("update").description("Update TimeBack integra
|
|
|
12447
12628
|
|
|
12448
12629
|
// src/commands/timeback/verify.ts
|
|
12449
12630
|
import { Command as Command21 } from "commander";
|
|
12450
|
-
var verifyCommand = new Command21("verify").description("Verify TimeBack integration for your game").option("--verbose, -v", "Output detailed resource information").
|
|
12631
|
+
var verifyCommand = new Command21("verify").description("Verify TimeBack integration for your game").option("--verbose, -v", "Output detailed resource information").option(
|
|
12632
|
+
"--env <environment>",
|
|
12633
|
+
"Environment to verify TimeBack integration in (staging or production)"
|
|
12634
|
+
).action(async (options) => {
|
|
12635
|
+
const { env } = options;
|
|
12451
12636
|
try {
|
|
12452
|
-
logger
|
|
12637
|
+
const environment = ensureEnvironment(env, logger);
|
|
12453
12638
|
const client = await requireAuthenticatedClient();
|
|
12639
|
+
logger.newLine();
|
|
12454
12640
|
const { game } = await getGameFromConfig(client);
|
|
12455
12641
|
const result = await runStep(
|
|
12456
|
-
|
|
12642
|
+
`Verifying TimeBack integration in ${environment}`,
|
|
12457
12643
|
() => client.timeback.management.verify(game.id),
|
|
12458
12644
|
"Verification complete"
|
|
12459
12645
|
);
|
|
@@ -12494,11 +12680,12 @@ timebackCommand.addCommand(cleanupCommand);
|
|
|
12494
12680
|
var __dirname = dirname4(fileURLToPath2(import.meta.url));
|
|
12495
12681
|
var packageJson = await loadPackageJson({ cwd: __dirname, searchUp: true, required: true });
|
|
12496
12682
|
program.name("playcademy").description("CLI for deploying and managing Playcademy games").version(packageJson?.version || "0.0.0").option("--profile <name>", "Use a specific authentication profile", "default").hook("preAction", (thisCommand) => {
|
|
12497
|
-
const options = thisCommand.
|
|
12683
|
+
const options = thisCommand.optsWithGlobals();
|
|
12498
12684
|
setCliContext({ profile: options.profile, workspace: process.cwd() });
|
|
12499
12685
|
});
|
|
12500
12686
|
program.addCommand(initCommand);
|
|
12501
12687
|
program.addCommand(loginCommand);
|
|
12688
|
+
program.addCommand(logoutCommand);
|
|
12502
12689
|
program.addCommand(profilesCommand);
|
|
12503
12690
|
program.addCommand(meCommand);
|
|
12504
12691
|
program.addCommand(devCommand);
|
|
@@ -12536,6 +12723,7 @@ export {
|
|
|
12536
12723
|
displayRegisteredRoutes,
|
|
12537
12724
|
displayResourcesStatus,
|
|
12538
12725
|
displaySuccessMessage,
|
|
12726
|
+
ensureEnvironment,
|
|
12539
12727
|
ensureGameExists,
|
|
12540
12728
|
findConfigPath,
|
|
12541
12729
|
generateEntryCode,
|
|
@@ -12543,6 +12731,7 @@ export {
|
|
|
12543
12731
|
generateJsonConfig,
|
|
12544
12732
|
getApiUrl,
|
|
12545
12733
|
getAuthPath,
|
|
12734
|
+
getAuthenticatedEnvironments,
|
|
12546
12735
|
getBackendHash,
|
|
12547
12736
|
getBackendSize,
|
|
12548
12737
|
getBaseUrl,
|
|
@@ -12574,6 +12763,7 @@ export {
|
|
|
12574
12763
|
loadGameStore,
|
|
12575
12764
|
logger,
|
|
12576
12765
|
needsBackend,
|
|
12766
|
+
normalizeEnvironment,
|
|
12577
12767
|
prepareDeploymentContext,
|
|
12578
12768
|
processConfigVariables,
|
|
12579
12769
|
promptForApiRoutes,
|