playcademy 0.18.1 → 0.18.2
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/cli.js +1 -1
- package/dist/index.d.ts +24 -12
- package/dist/index.js +465 -255
- package/dist/utils.js +558 -351
- package/dist/version.js +1 -1
- package/package.json +1 -1
- package/dist/constants/src/achievements.ts +0 -107
- package/dist/constants/src/auth.ts +0 -13
- package/dist/constants/src/character.ts +0 -16
- package/dist/constants/src/domains.ts +0 -50
- package/dist/constants/src/env-vars.ts +0 -20
- package/dist/constants/src/index.ts +0 -18
- package/dist/constants/src/overworld.ts +0 -330
- package/dist/constants/src/system.ts +0 -10
- package/dist/constants/src/timeback.ts +0 -118
- package/dist/constants/src/typescript.ts +0 -21
- package/dist/constants/src/workers.ts +0 -36
- package/dist/edge-play/src/constants.ts +0 -27
- package/dist/edge-play/src/entry/middleware.ts +0 -247
- package/dist/edge-play/src/entry/queue.test.ts +0 -279
- package/dist/edge-play/src/entry/queue.ts +0 -107
- package/dist/edge-play/src/entry/session.ts +0 -45
- package/dist/edge-play/src/entry/setup.ts +0 -78
- package/dist/edge-play/src/entry/types.ts +0 -30
- package/dist/edge-play/src/entry.ts +0 -94
- package/dist/edge-play/src/html.d.ts +0 -5
- package/dist/edge-play/src/index.ts +0 -4
- package/dist/edge-play/src/lib/errors.ts +0 -51
- package/dist/edge-play/src/lib/index.ts +0 -3
- package/dist/edge-play/src/lib/self-dispatch.test.ts +0 -244
- package/dist/edge-play/src/lib/self-dispatch.ts +0 -41
- package/dist/edge-play/src/lib/validation.test.ts +0 -190
- package/dist/edge-play/src/lib/validation.ts +0 -64
- package/dist/edge-play/src/polyfills.js +0 -54
- package/dist/edge-play/src/register-routes.ts +0 -59
- package/dist/edge-play/src/routes/health.ts +0 -104
- package/dist/edge-play/src/routes/index.ts +0 -66
- package/dist/edge-play/src/routes/integrations/timeback/end-activity.ts +0 -181
- package/dist/edge-play/src/routes/integrations/timeback/get-xp.ts +0 -159
- package/dist/edge-play/src/routes/root.html +0 -253
- package/dist/edge-play/src/routes/root.ts +0 -22
- package/dist/edge-play/src/stub-entry.ts +0 -161
- package/dist/edge-play/src/types.ts +0 -124
package/dist/index.js
CHANGED
|
@@ -2176,13 +2176,10 @@ function buildQueueImportStatements(queueHandlers) {
|
|
|
2176
2176
|
if (queueHandlers.length === 0) {
|
|
2177
2177
|
return "// No queue handlers";
|
|
2178
2178
|
}
|
|
2179
|
-
return
|
|
2180
|
-
|
|
2181
|
-
|
|
2182
|
-
|
|
2183
|
-
return `import queueHandler${index2} from '@game-server/${normalizedFile}'`;
|
|
2184
|
-
})
|
|
2185
|
-
].join("\n");
|
|
2179
|
+
return queueHandlers.map((handler, index2) => {
|
|
2180
|
+
const normalizedFile = handler.file.replace(/^server\//, "").replace(/\\/g, "/");
|
|
2181
|
+
return `import queueHandler${index2} from '@game-server/${normalizedFile}'`;
|
|
2182
|
+
}).join("\n");
|
|
2186
2183
|
}
|
|
2187
2184
|
function buildQueueHandlerCode(queueHandlers) {
|
|
2188
2185
|
if (queueHandlers.length === 0) {
|
|
@@ -4017,7 +4014,7 @@ import { existsSync as existsSync9, mkdirSync as mkdirSync2, readFileSync as rea
|
|
|
4017
4014
|
import { join as join13 } from "node:path";
|
|
4018
4015
|
|
|
4019
4016
|
// src/version.ts
|
|
4020
|
-
var cliVersion = false ? "0.0.0-dev" : "0.18.
|
|
4017
|
+
var cliVersion = false ? "0.0.0-dev" : "0.18.2";
|
|
4021
4018
|
|
|
4022
4019
|
// src/lib/init/database.ts
|
|
4023
4020
|
var drizzleConfigTemplate = loadTemplateString("database/drizzle-config.ts");
|
|
@@ -6381,8 +6378,8 @@ async function registerCustomRoutes(app, routes) {
|
|
|
6381
6378
|
}
|
|
6382
6379
|
|
|
6383
6380
|
// src/lib/dev/server.ts
|
|
6384
|
-
import { mkdir as
|
|
6385
|
-
import { join as
|
|
6381
|
+
import { mkdir as mkdir5 } from "fs/promises";
|
|
6382
|
+
import { join as join30 } from "path";
|
|
6386
6383
|
import { Log, LogLevel, Miniflare } from "miniflare";
|
|
6387
6384
|
|
|
6388
6385
|
// ../edge-play/src/constants.ts
|
|
@@ -6484,7 +6481,12 @@ Stop the other server or specify a different port with --port <number>.`
|
|
|
6484
6481
|
}
|
|
6485
6482
|
|
|
6486
6483
|
// src/lib/deploy/bundle.ts
|
|
6487
|
-
import {
|
|
6484
|
+
import { join as join29, relative as relative4 } from "node:path";
|
|
6485
|
+
|
|
6486
|
+
// src/lib/deploy/backend-runtime.ts
|
|
6487
|
+
import { existsSync as existsSync22 } from "node:fs";
|
|
6488
|
+
import { copyFile, mkdir as mkdir4, readFile as readFile4, rm as rm2, writeFile as writeFile4 } from "node:fs/promises";
|
|
6489
|
+
import { tmpdir as tmpdir3 } from "node:os";
|
|
6488
6490
|
import { join as join28 } from "node:path";
|
|
6489
6491
|
|
|
6490
6492
|
// ../utils/src/path.ts
|
|
@@ -6740,56 +6742,33 @@ function getMonorepoRoot() {
|
|
|
6740
6742
|
var isCompiledBinary = typeof IS_COMPILED_BINARY !== "undefined" && IS_COMPILED_BINARY;
|
|
6741
6743
|
|
|
6742
6744
|
// src/lib/build/plugins.ts
|
|
6745
|
+
var TEXT_LOADER_PATTERNS = [
|
|
6746
|
+
/edge-play\/src\/stub-entry\.ts$/,
|
|
6747
|
+
/edge-play\/src\/routes\/root\.html$/,
|
|
6748
|
+
/templates\/sample-route\.ts$/
|
|
6749
|
+
];
|
|
6743
6750
|
function textLoaderPlugin() {
|
|
6744
6751
|
return {
|
|
6745
6752
|
name: "text-loader",
|
|
6746
6753
|
setup(build3) {
|
|
6747
|
-
|
|
6748
|
-
|
|
6749
|
-
|
|
6750
|
-
|
|
6751
|
-
|
|
6752
|
-
|
|
6753
|
-
|
|
6754
|
-
|
|
6755
|
-
|
|
6756
|
-
|
|
6757
|
-
const text5 = await fs2.readFile(args.path, "utf8");
|
|
6758
|
-
return {
|
|
6759
|
-
contents: `export default ${JSON.stringify(text5)}`,
|
|
6760
|
-
loader: "js"
|
|
6761
|
-
};
|
|
6762
|
-
});
|
|
6763
|
-
build3.onLoad({ filter: /edge-play\/src\/routes\/root\.html$/ }, async (args) => {
|
|
6764
|
-
const fs2 = await import("fs/promises");
|
|
6765
|
-
const text5 = await fs2.readFile(args.path, "utf8");
|
|
6766
|
-
return {
|
|
6767
|
-
contents: `export default ${JSON.stringify(text5)}`,
|
|
6768
|
-
loader: "js"
|
|
6769
|
-
};
|
|
6770
|
-
});
|
|
6771
|
-
build3.onLoad({ filter: /templates\/sample-route\.ts$/ }, async (args) => {
|
|
6772
|
-
const fs2 = await import("fs/promises");
|
|
6773
|
-
const text5 = await fs2.readFile(args.path, "utf8");
|
|
6774
|
-
return {
|
|
6775
|
-
contents: `export default ${JSON.stringify(text5)}`,
|
|
6776
|
-
loader: "js"
|
|
6777
|
-
};
|
|
6778
|
-
});
|
|
6754
|
+
for (const filter of TEXT_LOADER_PATTERNS) {
|
|
6755
|
+
build3.onLoad({ filter }, async (args) => {
|
|
6756
|
+
const fs2 = await import("fs/promises");
|
|
6757
|
+
const text5 = await fs2.readFile(args.path, "utf8");
|
|
6758
|
+
return {
|
|
6759
|
+
contents: `export default ${JSON.stringify(text5)}`,
|
|
6760
|
+
loader: "js"
|
|
6761
|
+
};
|
|
6762
|
+
});
|
|
6763
|
+
}
|
|
6779
6764
|
}
|
|
6780
6765
|
};
|
|
6781
6766
|
}
|
|
6782
6767
|
|
|
6783
|
-
// src/lib/
|
|
6768
|
+
// src/lib/build/embed.ts
|
|
6784
6769
|
import { existsSync as existsSync21, mkdirSync as mkdirSync8, writeFileSync as writeFileSync13 } from "node:fs";
|
|
6785
6770
|
import { dirname as dirname6, join as join27 } from "node:path";
|
|
6786
|
-
|
|
6787
|
-
// src/lib/deploy/embedded-sources.ts
|
|
6788
|
-
var EMBEDDED_SOURCES = null;
|
|
6789
|
-
|
|
6790
|
-
// src/lib/deploy/extract-sources.ts
|
|
6791
|
-
var EXTRACTION_MARKER = ".embedded-sources.ok";
|
|
6792
|
-
function writeTree(baseDir, files) {
|
|
6771
|
+
function writeFileTree(baseDir, files) {
|
|
6793
6772
|
for (const [relativePath, content] of Object.entries(files)) {
|
|
6794
6773
|
const fullPath = join27(baseDir, relativePath);
|
|
6795
6774
|
const dir = dirname6(fullPath);
|
|
@@ -6799,27 +6778,225 @@ function writeTree(baseDir, files) {
|
|
|
6799
6778
|
writeFileSync13(fullPath, content);
|
|
6800
6779
|
}
|
|
6801
6780
|
}
|
|
6802
|
-
|
|
6803
|
-
|
|
6804
|
-
|
|
6805
|
-
|
|
6781
|
+
function createBundleExtractor(options) {
|
|
6782
|
+
const { name, cacheSubdir, getBundle } = options;
|
|
6783
|
+
const marker = `.${name}.ok`;
|
|
6784
|
+
let cachedDir = null;
|
|
6785
|
+
return () => {
|
|
6786
|
+
if (cachedDir) {
|
|
6787
|
+
return cachedDir;
|
|
6788
|
+
}
|
|
6789
|
+
const bundle = getBundle();
|
|
6790
|
+
if (!bundle) {
|
|
6791
|
+
throw new Error(`${name}: embedded bundle is null (not available in dev mode)`);
|
|
6792
|
+
}
|
|
6793
|
+
const dir = join27(cacheVersionDir(cliVersion), cacheSubdir);
|
|
6794
|
+
const markerPath = join27(dir, marker);
|
|
6795
|
+
if (!existsSync21(markerPath)) {
|
|
6796
|
+
mkdirSync8(dir, { recursive: true });
|
|
6797
|
+
writeFileTree(dir, bundle);
|
|
6798
|
+
writeFileSync13(markerPath, `${cliVersion}
|
|
6799
|
+
`, "utf8");
|
|
6800
|
+
}
|
|
6801
|
+
cachedDir = dir;
|
|
6802
|
+
return dir;
|
|
6803
|
+
};
|
|
6804
|
+
}
|
|
6805
|
+
|
|
6806
|
+
// src/lib/deploy/embedded-runtime.ts
|
|
6807
|
+
var EMBEDDED_BACKEND_RUNTIME = null;
|
|
6808
|
+
|
|
6809
|
+
// src/lib/deploy/extract-runtime.ts
|
|
6810
|
+
var extractEmbeddedBackendRuntime = createBundleExtractor({
|
|
6811
|
+
name: "embedded-backend-runtime",
|
|
6812
|
+
cacheSubdir: "backend-runtime",
|
|
6813
|
+
getBundle: () => EMBEDDED_BACKEND_RUNTIME
|
|
6814
|
+
});
|
|
6815
|
+
|
|
6816
|
+
// src/lib/deploy/backend-runtime.ts
|
|
6817
|
+
var BACKEND_RUNTIME_ENTRY = "index.js";
|
|
6818
|
+
var BACKEND_RUNTIME_POLYFILLS = "polyfills.js";
|
|
6819
|
+
var BACKEND_RUNTIME_MANIFEST = "manifest.json";
|
|
6820
|
+
var DEV_RUNTIME_CACHE_DIR = "backend-runtime-dev";
|
|
6821
|
+
function createNodePolyfillAliases(polyfillsPath) {
|
|
6822
|
+
return {
|
|
6823
|
+
fs: polyfillsPath,
|
|
6824
|
+
"fs/promises": polyfillsPath,
|
|
6825
|
+
path: polyfillsPath,
|
|
6826
|
+
os: polyfillsPath,
|
|
6827
|
+
process: polyfillsPath,
|
|
6828
|
+
"node:fs": polyfillsPath,
|
|
6829
|
+
"node:fs/promises": polyfillsPath,
|
|
6830
|
+
"node:path": polyfillsPath,
|
|
6831
|
+
"node:os": polyfillsPath,
|
|
6832
|
+
"node:process": polyfillsPath
|
|
6833
|
+
};
|
|
6834
|
+
}
|
|
6835
|
+
var WORKSPACE_SOURCE_EXTENSIONS = [".ts", ".tsx", ".js", ".mjs", ".cjs"];
|
|
6836
|
+
var RUNTIME_SOURCE_DIRS = [
|
|
6837
|
+
"packages/edge-play/src",
|
|
6838
|
+
"packages/sdk/src",
|
|
6839
|
+
"packages/constants/src",
|
|
6840
|
+
"packages/timeback/src",
|
|
6841
|
+
"packages/types/src",
|
|
6842
|
+
"packages/utils/src",
|
|
6843
|
+
"packages/cloudflare/src",
|
|
6844
|
+
"packages/logger/src"
|
|
6845
|
+
];
|
|
6846
|
+
async function getPackageVersion2(monorepoRoot, packageName) {
|
|
6847
|
+
try {
|
|
6848
|
+
const packageJson = JSON.parse(
|
|
6849
|
+
await readFile4(join28(monorepoRoot, "packages", packageName, "package.json"), "utf8")
|
|
6850
|
+
);
|
|
6851
|
+
return packageJson.version ?? "0.0.0-dev";
|
|
6852
|
+
} catch {
|
|
6853
|
+
return "0.0.0-dev";
|
|
6854
|
+
}
|
|
6855
|
+
}
|
|
6856
|
+
async function computeRuntimeInputFingerprint(monorepoRoot, sdkVersion) {
|
|
6857
|
+
const entries = await Promise.all(
|
|
6858
|
+
RUNTIME_SOURCE_DIRS.map(async (dir) => [
|
|
6859
|
+
dir,
|
|
6860
|
+
await hashDirectory(join28(monorepoRoot, dir), ["ts", "js", "json", "html"])
|
|
6861
|
+
])
|
|
6862
|
+
);
|
|
6863
|
+
return hashContent({ ...Object.fromEntries(entries), sdkVersion });
|
|
6864
|
+
}
|
|
6865
|
+
async function getRuntimeBuildMetadata(monorepoRoot) {
|
|
6866
|
+
const [cliVersion2, sdkVersion] = await Promise.all([
|
|
6867
|
+
getPackageVersion2(monorepoRoot, "cli"),
|
|
6868
|
+
getPackageVersion2(monorepoRoot, "sdk")
|
|
6869
|
+
]);
|
|
6870
|
+
const inputFingerprint = await computeRuntimeInputFingerprint(monorepoRoot, sdkVersion);
|
|
6871
|
+
return {
|
|
6872
|
+
cliVersion: cliVersion2,
|
|
6873
|
+
sdkVersion,
|
|
6874
|
+
runtimeBuildId: inputFingerprint.slice(0, 12),
|
|
6875
|
+
inputFingerprint,
|
|
6876
|
+
entry: BACKEND_RUNTIME_ENTRY,
|
|
6877
|
+
polyfills: BACKEND_RUNTIME_POLYFILLS
|
|
6878
|
+
};
|
|
6879
|
+
}
|
|
6880
|
+
function resolveWorkspaceSourceImport(monorepoRoot, specifier) {
|
|
6881
|
+
if (!specifier.startsWith("@playcademy/")) {
|
|
6882
|
+
return null;
|
|
6806
6883
|
}
|
|
6807
|
-
|
|
6808
|
-
|
|
6884
|
+
const pathParts = specifier.slice("@playcademy/".length).split("/");
|
|
6885
|
+
const packageName = pathParts.shift();
|
|
6886
|
+
if (!packageName) {
|
|
6887
|
+
return null;
|
|
6809
6888
|
}
|
|
6810
|
-
const
|
|
6811
|
-
const
|
|
6812
|
-
const
|
|
6813
|
-
|
|
6814
|
-
|
|
6815
|
-
|
|
6816
|
-
|
|
6817
|
-
|
|
6818
|
-
|
|
6819
|
-
|
|
6889
|
+
const basePath = join28(monorepoRoot, "packages", packageName, "src");
|
|
6890
|
+
const targetPath = pathParts.length > 0 ? join28(basePath, ...pathParts) : join28(basePath, "index");
|
|
6891
|
+
for (const extension of WORKSPACE_SOURCE_EXTENSIONS) {
|
|
6892
|
+
const withExtension = `${targetPath}${extension}`;
|
|
6893
|
+
if (existsSync22(withExtension)) {
|
|
6894
|
+
return withExtension;
|
|
6895
|
+
}
|
|
6896
|
+
}
|
|
6897
|
+
for (const extension of WORKSPACE_SOURCE_EXTENSIONS) {
|
|
6898
|
+
const indexPath = join28(targetPath, `index${extension}`);
|
|
6899
|
+
if (existsSync22(indexPath)) {
|
|
6900
|
+
return indexPath;
|
|
6901
|
+
}
|
|
6820
6902
|
}
|
|
6821
|
-
|
|
6822
|
-
|
|
6903
|
+
return null;
|
|
6904
|
+
}
|
|
6905
|
+
function createWorkspaceSourceResolverPlugin(monorepoRoot) {
|
|
6906
|
+
return {
|
|
6907
|
+
name: "playcademy-workspace-source-resolver",
|
|
6908
|
+
setup(build3) {
|
|
6909
|
+
build3.onResolve({ filter: /^@playcademy\// }, (args) => {
|
|
6910
|
+
const resolved = resolveWorkspaceSourceImport(monorepoRoot, args.path);
|
|
6911
|
+
return resolved ? { path: resolved } : null;
|
|
6912
|
+
});
|
|
6913
|
+
}
|
|
6914
|
+
};
|
|
6915
|
+
}
|
|
6916
|
+
async function writeRuntimeManifest(outdir, manifest) {
|
|
6917
|
+
await writeFile4(
|
|
6918
|
+
join28(outdir, BACKEND_RUNTIME_MANIFEST),
|
|
6919
|
+
`${JSON.stringify(manifest, null, 2)}
|
|
6920
|
+
`,
|
|
6921
|
+
"utf8"
|
|
6922
|
+
);
|
|
6923
|
+
}
|
|
6924
|
+
async function buildBackendRuntime(outdir) {
|
|
6925
|
+
const monorepoRoot = getMonorepoRoot();
|
|
6926
|
+
const manifest = await getRuntimeBuildMetadata(monorepoRoot);
|
|
6927
|
+
const runtimeEntry = join28(monorepoRoot, "packages", "edge-play", "src", "entry", "index.ts");
|
|
6928
|
+
const polyfillsEntry = join28(monorepoRoot, "packages", "edge-play", "src", "polyfills.js");
|
|
6929
|
+
const esbuild4 = await import("esbuild");
|
|
6930
|
+
await rm2(outdir, { recursive: true, force: true });
|
|
6931
|
+
await mkdir4(outdir, { recursive: true });
|
|
6932
|
+
await esbuild4.build({
|
|
6933
|
+
entryPoints: [runtimeEntry],
|
|
6934
|
+
outfile: join28(outdir, BACKEND_RUNTIME_ENTRY),
|
|
6935
|
+
bundle: true,
|
|
6936
|
+
format: "esm",
|
|
6937
|
+
platform: "browser",
|
|
6938
|
+
target: "es2022",
|
|
6939
|
+
write: true,
|
|
6940
|
+
sourcemap: false,
|
|
6941
|
+
minify: false,
|
|
6942
|
+
logLevel: "error",
|
|
6943
|
+
alias: createNodePolyfillAliases(polyfillsEntry),
|
|
6944
|
+
plugins: [textLoaderPlugin(), createWorkspaceSourceResolverPlugin(monorepoRoot)],
|
|
6945
|
+
define: {
|
|
6946
|
+
PLAYCADEMY_RUNTIME_CLI_VERSION: JSON.stringify(manifest.cliVersion),
|
|
6947
|
+
PLAYCADEMY_RUNTIME_SDK_VERSION: JSON.stringify(manifest.sdkVersion),
|
|
6948
|
+
PLAYCADEMY_RUNTIME_BUILD_ID: JSON.stringify(manifest.runtimeBuildId)
|
|
6949
|
+
}
|
|
6950
|
+
});
|
|
6951
|
+
await copyFile(polyfillsEntry, join28(outdir, BACKEND_RUNTIME_POLYFILLS));
|
|
6952
|
+
await writeRuntimeManifest(outdir, manifest);
|
|
6953
|
+
return manifest;
|
|
6954
|
+
}
|
|
6955
|
+
async function ensureDevBackendRuntime() {
|
|
6956
|
+
const monorepoRoot = getMonorepoRoot();
|
|
6957
|
+
const manifest = await getRuntimeBuildMetadata(monorepoRoot);
|
|
6958
|
+
const runtimeDir = join28(
|
|
6959
|
+
tmpdir3(),
|
|
6960
|
+
DEV_RUNTIME_CACHE_DIR,
|
|
6961
|
+
manifest.cliVersion,
|
|
6962
|
+
manifest.inputFingerprint
|
|
6963
|
+
);
|
|
6964
|
+
if (!existsSync22(join28(runtimeDir, BACKEND_RUNTIME_MANIFEST))) {
|
|
6965
|
+
await buildBackendRuntime(runtimeDir);
|
|
6966
|
+
}
|
|
6967
|
+
return runtimeDir;
|
|
6968
|
+
}
|
|
6969
|
+
async function readRuntimeManifest(runtimeDir) {
|
|
6970
|
+
const content = await readFile4(join28(runtimeDir, BACKEND_RUNTIME_MANIFEST), "utf8");
|
|
6971
|
+
return JSON.parse(content);
|
|
6972
|
+
}
|
|
6973
|
+
async function resolveBackendRuntimePaths() {
|
|
6974
|
+
const workspace = getWorkspace();
|
|
6975
|
+
const workspaceNodeModules = join28(workspace, "node_modules");
|
|
6976
|
+
if (isCompiledBinary) {
|
|
6977
|
+
const runtimeDir2 = extractEmbeddedBackendRuntime();
|
|
6978
|
+
const manifest2 = await readRuntimeManifest(runtimeDir2);
|
|
6979
|
+
const cliDepsRoot = join28(workspace, ".playcademy", "node_modules");
|
|
6980
|
+
return {
|
|
6981
|
+
runtimeDir: runtimeDir2,
|
|
6982
|
+
runtimeEntry: join28(runtimeDir2, manifest2.entry),
|
|
6983
|
+
polyfillsEntry: join28(runtimeDir2, manifest2.polyfills),
|
|
6984
|
+
workspaceNodeModules,
|
|
6985
|
+
cliDepsRoot,
|
|
6986
|
+
manifest: manifest2
|
|
6987
|
+
};
|
|
6988
|
+
}
|
|
6989
|
+
const monorepoRoot = getMonorepoRoot();
|
|
6990
|
+
const runtimeDir = await ensureDevBackendRuntime();
|
|
6991
|
+
const manifest = await readRuntimeManifest(runtimeDir);
|
|
6992
|
+
return {
|
|
6993
|
+
runtimeDir,
|
|
6994
|
+
runtimeEntry: join28(runtimeDir, manifest.entry),
|
|
6995
|
+
polyfillsEntry: join28(runtimeDir, manifest.polyfills),
|
|
6996
|
+
workspaceNodeModules,
|
|
6997
|
+
cliDepsRoot: monorepoRoot,
|
|
6998
|
+
manifest
|
|
6999
|
+
};
|
|
6823
7000
|
}
|
|
6824
7001
|
|
|
6825
7002
|
// src/lib/deploy/bundle.ts
|
|
@@ -6827,153 +7004,134 @@ async function discoverCustomRoutes(config) {
|
|
|
6827
7004
|
const workspace = getWorkspace();
|
|
6828
7005
|
const customRoutesConfig = config.integrations?.customRoutes;
|
|
6829
7006
|
const customRoutesDir = typeof customRoutesConfig === "object" && customRoutesConfig.directory || DEFAULT_API_ROUTES_DIRECTORY;
|
|
6830
|
-
const customRoutes = await discoverRoutes(
|
|
7007
|
+
const customRoutes = await discoverRoutes(join29(workspace, customRoutesDir));
|
|
6831
7008
|
const customRouteData = customRoutes.map((r) => ({
|
|
6832
7009
|
path: r.path,
|
|
6833
7010
|
file: r.file,
|
|
6834
|
-
//
|
|
7011
|
+
// relative path (e.g., 'server/api/test.ts'), not absolute
|
|
6835
7012
|
methods: r.methods
|
|
6836
7013
|
}));
|
|
6837
7014
|
return { customRouteData, customRoutesDir };
|
|
6838
7015
|
}
|
|
6839
|
-
function
|
|
6840
|
-
|
|
6841
|
-
|
|
6842
|
-
const { edgePlaySrc: edgePlaySrc2, constantsSrc } = extractEmbeddedSources();
|
|
6843
|
-
const constantsEntry2 = join28(constantsSrc, "index.ts");
|
|
6844
|
-
const workspaceNodeModules2 = join28(workspace, "node_modules");
|
|
6845
|
-
const playcademyNodeModules = join28(workspace, ".playcademy", "node_modules");
|
|
6846
|
-
return {
|
|
6847
|
-
isBuiltPackage: true,
|
|
6848
|
-
edgePlaySrc: edgePlaySrc2,
|
|
6849
|
-
constantsEntry: constantsEntry2,
|
|
6850
|
-
workspaceNodeModules: workspaceNodeModules2,
|
|
6851
|
-
cliDepsRoot: playcademyNodeModules
|
|
6852
|
-
};
|
|
7016
|
+
function getForbiddenImportMessage(specifier) {
|
|
7017
|
+
if (specifier === "@playcademy/sdk/server") {
|
|
7018
|
+
return "Use `c.get('sdk')` instead of importing the server SDK directly.";
|
|
6853
7019
|
}
|
|
6854
|
-
|
|
6855
|
-
|
|
6856
|
-
|
|
6857
|
-
|
|
6858
|
-
|
|
6859
|
-
|
|
6860
|
-
const cliPackageRoot = isBuiltPackage ? join28(distDir, "../../..") : join28(monorepoRoot, "packages/cli");
|
|
6861
|
-
const cliDepsRoot = isBuiltPackage ? join28(cliPackageRoot, "node_modules") : monorepoRoot;
|
|
6862
|
-
const workspaceNodeModules = join28(workspace, "node_modules");
|
|
6863
|
-
const constantsEntry = isBuiltPackage ? join28(embeddedEdgeSrc, "..", "..", "constants", "src", "index.ts") : join28(monorepoRoot, "packages", "constants", "src", "index.ts");
|
|
7020
|
+
if (specifier.startsWith("@playcademy/edge-play")) {
|
|
7021
|
+
return "Built-in backend runtime helpers are internal to the CLI-owned runtime.";
|
|
7022
|
+
}
|
|
7023
|
+
return "CLI-owned backend runtime packages are not available to game backend code.";
|
|
7024
|
+
}
|
|
7025
|
+
function createForbiddenRuntimeImportsPlugin(workspace) {
|
|
6864
7026
|
return {
|
|
6865
|
-
|
|
6866
|
-
|
|
6867
|
-
|
|
6868
|
-
|
|
6869
|
-
|
|
7027
|
+
name: "forbidden-backend-runtime-imports",
|
|
7028
|
+
setup(build3) {
|
|
7029
|
+
build3.onResolve(
|
|
7030
|
+
{
|
|
7031
|
+
filter: /^@playcademy\/(?:sdk\/server|edge-play(?:\/.*)?|constants(?:\/.*)?)$/
|
|
7032
|
+
},
|
|
7033
|
+
(args) => {
|
|
7034
|
+
if (!args.importer) {
|
|
7035
|
+
return null;
|
|
7036
|
+
}
|
|
7037
|
+
const importerPath = relative4(workspace, args.importer).replace(/\\/g, "/");
|
|
7038
|
+
return {
|
|
7039
|
+
errors: [
|
|
7040
|
+
{
|
|
7041
|
+
text: `Unsupported backend import "${args.path}" in ${importerPath}. ${getForbiddenImportMessage(args.path)} Use \`Context\`, \`c.env\`, \`c.get('sdk')\`, and \`c.get('playcademyUser')\` instead.`
|
|
7042
|
+
}
|
|
7043
|
+
]
|
|
7044
|
+
};
|
|
7045
|
+
}
|
|
7046
|
+
);
|
|
7047
|
+
}
|
|
6870
7048
|
};
|
|
6871
7049
|
}
|
|
6872
7050
|
function createEsbuildConfig(entryCode, paths, bundleConfig, customRoutesDir, options) {
|
|
6873
7051
|
const workspace = getWorkspace();
|
|
6874
|
-
const {
|
|
7052
|
+
const { runtimeEntry, polyfillsEntry, workspaceNodeModules, cliDepsRoot } = paths;
|
|
6875
7053
|
return {
|
|
6876
|
-
// ──── Input
|
|
7054
|
+
// ──── Input: generated entry code, not a real file ────
|
|
7055
|
+
// resolveDir = workspace so that bare specifiers in the generated code
|
|
7056
|
+
// (e.g. '@game-api/save.ts') resolve relative to the user's project root.
|
|
6877
7057
|
stdin: {
|
|
6878
7058
|
contents: entryCode,
|
|
6879
|
-
|
|
6880
|
-
resolveDir: edgePlaySrc,
|
|
6881
|
-
// Resolve relative imports from edge-play/src
|
|
7059
|
+
resolveDir: workspace,
|
|
6882
7060
|
loader: "ts"
|
|
6883
|
-
// Treat input as TypeScript
|
|
6884
7061
|
},
|
|
6885
|
-
// ──── Output
|
|
7062
|
+
// ──── Output configuration ────
|
|
6886
7063
|
bundle: true,
|
|
6887
|
-
// Bundle all dependencies into single file
|
|
6888
7064
|
format: "esm",
|
|
6889
|
-
//
|
|
7065
|
+
// Cloudflare Workers require ES modules
|
|
6890
7066
|
platform: "browser",
|
|
6891
|
-
// Workers
|
|
7067
|
+
// Workers run in a browser-like environment, not Node.js
|
|
6892
7068
|
target: "es2022",
|
|
6893
|
-
// Modern JavaScript for Workers runtime
|
|
6894
7069
|
write: false,
|
|
6895
|
-
// Return code as string
|
|
7070
|
+
// Return code as a string; the caller writes/uploads it
|
|
6896
7071
|
sourcemap: options.sourcemap ? "inline" : false,
|
|
6897
7072
|
minify: options.minify || false,
|
|
6898
|
-
logLevel: "
|
|
6899
|
-
//
|
|
6900
|
-
// ──── Module
|
|
6901
|
-
//
|
|
6902
|
-
//
|
|
6903
|
-
//
|
|
6904
|
-
//
|
|
7073
|
+
logLevel: "silent",
|
|
7074
|
+
// errors propagate as thrown exceptions; we don't want esbuild double-printing to stderr
|
|
7075
|
+
// ──── Module resolution ────
|
|
7076
|
+
// esbuild searches nodePaths in order for bare specifiers.
|
|
7077
|
+
// workspaceNodeModules: game project's own deps (hono, etc. if user installed them)
|
|
7078
|
+
// cliDepsRoot: CLI-managed deps (.playcademy/node_modules in binary mode,
|
|
7079
|
+
// monorepo root in dev mode) — where hono, @hono/node-server live
|
|
6905
7080
|
nodePaths: [workspaceNodeModules, cliDepsRoot],
|
|
6906
|
-
// ──── Build-time
|
|
6907
|
-
//
|
|
6908
|
-
//
|
|
7081
|
+
// ──── Build-time constants ────
|
|
7082
|
+
// PLAYCADEMY_CONFIG is accessed as a global in the generated entry code and in
|
|
7083
|
+
// the sealed runtime itself (passed to createBaseApp). It carries integrations
|
|
7084
|
+
// config, route metadata, queue metadata, etc.
|
|
6909
7085
|
define: {
|
|
6910
7086
|
PLAYCADEMY_CONFIG: JSON.stringify(bundleConfig)
|
|
6911
7087
|
},
|
|
6912
|
-
// ──── Import Aliases ────
|
|
6913
7088
|
alias: {
|
|
6914
|
-
// ┌─
|
|
6915
|
-
// │
|
|
6916
|
-
// │
|
|
6917
|
-
//
|
|
6918
|
-
|
|
6919
|
-
|
|
6920
|
-
//
|
|
6921
|
-
// │
|
|
6922
|
-
//
|
|
6923
|
-
|
|
6924
|
-
//
|
|
6925
|
-
|
|
6926
|
-
//
|
|
6927
|
-
// │
|
|
6928
|
-
//
|
|
6929
|
-
|
|
6930
|
-
//
|
|
6931
|
-
|
|
6932
|
-
//
|
|
6933
|
-
// │
|
|
6934
|
-
//
|
|
6935
|
-
|
|
6936
|
-
//
|
|
6937
|
-
|
|
6938
|
-
// │ that throw helpful errors if user code tries to use them. │
|
|
6939
|
-
// └─────────────────────────────────────────────────────────────────┘
|
|
6940
|
-
fs: join28(edgePlaySrc, "polyfills.js"),
|
|
6941
|
-
"fs/promises": join28(edgePlaySrc, "polyfills.js"),
|
|
6942
|
-
path: join28(edgePlaySrc, "polyfills.js"),
|
|
6943
|
-
os: join28(edgePlaySrc, "polyfills.js"),
|
|
6944
|
-
process: join28(edgePlaySrc, "polyfills.js")
|
|
7089
|
+
// ┌─ Sealed backend runtime ────────────────────────────────────────────┐
|
|
7090
|
+
// │ The pre-bundled artifact: edge-play + sdk/server + all internal │
|
|
7091
|
+
// │ @playcademy/* deps, zero external imports remaining. This alias │
|
|
7092
|
+
// │ is what enforces version isolation — game node_modules are ignored. │
|
|
7093
|
+
// └─────────────────────────────────────────────────────────────────────┘
|
|
7094
|
+
"@playcademy/backend-runtime": runtimeEntry,
|
|
7095
|
+
// ┌─ Game's custom route files ─────────────────────────────────────────┐
|
|
7096
|
+
// │ @game-api is a virtual module pointing to the game's API directory. │
|
|
7097
|
+
// │ Example: import * as route from '@game-api/save.ts' │
|
|
7098
|
+
// │ Resolves to: /user-project/server/api/save.ts │
|
|
7099
|
+
// └─────────────────────────────────────────────────────────────────────┘
|
|
7100
|
+
"@game-api": join29(workspace, customRoutesDir),
|
|
7101
|
+
// ┌─ Game's server library directory ───────────────────────────────────┐
|
|
7102
|
+
// │ @game-server is a virtual module for server-side utilities. │
|
|
7103
|
+
// │ Example: import { getAuth } from '@game-server/lib/auth' │
|
|
7104
|
+
// │ Resolves to: /user-project/server/lib/auth.ts │
|
|
7105
|
+
// └─────────────────────────────────────────────────────────────────────┘
|
|
7106
|
+
"@game-server": join29(workspace, "server"),
|
|
7107
|
+
// ┌─ Node.js polyfills for Cloudflare Workers ──────────────────────────┐
|
|
7108
|
+
// │ Workers don't have fs, path, os, process, etc. Redirect them to a │
|
|
7109
|
+
// │ polyfills stub bundled into the sealed runtime that throws a clear │
|
|
7110
|
+
// │ error if user code actually calls them at runtime. │
|
|
7111
|
+
// └─────────────────────────────────────────────────────────────────────┘
|
|
7112
|
+
...createNodePolyfillAliases(polyfillsEntry)
|
|
6945
7113
|
},
|
|
6946
|
-
|
|
6947
|
-
plugins: [textLoaderPlugin()],
|
|
6948
|
-
// Support Bun's 'with { type: "text" }' imports
|
|
6949
|
-
// ──── External Dependencies ────
|
|
7114
|
+
plugins: [createForbiddenRuntimeImportsPlugin(workspace)],
|
|
6950
7115
|
external: []
|
|
6951
|
-
// Bundle everything
|
|
7116
|
+
// Bundle everything — no externals allowed in Workers
|
|
6952
7117
|
};
|
|
6953
7118
|
}
|
|
6954
|
-
function loadEntryTemplate(paths) {
|
|
6955
|
-
const entryPath = paths ? join28(paths.edgePlaySrc, "entry.ts") : join28(getMonorepoRoot(), "packages", "edge-play", "src", "entry.ts");
|
|
6956
|
-
return readFileSync13(entryPath, "utf8");
|
|
6957
|
-
}
|
|
6958
7119
|
async function bundleBackend(config, options = {}) {
|
|
6959
7120
|
const esbuild4 = await import("esbuild");
|
|
6960
7121
|
const { customRouteData, customRoutesDir } = await discoverCustomRoutes(config);
|
|
6961
7122
|
const queueHandlers = discoverQueueHandlers();
|
|
6962
7123
|
validateQueueHandlersConfig(config, queueHandlers);
|
|
6963
|
-
const paths =
|
|
6964
|
-
const entryTemplate = loadEntryTemplate(paths);
|
|
7124
|
+
const paths = await resolveBackendRuntimePaths();
|
|
6965
7125
|
const bundleConfig = {
|
|
6966
7126
|
...config,
|
|
6967
7127
|
__routeMetadata: customRouteData,
|
|
6968
7128
|
__queueMetadata: queueHandlers
|
|
6969
7129
|
};
|
|
6970
|
-
const hasAuth = Boolean(config.integrations?.auth);
|
|
6971
7130
|
const entryCode = generateEntryCode(
|
|
6972
7131
|
customRouteData,
|
|
6973
7132
|
customRoutesDir,
|
|
6974
7133
|
queueHandlers,
|
|
6975
|
-
|
|
6976
|
-
entryTemplate
|
|
7134
|
+
Boolean(config.integrations?.auth)
|
|
6977
7135
|
);
|
|
6978
7136
|
const buildConfig = createEsbuildConfig(
|
|
6979
7137
|
entryCode,
|
|
@@ -6986,9 +7144,8 @@ async function bundleBackend(config, options = {}) {
|
|
|
6986
7144
|
if (!result.outputFiles?.[0]) {
|
|
6987
7145
|
throw new Error("Backend bundling failed: no output");
|
|
6988
7146
|
}
|
|
6989
|
-
const code = result.outputFiles[0].text;
|
|
6990
7147
|
return {
|
|
6991
|
-
code,
|
|
7148
|
+
code: result.outputFiles[0].text,
|
|
6992
7149
|
config,
|
|
6993
7150
|
customRoutes: customRouteData
|
|
6994
7151
|
};
|
|
@@ -6996,50 +7153,69 @@ async function bundleBackend(config, options = {}) {
|
|
|
6996
7153
|
function buildCustomRouteImportStatements(customRoutes, customRoutesDir) {
|
|
6997
7154
|
const normalizedRoutesDir = customRoutesDir.replace(/\\/g, "/").replace(/\/+/g, "/");
|
|
6998
7155
|
const customRoutesPrefix = normalizedRoutesDir.endsWith("/") ? normalizedRoutesDir : `${normalizedRoutesDir}/`;
|
|
6999
|
-
return customRoutes.map((route,
|
|
7156
|
+
return customRoutes.map((route, index2) => {
|
|
7000
7157
|
const normalizedFile = route.file.replace(/\\/g, "/").replace(/\/+/g, "/");
|
|
7001
7158
|
const importPath = normalizedFile.startsWith(customRoutesPrefix) ? normalizedFile.slice(customRoutesPrefix.length) : normalizedFile;
|
|
7002
|
-
return `import * as customRoute${
|
|
7159
|
+
return `import * as customRoute${index2} from '@game-api/${importPath}'`;
|
|
7003
7160
|
}).join("\n");
|
|
7004
7161
|
}
|
|
7005
|
-
function
|
|
7006
|
-
|
|
7007
|
-
|
|
7008
|
-
|
|
7009
|
-
|
|
7010
|
-
|
|
7011
|
-
|
|
7012
|
-
|
|
7013
|
-
|
|
7014
|
-
|
|
7015
|
-
);
|
|
7016
|
-
|
|
7017
|
-
|
|
7018
|
-
|
|
7019
|
-
|
|
7020
|
-
|
|
7021
|
-
|
|
7022
|
-
|
|
7023
|
-
|
|
7024
|
-
|
|
7025
|
-
|
|
7026
|
-
|
|
7027
|
-
|
|
7028
|
-
|
|
7029
|
-
|
|
7030
|
-
const
|
|
7031
|
-
|
|
7032
|
-
|
|
7033
|
-
|
|
7034
|
-
"import { getAuth } from '@game-server/lib/auth'"
|
|
7035
|
-
|
|
7036
|
-
|
|
7037
|
-
|
|
7038
|
-
|
|
7039
|
-
|
|
7040
|
-
|
|
7162
|
+
function buildCustomRouteModuleCode(customRoutes) {
|
|
7163
|
+
if (customRoutes.length === 0) {
|
|
7164
|
+
return "const __customRoutes = []";
|
|
7165
|
+
}
|
|
7166
|
+
return [
|
|
7167
|
+
"const __customRoutes = [",
|
|
7168
|
+
...customRoutes.map(
|
|
7169
|
+
(route, index2) => ` { path: ${JSON.stringify(route.path)}, module: customRoute${index2} },`
|
|
7170
|
+
),
|
|
7171
|
+
"]"
|
|
7172
|
+
].join("\n");
|
|
7173
|
+
}
|
|
7174
|
+
function generateEntryCode(customRoutes, customRoutesDir, queueHandlers, hasAuth = false) {
|
|
7175
|
+
const runtimeImports = [
|
|
7176
|
+
"createBaseApp",
|
|
7177
|
+
"registerBuiltinRoutes",
|
|
7178
|
+
"registerCustomRouteModules",
|
|
7179
|
+
"registerTerminalHandlers"
|
|
7180
|
+
];
|
|
7181
|
+
if (hasAuth) {
|
|
7182
|
+
runtimeImports.push("createSessionMiddleware");
|
|
7183
|
+
}
|
|
7184
|
+
if (queueHandlers.length > 0) {
|
|
7185
|
+
runtimeImports.push("createQueueRouter", "registerQueueIngressRoute");
|
|
7186
|
+
}
|
|
7187
|
+
const importBlocks = [
|
|
7188
|
+
`import { ${runtimeImports.join(", ")} } from '@playcademy/backend-runtime'`
|
|
7189
|
+
];
|
|
7190
|
+
if (hasAuth) {
|
|
7191
|
+
importBlocks.push("import { getAuth } from '@game-server/lib/auth'");
|
|
7192
|
+
}
|
|
7193
|
+
if (customRoutes.length > 0) {
|
|
7194
|
+
importBlocks.push(buildCustomRouteImportStatements(customRoutes, customRoutesDir));
|
|
7195
|
+
}
|
|
7196
|
+
if (queueHandlers.length > 0) {
|
|
7197
|
+
importBlocks.push(buildQueueImportStatements(queueHandlers));
|
|
7198
|
+
}
|
|
7199
|
+
const body = [
|
|
7200
|
+
"// PLAYCADEMY_CONFIG is injected at bundle time via esbuild define",
|
|
7201
|
+
"const app = createBaseApp(PLAYCADEMY_CONFIG)",
|
|
7202
|
+
""
|
|
7203
|
+
];
|
|
7204
|
+
if (hasAuth) {
|
|
7205
|
+
body.push("app.use('*', createSessionMiddleware(getAuth))", "");
|
|
7206
|
+
}
|
|
7207
|
+
body.push(
|
|
7208
|
+
"await registerBuiltinRoutes(app, PLAYCADEMY_CONFIG.integrations)",
|
|
7209
|
+
"",
|
|
7210
|
+
buildCustomRouteModuleCode(customRoutes),
|
|
7211
|
+
"registerCustomRouteModules(app, __customRoutes)",
|
|
7212
|
+
"",
|
|
7213
|
+
buildQueueHandlerCode(queueHandlers),
|
|
7214
|
+
"registerTerminalHandlers(app)",
|
|
7215
|
+
"",
|
|
7216
|
+
buildWorkerExportCode(queueHandlers)
|
|
7041
7217
|
);
|
|
7042
|
-
return
|
|
7218
|
+
return [...importBlocks, "", ...body].join("\n");
|
|
7043
7219
|
}
|
|
7044
7220
|
|
|
7045
7221
|
// src/lib/dev/server.ts
|
|
@@ -7159,9 +7335,9 @@ async function startDevServer(options) {
|
|
|
7159
7335
|
return { server: mf, port };
|
|
7160
7336
|
}
|
|
7161
7337
|
async function ensureDatabaseDirectory() {
|
|
7162
|
-
const dbDir =
|
|
7338
|
+
const dbDir = join30(getWorkspace(), CLI_DIRECTORIES.DATABASE);
|
|
7163
7339
|
try {
|
|
7164
|
-
await
|
|
7340
|
+
await mkdir5(dbDir, { recursive: true });
|
|
7165
7341
|
} catch (error) {
|
|
7166
7342
|
throw new Error(`Failed to create database directory: ${getErrorMessage(error)}`, {
|
|
7167
7343
|
cause: error
|
|
@@ -7170,9 +7346,9 @@ async function ensureDatabaseDirectory() {
|
|
|
7170
7346
|
return dbDir;
|
|
7171
7347
|
}
|
|
7172
7348
|
async function ensureKvDirectory() {
|
|
7173
|
-
const kvDir =
|
|
7349
|
+
const kvDir = join30(getWorkspace(), CLI_DIRECTORIES.KV);
|
|
7174
7350
|
try {
|
|
7175
|
-
await
|
|
7351
|
+
await mkdir5(kvDir, { recursive: true });
|
|
7176
7352
|
} catch (error) {
|
|
7177
7353
|
throw new Error(`Failed to create KV directory: ${getErrorMessage(error)}`, {
|
|
7178
7354
|
cause: error
|
|
@@ -7181,9 +7357,9 @@ async function ensureKvDirectory() {
|
|
|
7181
7357
|
return kvDir;
|
|
7182
7358
|
}
|
|
7183
7359
|
async function ensureBucketDirectory() {
|
|
7184
|
-
const bucketDir =
|
|
7360
|
+
const bucketDir = join30(getWorkspace(), CLI_DIRECTORIES.BUCKET);
|
|
7185
7361
|
try {
|
|
7186
|
-
await
|
|
7362
|
+
await mkdir5(bucketDir, { recursive: true });
|
|
7187
7363
|
} catch (error) {
|
|
7188
7364
|
throw new Error(`Failed to create bucket directory: ${getErrorMessage(error)}`, {
|
|
7189
7365
|
cause: error
|
|
@@ -7554,13 +7730,13 @@ import { confirm as confirm6, input as input3, select as select5 } from "@inquir
|
|
|
7554
7730
|
|
|
7555
7731
|
// src/lib/deploy/build-discovery.ts
|
|
7556
7732
|
init_file_loader();
|
|
7557
|
-
import { join as
|
|
7733
|
+
import { join as join31, relative as relative5 } from "path";
|
|
7558
7734
|
function findSingleBuildZip() {
|
|
7559
7735
|
const workspace = getWorkspace();
|
|
7560
|
-
const playcademyDir =
|
|
7736
|
+
const playcademyDir = join31(workspace, CLI_DIRECTORIES.WORKSPACE);
|
|
7561
7737
|
const zipFiles = findFilesByExtension(playcademyDir, "zip");
|
|
7562
7738
|
if (zipFiles.length === 1) {
|
|
7563
|
-
return zipFiles[0] ?
|
|
7739
|
+
return zipFiles[0] ? relative5(workspace, zipFiles[0]) : null;
|
|
7564
7740
|
}
|
|
7565
7741
|
return null;
|
|
7566
7742
|
}
|
|
@@ -7568,12 +7744,12 @@ function findSingleBuildZip() {
|
|
|
7568
7744
|
// src/lib/deploy/schema.ts
|
|
7569
7745
|
import { existsSync as existsSync24 } from "fs";
|
|
7570
7746
|
import { createRequire } from "module";
|
|
7571
|
-
import { join as
|
|
7747
|
+
import { join as join33 } from "path";
|
|
7572
7748
|
|
|
7573
7749
|
// src/lib/deploy/migrations.ts
|
|
7574
7750
|
import { existsSync as existsSync23 } from "fs";
|
|
7575
|
-
import { readFile as
|
|
7576
|
-
import { join as
|
|
7751
|
+
import { readFile as readFile5 } from "fs/promises";
|
|
7752
|
+
import { join as join32 } from "path";
|
|
7577
7753
|
import { bold as bold8 } from "colorette";
|
|
7578
7754
|
|
|
7579
7755
|
// src/lib/deploy/utils.ts
|
|
@@ -7595,25 +7771,25 @@ function getDeploymentId(gameSlug) {
|
|
|
7595
7771
|
}
|
|
7596
7772
|
|
|
7597
7773
|
// src/lib/deploy/migrations.ts
|
|
7598
|
-
var DB_RELATIVE_CANDIDATES = ["migrations",
|
|
7599
|
-
var ROOT_RELATIVE_CANDIDATES = [
|
|
7774
|
+
var DB_RELATIVE_CANDIDATES = ["migrations", join32("..", "migrations"), "drizzle"];
|
|
7775
|
+
var ROOT_RELATIVE_CANDIDATES = [join32("db", "migrations"), "drizzle"];
|
|
7600
7776
|
var META_DIR = "meta";
|
|
7601
7777
|
var JOURNAL_FILE = "_journal.json";
|
|
7602
7778
|
var STATEMENT_BREAKPOINT_RE = /--> statement-breakpoint/g;
|
|
7603
7779
|
async function getMigrationsDirectory() {
|
|
7604
7780
|
const workspace = getWorkspace();
|
|
7605
7781
|
const dbDirectory = await getDatabaseDirectory();
|
|
7606
|
-
const dbDirAbs =
|
|
7782
|
+
const dbDirAbs = join32(workspace, dbDirectory);
|
|
7607
7783
|
for (const candidate of DB_RELATIVE_CANDIDATES) {
|
|
7608
|
-
const candidateAbs =
|
|
7609
|
-
const journalPath =
|
|
7784
|
+
const candidateAbs = join32(dbDirAbs, candidate);
|
|
7785
|
+
const journalPath = join32(candidateAbs, META_DIR, JOURNAL_FILE);
|
|
7610
7786
|
if (existsSync23(journalPath)) {
|
|
7611
7787
|
return candidateAbs;
|
|
7612
7788
|
}
|
|
7613
7789
|
}
|
|
7614
7790
|
for (const candidate of ROOT_RELATIVE_CANDIDATES) {
|
|
7615
|
-
const candidateAbs =
|
|
7616
|
-
const journalPath =
|
|
7791
|
+
const candidateAbs = join32(workspace, candidate);
|
|
7792
|
+
const journalPath = join32(candidateAbs, META_DIR, JOURNAL_FILE);
|
|
7617
7793
|
if (existsSync23(journalPath)) {
|
|
7618
7794
|
return candidateAbs;
|
|
7619
7795
|
}
|
|
@@ -7643,9 +7819,9 @@ async function readMigrationJournal() {
|
|
|
7643
7819
|
if (!migrationsDir) {
|
|
7644
7820
|
return null;
|
|
7645
7821
|
}
|
|
7646
|
-
const journalPath =
|
|
7822
|
+
const journalPath = join32(migrationsDir, META_DIR, JOURNAL_FILE);
|
|
7647
7823
|
try {
|
|
7648
|
-
const raw = await
|
|
7824
|
+
const raw = await readFile5(journalPath, "utf8");
|
|
7649
7825
|
const journal = JSON.parse(raw);
|
|
7650
7826
|
if (!Array.isArray(journal.entries)) {
|
|
7651
7827
|
logger.warn("Migration journal has no entries array");
|
|
@@ -7689,14 +7865,14 @@ async function getUnappliedMigrations(lastAppliedTag) {
|
|
|
7689
7865
|
}
|
|
7690
7866
|
const results = [];
|
|
7691
7867
|
for (const entry of unapplied) {
|
|
7692
|
-
const sqlPath =
|
|
7868
|
+
const sqlPath = join32(migrationsDir, `${entry.tag}.sql`);
|
|
7693
7869
|
if (!existsSync23(sqlPath)) {
|
|
7694
7870
|
throw new Error(
|
|
7695
7871
|
`Migration file not found: ${sqlPath}
|
|
7696
7872
|
The journal references migration "${entry.tag}" but the .sql file is missing.`
|
|
7697
7873
|
);
|
|
7698
7874
|
}
|
|
7699
|
-
const raw = await
|
|
7875
|
+
const raw = await readFile5(sqlPath, "utf8");
|
|
7700
7876
|
const sql2 = raw.replace(STATEMENT_BREAKPOINT_RE, "").trim();
|
|
7701
7877
|
results.push({ tag: entry.tag, sql: sql2 });
|
|
7702
7878
|
}
|
|
@@ -7800,7 +7976,7 @@ async function loadAndValidateMigrations(workspace) {
|
|
|
7800
7976
|
// src/lib/deploy/schema.ts
|
|
7801
7977
|
function getDrizzleKitApiExports() {
|
|
7802
7978
|
try {
|
|
7803
|
-
const projectRequire = createRequire(
|
|
7979
|
+
const projectRequire = createRequire(join33(process.cwd(), "package.json"));
|
|
7804
7980
|
return projectRequire("drizzle-kit/api");
|
|
7805
7981
|
} catch {
|
|
7806
7982
|
const cliRequire = createRequire(import.meta.url);
|
|
@@ -7810,7 +7986,7 @@ function getDrizzleKitApiExports() {
|
|
|
7810
7986
|
async function getPushSchemaInfo(previousSchemaSnapshot) {
|
|
7811
7987
|
const workspace = getWorkspace();
|
|
7812
7988
|
const dbDirectory = await getDatabaseDirectory();
|
|
7813
|
-
const schemaPath =
|
|
7989
|
+
const schemaPath = join33(workspace, dbDirectory, SCHEMA_SUBDIRECTORY, DB_FILES.SCHEMA_INDEX);
|
|
7814
7990
|
if (!existsSync24(schemaPath)) {
|
|
7815
7991
|
return null;
|
|
7816
7992
|
}
|
|
@@ -8293,7 +8469,7 @@ function logDeploymentPlanDebug(plan, context2) {
|
|
|
8293
8469
|
|
|
8294
8470
|
// src/lib/deploy/preparation.ts
|
|
8295
8471
|
import { stat } from "node:fs/promises";
|
|
8296
|
-
import { join as
|
|
8472
|
+
import { join as join34 } from "node:path";
|
|
8297
8473
|
|
|
8298
8474
|
// ../data/src/domains/game/helpers.ts
|
|
8299
8475
|
function isHostedGame(game) {
|
|
@@ -8906,8 +9082,8 @@ async function bundleAndHash(context2) {
|
|
|
8906
9082
|
const bundle = await bundleBackend(context2.fullConfig);
|
|
8907
9083
|
const bundleHash = hashContent(bundle.code);
|
|
8908
9084
|
const [serverSize, dbSize] = await Promise.all([
|
|
8909
|
-
getDirectorySize(
|
|
8910
|
-
getDirectorySize(
|
|
9085
|
+
getDirectorySize(join34(context2.projectPath, SERVER_ROOT_DIRECTORY)),
|
|
9086
|
+
getDirectorySize(join34(context2.projectPath, DEFAULT_DATABASE_DIRECTORY))
|
|
8911
9087
|
]);
|
|
8912
9088
|
context2.currentBackendBundle = bundle;
|
|
8913
9089
|
context2.currentBackendBundleHash = bundleHash;
|
|
@@ -9082,8 +9258,8 @@ function hasOptionalFieldsMissing(missing) {
|
|
|
9082
9258
|
|
|
9083
9259
|
// src/lib/deploy/steps.ts
|
|
9084
9260
|
import { existsSync as existsSync26 } from "fs";
|
|
9085
|
-
import { readFile as
|
|
9086
|
-
import { basename as basename2, join as
|
|
9261
|
+
import { readFile as readFile6 } from "fs/promises";
|
|
9262
|
+
import { basename as basename2, join as join35, resolve as resolve11 } from "path";
|
|
9087
9263
|
|
|
9088
9264
|
// src/lib/deploy/stub.ts
|
|
9089
9265
|
import * as esbuild3 from "esbuild";
|
|
@@ -9129,7 +9305,7 @@ function prepareGameMetadata(config) {
|
|
|
9129
9305
|
async function prepareBuildFile(buildPath) {
|
|
9130
9306
|
const resolvedPath = resolve11(buildPath);
|
|
9131
9307
|
if (resolvedPath.endsWith(".zip") && existsSync26(resolvedPath)) {
|
|
9132
|
-
const buffer = await
|
|
9308
|
+
const buffer = await readFile6(resolvedPath);
|
|
9133
9309
|
const uint8Array = new Uint8Array(buffer);
|
|
9134
9310
|
const blob = new Blob([uint8Array], { type: "application/zip" });
|
|
9135
9311
|
return new File([blob], basename2(resolvedPath), { type: "application/zip" });
|
|
@@ -9305,8 +9481,8 @@ async function deployGame(context2, shouldUploadBuild, shouldDeployBackend) {
|
|
|
9305
9481
|
schema: deploymentPrep.schemaInfo || void 0
|
|
9306
9482
|
};
|
|
9307
9483
|
const [serverSize, dbSize] = await Promise.all([
|
|
9308
|
-
getDirectorySize(
|
|
9309
|
-
getDirectorySize(
|
|
9484
|
+
getDirectorySize(join35(context2.projectPath, SERVER_ROOT_DIRECTORY)),
|
|
9485
|
+
getDirectorySize(join35(context2.projectPath, DEFAULT_DATABASE_DIRECTORY))
|
|
9310
9486
|
]);
|
|
9311
9487
|
const isMigrateMode = Boolean(deploymentPrep.schemaInfo?.migrationTag);
|
|
9312
9488
|
backendMetadata = {
|
|
@@ -9368,7 +9544,7 @@ async function deployGame(context2, shouldUploadBuild, shouldDeployBackend) {
|
|
|
9368
9544
|
|
|
9369
9545
|
// src/lib/db/path.ts
|
|
9370
9546
|
import { copyFileSync, existsSync as existsSync27, mkdirSync as mkdirSync9, readdirSync as readdirSync4, unlinkSync } from "fs";
|
|
9371
|
-
import { join as
|
|
9547
|
+
import { join as join36 } from "path";
|
|
9372
9548
|
var DB_DIRECTORY = CLI_DIRECTORIES.DATABASE;
|
|
9373
9549
|
var INITIAL_DB_NAME = CLI_FILES.INITIAL_DATABASE;
|
|
9374
9550
|
function ensureDirectoryExists(dir) {
|
|
@@ -9377,7 +9553,7 @@ function ensureDirectoryExists(dir) {
|
|
|
9377
9553
|
}
|
|
9378
9554
|
}
|
|
9379
9555
|
function findMiniflareDatabase(dbDir) {
|
|
9380
|
-
const miniflareDir =
|
|
9556
|
+
const miniflareDir = join36(dbDir, MINIFLARE_D1_DIRECTORY);
|
|
9381
9557
|
if (!existsSync27(miniflareDir)) {
|
|
9382
9558
|
return null;
|
|
9383
9559
|
}
|
|
@@ -9385,7 +9561,7 @@ function findMiniflareDatabase(dbDir) {
|
|
|
9385
9561
|
if (sqliteFiles.length === 0) {
|
|
9386
9562
|
return null;
|
|
9387
9563
|
}
|
|
9388
|
-
return
|
|
9564
|
+
return join36(miniflareDir, sqliteFiles[0]);
|
|
9389
9565
|
}
|
|
9390
9566
|
function migrateInitialDbToTarget(initialPath, targetPath) {
|
|
9391
9567
|
if (!existsSync27(initialPath)) {
|
|
@@ -9395,7 +9571,7 @@ function migrateInitialDbToTarget(initialPath, targetPath) {
|
|
|
9395
9571
|
unlinkSync(initialPath);
|
|
9396
9572
|
}
|
|
9397
9573
|
function getDevDbPath() {
|
|
9398
|
-
const initialDbPath =
|
|
9574
|
+
const initialDbPath = join36(DB_DIRECTORY, INITIAL_DB_NAME);
|
|
9399
9575
|
ensureDirectoryExists(DB_DIRECTORY);
|
|
9400
9576
|
const miniflareDbPath = findMiniflareDatabase(DB_DIRECTORY);
|
|
9401
9577
|
if (miniflareDbPath) {
|
|
@@ -9634,10 +9810,10 @@ async function bundleSeedWorker(seedFilePath, projectPath) {
|
|
|
9634
9810
|
// src/lib/db/reset.ts
|
|
9635
9811
|
import { execSync as execSync7 } from "child_process";
|
|
9636
9812
|
import { rmSync as rmSync3 } from "fs";
|
|
9637
|
-
import { join as
|
|
9813
|
+
import { join as join37 } from "path";
|
|
9638
9814
|
async function resetDatabase(workspace, mf, options = { debug: false }) {
|
|
9639
9815
|
const { debug } = options;
|
|
9640
|
-
const dbDir =
|
|
9816
|
+
const dbDir = join37(workspace, CLI_DIRECTORIES.DATABASE);
|
|
9641
9817
|
await runStep(
|
|
9642
9818
|
"Resetting database...",
|
|
9643
9819
|
async () => {
|
|
@@ -10080,14 +10256,14 @@ function getCallbackUrl() {
|
|
|
10080
10256
|
}
|
|
10081
10257
|
|
|
10082
10258
|
// src/lib/bucket/bulk.ts
|
|
10083
|
-
import { readFileSync as
|
|
10259
|
+
import { readFileSync as readFileSync13 } from "fs";
|
|
10084
10260
|
import { dim as dim9 } from "colorette";
|
|
10085
10261
|
|
|
10086
10262
|
// src/lib/bucket/collect.ts
|
|
10087
10263
|
import { readdirSync as readdirSync5, statSync as statSync3 } from "fs";
|
|
10088
|
-
import { join as
|
|
10264
|
+
import { join as join38, relative as relative6, sep as sep2 } from "path";
|
|
10089
10265
|
function shouldSkipFile(filePath, baseDir, gitignorePatterns) {
|
|
10090
|
-
const relativePath =
|
|
10266
|
+
const relativePath = relative6(baseDir, filePath);
|
|
10091
10267
|
const pathParts = relativePath.split(sep2);
|
|
10092
10268
|
const alwaysSkip = BUCKET_ALWAYS_SKIP;
|
|
10093
10269
|
for (const part of pathParts) {
|
|
@@ -10102,7 +10278,7 @@ function collectFiles(directory, baseDir, gitignorePatterns) {
|
|
|
10102
10278
|
try {
|
|
10103
10279
|
const entries = readdirSync5(directory, { withFileTypes: true });
|
|
10104
10280
|
for (const entry of entries) {
|
|
10105
|
-
const fullPath =
|
|
10281
|
+
const fullPath = join38(directory, entry.name);
|
|
10106
10282
|
if (!shouldSkipFile(fullPath, baseDir, gitignorePatterns)) {
|
|
10107
10283
|
if (entry.isDirectory()) {
|
|
10108
10284
|
files.push(...collectFiles(fullPath, baseDir, gitignorePatterns));
|
|
@@ -10110,7 +10286,7 @@ function collectFiles(directory, baseDir, gitignorePatterns) {
|
|
|
10110
10286
|
const stats = statSync3(fullPath);
|
|
10111
10287
|
files.push({
|
|
10112
10288
|
absolutePath: fullPath,
|
|
10113
|
-
relativePath:
|
|
10289
|
+
relativePath: relative6(baseDir, fullPath),
|
|
10114
10290
|
size: stats.size
|
|
10115
10291
|
});
|
|
10116
10292
|
}
|
|
@@ -10208,7 +10384,7 @@ async function uploadFilesRemote(files, gameSlug, prefix, uploadFn) {
|
|
|
10208
10384
|
`Uploading ${files.length} files ${dim9(`[${formatBytes(totalSize)}]`)}`,
|
|
10209
10385
|
async () => {
|
|
10210
10386
|
for (const file of files) {
|
|
10211
|
-
const fileBuffer =
|
|
10387
|
+
const fileBuffer = readFileSync13(file.absolutePath);
|
|
10212
10388
|
const contentType = getContentType(file.absolutePath);
|
|
10213
10389
|
const key = getBucketKey(file.relativePath, prefix);
|
|
10214
10390
|
await uploadFn(gameSlug, key, fileBuffer, contentType);
|
|
@@ -10224,7 +10400,7 @@ async function uploadFilesLocal(files, prefix, uploadFn) {
|
|
|
10224
10400
|
`Uploading ${files.length} files ${dim9(`[${formatBytes(totalSize)}]`)}`,
|
|
10225
10401
|
async () => {
|
|
10226
10402
|
for (const file of files) {
|
|
10227
|
-
const fileBuffer =
|
|
10403
|
+
const fileBuffer = readFileSync13(file.absolutePath);
|
|
10228
10404
|
const contentType = getContentType(file.absolutePath);
|
|
10229
10405
|
const key = getBucketKey(file.relativePath, prefix);
|
|
10230
10406
|
await uploadFn(key, new Uint8Array(fileBuffer).buffer, contentType);
|
|
@@ -11019,6 +11195,39 @@ function normalizeVersion(version) {
|
|
|
11019
11195
|
}
|
|
11020
11196
|
return trimmed.replace(/^[vV]/, "");
|
|
11021
11197
|
}
|
|
11198
|
+
function parseVersion(v) {
|
|
11199
|
+
const [version, ...pre] = v.split("-");
|
|
11200
|
+
const parts = version.split(".").map(Number);
|
|
11201
|
+
if (parts.some((n) => Number.isNaN(n))) {
|
|
11202
|
+
return null;
|
|
11203
|
+
}
|
|
11204
|
+
return { parts, prerelease: pre.length > 0 ? pre.join("-") : null };
|
|
11205
|
+
}
|
|
11206
|
+
function compareVersions(a, b) {
|
|
11207
|
+
const va = parseVersion(a);
|
|
11208
|
+
const vb = parseVersion(b);
|
|
11209
|
+
if (!va || !vb) {
|
|
11210
|
+
return 0;
|
|
11211
|
+
}
|
|
11212
|
+
const maxLen = Math.max(va.parts.length, vb.parts.length);
|
|
11213
|
+
for (let i = 0; i < maxLen; i++) {
|
|
11214
|
+
const pa = va.parts[i] ?? 0;
|
|
11215
|
+
const pb = vb.parts[i] ?? 0;
|
|
11216
|
+
if (pa > pb) {
|
|
11217
|
+
return 1;
|
|
11218
|
+
}
|
|
11219
|
+
if (pa < pb) {
|
|
11220
|
+
return -1;
|
|
11221
|
+
}
|
|
11222
|
+
}
|
|
11223
|
+
if (!va.prerelease && vb.prerelease) {
|
|
11224
|
+
return 1;
|
|
11225
|
+
}
|
|
11226
|
+
if (va.prerelease && !vb.prerelease) {
|
|
11227
|
+
return -1;
|
|
11228
|
+
}
|
|
11229
|
+
return 0;
|
|
11230
|
+
}
|
|
11022
11231
|
async function fetchLatestVersion() {
|
|
11023
11232
|
const response = await fetch(LATEST_VERSION_URL);
|
|
11024
11233
|
if (!response.ok) {
|
|
@@ -11055,6 +11264,7 @@ export {
|
|
|
11055
11264
|
collectBulkFiles,
|
|
11056
11265
|
collectFiles,
|
|
11057
11266
|
compareIntegrationKeys,
|
|
11267
|
+
compareVersions,
|
|
11058
11268
|
computeSecretsDiff,
|
|
11059
11269
|
computeSecretsHashes,
|
|
11060
11270
|
confirmDeploymentPlan,
|