@genex-ai/cli-demo 1.36.12-dev.999 → 1.36.13-dev.1018

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.
Files changed (3) hide show
  1. package/README.md +3 -1
  2. package/dist/index.js +100 -12
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -92,7 +92,9 @@ the original folder can't be found.
92
92
  `dist/` to R2 through a short-lived scoped upload token and flips a live pointer;
93
93
  the editable source is pushed to the repo's single `main` branch (for Remix). Game
94
94
  bytes never pass through our API. Pass `--no-build` to deploy whatever is already
95
- built.
95
+ built. Pass `--source <dir>` (also on `make-remixable`) when the game's own files live
96
+ in another folder than the one you deploy from: that folder is pushed as the source,
97
+ while the project, the build and `dist/` are still read from here.
96
98
 
97
99
  - **`genex preview`** uploads the current build to the project's hosted draft URL
98
100
  (`https://<slug>.genex.technology/`) without listing it publicly — re-run it
package/dist/index.js CHANGED
@@ -1031,6 +1031,7 @@ var LFS_PATTERNS = [
1031
1031
  "*.vrm",
1032
1032
  "*.fbx",
1033
1033
  "*.obj",
1034
+ "*.blend",
1034
1035
  // textures / images
1035
1036
  "*.png",
1036
1037
  "*.jpg",
@@ -1041,13 +1042,39 @@ var LFS_PATTERNS = [
1041
1042
  "*.hdr",
1042
1043
  "*.exr",
1043
1044
  "*.tga",
1045
+ "*.psd",
1046
+ "*.tif",
1047
+ "*.tiff",
1044
1048
  // audio / video
1045
1049
  "*.mp3",
1046
1050
  "*.ogg",
1047
1051
  "*.wav",
1048
1052
  "*.m4a",
1049
1053
  "*.mp4",
1050
- "*.webm"
1054
+ "*.webm",
1055
+ "*.aif",
1056
+ "*.aiff",
1057
+ "*.flac",
1058
+ "*.mov",
1059
+ "*.avi",
1060
+ // fonts
1061
+ "*.ttf",
1062
+ "*.otf",
1063
+ // engine packages and packed assets (Unity, Unreal, Godot)
1064
+ "*.unitypackage",
1065
+ "*.bundle",
1066
+ "*.uasset",
1067
+ "*.umap",
1068
+ "*.pck",
1069
+ // native libraries and plugins
1070
+ "*.dll",
1071
+ "*.so",
1072
+ "*.dylib",
1073
+ "*.a",
1074
+ "*.lib",
1075
+ // archives
1076
+ "*.zip",
1077
+ "*.7z"
1051
1078
  ];
1052
1079
  async function writeGitattributes(dir, log) {
1053
1080
  const file = path4.join(dir, ".gitattributes");
@@ -5944,8 +5971,9 @@ async function deployGame(ctx, opts, log) {
5944
5971
  return false;
5945
5972
  }
5946
5973
  let sourceCommitSha;
5974
+ const sourceDir = opts.sourceDir ?? cwd;
5947
5975
  const pushed = await pushSource(
5948
- cwd,
5976
+ sourceDir,
5949
5977
  ctx,
5950
5978
  log,
5951
5979
  opts.channel === "staging" ? "preview" : "main",
@@ -5959,11 +5987,14 @@ async function deployGame(ctx, opts, log) {
5959
5987
  const published = await callPublish(ctx, commit, opts, log, sourceCommitSha, capabilities);
5960
5988
  if (!published) return false;
5961
5989
  if (opts.channel === "staging") {
5962
- const tree = await sourceTreeHash(cwd);
5990
+ const pushedHere = opts.sourceDir === void 0;
5991
+ const tree = pushedHere ? await sourceTreeHash(cwd) : null;
5963
5992
  const current = await readProject(cwd);
5964
5993
  if (current) {
5994
+ const { sourceTree: recorded, ...rest } = current;
5995
+ const kept = pushedHere && recorded ? { sourceTree: recorded } : {};
5965
5996
  await writeProject(
5966
- { ...current, stagingCommit: commit, ...tree ? { sourceTree: tree } : {} },
5997
+ { ...rest, ...kept, stagingCommit: commit, ...tree ? { sourceTree: tree } : {} },
5967
5998
  cwd
5968
5999
  ).catch(() => {
5969
6000
  });
@@ -6229,13 +6260,13 @@ async function callPublish(ctx, commit, opts, log, sourceCommitSha, capabilities
6229
6260
  }
6230
6261
  return { url: body?.url ?? "" };
6231
6262
  }
6232
- async function pushSource(cwd, ctx, log, branch = "main", expectStagingCommit, onCommit) {
6263
+ async function pushSource(sourceDir, ctx, log, branch = "main", expectStagingCommit, onCommit) {
6233
6264
  const target = await fetchPushUrl(ctx, log, expectStagingCommit);
6234
6265
  if (target === "stale") return "stale";
6235
6266
  if (!target) return false;
6236
6267
  const ref = target.managed ? branch : "main";
6237
6268
  const first = await pushWorktree(
6238
- cwd,
6269
+ sourceDir,
6239
6270
  target.pushUrl,
6240
6271
  target.managed,
6241
6272
  log,
@@ -6253,7 +6284,7 @@ async function pushSource(cwd, ctx, log, branch = "main", expectStagingCommit, o
6253
6284
  if (fresh === "stale") return "stale";
6254
6285
  if (!fresh) return false;
6255
6286
  return await pushWorktree(
6256
- cwd,
6287
+ sourceDir,
6257
6288
  fresh.pushUrl,
6258
6289
  fresh.managed,
6259
6290
  log,
@@ -6263,6 +6294,34 @@ async function pushSource(cwd, ctx, log, branch = "main", expectStagingCommit, o
6263
6294
  fresh.sourceLimits
6264
6295
  ) === true;
6265
6296
  }
6297
+ async function resolveSourceDir(dir, cwd = process.cwd()) {
6298
+ const abs = path17.resolve(cwd, dir);
6299
+ const stat = await fs17.lstat(abs).catch(() => null);
6300
+ if (!stat) return { refused: `--source ${abs} does not exist.` };
6301
+ if (stat.isSymbolicLink()) {
6302
+ return { refused: `--source ${abs} is a symbolic link. Pass the folder itself.` };
6303
+ }
6304
+ if (!stat.isDirectory()) return { refused: `--source ${abs} is not a folder.` };
6305
+ const real = await fs17.realpath(abs);
6306
+ const project = await fs17.realpath(cwd).catch(() => path17.resolve(cwd));
6307
+ const genex = path17.join(project, ".genex");
6308
+ const genexTarget = await fs17.realpath(genex).catch(() => genex);
6309
+ for (const meta of /* @__PURE__ */ new Set([genex, genexTarget])) {
6310
+ if (real === meta) {
6311
+ return { refused: `--source ${abs} is this project's .genex folder, not the game's source.` };
6312
+ }
6313
+ if (isInside(meta, real)) {
6314
+ return {
6315
+ refused: `--source ${abs} holds this project's .genex folder. Pass a separate folder with the game's own files.`
6316
+ };
6317
+ }
6318
+ }
6319
+ return { dir: real };
6320
+ }
6321
+ function isInside(child, parent) {
6322
+ const rel = path17.relative(parent, child);
6323
+ return rel !== "" && rel !== ".." && !rel.startsWith(`..${path17.sep}`) && !path17.isAbsolute(rel);
6324
+ }
6266
6325
  var WORKSPACE_SOURCE_REF = "workspace";
6267
6326
  function gitLfsInstallCommand(platform) {
6268
6327
  if (platform === "darwin") {
@@ -6274,7 +6333,7 @@ function gitLfsInstallCommand(platform) {
6274
6333
  }
6275
6334
  return { bin: "sudo", args: ["-n", "apt-get", "install", "-y", "git-lfs"], env: {} };
6276
6335
  }
6277
- async function pushWorktree(cwd, pushUrl, managed, log, branch = "main", onCommit, skipSizeCheck = false, limits) {
6336
+ async function pushWorktree(workTree, pushUrl, managed, log, branch = "main", onCommit, skipSizeCheck = false, limits) {
6278
6337
  const EMPTY_TREE = "4b825dc642cb6eb9a060e54bf8d69288fbee4904";
6279
6338
  const failed = () => {
6280
6339
  log.error("Couldn't save your game's source \u2014 please try again.");
@@ -6296,7 +6355,7 @@ async function pushWorktree(cwd, pushUrl, managed, log, branch = "main", onCommi
6296
6355
  try {
6297
6356
  if ((await run("git", ["init", "-q"], base)).code !== 0) return failed();
6298
6357
  await fs17.writeFile(path17.join(gitDir, "info", "exclude"), excludeFile());
6299
- const env = { ...base, GIT_WORK_TREE: cwd, GIT_INDEX_FILE: path17.join(gitDir, "index-source") };
6358
+ const env = { ...base, GIT_WORK_TREE: workTree, GIT_INDEX_FILE: path17.join(gitDir, "index-source") };
6300
6359
  let lfs = (await run("git", ["lfs", "version"], base)).code !== 0 ? false : true;
6301
6360
  if (!lfs) {
6302
6361
  log.step("Installing git-lfs (keeps large binary assets out of the source push)\u2026");
@@ -6310,7 +6369,7 @@ async function pushWorktree(cwd, pushUrl, managed, log, branch = "main", onCommi
6310
6369
  }
6311
6370
  }
6312
6371
  if (lfs) {
6313
- await writeGitattributes(cwd, log);
6372
+ await writeGitattributes(workTree, log);
6314
6373
  const filters = [
6315
6374
  ["filter.lfs.clean", "git-lfs clean -- %f"],
6316
6375
  ["filter.lfs.smudge", "git-lfs smudge -- %f"],
@@ -6325,7 +6384,7 @@ async function pushWorktree(cwd, pushUrl, managed, log, branch = "main", onCommi
6325
6384
  log.error("Nothing to publish \u2014 the project has no files.");
6326
6385
  return "failed";
6327
6386
  }
6328
- const payload = await measurePayload(cwd, staged);
6387
+ const payload = await measurePayload(workTree, staged);
6329
6388
  log.dim(`Source: ${payload.files} files, ${formatBytes2(payload.bytes)}.`);
6330
6389
  const ceiling = limits ?? FALLBACK_SOURCE_LIMITS;
6331
6390
  if (!skipSizeCheck && isOversized(payload, ceiling)) {
@@ -6939,6 +6998,12 @@ async function runPreview(opts) {
6939
6998
  process.exitCode = 1;
6940
6999
  return;
6941
7000
  }
7001
+ const source = opts.sourceDir === void 0 ? void 0 : await resolveSourceDir(opts.sourceDir);
7002
+ if (source && "refused" in source) {
7003
+ log.error(`${source.refused} Nothing was uploaded.`);
7004
+ process.exitCode = 1;
7005
+ return;
7006
+ }
6942
7007
  const apiUrl = getApiUrl(meta.apiUrl);
6943
7008
  const token = await readUserToken(opts.envPath, apiUrl);
6944
7009
  if (!token) {
@@ -6965,6 +7030,7 @@ async function runPreview(opts) {
6965
7030
  channel: "staging",
6966
7031
  noBuild: opts.noBuild,
6967
7032
  force: opts.force,
7033
+ sourceDir: source?.dir,
6968
7034
  matchmaking: detections.matchmaking,
6969
7035
  embedSdkVersion: detections.embedSdkVersion,
6970
7036
  multiplayer: detections.multiplayer,
@@ -8271,6 +8337,12 @@ async function runMakeRemixable(opts) {
8271
8337
  process.exitCode = 1;
8272
8338
  return;
8273
8339
  }
8340
+ const source = opts.sourceDir === void 0 ? void 0 : await resolveSourceDir(opts.sourceDir);
8341
+ if (source && "refused" in source) {
8342
+ log.error(`${source.refused} Nothing was pushed.`);
8343
+ process.exitCode = 1;
8344
+ return;
8345
+ }
8274
8346
  const apiUrl = getApiUrl(opts.apiUrl ?? meta.apiUrl);
8275
8347
  const token = await readUserToken(opts.envPath, apiUrl);
8276
8348
  if (!token) {
@@ -8312,7 +8384,7 @@ async function runMakeRemixable(opts) {
8312
8384
  return;
8313
8385
  }
8314
8386
  log.step("Copying your game's source to the public repo\u2026");
8315
- if (await pushWorktree(process.cwd(), data.pushUrl, true, log) !== true) {
8387
+ if (await pushWorktree(source?.dir ?? process.cwd(), data.pushUrl, true, log) !== true) {
8316
8388
  process.exitCode = 1;
8317
8389
  return;
8318
8390
  }
@@ -8763,6 +8835,12 @@ async function runPublish(opts) {
8763
8835
  process.exitCode = 1;
8764
8836
  return;
8765
8837
  }
8838
+ const source = opts.sourceDir === void 0 ? void 0 : await resolveSourceDir(opts.sourceDir);
8839
+ if (source && "refused" in source) {
8840
+ log.error(`${source.refused} Nothing was uploaded.`);
8841
+ process.exitCode = 1;
8842
+ return;
8843
+ }
8766
8844
  const apiUrl = getApiUrl(opts.apiUrl ?? meta.apiUrl);
8767
8845
  const token = opts.token ?? await readUserToken(opts.envPath, apiUrl);
8768
8846
  if (!token) {
@@ -8783,6 +8861,7 @@ async function runPublish(opts) {
8783
8861
  channel: "staging",
8784
8862
  noBuild: opts.noBuild,
8785
8863
  force: opts.force,
8864
+ sourceDir: source?.dir,
8786
8865
  matchmaking: detections.matchmaking,
8787
8866
  embedSdkVersion: detections.embedSdkVersion,
8788
8867
  multiplayer: detections.multiplayer,
@@ -28852,6 +28931,9 @@ ${c.bold("Options for `rename`")}
28852
28931
 
28853
28932
  ${c.bold("Options for `preview` / `publish`")}
28854
28933
  --no-build Skip the build step; deploy whatever is already built.
28934
+ --source <dir> Push <dir> as the game's editable source instead of this
28935
+ folder. The project, the build and dist/ still come from
28936
+ here. Also on 'make-remixable'.
28855
28937
  --no-push (publish) Skip build + push; only flip the gallery flag.
28856
28938
  --title <title> (publish) Gallery title.
28857
28939
  --description <text> (publish) Gallery description.
@@ -29494,6 +29576,9 @@ function parseArgs(argv) {
29494
29576
  ...Object.keys(UI_NUMBER_FLAGS),
29495
29577
  "--source-repo-url",
29496
29578
  "--source-author",
29579
+ // `preview` / `publish` / `make-remixable --source <dir>`: the folder pushed as the
29580
+ // game's source when it is not the one the command runs in.
29581
+ "--source",
29497
29582
  "--license",
29498
29583
  "--purchase-url",
29499
29584
  "--product-name",
@@ -30258,6 +30343,9 @@ function applyValueFlag(options, flag, value) {
30258
30343
  case "--src":
30259
30344
  options.src = value;
30260
30345
  break;
30346
+ case "--source":
30347
+ options.sourceDir = value;
30348
+ break;
30261
30349
  case "--clip":
30262
30350
  options.clipPath = value;
30263
30351
  break;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@genex-ai/cli-demo",
3
- "version": "1.36.12-dev.999",
3
+ "version": "1.36.13-dev.1018",
4
4
  "description": "Set up your project's agent workspace (.claude/.codex/.cursor in the game folder), authorize, create a game project, generate AI assets, and publish (genex CLI).",
5
5
  "type": "module",
6
6
  "bin": {