playcademy 0.28.1-beta.13 → 0.28.1-beta.14
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/bucket.d.ts +15 -0
- package/dist/bucket.js +1 -1
- package/dist/cli.js +6 -3
- package/dist/constants.js +1 -1
- package/dist/db.js +5 -2
- package/dist/index.d.ts +15 -0
- package/dist/index.js +281 -115
- package/dist/runtime/dashboard-runtime/manifest.json +4 -4
- package/dist/runtime/game-runtime/index.js +3 -3
- package/dist/runtime/game-runtime/manifest.json +4 -4
- package/dist/utils.d.ts +15 -0
- package/dist/utils.js +6 -3
- package/dist/version.js +1 -1
- package/package.json +2 -2
package/dist/bucket.d.ts
CHANGED
|
@@ -138,6 +138,19 @@ interface DashboardThemeConfig {
|
|
|
138
138
|
/** Secondary/accent color as a hex string, e.g. '#ffd166' */
|
|
139
139
|
secondary?: string;
|
|
140
140
|
}
|
|
141
|
+
/**
|
|
142
|
+
* Child-catalog contract generation (see @playcademy/sdk/contracts).
|
|
143
|
+
* The extractor is a repo-local script (run with the CLI's runtime) that
|
|
144
|
+
* prints `{ generatedFrom, deliveries }` as JSON on stdout; the CLI
|
|
145
|
+
* validates, stamps the contract fields, and writes
|
|
146
|
+
* `.playcademy/catalog.json` deterministically. The document carries no
|
|
147
|
+
* app identity — consuming repos assign the namespace key from sync
|
|
148
|
+
* provenance.
|
|
149
|
+
*/
|
|
150
|
+
interface CatalogConfig {
|
|
151
|
+
/** Path to the extractor script, relative to the config file. */
|
|
152
|
+
extractor: string;
|
|
153
|
+
}
|
|
141
154
|
/**
|
|
142
155
|
* Unified Playcademy configuration
|
|
143
156
|
* Used for playcademy.config.{js,json}
|
|
@@ -170,6 +183,8 @@ interface PlaycademyConfig {
|
|
|
170
183
|
dashboard?: DashboardConfig | boolean;
|
|
171
184
|
/** Integrations (database, custom routes, external services) */
|
|
172
185
|
integrations?: IntegrationsConfig;
|
|
186
|
+
/** Child-catalog contract generation (`playcademy catalog`) */
|
|
187
|
+
catalog?: CatalogConfig;
|
|
173
188
|
}
|
|
174
189
|
|
|
175
190
|
/**
|
package/dist/bucket.js
CHANGED
|
@@ -44,7 +44,7 @@ var GAME_API_ROUTES_DIRECTORY = join2(GAME_SERVER_ROOT_DIRECTORY, "api");
|
|
|
44
44
|
// ../better-auth/package.json
|
|
45
45
|
var package_default = {
|
|
46
46
|
name: "@playcademy/better-auth",
|
|
47
|
-
version: "0.0.21-beta.
|
|
47
|
+
version: "0.0.21-beta.14",
|
|
48
48
|
type: "module",
|
|
49
49
|
exports: {
|
|
50
50
|
"./server": {
|
package/dist/cli.js
CHANGED
|
@@ -514,7 +514,10 @@ function nestColor(content, color2) {
|
|
|
514
514
|
function customTransform(text) {
|
|
515
515
|
let result = text;
|
|
516
516
|
result = result.replace(/<<([^>]+)>>/g, (_, url) => blueBright(underline(url)));
|
|
517
|
-
result = result.replace(
|
|
517
|
+
result = result.replace(
|
|
518
|
+
/<([^>]+)>/g,
|
|
519
|
+
(match, inner) => blueBright(/[./]/.test(inner) ? inner : match)
|
|
520
|
+
);
|
|
518
521
|
result = result.replace(/`([^`]+)`/g, (_, code) => nestColor(code, greenBright));
|
|
519
522
|
return result;
|
|
520
523
|
}
|
|
@@ -1207,7 +1210,7 @@ var SAMPLE_BUCKET_FILENAME = "bucket.ts";
|
|
|
1207
1210
|
// ../better-auth/package.json
|
|
1208
1211
|
var package_default = {
|
|
1209
1212
|
name: "@playcademy/better-auth",
|
|
1210
|
-
version: "0.0.21-beta.
|
|
1213
|
+
version: "0.0.21-beta.14",
|
|
1211
1214
|
type: "module",
|
|
1212
1215
|
exports: {
|
|
1213
1216
|
"./server": {
|
|
@@ -3041,7 +3044,7 @@ import { existsSync as existsSync11, mkdirSync as mkdirSync5, readFileSync as re
|
|
|
3041
3044
|
import { join as join13 } from "node:path";
|
|
3042
3045
|
|
|
3043
3046
|
// src/version.ts
|
|
3044
|
-
var cliVersion = false ? "0.0.0-dev" : "0.28.1-beta.
|
|
3047
|
+
var cliVersion = false ? "0.0.0-dev" : "0.28.1-beta.14";
|
|
3045
3048
|
|
|
3046
3049
|
// src/lib/init/database.ts
|
|
3047
3050
|
var drizzleConfigTemplate = loadTemplateString("database/drizzle-config.ts");
|
package/dist/constants.js
CHANGED
package/dist/db.js
CHANGED
|
@@ -2335,7 +2335,7 @@ var GAME_API_ROUTES_DIRECTORY = join2(GAME_SERVER_ROOT_DIRECTORY, "api");
|
|
|
2335
2335
|
// ../better-auth/package.json
|
|
2336
2336
|
var package_default = {
|
|
2337
2337
|
name: "@playcademy/better-auth",
|
|
2338
|
-
version: "0.0.21-beta.
|
|
2338
|
+
version: "0.0.21-beta.14",
|
|
2339
2339
|
type: "module",
|
|
2340
2340
|
exports: {
|
|
2341
2341
|
"./server": {
|
|
@@ -2817,7 +2817,10 @@ function nestColor(content, color2) {
|
|
|
2817
2817
|
function customTransform(text) {
|
|
2818
2818
|
let result = text;
|
|
2819
2819
|
result = result.replace(/<<([^>]+)>>/g, (_, url) => blueBright(underline(url)));
|
|
2820
|
-
result = result.replace(
|
|
2820
|
+
result = result.replace(
|
|
2821
|
+
/<([^>]+)>/g,
|
|
2822
|
+
(match, inner) => blueBright(/[./]/.test(inner) ? inner : match)
|
|
2823
|
+
);
|
|
2821
2824
|
result = result.replace(/`([^`]+)`/g, (_, code) => nestColor(code, greenBright));
|
|
2822
2825
|
return result;
|
|
2823
2826
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -479,6 +479,19 @@ interface DashboardThemeConfig {
|
|
|
479
479
|
/** Secondary/accent color as a hex string, e.g. '#ffd166' */
|
|
480
480
|
secondary?: string;
|
|
481
481
|
}
|
|
482
|
+
/**
|
|
483
|
+
* Child-catalog contract generation (see @playcademy/sdk/contracts).
|
|
484
|
+
* The extractor is a repo-local script (run with the CLI's runtime) that
|
|
485
|
+
* prints `{ generatedFrom, deliveries }` as JSON on stdout; the CLI
|
|
486
|
+
* validates, stamps the contract fields, and writes
|
|
487
|
+
* `.playcademy/catalog.json` deterministically. The document carries no
|
|
488
|
+
* app identity — consuming repos assign the namespace key from sync
|
|
489
|
+
* provenance.
|
|
490
|
+
*/
|
|
491
|
+
interface CatalogConfig {
|
|
492
|
+
/** Path to the extractor script, relative to the config file. */
|
|
493
|
+
extractor: string;
|
|
494
|
+
}
|
|
482
495
|
/**
|
|
483
496
|
* Unified Playcademy configuration
|
|
484
497
|
* Used for playcademy.config.{js,json}
|
|
@@ -511,6 +524,8 @@ interface PlaycademyConfig {
|
|
|
511
524
|
dashboard?: DashboardConfig | boolean;
|
|
512
525
|
/** Integrations (database, custom routes, external services) */
|
|
513
526
|
integrations?: IntegrationsConfig;
|
|
527
|
+
/** Child-catalog contract generation (`playcademy catalog`) */
|
|
528
|
+
catalog?: CatalogConfig;
|
|
514
529
|
}
|
|
515
530
|
|
|
516
531
|
/**
|
package/dist/index.js
CHANGED
|
@@ -2346,7 +2346,7 @@ var SAMPLE_BUCKET_FILENAME = "bucket.ts";
|
|
|
2346
2346
|
// ../better-auth/package.json
|
|
2347
2347
|
var package_default = {
|
|
2348
2348
|
name: "@playcademy/better-auth",
|
|
2349
|
-
version: "0.0.21-beta.
|
|
2349
|
+
version: "0.0.21-beta.14",
|
|
2350
2350
|
type: "module",
|
|
2351
2351
|
exports: {
|
|
2352
2352
|
"./server": {
|
|
@@ -3168,7 +3168,10 @@ function nestColor(content, color2) {
|
|
|
3168
3168
|
function customTransform(text4) {
|
|
3169
3169
|
let result = text4;
|
|
3170
3170
|
result = result.replace(/<<([^>]+)>>/g, (_, url) => blueBright(underline(url)));
|
|
3171
|
-
result = result.replace(
|
|
3171
|
+
result = result.replace(
|
|
3172
|
+
/<([^>]+)>/g,
|
|
3173
|
+
(match, inner) => blueBright(/[./]/.test(inner) ? inner : match)
|
|
3174
|
+
);
|
|
3172
3175
|
result = result.replace(/`([^`]+)`/g, (_, code) => nestColor(code, greenBright));
|
|
3173
3176
|
return result;
|
|
3174
3177
|
}
|
|
@@ -6235,7 +6238,7 @@ async function checkbox(config) {
|
|
|
6235
6238
|
// src/lib/core/subprocess.ts
|
|
6236
6239
|
import { spawn } from "node:child_process";
|
|
6237
6240
|
function runShell(command, options = {}) {
|
|
6238
|
-
return new Promise((
|
|
6241
|
+
return new Promise((resolve19, reject) => {
|
|
6239
6242
|
const env = { ...options.env ?? process.env };
|
|
6240
6243
|
delete env.ESBUILD_BINARY_PATH;
|
|
6241
6244
|
const child = spawn(command, {
|
|
@@ -6255,7 +6258,7 @@ function runShell(command, options = {}) {
|
|
|
6255
6258
|
child.on("error", reject);
|
|
6256
6259
|
child.on("close", (code) => {
|
|
6257
6260
|
if (code === 0) {
|
|
6258
|
-
|
|
6261
|
+
resolve19();
|
|
6259
6262
|
} else {
|
|
6260
6263
|
reject(
|
|
6261
6264
|
Object.assign(new Error(`Command failed: ${command}`), {
|
|
@@ -6468,7 +6471,7 @@ import { existsSync as existsSync11, mkdirSync as mkdirSync2, readFileSync as re
|
|
|
6468
6471
|
import { join as join13 } from "node:path";
|
|
6469
6472
|
|
|
6470
6473
|
// src/version.ts
|
|
6471
|
-
var cliVersion = false ? "0.0.0-dev" : "0.28.1-beta.
|
|
6474
|
+
var cliVersion = false ? "0.0.0-dev" : "0.28.1-beta.14";
|
|
6472
6475
|
|
|
6473
6476
|
// src/lib/init/database.ts
|
|
6474
6477
|
var drizzleConfigTemplate = loadTemplateString("database/drizzle-config.ts");
|
|
@@ -10160,14 +10163,14 @@ function readServerInfo(type, projectRoot) {
|
|
|
10160
10163
|
return servers[0] || null;
|
|
10161
10164
|
}
|
|
10162
10165
|
async function isPortInUse(port) {
|
|
10163
|
-
return new Promise((
|
|
10166
|
+
return new Promise((resolve19) => {
|
|
10164
10167
|
const server = createServer();
|
|
10165
10168
|
server.once("error", () => {
|
|
10166
|
-
|
|
10169
|
+
resolve19(true);
|
|
10167
10170
|
});
|
|
10168
10171
|
server.once("listening", () => {
|
|
10169
10172
|
server.close();
|
|
10170
|
-
|
|
10173
|
+
resolve19(false);
|
|
10171
10174
|
});
|
|
10172
10175
|
server.listen(port, "0.0.0.0");
|
|
10173
10176
|
});
|
|
@@ -10178,7 +10181,7 @@ async function waitForPort(port, timeoutMs = 5e3) {
|
|
|
10178
10181
|
if (Date.now() - start > timeoutMs) {
|
|
10179
10182
|
throw new Error(`Port ${port} is already in use`);
|
|
10180
10183
|
}
|
|
10181
|
-
await new Promise((
|
|
10184
|
+
await new Promise((resolve19) => setTimeout(resolve19, 100));
|
|
10182
10185
|
}
|
|
10183
10186
|
}
|
|
10184
10187
|
|
|
@@ -13451,7 +13454,7 @@ function sleep(ms) {
|
|
|
13451
13454
|
if (ms <= 0) {
|
|
13452
13455
|
return Promise.resolve();
|
|
13453
13456
|
}
|
|
13454
|
-
return new Promise((
|
|
13457
|
+
return new Promise((resolve19) => setTimeout(resolve19, ms));
|
|
13455
13458
|
}
|
|
13456
13459
|
async function runWithConcurrency(items, concurrency, worker) {
|
|
13457
13460
|
if (items.length === 0) {
|
|
@@ -15848,21 +15851,21 @@ var Matcher = class {
|
|
|
15848
15851
|
* @returns {string}
|
|
15849
15852
|
*/
|
|
15850
15853
|
toString(separator, includeNamespace = true) {
|
|
15851
|
-
const
|
|
15852
|
-
const isDefault =
|
|
15854
|
+
const sep7 = separator || this.separator;
|
|
15855
|
+
const isDefault = sep7 === this.separator && includeNamespace === true;
|
|
15853
15856
|
if (isDefault) {
|
|
15854
15857
|
if (this._pathStringCache !== null) {
|
|
15855
15858
|
return this._pathStringCache;
|
|
15856
15859
|
}
|
|
15857
15860
|
const result = this.path.map(
|
|
15858
15861
|
(n) => n.namespace ? `${n.namespace}:${n.tag}` : n.tag
|
|
15859
|
-
).join(
|
|
15862
|
+
).join(sep7);
|
|
15860
15863
|
this._pathStringCache = result;
|
|
15861
15864
|
return result;
|
|
15862
15865
|
}
|
|
15863
15866
|
return this.path.map(
|
|
15864
15867
|
(n) => includeNamespace && n.namespace ? `${n.namespace}:${n.tag}` : n.tag
|
|
15865
|
-
).join(
|
|
15868
|
+
).join(sep7);
|
|
15866
15869
|
}
|
|
15867
15870
|
/**
|
|
15868
15871
|
* Get path as array of tag names.
|
|
@@ -24798,6 +24801,162 @@ async function bundleStubWorker() {
|
|
|
24798
24801
|
return cachedBundle;
|
|
24799
24802
|
}
|
|
24800
24803
|
|
|
24804
|
+
// src/lib/catalog/document.ts
|
|
24805
|
+
import {
|
|
24806
|
+
CATALOG_LEVELS,
|
|
24807
|
+
CATALOG_READINESS,
|
|
24808
|
+
CHILD_ATTEMPT_CONTRACT,
|
|
24809
|
+
CHILD_CATALOG_CONTRACT
|
|
24810
|
+
} from "@playcademy/sdk/contracts";
|
|
24811
|
+
var CatalogError = class extends Error {
|
|
24812
|
+
hint;
|
|
24813
|
+
constructor(message2, hint) {
|
|
24814
|
+
super(message2);
|
|
24815
|
+
this.name = "CatalogError";
|
|
24816
|
+
this.hint = hint;
|
|
24817
|
+
}
|
|
24818
|
+
};
|
|
24819
|
+
function isRecord3(value) {
|
|
24820
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
24821
|
+
}
|
|
24822
|
+
function assertExtractorOutput(value) {
|
|
24823
|
+
if (!isRecord3(value)) {
|
|
24824
|
+
throw new CatalogError("Extractor output must be a JSON object");
|
|
24825
|
+
}
|
|
24826
|
+
if (typeof value.generatedFrom !== "string" || value.generatedFrom.length === 0) {
|
|
24827
|
+
throw new CatalogError(
|
|
24828
|
+
'Extractor output is missing "generatedFrom"',
|
|
24829
|
+
'Name the in-repo source of truth, e.g. "data/e_level_route_catalog.json"'
|
|
24830
|
+
);
|
|
24831
|
+
}
|
|
24832
|
+
if (!isRecord3(value.deliveries)) {
|
|
24833
|
+
throw new CatalogError(
|
|
24834
|
+
'Extractor output is missing "deliveries" (lesson id \u2192 level \u2192 readiness)'
|
|
24835
|
+
);
|
|
24836
|
+
}
|
|
24837
|
+
for (const [lessonId, levels] of Object.entries(value.deliveries)) {
|
|
24838
|
+
if (!isRecord3(levels)) {
|
|
24839
|
+
throw new CatalogError(`Delivery "${lessonId}" must map levels to readiness`);
|
|
24840
|
+
}
|
|
24841
|
+
for (const [level, readiness] of Object.entries(levels)) {
|
|
24842
|
+
if (!CATALOG_LEVELS.includes(level)) {
|
|
24843
|
+
throw new CatalogError(
|
|
24844
|
+
`Delivery "${lessonId}" has unknown level "${level}"`,
|
|
24845
|
+
`Levels are: ${CATALOG_LEVELS.join(", ")}`
|
|
24846
|
+
);
|
|
24847
|
+
}
|
|
24848
|
+
if (!CATALOG_READINESS.includes(readiness)) {
|
|
24849
|
+
throw new CatalogError(
|
|
24850
|
+
`Delivery "${lessonId}" level "${level}" has unknown readiness "${String(readiness)}"`,
|
|
24851
|
+
`Readiness values are: ${CATALOG_READINESS.join(", ")}`
|
|
24852
|
+
);
|
|
24853
|
+
}
|
|
24854
|
+
}
|
|
24855
|
+
}
|
|
24856
|
+
}
|
|
24857
|
+
function buildCatalog(output, generatedBy) {
|
|
24858
|
+
return {
|
|
24859
|
+
contract: CHILD_CATALOG_CONTRACT,
|
|
24860
|
+
evidence: CHILD_ATTEMPT_CONTRACT,
|
|
24861
|
+
generatedBy,
|
|
24862
|
+
generatedFrom: output.generatedFrom,
|
|
24863
|
+
deliveries: output.deliveries
|
|
24864
|
+
};
|
|
24865
|
+
}
|
|
24866
|
+
function sortDeep(value) {
|
|
24867
|
+
if (Array.isArray(value)) {
|
|
24868
|
+
return value.map(sortDeep);
|
|
24869
|
+
}
|
|
24870
|
+
if (isRecord3(value)) {
|
|
24871
|
+
const out = {};
|
|
24872
|
+
for (const key of Object.keys(value).toSorted()) {
|
|
24873
|
+
out[key] = sortDeep(value[key]);
|
|
24874
|
+
}
|
|
24875
|
+
return out;
|
|
24876
|
+
}
|
|
24877
|
+
return value;
|
|
24878
|
+
}
|
|
24879
|
+
function renderCatalog(catalog) {
|
|
24880
|
+
return `${JSON.stringify(sortDeep(catalog), null, 2)}
|
|
24881
|
+
`;
|
|
24882
|
+
}
|
|
24883
|
+
|
|
24884
|
+
// src/lib/catalog/extract.ts
|
|
24885
|
+
import { spawnSync } from "node:child_process";
|
|
24886
|
+
import { existsSync as existsSync32, mkdirSync as mkdirSync11, readFileSync as readFileSync15, writeFileSync as writeFileSync17 } from "node:fs";
|
|
24887
|
+
import { dirname as dirname9, join as join44, relative as relative7, resolve as resolve14, sep as sep4 } from "node:path";
|
|
24888
|
+
function jsRuntime() {
|
|
24889
|
+
if (!process.isBun) {
|
|
24890
|
+
return process.execPath;
|
|
24891
|
+
}
|
|
24892
|
+
const found = Bun.which("bun") ?? Bun.which("node");
|
|
24893
|
+
if (!found) {
|
|
24894
|
+
throw new CatalogError(
|
|
24895
|
+
"No JavaScript runtime found to run the extractor",
|
|
24896
|
+
"Install bun (or node) and make sure it is on PATH"
|
|
24897
|
+
);
|
|
24898
|
+
}
|
|
24899
|
+
return found;
|
|
24900
|
+
}
|
|
24901
|
+
var CATALOG_PATH = ".playcademy/catalog.json";
|
|
24902
|
+
function assertNotIgnored(path4, root) {
|
|
24903
|
+
const result = spawnSync("git", ["check-ignore", "-q", path4], { cwd: root });
|
|
24904
|
+
if (result.error || result.status !== 0) {
|
|
24905
|
+
return;
|
|
24906
|
+
}
|
|
24907
|
+
throw new CatalogError(
|
|
24908
|
+
`<${CATALOG_PATH}> is gitignored, so it would never be committed or synced`,
|
|
24909
|
+
"Narrow the ignore: replace '.playcademy' with '.playcademy/*' plus '!.playcademy/catalog.json'"
|
|
24910
|
+
);
|
|
24911
|
+
}
|
|
24912
|
+
async function extractCatalog() {
|
|
24913
|
+
const { config, configPath } = await loadConfigWithPath();
|
|
24914
|
+
const root = dirname9(configPath);
|
|
24915
|
+
const extractor = config.catalog?.extractor;
|
|
24916
|
+
if (!extractor) {
|
|
24917
|
+
throw new CatalogError(
|
|
24918
|
+
"No catalog extractor configured",
|
|
24919
|
+
"Add `catalog: { extractor: './tools/extract-catalog.mjs' }` to <playcademy.config>"
|
|
24920
|
+
);
|
|
24921
|
+
}
|
|
24922
|
+
const extractorPath = resolve14(root, extractor);
|
|
24923
|
+
if (!existsSync32(extractorPath)) {
|
|
24924
|
+
throw new CatalogError(`Catalog extractor not found: <${extractor}>`);
|
|
24925
|
+
}
|
|
24926
|
+
const result = spawnSync(jsRuntime(), [extractorPath], {
|
|
24927
|
+
cwd: root,
|
|
24928
|
+
encoding: "utf8",
|
|
24929
|
+
maxBuffer: 16 * 1024 * 1024
|
|
24930
|
+
});
|
|
24931
|
+
if (result.status !== 0) {
|
|
24932
|
+
throw new CatalogError(
|
|
24933
|
+
`Catalog extractor exited with ${String(result.status)}`,
|
|
24934
|
+
result.stderr?.trim() || void 0
|
|
24935
|
+
);
|
|
24936
|
+
}
|
|
24937
|
+
let parsed;
|
|
24938
|
+
try {
|
|
24939
|
+
parsed = JSON.parse(result.stdout);
|
|
24940
|
+
} catch {
|
|
24941
|
+
throw new CatalogError(
|
|
24942
|
+
"Catalog extractor did not print valid JSON on stdout",
|
|
24943
|
+
"The extractor must print only the JSON document (log to stderr instead)"
|
|
24944
|
+
);
|
|
24945
|
+
}
|
|
24946
|
+
assertExtractorOutput(parsed);
|
|
24947
|
+
const generatedBy = relative7(root, extractorPath).split(sep4).join("/");
|
|
24948
|
+
const catalog = buildCatalog(parsed, generatedBy);
|
|
24949
|
+
const path4 = join44(root, CATALOG_PATH);
|
|
24950
|
+
assertNotIgnored(path4, root);
|
|
24951
|
+
const rendered = renderCatalog(catalog);
|
|
24952
|
+
const existing = existsSync32(path4) ? readFileSync15(path4, "utf8") : "";
|
|
24953
|
+
return { catalog, path: path4, rendered, current: existing === rendered };
|
|
24954
|
+
}
|
|
24955
|
+
function writeCatalog(run) {
|
|
24956
|
+
mkdirSync11(dirname9(run.path), { recursive: true });
|
|
24957
|
+
writeFileSync17(run.path, run.rendered);
|
|
24958
|
+
}
|
|
24959
|
+
|
|
24801
24960
|
// src/lib/dashboard/report.ts
|
|
24802
24961
|
import { underline as underline2 } from "colorette";
|
|
24803
24962
|
function reportCredentialLink(kind, email, token, dashboardUrl) {
|
|
@@ -24885,8 +25044,8 @@ async function bootstrapDashboardAdmin(slug, dashboardUrl) {
|
|
|
24885
25044
|
}
|
|
24886
25045
|
|
|
24887
25046
|
// src/lib/dashboard/init.ts
|
|
24888
|
-
import { existsSync as
|
|
24889
|
-
import { join as
|
|
25047
|
+
import { existsSync as existsSync33, mkdirSync as mkdirSync12, readdirSync as readdirSync4, readFileSync as readFileSync16, writeFileSync as writeFileSync18 } from "node:fs";
|
|
25048
|
+
import { join as join45, normalize as normalize3, resolve as resolve15 } from "node:path";
|
|
24890
25049
|
var DASHBOARD_PLUGIN_CALL = "playcademy({ dashboard: true })";
|
|
24891
25050
|
function resolveScaffoldDirectory(dashboard, requested) {
|
|
24892
25051
|
const normalized = normalizeDashboardConfig(dashboard);
|
|
@@ -24905,8 +25064,8 @@ async function scaffoldDashboard(options) {
|
|
|
24905
25064
|
const { config, configPath, configDir } = await loadConfigWithPath(options.configPath);
|
|
24906
25065
|
setCliContext({ workspace: configDir });
|
|
24907
25066
|
const directory = resolveScaffoldDirectory(config.dashboard, options.directory);
|
|
24908
|
-
const destDir =
|
|
24909
|
-
if (
|
|
25067
|
+
const destDir = resolve15(configDir, directory);
|
|
25068
|
+
if (existsSync33(destDir) && readdirSync4(destDir).length > 0) {
|
|
24910
25069
|
throw new Error(
|
|
24911
25070
|
`${directory} already exists and is not empty. Remove it or pass a different directory.`
|
|
24912
25071
|
);
|
|
@@ -24938,10 +25097,10 @@ async function scaffoldDashboard(options) {
|
|
|
24938
25097
|
displayNextSteps(pm, directory);
|
|
24939
25098
|
}
|
|
24940
25099
|
function renamePackage(destDir, projectName) {
|
|
24941
|
-
const pkgPath =
|
|
24942
|
-
const pkg = JSON.parse(
|
|
25100
|
+
const pkgPath = join45(destDir, "package.json");
|
|
25101
|
+
const pkg = JSON.parse(readFileSync16(pkgPath, "utf8"));
|
|
24943
25102
|
pkg.name = `${generateSlug(projectName)}-dashboard`;
|
|
24944
|
-
|
|
25103
|
+
writeFileSync18(pkgPath, `${JSON.stringify(pkg, null, 2)}
|
|
24945
25104
|
`);
|
|
24946
25105
|
}
|
|
24947
25106
|
async function configureVitePlugin(destDir) {
|
|
@@ -24955,7 +25114,7 @@ async function configureVitePlugin(destDir) {
|
|
|
24955
25114
|
async function enableDashboardInConfig(configPath, directory) {
|
|
24956
25115
|
const value = dashboardConfigValue(directory);
|
|
24957
25116
|
const valueSource = value === true ? "true" : `{ directory: '${directory}' }`;
|
|
24958
|
-
const content =
|
|
25117
|
+
const content = readFileSync16(configPath, "utf8");
|
|
24959
25118
|
if (configPath.endsWith(".json")) {
|
|
24960
25119
|
const parsed = JSON.parse(content);
|
|
24961
25120
|
if (parsed.dashboard !== void 0 && parsed.dashboard !== false) {
|
|
@@ -24968,13 +25127,13 @@ async function enableDashboardInConfig(configPath, directory) {
|
|
|
24968
25127
|
"dashboard",
|
|
24969
25128
|
value
|
|
24970
25129
|
]);
|
|
24971
|
-
|
|
25130
|
+
writeFileSync18(configPath, `${JSON.stringify(Object.fromEntries(entries), null, 4)}
|
|
24972
25131
|
`);
|
|
24973
25132
|
return;
|
|
24974
25133
|
}
|
|
24975
25134
|
const disabledKey = /(["']?dashboard["']?\s*:\s*)false/;
|
|
24976
25135
|
if (disabledKey.test(content)) {
|
|
24977
|
-
|
|
25136
|
+
writeFileSync18(configPath, content.replace(disabledKey, `$1${valueSource}`));
|
|
24978
25137
|
await formatConfigWithPrettier(configPath);
|
|
24979
25138
|
return;
|
|
24980
25139
|
}
|
|
@@ -24988,7 +25147,7 @@ async function enableDashboardInConfig(configPath, directory) {
|
|
|
24988
25147
|
]);
|
|
24989
25148
|
return;
|
|
24990
25149
|
}
|
|
24991
|
-
|
|
25150
|
+
writeFileSync18(configPath, updated);
|
|
24992
25151
|
await formatConfigWithPrettier(configPath);
|
|
24993
25152
|
}
|
|
24994
25153
|
function displayNextSteps(pm, directory) {
|
|
@@ -25003,17 +25162,17 @@ function displayNextSteps(pm, directory) {
|
|
|
25003
25162
|
logger.newLine();
|
|
25004
25163
|
}
|
|
25005
25164
|
function scaffoldSampleApiRoute(destDir) {
|
|
25006
|
-
const apiDir =
|
|
25007
|
-
if (
|
|
25165
|
+
const apiDir = join45(destDir, DASHBOARD_API_ROUTES_DIRECTORY);
|
|
25166
|
+
if (existsSync33(apiDir)) {
|
|
25008
25167
|
return;
|
|
25009
25168
|
}
|
|
25010
|
-
|
|
25011
|
-
|
|
25012
|
-
const gitignorePath =
|
|
25169
|
+
mkdirSync12(apiDir, { recursive: true });
|
|
25170
|
+
writeFileSync18(join45(apiDir, "whoami.ts"), loadTemplateString("dashboard-sample-route.ts"));
|
|
25171
|
+
const gitignorePath = join45(destDir, ".gitignore");
|
|
25013
25172
|
const entry = "dashboard-env.d.ts";
|
|
25014
|
-
const existing =
|
|
25173
|
+
const existing = existsSync33(gitignorePath) ? readFileSync16(gitignorePath, "utf8") : "";
|
|
25015
25174
|
if (!existing.split("\n").some((line) => line.trim() === entry)) {
|
|
25016
|
-
|
|
25175
|
+
writeFileSync18(
|
|
25017
25176
|
gitignorePath,
|
|
25018
25177
|
`${existing.replace(/\n*$/, "\n")}
|
|
25019
25178
|
# Generated by Playcademy
|
|
@@ -25087,7 +25246,7 @@ async function loadProjectBase(configPath) {
|
|
|
25087
25246
|
|
|
25088
25247
|
// src/lib/upgrade/channel.ts
|
|
25089
25248
|
import { mkdir as mkdir6, readFile as readFile6, writeFile as writeFile5 } from "node:fs/promises";
|
|
25090
|
-
import { join as
|
|
25249
|
+
import { join as join46 } from "node:path";
|
|
25091
25250
|
var RELEASE_CHANNELS = ["stable", "beta"];
|
|
25092
25251
|
var CDN_BASE_URLS = {
|
|
25093
25252
|
stable: "https://cdn.playcademy.net/cli",
|
|
@@ -25101,7 +25260,7 @@ function getLatestVersionUrl(channel) {
|
|
|
25101
25260
|
}
|
|
25102
25261
|
var CHANNEL_FILE = "channel";
|
|
25103
25262
|
function getChannelFilePath() {
|
|
25104
|
-
return
|
|
25263
|
+
return join46(getConfigDir(), CHANNEL_FILE);
|
|
25105
25264
|
}
|
|
25106
25265
|
function channelFromVersion(version3) {
|
|
25107
25266
|
return version3.includes("-beta") ? "beta" : "stable";
|
|
@@ -25135,18 +25294,18 @@ var KNOWN_KEYS = [
|
|
|
25135
25294
|
"@playcademy/sdk",
|
|
25136
25295
|
"@playcademy/vite-plugin"
|
|
25137
25296
|
];
|
|
25138
|
-
function
|
|
25297
|
+
function isRecord4(value) {
|
|
25139
25298
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
25140
25299
|
}
|
|
25141
25300
|
var FLOOR_VERSION_RE = /^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?$/;
|
|
25142
25301
|
function validateCompatibilityManifest(data) {
|
|
25143
|
-
if (!
|
|
25302
|
+
if (!isRecord4(data)) {
|
|
25144
25303
|
return null;
|
|
25145
25304
|
}
|
|
25146
25305
|
if (typeof data.updatedAt !== "string") {
|
|
25147
25306
|
return null;
|
|
25148
25307
|
}
|
|
25149
|
-
if (!
|
|
25308
|
+
if (!isRecord4(data.minimumVersions)) {
|
|
25150
25309
|
return null;
|
|
25151
25310
|
}
|
|
25152
25311
|
const minimumVersions = {};
|
|
@@ -25183,7 +25342,7 @@ async function fetchCompatibilityManifest(channel) {
|
|
|
25183
25342
|
}
|
|
25184
25343
|
|
|
25185
25344
|
// src/lib/deploy/game/baseline-evidence.ts
|
|
25186
|
-
import { existsSync as
|
|
25345
|
+
import { existsSync as existsSync34 } from "fs";
|
|
25187
25346
|
import { readFile as readFile7 } from "fs/promises";
|
|
25188
25347
|
async function loadBaselineEvidence() {
|
|
25189
25348
|
const migrationsDir = await getMigrationsDirectory();
|
|
@@ -25199,7 +25358,7 @@ async function loadBaselineEvidence() {
|
|
|
25199
25358
|
let previous = { tables: {} };
|
|
25200
25359
|
for (const entry of sorted) {
|
|
25201
25360
|
const snapshotPath = migrationSnapshotPath(migrationsDir, entry.idx);
|
|
25202
|
-
if (!
|
|
25361
|
+
if (!existsSync34(snapshotPath)) {
|
|
25203
25362
|
return null;
|
|
25204
25363
|
}
|
|
25205
25364
|
const snapshot = JSON.parse(await readFile7(snapshotPath, "utf8"));
|
|
@@ -25561,13 +25720,13 @@ async function loadDeployConfig(configPath) {
|
|
|
25561
25720
|
}
|
|
25562
25721
|
|
|
25563
25722
|
// src/lib/deploy/dashboard.ts
|
|
25564
|
-
import { existsSync as
|
|
25565
|
-
import { join as
|
|
25723
|
+
import { existsSync as existsSync36 } from "node:fs";
|
|
25724
|
+
import { join as join49 } from "node:path";
|
|
25566
25725
|
import { underline as underline3 } from "colorette";
|
|
25567
25726
|
|
|
25568
25727
|
// ../utils/src/zip.ts
|
|
25569
25728
|
import { mkdir as mkdir7, readdir, readFile as readFile8, writeFile as writeFile6 } from "fs/promises";
|
|
25570
|
-
import { join as
|
|
25729
|
+
import { join as join47, relative as relative8, sep as sep5 } from "path";
|
|
25571
25730
|
import JSZip2 from "jszip";
|
|
25572
25731
|
async function createZipFromDirectory(sourceDir) {
|
|
25573
25732
|
try {
|
|
@@ -25575,8 +25734,8 @@ async function createZipFromDirectory(sourceDir) {
|
|
|
25575
25734
|
const entries = await readdir(sourceDir, { withFileTypes: true, recursive: true });
|
|
25576
25735
|
for (const entry of entries) {
|
|
25577
25736
|
if (entry.isFile()) {
|
|
25578
|
-
const filePath =
|
|
25579
|
-
const entryName =
|
|
25737
|
+
const filePath = join47(entry.parentPath, entry.name);
|
|
25738
|
+
const entryName = relative8(sourceDir, filePath).replaceAll(sep5, "/");
|
|
25580
25739
|
zip.file(entryName, readFile8(filePath));
|
|
25581
25740
|
}
|
|
25582
25741
|
}
|
|
@@ -25703,8 +25862,8 @@ async function executeUpdates(workspace, deps) {
|
|
|
25703
25862
|
}
|
|
25704
25863
|
|
|
25705
25864
|
// src/lib/deploy/version-gate.ts
|
|
25706
|
-
import { existsSync as
|
|
25707
|
-
import { join as
|
|
25865
|
+
import { existsSync as existsSync35, readFileSync as readFileSync17 } from "node:fs";
|
|
25866
|
+
import { join as join48 } from "node:path";
|
|
25708
25867
|
|
|
25709
25868
|
// src/lib/upgrade/version.ts
|
|
25710
25869
|
var SAFE_VERSION_PATTERN = /^(?:[0-9a-zA-Z][0-9a-zA-Z._\-+]*|[vV][0-9a-zA-Z][0-9a-zA-Z._\-+]*)$/;
|
|
@@ -25825,12 +25984,12 @@ function isDevCliVersion(version3) {
|
|
|
25825
25984
|
return version3.startsWith("0.0.0") || version3.includes("-dev");
|
|
25826
25985
|
}
|
|
25827
25986
|
function resolveInstalledVersion(name, cwd) {
|
|
25828
|
-
const pkgJsonPath =
|
|
25829
|
-
if (!
|
|
25987
|
+
const pkgJsonPath = join48(cwd, "node_modules", name, "package.json");
|
|
25988
|
+
if (!existsSync35(pkgJsonPath)) {
|
|
25830
25989
|
return null;
|
|
25831
25990
|
}
|
|
25832
25991
|
try {
|
|
25833
|
-
const parsed = JSON.parse(
|
|
25992
|
+
const parsed = JSON.parse(readFileSync17(pkgJsonPath, "utf8"));
|
|
25834
25993
|
return typeof parsed.version === "string" ? parsed.version : null;
|
|
25835
25994
|
} catch {
|
|
25836
25995
|
return null;
|
|
@@ -25990,7 +26149,7 @@ async function deployDashboard(options) {
|
|
|
25990
26149
|
() => runShell(dashboard.buildCommand, { cwd: dashboard.directory })
|
|
25991
26150
|
);
|
|
25992
26151
|
}
|
|
25993
|
-
if (!
|
|
26152
|
+
if (!existsSync36(join49(dashboard.buildPath, "index.html"))) {
|
|
25994
26153
|
throw new Error(
|
|
25995
26154
|
`Dashboard build output at ${dashboard.buildPath} has no index.html; check the dashboard's build configuration`
|
|
25996
26155
|
);
|
|
@@ -26603,7 +26762,7 @@ function displayDeploymentDiff(options) {
|
|
|
26603
26762
|
}
|
|
26604
26763
|
|
|
26605
26764
|
// src/lib/deploy/game/interaction.ts
|
|
26606
|
-
import { join as
|
|
26765
|
+
import { join as join51 } from "path";
|
|
26607
26766
|
import { bold as bold9 } from "colorette";
|
|
26608
26767
|
import { ApiError as ApiError4 } from "@playcademy/sdk/internal";
|
|
26609
26768
|
|
|
@@ -26670,7 +26829,7 @@ var DEPLOY_REFUSAL_CODES = new Set(REFUSAL_CODES);
|
|
|
26670
26829
|
|
|
26671
26830
|
// src/lib/deploy/game/rollback-check.ts
|
|
26672
26831
|
import { readFile as readFile9 } from "node:fs/promises";
|
|
26673
|
-
import { resolve as
|
|
26832
|
+
import { resolve as resolve16 } from "node:path";
|
|
26674
26833
|
import JSZip3 from "jszip";
|
|
26675
26834
|
var PLAYCADEMY_MANIFEST_FILE = "playcademy.manifest.json";
|
|
26676
26835
|
var TRACKED_VERSIONS = [
|
|
@@ -26697,11 +26856,11 @@ function rollbackDisplayName(name) {
|
|
|
26697
26856
|
return TRACKED_VERSIONS.find((entry) => entry.key === name).displayName;
|
|
26698
26857
|
}
|
|
26699
26858
|
function isManifestV2(manifest) {
|
|
26700
|
-
return
|
|
26859
|
+
return isRecord4(manifest) && manifest.version === "2" && isRecord4(manifest.versions);
|
|
26701
26860
|
}
|
|
26702
26861
|
async function readBuildManifest(buildPath) {
|
|
26703
26862
|
try {
|
|
26704
|
-
const zip = await JSZip3.loadAsync(await readFile9(
|
|
26863
|
+
const zip = await JSZip3.loadAsync(await readFile9(resolve16(buildPath)));
|
|
26705
26864
|
const manifestFile = zip.file(PLAYCADEMY_MANIFEST_FILE) ?? Object.values(zip.files).find(
|
|
26706
26865
|
(file) => !file.dir && file.name.endsWith(`/${PLAYCADEMY_MANIFEST_FILE}`)
|
|
26707
26866
|
);
|
|
@@ -26746,7 +26905,7 @@ async function detectVersionRollback(context2, plan, fetchLiveGame) {
|
|
|
26746
26905
|
}
|
|
26747
26906
|
|
|
26748
26907
|
// src/lib/deploy/game/timeback-drift.ts
|
|
26749
|
-
import { basename as basename3, join as
|
|
26908
|
+
import { basename as basename3, join as join50 } from "node:path";
|
|
26750
26909
|
async function detectDeployTimebackDrift(context2) {
|
|
26751
26910
|
const timebackConfig = context2.fullConfig?.integrations?.timeback;
|
|
26752
26911
|
const gameId = context2.existingGame?.id;
|
|
@@ -26871,7 +27030,7 @@ async function applyDeployTimebackConfigSync(args) {
|
|
|
26871
27030
|
timebackConfig,
|
|
26872
27031
|
snapshot.platformConfigs
|
|
26873
27032
|
);
|
|
26874
|
-
const configPath =
|
|
27033
|
+
const configPath = join50(context2.projectPath, context2.configFileName);
|
|
26875
27034
|
await updateTimebackConfig(configPath, nextTimeback);
|
|
26876
27035
|
fullConfig.integrations.timeback = nextTimeback;
|
|
26877
27036
|
logger.success(
|
|
@@ -26958,14 +27117,14 @@ function getLocalOverrideCourseChangeCounts(snapshot) {
|
|
|
26958
27117
|
}
|
|
26959
27118
|
|
|
26960
27119
|
// src/lib/deploy/game/validate.ts
|
|
26961
|
-
import { existsSync as
|
|
26962
|
-
import { resolve as
|
|
27120
|
+
import { existsSync as existsSync37 } from "fs";
|
|
27121
|
+
import { resolve as resolve17 } from "path";
|
|
26963
27122
|
function validateBuildPath(path4) {
|
|
26964
27123
|
if (!path4.trim()) {
|
|
26965
27124
|
return "Build path is required";
|
|
26966
27125
|
}
|
|
26967
|
-
const resolvedPath =
|
|
26968
|
-
if (!
|
|
27126
|
+
const resolvedPath = resolve17(path4.trim());
|
|
27127
|
+
if (!existsSync37(resolvedPath)) {
|
|
26969
27128
|
return `Build path not found: ${path4.trim()}`;
|
|
26970
27129
|
}
|
|
26971
27130
|
return true;
|
|
@@ -27520,7 +27679,7 @@ async function applyPlatformValuesToLocalConfig(args) {
|
|
|
27520
27679
|
writeDisplayName
|
|
27521
27680
|
});
|
|
27522
27681
|
applyUpdatesToContext(context2, updates, writeDisplayName);
|
|
27523
|
-
const configPath =
|
|
27682
|
+
const configPath = join51(context2.projectPath, context2.configFileName);
|
|
27524
27683
|
const result = await updateConfigScalars(configPath, updates);
|
|
27525
27684
|
reportConfigUpdate(result, unresolvableLabels, context2.configFileName);
|
|
27526
27685
|
return true;
|
|
@@ -27635,7 +27794,7 @@ var PLAYCADEMY_PLATFORM_VALUES = ["web", "godot"];
|
|
|
27635
27794
|
function narrowToPlaycademyPlatform(value) {
|
|
27636
27795
|
return PLAYCADEMY_PLATFORM_VALUES.includes(value) ? value : null;
|
|
27637
27796
|
}
|
|
27638
|
-
function
|
|
27797
|
+
function isRecord5(value) {
|
|
27639
27798
|
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
27640
27799
|
}
|
|
27641
27800
|
function extractDeployServerError(error) {
|
|
@@ -27643,7 +27802,7 @@ function extractDeployServerError(error) {
|
|
|
27643
27802
|
return null;
|
|
27644
27803
|
}
|
|
27645
27804
|
const details = error.details;
|
|
27646
|
-
if (!
|
|
27805
|
+
if (!isRecord5(details)) {
|
|
27647
27806
|
return null;
|
|
27648
27807
|
}
|
|
27649
27808
|
if (typeof details.code === "string") {
|
|
@@ -27652,7 +27811,7 @@ function extractDeployServerError(error) {
|
|
|
27652
27811
|
if (Array.isArray(details.events)) {
|
|
27653
27812
|
for (let i = details.events.length - 1; i >= 0; i--) {
|
|
27654
27813
|
const event = details.events[i];
|
|
27655
|
-
if (
|
|
27814
|
+
if (isRecord5(event) && isRecord5(event.details) && typeof event.details.code === "string") {
|
|
27656
27815
|
return { code: event.details.code, message: error.message, details: event.details };
|
|
27657
27816
|
}
|
|
27658
27817
|
}
|
|
@@ -27672,7 +27831,7 @@ function verdictLines(value) {
|
|
|
27672
27831
|
if (!Array.isArray(value)) {
|
|
27673
27832
|
return [];
|
|
27674
27833
|
}
|
|
27675
|
-
return value.filter(
|
|
27834
|
+
return value.filter(isRecord5).filter((entry) => typeof entry.tag === "string").map(
|
|
27676
27835
|
(entry) => ` ${entry.tag}${typeof entry.detail === "string" ? `: ${entry.detail}` : ""}`
|
|
27677
27836
|
);
|
|
27678
27837
|
}
|
|
@@ -27702,7 +27861,7 @@ function reportDeploymentStateConflict(serverError, claimedBaselineHash, current
|
|
|
27702
27861
|
function migrationFailureGuidance(args) {
|
|
27703
27862
|
const { tag: tag2, d1Message, details, context: context2 } = args;
|
|
27704
27863
|
const resolveHint = ` \`${repairCommand(`db mark ${tag2} --applied`)}\``;
|
|
27705
|
-
const assessment =
|
|
27864
|
+
const assessment = isRecord5(details.alreadyApplied) ? details.alreadyApplied : null;
|
|
27706
27865
|
const present = stringList(assessment?.present);
|
|
27707
27866
|
const missing = stringList(assessment?.missing);
|
|
27708
27867
|
if (assessment?.verdict === "all-present") {
|
|
@@ -27941,7 +28100,7 @@ function renderDeployServerError(error, context2) {
|
|
|
27941
28100
|
}
|
|
27942
28101
|
case DEPLOY_ERROR_CODES.checksumMismatch: {
|
|
27943
28102
|
const mismatches = Array.isArray(details.mismatches) ? details.mismatches : [];
|
|
27944
|
-
const tags = mismatches.filter(
|
|
28103
|
+
const tags = mismatches.filter(isRecord5).map((mismatch) => mismatch.tag).filter((tag2) => typeof tag2 === "string");
|
|
27945
28104
|
logger.admonition("warning", "Migration Checksum Mismatch", checksumMismatchLines(tags));
|
|
27946
28105
|
return true;
|
|
27947
28106
|
}
|
|
@@ -28257,7 +28416,7 @@ function logDeploymentPlanDebug(plan, context2) {
|
|
|
28257
28416
|
|
|
28258
28417
|
// src/lib/deploy/game/preparation.ts
|
|
28259
28418
|
import { stat } from "node:fs/promises";
|
|
28260
|
-
import { join as
|
|
28419
|
+
import { join as join52 } from "node:path";
|
|
28261
28420
|
|
|
28262
28421
|
// ../data/src/domains/game/helpers.ts
|
|
28263
28422
|
import { and, eq } from "drizzle-orm";
|
|
@@ -29114,8 +29273,8 @@ async function bundleAndHash(context2) {
|
|
|
29114
29273
|
});
|
|
29115
29274
|
const bundleHash = hashContent(bundle.code);
|
|
29116
29275
|
const [serverSize, dbSize] = await Promise.all([
|
|
29117
|
-
getDirectorySize(
|
|
29118
|
-
getDirectorySize(
|
|
29276
|
+
getDirectorySize(join52(context2.projectPath, GAME_SERVER_ROOT_DIRECTORY)),
|
|
29277
|
+
getDirectorySize(join52(context2.projectPath, DEFAULT_DATABASE_DIRECTORY))
|
|
29119
29278
|
]);
|
|
29120
29279
|
context2.currentBackendBundle = bundle;
|
|
29121
29280
|
context2.currentBackendBundleHash = bundleHash;
|
|
@@ -29285,12 +29444,12 @@ function hasOptionalFieldsMissing(missing) {
|
|
|
29285
29444
|
}
|
|
29286
29445
|
|
|
29287
29446
|
// src/lib/deploy/game/steps.ts
|
|
29288
|
-
import { existsSync as
|
|
29447
|
+
import { existsSync as existsSync38 } from "fs";
|
|
29289
29448
|
import { readFile as readFile10 } from "fs/promises";
|
|
29290
|
-
import { basename as basename4, resolve as
|
|
29449
|
+
import { basename as basename4, resolve as resolve18 } from "path";
|
|
29291
29450
|
async function prepareBuildFile(buildPath) {
|
|
29292
|
-
const resolvedPath =
|
|
29293
|
-
if (resolvedPath.endsWith(".zip") &&
|
|
29451
|
+
const resolvedPath = resolve18(buildPath);
|
|
29452
|
+
if (resolvedPath.endsWith(".zip") && existsSync38(resolvedPath)) {
|
|
29294
29453
|
const buffer = await readFile10(resolvedPath);
|
|
29295
29454
|
const uint8Array = new Uint8Array(buffer);
|
|
29296
29455
|
const blob = new Blob([uint8Array], { type: "application/zip" });
|
|
@@ -29595,11 +29754,11 @@ import { dim as dim9 } from "colorette";
|
|
|
29595
29754
|
|
|
29596
29755
|
// src/lib/nudge/state.ts
|
|
29597
29756
|
import { mkdir as mkdir8, readFile as readFile11, writeFile as writeFile7 } from "node:fs/promises";
|
|
29598
|
-
import { join as
|
|
29757
|
+
import { join as join53 } from "node:path";
|
|
29599
29758
|
var NUDGE_STATE_FILE = "nudge-state.json";
|
|
29600
29759
|
var NUDGE_COOLDOWN_MS = 24 * 60 * 60 * 1e3;
|
|
29601
29760
|
function getStatePath() {
|
|
29602
|
-
return
|
|
29761
|
+
return join53(getConfigDir(), NUDGE_STATE_FILE);
|
|
29603
29762
|
}
|
|
29604
29763
|
async function loadNudgeState() {
|
|
29605
29764
|
try {
|
|
@@ -29675,35 +29834,35 @@ async function maybeShowUpdateNudge(options) {
|
|
|
29675
29834
|
}
|
|
29676
29835
|
|
|
29677
29836
|
// src/lib/db/path.ts
|
|
29678
|
-
import { copyFileSync, existsSync as
|
|
29679
|
-
import { join as
|
|
29837
|
+
import { copyFileSync, existsSync as existsSync39, mkdirSync as mkdirSync13, readdirSync as readdirSync5, unlinkSync } from "fs";
|
|
29838
|
+
import { join as join54 } from "path";
|
|
29680
29839
|
var DB_DIRECTORY = CLI_DIRECTORIES.DATABASE;
|
|
29681
29840
|
var INITIAL_DB_NAME = CLI_FILES.INITIAL_DATABASE;
|
|
29682
29841
|
function ensureDirectoryExists(dir) {
|
|
29683
|
-
if (!
|
|
29684
|
-
|
|
29842
|
+
if (!existsSync39(dir)) {
|
|
29843
|
+
mkdirSync13(dir, { recursive: true });
|
|
29685
29844
|
}
|
|
29686
29845
|
}
|
|
29687
29846
|
function findMiniflareDatabase(dbDir) {
|
|
29688
|
-
const miniflareDir =
|
|
29689
|
-
if (!
|
|
29847
|
+
const miniflareDir = join54(dbDir, MINIFLARE_D1_DIRECTORY);
|
|
29848
|
+
if (!existsSync39(miniflareDir)) {
|
|
29690
29849
|
return null;
|
|
29691
29850
|
}
|
|
29692
29851
|
const sqliteFiles = readdirSync5(miniflareDir).filter((file) => file.endsWith(".sqlite"));
|
|
29693
29852
|
if (sqliteFiles.length === 0) {
|
|
29694
29853
|
return null;
|
|
29695
29854
|
}
|
|
29696
|
-
return
|
|
29855
|
+
return join54(miniflareDir, sqliteFiles[0]);
|
|
29697
29856
|
}
|
|
29698
29857
|
function migrateInitialDbToTarget(initialPath, targetPath) {
|
|
29699
|
-
if (!
|
|
29858
|
+
if (!existsSync39(initialPath)) {
|
|
29700
29859
|
return;
|
|
29701
29860
|
}
|
|
29702
29861
|
copyFileSync(initialPath, targetPath);
|
|
29703
29862
|
unlinkSync(initialPath);
|
|
29704
29863
|
}
|
|
29705
29864
|
function getDevDbPath() {
|
|
29706
|
-
const initialDbPath =
|
|
29865
|
+
const initialDbPath = join54(DB_DIRECTORY, INITIAL_DB_NAME);
|
|
29707
29866
|
ensureDirectoryExists(DB_DIRECTORY);
|
|
29708
29867
|
const miniflareDbPath = findMiniflareDatabase(DB_DIRECTORY);
|
|
29709
29868
|
if (miniflareDbPath) {
|
|
@@ -30404,10 +30563,10 @@ async function bundleSeedWorker(seedFilePath, projectPath) {
|
|
|
30404
30563
|
// src/lib/db/reset.ts
|
|
30405
30564
|
import { execSync as execSync8 } from "child_process";
|
|
30406
30565
|
import { rmSync as rmSync3 } from "fs";
|
|
30407
|
-
import { join as
|
|
30566
|
+
import { join as join55 } from "path";
|
|
30408
30567
|
async function resetDatabase(workspace, mf, options = { debug: false }) {
|
|
30409
30568
|
const { debug } = options;
|
|
30410
|
-
const dbDir =
|
|
30569
|
+
const dbDir = join55(workspace, CLI_DIRECTORIES.DATABASE);
|
|
30411
30570
|
await runStep(
|
|
30412
30571
|
"Resetting database...",
|
|
30413
30572
|
async () => {
|
|
@@ -30819,7 +30978,7 @@ function startCallbackServer(timeoutMs, expectedState) {
|
|
|
30819
30978
|
bound = res;
|
|
30820
30979
|
bindFailed = rej;
|
|
30821
30980
|
});
|
|
30822
|
-
const result = new Promise((
|
|
30981
|
+
const result = new Promise((resolve19) => {
|
|
30823
30982
|
let server = null;
|
|
30824
30983
|
let timeoutId = null;
|
|
30825
30984
|
let didBind = false;
|
|
@@ -30838,7 +30997,7 @@ function startCallbackServer(timeoutMs, expectedState) {
|
|
|
30838
30997
|
}
|
|
30839
30998
|
timeoutId = setTimeout(() => {
|
|
30840
30999
|
cleanup(() => {
|
|
30841
|
-
|
|
31000
|
+
resolve19({
|
|
30842
31001
|
success: false,
|
|
30843
31002
|
error: "Authentication timed out. Please try again."
|
|
30844
31003
|
});
|
|
@@ -30856,7 +31015,7 @@ function startCallbackServer(timeoutMs, expectedState) {
|
|
|
30856
31015
|
res.writeHead(200, { "Content-Type": "text/html" });
|
|
30857
31016
|
res.end(SUCCESS_HTML);
|
|
30858
31017
|
cleanup(() => {
|
|
30859
|
-
|
|
31018
|
+
resolve19(parsed);
|
|
30860
31019
|
});
|
|
30861
31020
|
return;
|
|
30862
31021
|
}
|
|
@@ -30874,7 +31033,7 @@ function startCallbackServer(timeoutMs, expectedState) {
|
|
|
30874
31033
|
bindFailed(new Error(message2));
|
|
30875
31034
|
}
|
|
30876
31035
|
cleanup(() => {
|
|
30877
|
-
|
|
31036
|
+
resolve19({ success: false, error: message2 });
|
|
30878
31037
|
});
|
|
30879
31038
|
});
|
|
30880
31039
|
server.listen(CALLBACK_PORT);
|
|
@@ -31016,7 +31175,7 @@ async function promptForPassword() {
|
|
|
31016
31175
|
|
|
31017
31176
|
// src/lib/bucket/collect.ts
|
|
31018
31177
|
import { readdirSync as readdirSync6, statSync as statSync5 } from "fs";
|
|
31019
|
-
import { join as
|
|
31178
|
+
import { join as join56, relative as relative9, sep as sep6 } from "path";
|
|
31020
31179
|
function isEnvFile(name) {
|
|
31021
31180
|
const lower = name.toLowerCase();
|
|
31022
31181
|
return lower === ".env" || lower === ".envrc" || lower.startsWith(".env.");
|
|
@@ -31025,8 +31184,8 @@ function isAlwaysSkippedName(segment) {
|
|
|
31025
31184
|
return BUCKET_ALWAYS_SKIP.includes(segment) || isEnvFile(segment);
|
|
31026
31185
|
}
|
|
31027
31186
|
function shouldSkipFile(filePath, baseDir, gitignorePatterns) {
|
|
31028
|
-
const relativePath =
|
|
31029
|
-
for (const part of relativePath.split(
|
|
31187
|
+
const relativePath = relative9(baseDir, filePath);
|
|
31188
|
+
for (const part of relativePath.split(sep6)) {
|
|
31030
31189
|
if (isAlwaysSkippedName(part)) {
|
|
31031
31190
|
return true;
|
|
31032
31191
|
}
|
|
@@ -31038,7 +31197,7 @@ function collectFiles(directory, baseDir, gitignorePatterns) {
|
|
|
31038
31197
|
try {
|
|
31039
31198
|
const entries = readdirSync6(directory, { withFileTypes: true });
|
|
31040
31199
|
for (const entry of entries) {
|
|
31041
|
-
const fullPath =
|
|
31200
|
+
const fullPath = join56(directory, entry.name);
|
|
31042
31201
|
if (!shouldSkipFile(fullPath, baseDir, gitignorePatterns)) {
|
|
31043
31202
|
if (entry.isDirectory()) {
|
|
31044
31203
|
files.push(...collectFiles(fullPath, baseDir, gitignorePatterns));
|
|
@@ -31046,7 +31205,7 @@ function collectFiles(directory, baseDir, gitignorePatterns) {
|
|
|
31046
31205
|
const stats = statSync5(fullPath);
|
|
31047
31206
|
files.push({
|
|
31048
31207
|
absolutePath: fullPath,
|
|
31049
|
-
relativePath:
|
|
31208
|
+
relativePath: relative9(baseDir, fullPath),
|
|
31050
31209
|
size: stats.size
|
|
31051
31210
|
});
|
|
31052
31211
|
}
|
|
@@ -31084,10 +31243,10 @@ async function confirmDestructive(message2, hint) {
|
|
|
31084
31243
|
import { ApiError as ApiError6 } from "@playcademy/sdk/internal";
|
|
31085
31244
|
|
|
31086
31245
|
// src/lib/bucket/local.ts
|
|
31087
|
-
import { join as
|
|
31246
|
+
import { join as join57 } from "path";
|
|
31088
31247
|
import { Miniflare as Miniflare3 } from "miniflare";
|
|
31089
31248
|
async function openLocalBucket() {
|
|
31090
|
-
const bucketDir =
|
|
31249
|
+
const bucketDir = join57(getWorkspace(), CLI_DIRECTORIES.BUCKET);
|
|
31091
31250
|
const mf = new Miniflare3({
|
|
31092
31251
|
modules: [{ type: "ESModule", path: "index.mjs", contents: "" }],
|
|
31093
31252
|
r2Buckets: [CLOUDFLARE_BINDINGS.BUCKET],
|
|
@@ -31312,12 +31471,12 @@ async function runDeletePlan(plan, adapter, location, options) {
|
|
|
31312
31471
|
}
|
|
31313
31472
|
|
|
31314
31473
|
// src/lib/bucket/dev.ts
|
|
31315
|
-
import { existsSync as
|
|
31316
|
-
import { join as
|
|
31474
|
+
import { existsSync as existsSync40 } from "fs";
|
|
31475
|
+
import { join as join58 } from "path";
|
|
31317
31476
|
var ASSET_DEV_ROUTE_PREFIX = ASSET_ROUTE_PREFIX;
|
|
31318
31477
|
function hasCustomAssetsRoute(projectRoot, config) {
|
|
31319
31478
|
const routesDir = getGameRoutesDirectory(projectRoot, config);
|
|
31320
|
-
return
|
|
31479
|
+
return existsSync40(join58(routesDir, "assets")) || existsSync40(join58(routesDir, "assets.ts"));
|
|
31321
31480
|
}
|
|
31322
31481
|
function openLocalAssetBucket() {
|
|
31323
31482
|
return openLocalBucket();
|
|
@@ -31343,7 +31502,7 @@ async function readLocalAsset(bucket, servingKey) {
|
|
|
31343
31502
|
|
|
31344
31503
|
// src/lib/bucket/hash.ts
|
|
31345
31504
|
import { createHash as createHash5 } from "crypto";
|
|
31346
|
-
import { readFileSync as
|
|
31505
|
+
import { readFileSync as readFileSync18 } from "fs";
|
|
31347
31506
|
import { extname as extname3 } from "path";
|
|
31348
31507
|
var HASH_LENGTH = 8;
|
|
31349
31508
|
function computeHash(buffer) {
|
|
@@ -31358,7 +31517,7 @@ function insertHash(key, hash) {
|
|
|
31358
31517
|
}
|
|
31359
31518
|
function hashFiles(files) {
|
|
31360
31519
|
return files.map((file) => {
|
|
31361
|
-
const buffer =
|
|
31520
|
+
const buffer = readFileSync18(file.absolutePath);
|
|
31362
31521
|
const contentHash = computeHash(buffer);
|
|
31363
31522
|
const key = getBucketKey(file.relativePath);
|
|
31364
31523
|
return {
|
|
@@ -32588,7 +32747,7 @@ async function connectToLogStream(config) {
|
|
|
32588
32747
|
if (backfillTask && !interrupted) {
|
|
32589
32748
|
await Promise.race([
|
|
32590
32749
|
backfillTask,
|
|
32591
|
-
new Promise((
|
|
32750
|
+
new Promise((resolve19) => setTimeout(resolve19, BACKFILL_EXIT_GRACE_MS))
|
|
32592
32751
|
]);
|
|
32593
32752
|
}
|
|
32594
32753
|
report?.();
|
|
@@ -33293,7 +33452,7 @@ function formatExit(name, code, signal) {
|
|
|
33293
33452
|
return `${name} exited`;
|
|
33294
33453
|
}
|
|
33295
33454
|
function upgradeStandalone(targetVersion, channel) {
|
|
33296
|
-
return new Promise((
|
|
33455
|
+
return new Promise((resolve19, reject) => {
|
|
33297
33456
|
const curl = spawn2("curl", ["-fsSL", INSTALL_SCRIPT_URL], {
|
|
33298
33457
|
stdio: ["ignore", "pipe", "pipe"]
|
|
33299
33458
|
});
|
|
@@ -33327,7 +33486,7 @@ function upgradeStandalone(targetVersion, channel) {
|
|
|
33327
33486
|
if (error) {
|
|
33328
33487
|
reject(error);
|
|
33329
33488
|
} else {
|
|
33330
|
-
|
|
33489
|
+
resolve19({ stdout: stdout2, stderr });
|
|
33331
33490
|
}
|
|
33332
33491
|
}
|
|
33333
33492
|
function tryFinalize() {
|
|
@@ -33395,7 +33554,7 @@ function upgradeStandalone(targetVersion, channel) {
|
|
|
33395
33554
|
}
|
|
33396
33555
|
|
|
33397
33556
|
// src/lib/upgrade/verify.ts
|
|
33398
|
-
import { spawnSync } from "node:child_process";
|
|
33557
|
+
import { spawnSync as spawnSync2 } from "node:child_process";
|
|
33399
33558
|
function extractReportedVersion(stdout2) {
|
|
33400
33559
|
const lastLine = stdout2.trim().split("\n").at(-1)?.trim();
|
|
33401
33560
|
if (!lastLine) {
|
|
@@ -33409,7 +33568,7 @@ function extractReportedVersion(stdout2) {
|
|
|
33409
33568
|
}
|
|
33410
33569
|
function verifyInstalledBinary(expectedVersion) {
|
|
33411
33570
|
const expected = normalizeVersion(expectedVersion);
|
|
33412
|
-
const result =
|
|
33571
|
+
const result = spawnSync2(process.execPath, ["--version"], {
|
|
33413
33572
|
encoding: "utf8",
|
|
33414
33573
|
timeout: 3e4
|
|
33415
33574
|
});
|
|
@@ -33429,10 +33588,10 @@ function verifyInstalledBinary(expectedVersion) {
|
|
|
33429
33588
|
|
|
33430
33589
|
// src/lib/upgrade/windows.ts
|
|
33431
33590
|
import { createHash as createHash6 } from "node:crypto";
|
|
33432
|
-
import { existsSync as
|
|
33591
|
+
import { existsSync as existsSync41 } from "node:fs";
|
|
33433
33592
|
import { copyFile, mkdir as mkdir9, open as open2, rename, rm as rm3 } from "node:fs/promises";
|
|
33434
33593
|
import { homedir as homedir3 } from "node:os";
|
|
33435
|
-
import { basename as basename5, dirname as
|
|
33594
|
+
import { basename as basename5, dirname as dirname10, join as join59 } from "node:path";
|
|
33436
33595
|
var COMPANION_TOOLS = ["workerd", "esbuild"];
|
|
33437
33596
|
function windowsArtifacts(arch = process.arch) {
|
|
33438
33597
|
if (arch !== "x64") {
|
|
@@ -33459,8 +33618,8 @@ function cliDestinations(execPath, canonical, existingLocalBin) {
|
|
|
33459
33618
|
}
|
|
33460
33619
|
function resolveCliDestinations() {
|
|
33461
33620
|
const canonical = nativeBinaryPath("playcademy");
|
|
33462
|
-
const localBin =
|
|
33463
|
-
return cliDestinations(process.execPath, canonical,
|
|
33621
|
+
const localBin = join59(homedir3(), ".local", "bin", basename5(canonical));
|
|
33622
|
+
return cliDestinations(process.execPath, canonical, existsSync41(localBin) ? localBin : null);
|
|
33464
33623
|
}
|
|
33465
33624
|
function parseChecksums(text4) {
|
|
33466
33625
|
const checksums = /* @__PURE__ */ new Map();
|
|
@@ -33517,7 +33676,7 @@ async function upgradeWindows(targetVersion, channel) {
|
|
|
33517
33676
|
return { remote, expected, dests };
|
|
33518
33677
|
});
|
|
33519
33678
|
await Promise.all(
|
|
33520
|
-
[...new Set(plans.flatMap((plan) => plan.dests.map((dest) =>
|
|
33679
|
+
[...new Set(plans.flatMap((plan) => plan.dests.map((dest) => dirname10(dest))))].map(
|
|
33521
33680
|
(dir) => mkdir9(dir, { recursive: true })
|
|
33522
33681
|
)
|
|
33523
33682
|
);
|
|
@@ -33664,6 +33823,8 @@ async function resolveTarget(targetVersion, channelOverride) {
|
|
|
33664
33823
|
}
|
|
33665
33824
|
export {
|
|
33666
33825
|
ASSET_DEV_ROUTE_PREFIX,
|
|
33826
|
+
CATALOG_PATH,
|
|
33827
|
+
CatalogError,
|
|
33667
33828
|
ConfigError,
|
|
33668
33829
|
DEFAULT_DASHBOARD_DIRECTORY,
|
|
33669
33830
|
DeployBlockedError,
|
|
@@ -33691,10 +33852,12 @@ export {
|
|
|
33691
33852
|
applySecretsChanges,
|
|
33692
33853
|
assembleLogicalLevel,
|
|
33693
33854
|
assertDestructiveConfirmToken,
|
|
33855
|
+
assertExtractorOutput,
|
|
33694
33856
|
assertRemoteWhenEnvGiven,
|
|
33695
33857
|
assessmentFixturePath,
|
|
33696
33858
|
blockDeploy,
|
|
33697
33859
|
bootstrapDashboardAdmin,
|
|
33860
|
+
buildCatalog,
|
|
33698
33861
|
buildCollectorUrl,
|
|
33699
33862
|
buildDatabasePlan,
|
|
33700
33863
|
buildDatabaseResetPayload,
|
|
@@ -33820,6 +33983,7 @@ export {
|
|
|
33820
33983
|
executeSeedFile,
|
|
33821
33984
|
executeUpdates,
|
|
33822
33985
|
exitAfterStdoutDrain,
|
|
33986
|
+
extractCatalog,
|
|
33823
33987
|
extractDeployServerError,
|
|
33824
33988
|
fetchCompatibilityManifest,
|
|
33825
33989
|
fetchDashboardUrl,
|
|
@@ -33956,7 +34120,7 @@ export {
|
|
|
33956
34120
|
isPluginConfigured,
|
|
33957
34121
|
isProcessExitLikeError,
|
|
33958
34122
|
isPushAdopted,
|
|
33959
|
-
|
|
34123
|
+
isRecord4 as isRecord,
|
|
33960
34124
|
isResolvableDriftLabel,
|
|
33961
34125
|
isRetryable,
|
|
33962
34126
|
isSchemaAdopted,
|
|
@@ -34058,6 +34222,7 @@ export {
|
|
|
34058
34222
|
refuseRun,
|
|
34059
34223
|
removeDeployedGame,
|
|
34060
34224
|
removeProfile,
|
|
34225
|
+
renderCatalog,
|
|
34061
34226
|
renderDeleteRun,
|
|
34062
34227
|
renderDeployServerError,
|
|
34063
34228
|
renderRestoreUnsupported,
|
|
@@ -34167,5 +34332,6 @@ export {
|
|
|
34167
34332
|
validateQueueKey,
|
|
34168
34333
|
validateTimebackCourseRequirements,
|
|
34169
34334
|
withLocalBucket,
|
|
34170
|
-
writeAssessmentFixtureBundle
|
|
34335
|
+
writeAssessmentFixtureBundle,
|
|
34336
|
+
writeCatalog
|
|
34171
34337
|
};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
|
-
"cliVersion": "0.28.1-beta.
|
|
3
|
-
"sdkVersion": "0.16.1-beta.
|
|
4
|
-
"runtimeBuildId": "
|
|
5
|
-
"inputFingerprint": "
|
|
2
|
+
"cliVersion": "0.28.1-beta.14",
|
|
3
|
+
"sdkVersion": "0.16.1-beta.14",
|
|
4
|
+
"runtimeBuildId": "3ce61e6be9e1",
|
|
5
|
+
"inputFingerprint": "3ce61e6be9e1a0a36a9263642202c3a2d3227b315087e86599fba386a455f421",
|
|
6
6
|
"entry": "index.js"
|
|
7
7
|
}
|
|
@@ -12056,9 +12056,9 @@ var init_list = __esm({
|
|
|
12056
12056
|
// ../edge-play/src/game/lib/metadata.ts
|
|
12057
12057
|
function getRuntimeMetadata() {
|
|
12058
12058
|
return {
|
|
12059
|
-
cliVersion: true ? "0.28.1-beta.
|
|
12060
|
-
sdkVersion: true ? "0.16.1-beta.
|
|
12061
|
-
buildId: true ? "
|
|
12059
|
+
cliVersion: true ? "0.28.1-beta.14" : "0.0.0-dev",
|
|
12060
|
+
sdkVersion: true ? "0.16.1-beta.14" : "0.0.0-dev",
|
|
12061
|
+
buildId: true ? "3ce61e6be9e1" : "dev-source"
|
|
12062
12062
|
};
|
|
12063
12063
|
}
|
|
12064
12064
|
var init_metadata = __esm({
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
|
-
"cliVersion": "0.28.1-beta.
|
|
3
|
-
"sdkVersion": "0.16.1-beta.
|
|
4
|
-
"runtimeBuildId": "
|
|
5
|
-
"inputFingerprint": "
|
|
2
|
+
"cliVersion": "0.28.1-beta.14",
|
|
3
|
+
"sdkVersion": "0.16.1-beta.14",
|
|
4
|
+
"runtimeBuildId": "3ce61e6be9e1",
|
|
5
|
+
"inputFingerprint": "3ce61e6be9e1a0a36a9263642202c3a2d3227b315087e86599fba386a455f421",
|
|
6
6
|
"entry": "index.js"
|
|
7
7
|
}
|
package/dist/utils.d.ts
CHANGED
|
@@ -141,6 +141,19 @@ interface DashboardThemeConfig {
|
|
|
141
141
|
/** Secondary/accent color as a hex string, e.g. '#ffd166' */
|
|
142
142
|
secondary?: string;
|
|
143
143
|
}
|
|
144
|
+
/**
|
|
145
|
+
* Child-catalog contract generation (see @playcademy/sdk/contracts).
|
|
146
|
+
* The extractor is a repo-local script (run with the CLI's runtime) that
|
|
147
|
+
* prints `{ generatedFrom, deliveries }` as JSON on stdout; the CLI
|
|
148
|
+
* validates, stamps the contract fields, and writes
|
|
149
|
+
* `.playcademy/catalog.json` deterministically. The document carries no
|
|
150
|
+
* app identity — consuming repos assign the namespace key from sync
|
|
151
|
+
* provenance.
|
|
152
|
+
*/
|
|
153
|
+
interface CatalogConfig {
|
|
154
|
+
/** Path to the extractor script, relative to the config file. */
|
|
155
|
+
extractor: string;
|
|
156
|
+
}
|
|
144
157
|
/**
|
|
145
158
|
* Unified Playcademy configuration
|
|
146
159
|
* Used for playcademy.config.{js,json}
|
|
@@ -173,6 +186,8 @@ interface PlaycademyConfig {
|
|
|
173
186
|
dashboard?: DashboardConfig | boolean;
|
|
174
187
|
/** Integrations (database, custom routes, external services) */
|
|
175
188
|
integrations?: IntegrationsConfig;
|
|
189
|
+
/** Child-catalog contract generation (`playcademy catalog`) */
|
|
190
|
+
catalog?: CatalogConfig;
|
|
176
191
|
}
|
|
177
192
|
|
|
178
193
|
/**
|
package/dist/utils.js
CHANGED
|
@@ -388,7 +388,7 @@ var DASHBOARD_API_ROUTES_DIRECTORY = "api";
|
|
|
388
388
|
// ../better-auth/package.json
|
|
389
389
|
var package_default = {
|
|
390
390
|
name: "@playcademy/better-auth",
|
|
391
|
-
version: "0.0.21-beta.
|
|
391
|
+
version: "0.0.21-beta.14",
|
|
392
392
|
type: "module",
|
|
393
393
|
exports: {
|
|
394
394
|
"./server": {
|
|
@@ -828,7 +828,10 @@ function nestColor(content, color2) {
|
|
|
828
828
|
function customTransform(text) {
|
|
829
829
|
let result = text;
|
|
830
830
|
result = result.replace(/<<([^>]+)>>/g, (_, url) => blueBright(underline(url)));
|
|
831
|
-
result = result.replace(
|
|
831
|
+
result = result.replace(
|
|
832
|
+
/<([^>]+)>/g,
|
|
833
|
+
(match, inner) => blueBright(/[./]/.test(inner) ? inner : match)
|
|
834
|
+
);
|
|
832
835
|
result = result.replace(/`([^`]+)`/g, (_, code) => nestColor(code, greenBright));
|
|
833
836
|
return result;
|
|
834
837
|
}
|
|
@@ -2831,7 +2834,7 @@ import { existsSync as existsSync9, mkdirSync as mkdirSync2, writeFileSync as wr
|
|
|
2831
2834
|
import { dirname as dirname4, join as join14 } from "node:path";
|
|
2832
2835
|
|
|
2833
2836
|
// src/version.ts
|
|
2834
|
-
var cliVersion = false ? "0.0.0-dev" : "0.28.1-beta.
|
|
2837
|
+
var cliVersion = false ? "0.0.0-dev" : "0.28.1-beta.14";
|
|
2835
2838
|
|
|
2836
2839
|
// src/lib/build/binary-resource.ts
|
|
2837
2840
|
function writeFileTree(baseDir, files) {
|
package/dist/version.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "playcademy",
|
|
3
|
-
"version": "0.28.1-beta.
|
|
3
|
+
"version": "0.28.1-beta.14",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"exports": {
|
|
6
6
|
".": {
|
|
@@ -55,7 +55,7 @@
|
|
|
55
55
|
},
|
|
56
56
|
"dependencies": {
|
|
57
57
|
"@inquirer/prompts": "^7.8.6",
|
|
58
|
-
"@playcademy/sdk": "0.16.1-beta.
|
|
58
|
+
"@playcademy/sdk": "0.16.1-beta.14",
|
|
59
59
|
"chokidar": "^4.0.3",
|
|
60
60
|
"colorette": "^2.0.20",
|
|
61
61
|
"commander": "^14.0.1",
|