@puzzmo/cli 1.0.47 → 1.0.48

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.
@@ -4,7 +4,7 @@ import fs from "node:fs";
4
4
  import path from "node:path";
5
5
  import * as p from "@clack/prompts";
6
6
  import { GameNotFoundError, uploadFiles } from "../util/api.js";
7
- import { findTokensForTeam, getTokens, resolveServerForTeam, sourceToURL } from "../util/config.js";
7
+ import { defaultSource, findTokensForTeam, getTokens, normalizeSource, resolveServerForTeam, sourceToURL, } from "../util/config.js";
8
8
  import { createUserGame } from "../util/createGame.js";
9
9
  import { discoverGames } from "../util/discoverGames.js";
10
10
  /** Uploads game build artifacts to Puzzmo by discovering puzzmo.json files in `dir` */
@@ -24,25 +24,26 @@ export const upload = async (dir, options = {}) => {
24
24
  console.error(`No puzzmo.json files found under ${rootDir}`);
25
25
  process.exit(1);
26
26
  }
27
- console.log(`Found ${games.length} game(s) under ${rootDir}`);
28
- for (const game of games) {
29
- console.log(` - ${game.puzzmoFile.game.slug} (${path.relative(rootDir, game.distDir) || "."})`);
30
- }
31
- if (discoveryErrors.length) {
32
- console.log(`\n${discoveryErrors.length} puzzmo.json file(s) could not be loaded:`);
33
- for (const err of discoveryErrors) {
34
- console.log(` - ${err.slug ?? path.relative(rootDir, err.puzzmoJsonPath)}`);
35
- for (const e of err.errors)
36
- console.log(` ${e}`);
27
+ const multi = games.length + discoveryErrors.length > 1;
28
+ if (multi) {
29
+ console.log(`Found ${plural(games.length, "game")} under ${rootDir}`);
30
+ for (const game of games) {
31
+ console.log(` - ${game.puzzmoFile.game.slug} (${path.relative(rootDir, game.distDir) || "."})`);
32
+ }
33
+ if (discoveryErrors.length) {
34
+ console.log(`\n${plural(discoveryErrors.length, "puzzmo.json file")} could not be loaded:`);
35
+ for (const err of discoveryErrors) {
36
+ console.log(` - ${err.slug ?? path.relative(rootDir, err.puzzmoJsonPath)}`);
37
+ for (const e of err.errors)
38
+ console.log(` ${e}`);
39
+ }
37
40
  }
38
41
  }
39
42
  const sha = getGitSHA(rootDir) || hashGames(games);
40
43
  const description = getGitMessage(rootDir);
41
44
  const repoURL = getGitRepoURL(rootDir);
42
- if (description)
45
+ if (description && multi)
43
46
  console.log(`\nMessage: ${description}`);
44
- if (repoURL)
45
- console.log(`Repo: ${repoURL}`);
46
47
  const results = [];
47
48
  for (const err of discoveryErrors) {
48
49
  results.push({ ok: false, slug: err.slug ?? path.relative(rootDir, err.puzzmoJsonPath), error: err.errors.join("; ") });
@@ -50,7 +51,8 @@ export const upload = async (dir, options = {}) => {
50
51
  for (let i = 0; i < games.length; i++) {
51
52
  const game = games[i];
52
53
  const slug = game.puzzmoFile.game.slug;
53
- console.log(`\n[${i + 1}/${games.length}] Uploading ${slug}`);
54
+ const prefix = multi ? `[${i + 1}/${games.length}] ` : "";
55
+ const distLabel = path.relative(rootDir, game.distDir) || ".";
54
56
  const teamID = game.puzzmoFile.game.teamID;
55
57
  const credential = await resolveServerForTeam(teamID);
56
58
  if (!credential) {
@@ -58,16 +60,20 @@ export const upload = async (dir, options = {}) => {
58
60
  const message = matches.length === 0
59
61
  ? `No saved token for team ${teamID}. Run \`puzzmo login <token>\` (use \`--source\` if the token is for a non-default server).`
60
62
  : `Token for team ${teamID} is registered against ${matches.map((m) => m.source).join(", ")} but none of those servers are reachable.`;
61
- console.error(` ${message}`);
63
+ console.error(`\n${prefix}Uploading ${slug} from ${distLabel}\n ${message}`);
62
64
  results.push({ ok: false, slug, error: message });
63
65
  continue;
64
66
  }
65
67
  const apiURL = sourceToURL(credential.source);
66
- console.log(` Server: ${credential.source}`);
68
+ console.log(`\n${prefix}Uploading ${slug} from ${distLabel}`);
69
+ if (!isDefaultServer(credential.source))
70
+ console.log(` Server: ${credential.source}`);
71
+ if (description && !multi)
72
+ console.log(` Message: ${description}`);
67
73
  try {
68
74
  let result;
69
75
  try {
70
- result = await uploadOneGame(game, { credential, apiURL, sha, description, repoURL, verbose, rootDir });
76
+ result = await uploadOneGame(game, { credential, apiURL, sha, description, repoURL, verbose });
71
77
  }
72
78
  catch (e) {
73
79
  if (!(e instanceof GameNotFoundError))
@@ -75,7 +81,7 @@ export const upload = async (dir, options = {}) => {
75
81
  const created = await maybeCreateMissingGame(e, game, { apiURL, teamAccessToken: credential.token });
76
82
  if (!created)
77
83
  throw e;
78
- result = await uploadOneGame(game, { credential, apiURL, sha, description, repoURL, verbose, rootDir });
84
+ result = await uploadOneGame(game, { credential, apiURL, sha, description, repoURL, verbose });
79
85
  }
80
86
  results.push(result);
81
87
  }
@@ -85,32 +91,37 @@ export const upload = async (dir, options = {}) => {
85
91
  results.push({ ok: false, slug, error: message });
86
92
  }
87
93
  }
88
- printReport(results);
94
+ printSummary(results, multi);
89
95
  const anyFailed = results.some((r) => !r.ok);
90
96
  if (anyFailed)
91
97
  process.exit(1);
92
98
  };
93
99
  /** Uploads a single discovered game; throws on failure */
94
100
  const uploadOneGame = async (game, opts) => {
95
- const { credential, apiURL, sha, description, repoURL, verbose, rootDir } = opts;
101
+ const { credential, apiURL, sha, description, repoURL, verbose } = opts;
96
102
  const { puzzmoFile, distDir } = game;
97
103
  const gameSlug = puzzmoFile.game.slug;
98
104
  const files = collectFiles(distDir);
99
105
  if (!files.length)
100
106
  throw new Error(`Dist folder is empty: ${distDir}`);
101
- console.log(` Directory: ${path.relative(rootDir, distDir) || distDir}`);
102
107
  let totalBytes = 0;
103
108
  for (const file of files)
104
109
  totalBytes += fs.statSync(file).size;
105
- console.log(` ${files.length} file(s), ${formatBytes(totalBytes)} total (sha ${sha.slice(0, 8)})`);
110
+ console.log(` ${plural(files.length, "file")}, ${formatBytes(totalBytes)} (sha ${sha.slice(0, 8)})`);
106
111
  const result = await uploadFiles(apiURL, credential.token, gameSlug, sha, files, distDir, puzzmoFile, (batch, totalBatches, uploaded) => {
107
- console.log(` Batch ${batch}/${totalBatches} done (${uploaded} file(s) uploaded)`);
112
+ console.log(` Batch ${batch}/${totalBatches} done (${plural(uploaded, "file")} uploaded)`);
108
113
  }, { verbose, description, repoURL });
109
- console.log(` Done - ${result.versionID}`);
110
114
  if (result.integrationsChanged && result.versionsURL) {
111
- console.log(` Integrations changed — staged on a new upcoming version:`);
115
+ console.log(` Uploaded. Integrations changed — a new version has been staged for your team:`);
112
116
  console.log(` ${result.versionsURL}`);
113
117
  }
118
+ else if (result.gameURL) {
119
+ console.log(` Uploaded — live now for your team at:`);
120
+ console.log(` ${result.gameURL}`);
121
+ }
122
+ else {
123
+ console.log(` Uploaded.`);
124
+ }
114
125
  return {
115
126
  ok: true,
116
127
  slug: gameSlug,
@@ -120,21 +131,51 @@ const uploadOneGame = async (game, opts) => {
120
131
  versionID: result.versionID,
121
132
  assetsBase: result.assetsBase,
122
133
  integrationsChanged: result.integrationsChanged,
134
+ gameURL: result.gameURL,
123
135
  versionsURL: result.versionsURL,
124
136
  };
125
137
  };
126
- /** Prints a final summary of every game's outcome */
127
- const printReport = (results) => {
128
- console.log(`\nUpload report (${results.length} game${results.length === 1 ? "" : "s"})`);
138
+ /** Prints the closing summary: failure count for all-fail, otherwise the puzzmonaut delivering the success line. */
139
+ const printSummary = (results, multi) => {
129
140
  const successes = results.filter((r) => r.ok);
130
141
  const failures = results.filter((r) => !r.ok);
131
- for (const r of successes) {
132
- console.log(` OK ${r.slug.padEnd(24)} ${formatBytes(r.totalBytes).padStart(8)} ${r.source.padEnd(20)} ${r.versionID}`);
133
- }
134
- for (const r of failures) {
135
- console.log(` FAIL ${r.slug.padEnd(24)} ${r.error}`);
142
+ if (successes.length === 0) {
143
+ if (multi)
144
+ console.log(`\n${plural(failures.length, "game")} failed.`);
145
+ return;
136
146
  }
137
- console.log(`\n${successes.length} succeeded, ${failures.length} failed`);
147
+ const lines = [];
148
+ if (multi && failures.length === 0)
149
+ lines.push(`${plural(successes.length, "game")} uploaded!`);
150
+ else if (multi)
151
+ lines.push(`${successes.length} of ${results.length} uploaded, ${failures.length} failed.`);
152
+ else
153
+ lines.push("Uploaded!");
154
+ console.log("");
155
+ console.log(puzzmonautSays(lines));
156
+ };
157
+ const plural = (n, singular, pluralForm) => `${n} ${n === 1 ? singular : (pluralForm ?? `${singular}s`)}`;
158
+ const isDefaultServer = (source) => normalizeSource(source) === normalizeSource(defaultSource);
159
+ const yellow = (s) => (process.stdout.isTTY ? `\x1b[33m${s}\x1b[0m` : s);
160
+ const blackOnYellow = (s) => (process.stdout.isTTY ? `\x1b[30;43m${s}\x1b[0m` : s);
161
+ const puzzmonautLines = [
162
+ ` ${yellow("▟████▙")}`,
163
+ ` ${yellow("██")}${blackOnYellow("▝ ▘ ")} ${yellow("██")}`,
164
+ `${yellow(" ██")}${blackOnYellow(" ▄▖")}${yellow("██")}`,
165
+ ` ${yellow("▝▀▀▀▀▘")}`,
166
+ ];
167
+ const visualWidth = (s) => s.replace(/\u001b\[[0-9;]*m/g, "").length;
168
+ /** Renders the puzzmonaut with message lines vertically centered to its right. */
169
+ const puzzmonautSays = (messages) => {
170
+ const iconWidth = Math.max(...puzzmonautLines.map(visualWidth));
171
+ const startRow = Math.max(0, Math.floor((puzzmonautLines.length - messages.length) / 2));
172
+ return puzzmonautLines
173
+ .map((line, i) => {
174
+ const pad = " ".repeat(iconWidth - visualWidth(line));
175
+ const msg = messages[i - startRow] ?? "";
176
+ return `${line}${pad} ${msg}`.trimEnd();
177
+ })
178
+ .join("\n");
138
179
  };
139
180
  /** Collects all files in a directory recursively */
140
181
  const collectFiles = (dir) => {
@@ -224,7 +265,7 @@ const maybeCreateMissingGame = async (err, game, opts) => {
224
265
  return false;
225
266
  try {
226
267
  const created = await createUserGame({ apiURL: opts.apiURL, displayName, teamAccessToken: opts.teamAccessToken });
227
- console.log(` Created game ${created.slug} (${created.id})`);
268
+ console.log(` Created game ${created.slug}`);
228
269
  if (created.slug !== slug) {
229
270
  console.warn(` Server picked slug "${created.slug}" but your puzzmo.json uses "${slug}". Update puzzmo.json before re-uploading.`);
230
271
  return false;
@@ -1 +1 @@
1
- {"version":3,"file":"upload.js","sourceRoot":"","sources":["../../src/commands/upload.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"upload.js","sourceRoot":"","sources":["../../src/commands/upload.ts"],"names":[],"mappings":"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"}
package/lib/util/api.d.ts CHANGED
@@ -19,6 +19,7 @@ type CompleteResponse = {
19
19
  assetsBase: string;
20
20
  versionID: string;
21
21
  integrationsChanged: boolean;
22
+ gameURL: string | null;
22
23
  versionsURL: string | null;
23
24
  error?: string;
24
25
  };
package/lib/util/api.js CHANGED
@@ -101,8 +101,6 @@ export const uploadFiles = async (apiURL, token, gameSlug, sha, filePaths, baseD
101
101
  throw new GameNotFoundError(gameSlug, e.message);
102
102
  throw e;
103
103
  }
104
- if (verbose)
105
- console.log(` session: ${init.sessionID}`);
106
104
  // Step 2: Upload files in concurrent batches
107
105
  const fileURL = `${apiURL}/cliUpload/${init.sessionID}/file`;
108
106
  const totalBatches = Math.ceil(filePaths.length / batchSize);
@@ -119,6 +117,7 @@ export const uploadFiles = async (apiURL, token, gameSlug, sha, filePaths, baseD
119
117
  return {
120
118
  ...complete,
121
119
  integrationsChanged: !!init.integrationsChanged,
120
+ gameURL: init.gameURL ?? null,
122
121
  versionsURL: init.versionsURL ?? null,
123
122
  };
124
123
  };
@@ -1 +1 @@
1
- {"version":3,"file":"api.js","sourceRoot":"","sources":["../../src/util/api.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"api.js","sourceRoot":"","sources":["../../src/util/api.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@puzzmo/cli",
3
- "version": "1.0.47",
3
+ "version": "1.0.48",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "puzzmo": "./lib/index.js"
@@ -0,0 +1,338 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-07/schema#",
3
+ "$ref": "#/definitions/PuzzmoFile",
4
+ "definitions": {
5
+ "PuzzmoFile": {
6
+ "type": "object",
7
+ "properties": {
8
+ "game": {
9
+ "type": "object",
10
+ "properties": {
11
+ "displayName": {
12
+ "type": "string",
13
+ "description": "Display name shown in the UI, use | to indicate where a line break should go"
14
+ },
15
+ "slug": {
16
+ "type": "string",
17
+ "description": "URL-friendly identifier for the game"
18
+ },
19
+ "teamID": {
20
+ "type": "string",
21
+ "description": "The team ID that owns this game"
22
+ }
23
+ },
24
+ "required": ["displayName", "slug", "teamID"],
25
+ "additionalProperties": false,
26
+ "description": "Metadata about the game"
27
+ },
28
+ "integrations": {
29
+ "$ref": "#/definitions/Augmentations",
30
+ "description": "Game integrations with Puzzmo platform systems (leaderboards, stats, completion UI, etc.)"
31
+ },
32
+ "output": {
33
+ "type": "object",
34
+ "properties": {
35
+ "dir": {
36
+ "type": "string",
37
+ "description": "Path to the built artifacts. Resolved relative to the puzzmo.json's directory. Can be shared across games (e.g. `../../dist/<slug>`) or per-game (e.g. `./build`)."
38
+ }
39
+ },
40
+ "required": ["dir"],
41
+ "additionalProperties": false,
42
+ "description": "Where the built game artifacts live for this game. Used by `puzzmo upload` and `puzzmo validate` to find the dist folder when running from a repo root. If omitted, the CLI looks for a `dist`, `build`, or `built` folder — first next to puzzmo.json, then walking up to the repo root, optionally with `<slug>` as a sub-folder for shared output dirs."
43
+ }
44
+ },
45
+ "required": ["game"],
46
+ "additionalProperties": false,
47
+ "description": "The schema for a puzzmo.json file that lives alongside a game's build artifacts"
48
+ },
49
+ "Augmentations": {
50
+ "type": "object",
51
+ "properties": {
52
+ "leaderboards": {
53
+ "type": "array",
54
+ "items": {
55
+ "$ref": "#/definitions/LeaderboardExpressionSetup"
56
+ },
57
+ "description": "Dynamic leaderboards for this game"
58
+ },
59
+ "puzzleAggregateStats": {
60
+ "type": "array",
61
+ "items": {
62
+ "type": "object",
63
+ "properties": {
64
+ "deedID": {
65
+ "$ref": "#/definitions/DeedKeys",
66
+ "description": "Sometimes, instead of an expression, you may need to hook up to a deed"
67
+ },
68
+ "stableID": {
69
+ "type": ["string", "null"],
70
+ "description": "For a lot of augmentations, this acts as an \"id\" and should be unique and treated as a lower, kebab-case string.\n\nFor a leaderboard:\n- A stable ID has to be in the format of `game-[gameslug]:[your value name]` for a game-based leaderboard (value here likely can be your deedID). The formatting will get validated on puzzle creation, and in TypeScript."
71
+ },
72
+ "filterExp": {
73
+ "type": "string",
74
+ "description": "An expression string which can stop something from happening. A concrete example: Whether to post to a leaderboard or not. If the expression returns true or > 0 then the entry is considered allowed for the leaderboard."
75
+ },
76
+ "valueExp": {
77
+ "type": "string",
78
+ "description": "An expression string which can be used to generate the value for whatever your config is based on. The API will provide a set of appropriate variables for you to use in this JS-like expression string. They are based on \"AngularJS Expressions\" which you can read about here: https://docs.angularjs.org/guide/expression"
79
+ }
80
+ },
81
+ "additionalProperties": false
82
+ },
83
+ "description": "Puzzle-specific aggregate stats that track data across all completions of a specific puzzle (e.g. \"how many perfect scores on this puzzle\"). Unlike `userAggregateStats` which are per-user, these accumulate data across all players for a single puzzle instance.\n\nEvaluated at game completion. Expression scope includes:\n\n- All deed values from the gameplay (camelCase keys, e.g. `excessMoves` from `excess-moves` deed)\n- `prior`: The previous value of this stat for the puzzle\n- `wallClockComplete`: Seconds since daily start when completed (if today's daily)\n\nTwo ways to define stats:\n\n1. Via `deedID`: Looks up the deed value and adds it to prior (simple accumulation) 2. Via `valueExp`: Full expression control, e.g. `prior + 1` to count occurrences\n\nUse `filterExp` to conditionally update, e.g. `excessMoves === 0` to only count perfect games. The `stableID` is required and used as the storage key for this stat.\n\nExample: Count perfect completions\n\n```json { \"stableID\": \"perfects\", \"filterExp\": \"excessMoves === 0\", \"valueExp\": \"prior + 1\" } ```"
84
+ },
85
+ "userAggregateStats": {
86
+ "type": "array",
87
+ "items": {
88
+ "type": "object",
89
+ "properties": {
90
+ "deedID": {
91
+ "$ref": "#/definitions/DeedKeys",
92
+ "description": "Sometimes, instead of an expression, you may need to hook up to a deed"
93
+ },
94
+ "stableID": {
95
+ "type": ["string", "null"],
96
+ "description": "For a lot of augmentations, this acts as an \"id\" and should be unique and treated as a lower, kebab-case string.\n\nFor a leaderboard:\n- A stable ID has to be in the format of `game-[gameslug]:[your value name]` for a game-based leaderboard (value here likely can be your deedID). The formatting will get validated on puzzle creation, and in TypeScript."
97
+ },
98
+ "filterExp": {
99
+ "type": "string",
100
+ "description": "An expression string which can stop something from happening. A concrete example: Whether to post to a leaderboard or not. If the expression returns true or > 0 then the entry is considered allowed for the leaderboard."
101
+ },
102
+ "valueExp": {
103
+ "type": "string",
104
+ "description": "An expression string which can be used to generate the value for whatever your config is based on. The API will provide a set of appropriate variables for you to use in this JS-like expression string. They are based on \"AngularJS Expressions\" which you can read about here: https://docs.angularjs.org/guide/expression"
105
+ }
106
+ },
107
+ "additionalProperties": false
108
+ },
109
+ "description": "User-specific aggregate stats stored per-user, tied to the game or remix. These track lifetime stats for individual players (e.g. \"total points earned\", \"best score\"). Stats are keyed by game symbol, or `{symbol}-{remixSlug}` if the remix has the uniqueStats flag.\n\nEvaluated at game completion. Expression scope includes:\n\n- `deeds`: All deed values from the gameplay (camelCase keys, e.g. `deeds.tilesCleared`)\n- `prior`: The previous value of this stat for the user (for running totals/max/min)\n- `uas`: The user's existing aggregate stats object\n- Game symbol keys containing prior deed stats\n\nTwo ways to define stats:\n\n1. Via `deedID`: Looks up the deed value and adds it to prior (simple accumulation) 2. Via `valueExp`: Full expression control, e.g. `prior > deeds.score ? prior : deeds.score` for max\n\nUse `filterExp` to conditionally update (e.g. only count completed games). The `stableID` is required and used as the storage key for this stat.\n\nExample: Track the user's best score\n\n```json { \"stableID\": \"best-score\", \"valueExp\": \"prior > deeds.score ? prior : deeds.score\" } ```"
110
+ },
111
+ "userStatDisplays": {
112
+ "type": "array",
113
+ "items": {
114
+ "type": "object",
115
+ "properties": {
116
+ "userAggregateStatStableID": {
117
+ "type": "string",
118
+ "description": "The stableID from userAggregateStats to display. Converted to camelCase for lookup (e.g. \"best-score\" -> \"bestScore\")."
119
+ },
120
+ "formatString": {
121
+ "type": "string",
122
+ "description": "Format string. Use `%@` as placeholder for the value (e.g., \"Best score: %@\" -> \"Best score: 1234\")."
123
+ },
124
+ "displayID": {
125
+ "type": "number",
126
+ "description": "Unique ID for this stat within the game section. Used for user selection persistence. Negative IDs are reserved for system stats."
127
+ },
128
+ "hideExp": {
129
+ "type": "string",
130
+ "description": "Optional expression to determine visibility. Receives `{ value }` in scope. Return truthy to hide."
131
+ },
132
+ "order": {
133
+ "type": "number",
134
+ "description": "Display order within section (default: 0). Negative numbers are reserved for system prefix stats."
135
+ }
136
+ },
137
+ "required": ["userAggregateStatStableID", "formatString", "displayID"],
138
+ "additionalProperties": false
139
+ },
140
+ "description": "Configuration for how user aggregate stats are displayed on user profiles. Maps stats from `userAggregateStats` to formatted display strings shown in the profile stats section.\n\nThe profile section automatically includes prefix stats (games played, hours played, best streak) before any custom stats defined here.\n\nThe `hideExp` expression receives `{ value }` in scope where `value` is the stat's current value. Common pattern: `\"!value\"` to hide when zero/undefined."
141
+ },
142
+ "persistedDeeds": {
143
+ "type": "array",
144
+ "items": {
145
+ "$ref": "#/definitions/ExpressionSetup"
146
+ },
147
+ "description": "Converts temporary (pipeline) deeds into persisted deeds at game completion time. Use this to persist computed values derived from temporary deed data.\n\nFor each config, the `valueExp` is evaluated against the deed scope, and the result is stored as a permanent deed using `stableID` (or `deedID`) as the storage key.\n\nExpression scope includes all deeds from the gameplay (camelCase keys, e.g. `points` from `points` deed). Values are floored to integers before storage.\n\nUse `filterExp` to conditionally persist (e.g. only persist if a threshold is met). Either `stableID` or `deedID` is required as the storage key.\n\nExample: Persist a computed score only when player achieves a threshold\n\n```json { \"stableID\": \"computed-bonus\", \"filterExp\": \"points > 100\", \"valueExp\": \"points * 2\" } ```\n\nCommon use case: Take a temporary deed and persist it for use in completion tables or sidebars."
148
+ },
149
+ "completionTable": {
150
+ "type": "array",
151
+ "items": {
152
+ "type": "object",
153
+ "properties": {
154
+ "title": {
155
+ "type": "string",
156
+ "description": "Label shown on the left side of the table row"
157
+ },
158
+ "persistedDeedID": {
159
+ "type": "string",
160
+ "description": "ID of the persisted deed to look up (must match a deed stored on the gameplay)"
161
+ },
162
+ "formatString": {
163
+ "type": "string",
164
+ "description": "Format string. Use `%@` as placeholder for the value."
165
+ }
166
+ },
167
+ "required": ["title", "persistedDeedID", "formatString"],
168
+ "additionalProperties": false
169
+ },
170
+ "description": "Additional rows to display in the Today page completion table for a completed game. Shows custom stats alongside the default game stats (time, score, hints, etc.).\n\nEach entry looks up a persisted deed by `persistedDeedID` and formats its value using `formatString`. Custom entries appear before the default game stats. The table is rendered as title/value pairs.\n\nNote: Only works with persisted deeds. Use `persistedDeeds` augmentation first if you need to convert temporary deeds into persisted ones for display here.\n\nExample: Show a custom \"Bonus Points\" stat\n\n```json { \"title\": \"Bonus Points\", \"persistedDeedID\": \"bonus-points\", \"formatString\": \"%@ pts\" } ```"
171
+ },
172
+ "completionSidebar": {
173
+ "type": "array",
174
+ "items": {
175
+ "$ref": "#/definitions/ExpressionSetup"
176
+ },
177
+ "description": "Additional stats to display in the game completion sidebar/popover on the Today page. Use this to show deed values that don't have an associated leaderboard.\n\nThese items are merged with leaderboard entries, sorted by `sortValue`, and displayed as a list of stats after game completion. Each entry looks up a deed by `deedID` and formats its value using `formatString`.\n\nItems can include:\n\n- `display` or `secondaryName`: Label shown for the stat\n- `deedID`: Which deed to look up for the value\n- `formatString`: How to format the value (e.g. \"%@ pts\")\n- `sortValue`: Order relative to other sidebar items (lower = earlier)\n- `order`: \"Lower=better\" or default (higher=better) for directional indicators\n\nExample: Show a custom \"Combos\" stat\n\n```json { \"completionSidebar\": [ { \"deedID\": \"combo-count\", \"displayName\": \"Combos\", \"formatString\": \"%@\", \"sortValue\": 10 } ] } ```"
178
+ },
179
+ "completionNotables": {
180
+ "type": "array",
181
+ "items": {
182
+ "type": "object",
183
+ "properties": {
184
+ "valueExp": {
185
+ "type": "string",
186
+ "description": "Expression evaluated against deed scope. If truthy, the notable is awarded."
187
+ },
188
+ "notableIndex": {
189
+ "type": "number",
190
+ "description": "For code-based notables: 0 for UserAwardsBitmapKeys, 1 for UserAwardsBitmap1Keys. Not needed for system notables."
191
+ },
192
+ "notableName": {
193
+ "type": "string",
194
+ "description": "Notable identifier. For code-based: the enum key name (Puzzmo team games only). For system notables: \"{index}-{bitmapValue}\" format."
195
+ }
196
+ },
197
+ "required": ["valueExp", "notableName"],
198
+ "additionalProperties": false
199
+ },
200
+ "description": "Awards notables (achievements/badges) to users when conditions are met at game completion. When a notable is awarded, it appears on the user's profile and creates a social news item.\n\nThe `valueExp` is evaluated against the game's deed scope. If it returns truthy, the notable is awarded. Expression scope includes all deed values from the gameplay (camelCase keys).\n\nTwo types of notables:\n\n1. **Code-based notables**: Use `notableName` (e.g. \"jokinAround\") with `notableIndex` (0 or 1). These reference predefined notables in UserAwardsBitmapKeys (index 0) or UserAwardsBitmap1Keys (index 1). **Restricted to games owned by the Puzzmo team.** 2. **System notables**: Use `notableName` as \"{index}-{bitmapValue}\" format (e.g. \"2-4\"). These reference dynamic notables stored in the SystemNotable database table. Available to all games.\n\nExample: Award a notable when player scores over 100 points\n\n```json { \"completionNotables\": [ { \"valueExp\": \"score > 100\", \"notableIndex\": 0, \"notableName\": \"jokinAround\" }, { \"valueExp\": \"perfect === true\", \"notableName\": \"2-4\" } ] } ```"
201
+ },
202
+ "forceGameSettings": {
203
+ "type": "object",
204
+ "description": "Forces specific game settings for this puzzle, overriding user preferences. Only applies when set via puzzle front-matter (not from game-level augmentations).\n\nWhen a puzzle has forced settings, those settings are locked in the UI and displayed as read-only with a note that the setting is specific to this puzzle. Users cannot change forced settings.\n\nThe settings object keys/values are game-specific. To find valid settings for a game, set the setting yourself in the game and check your user profile in the admin to see the stored format.\n\nExample: Force monochrome grid mode for a crossword puzzle\n\n```json { \"forceGameSettings\": { \"monoGrid\": true } } ```"
205
+ }
206
+ },
207
+ "additionalProperties": false,
208
+ "description": "Site-wide hooks which are sent at puzzle creation, (via front-matter), via the game, and gameplay completion messages.\n\nGames/Variants/FrontMatter: Supports All Fields. Game Completion: Just \"leaderboards\" and \"completionNotables\""
209
+ },
210
+ "LeaderboardExpressionSetup": {
211
+ "type": "object",
212
+ "additionalProperties": false,
213
+ "properties": {
214
+ "stableID": {
215
+ "type": ["string", "null"],
216
+ "description": "For a lot of augmentations, this acts as an \"id\" and should be unique and treated as a lower, kebab-case string.\n\nFor a leaderboard:\n- A stable ID has to be in the format of `game-[gameslug]:[your value name]` for a game-based leaderboard (value here likely can be your deedID). The formatting will get validated on puzzle creation, and in TypeScript."
217
+ },
218
+ "scoreTechnique": {
219
+ "type": ["string", "null"],
220
+ "enum": ["AggregateOfBest", "AggregateOfAll", null],
221
+ "description": "Provides a way to control how we handle different scoring algorithms, right now you have the default (overwrite on best) and \"AggregateOfBest\" which aggregates based on the"
222
+ },
223
+ "rotation": {
224
+ "type": "string",
225
+ "enum": ["Weekly", "Monthly"],
226
+ "description": "How often does this leaderboard rotate? Leaving empty is means daily"
227
+ },
228
+ "icons": {
229
+ "type": "array",
230
+ "items": {
231
+ "type": "string"
232
+ },
233
+ "description": "What icons should show above the leaderboard? These want to be game slugs"
234
+ },
235
+ "rules": {
236
+ "type": "string",
237
+ "description": "A \\n separated list of rules to put under a leaderboard"
238
+ },
239
+ "subscoreExp": {
240
+ "type": "string",
241
+ "description": "An expression to grab a subscore"
242
+ },
243
+ "championsLeague": {
244
+ "type": "boolean",
245
+ "const": true,
246
+ "description": "Support having a champion's league, where we extract the top players from the game and move them into a new league. Only available for use on the Game augmentations (and not at puzzles/variants/runtime etc) and on leaderboards with a rotation of null (daily.)"
247
+ },
248
+ "postCompletion": {
249
+ "type": "boolean",
250
+ "const": true,
251
+ "description": "This leaderboard is only submitted to via a post-completion checkpoint, not during the normal completion pipeline. We use this for games which have secret metagames which occur after the game has been completed."
252
+ },
253
+ "displayName": {
254
+ "type": "string",
255
+ "description": "What do we call this datum"
256
+ },
257
+ "secondaryName": {
258
+ "type": "string",
259
+ "description": "An optional secondary name for this config. For example, on a leaderboard this is used in the completion sidebar"
260
+ },
261
+ "order": {
262
+ "type": "string",
263
+ "enum": ["Higher=better", "Lower=better"],
264
+ "description": "Just saying it how it is, for some augmentations, this isn't necessary"
265
+ },
266
+ "deedID": {
267
+ "$ref": "#/definitions/DeedKeys",
268
+ "description": "Sometimes, instead of an expression, you may need to hook up to a deed"
269
+ },
270
+ "formatString": {
271
+ "type": "string",
272
+ "description": "A custom string formatter, slightly based on printf.\n\n- `%+`: Adds a plus sign _only_ to positive numbers\n- `%@`: Takes the value and replaces the token with the value. If a number it is 'toLocaleString(\"en-US\")'ed\n- `%TD`: Takes the text definition for a deed and replaces the token with the value\n- `\"[time]\"`: Converts a number of seconds to a colon-separated time string (must be exact match)"
273
+ },
274
+ "filterExp": {
275
+ "type": "string",
276
+ "description": "An expression string which can stop something from happening. A concrete example: Whether to post to a leaderboard or not. If the expression returns true or > 0 then the entry is considered allowed for the leaderboard."
277
+ },
278
+ "valueExp": {
279
+ "type": "string",
280
+ "description": "An expression string which can be used to generate the value for whatever your config is based on. The API will provide a set of appropriate variables for you to use in this JS-like expression string. They are based on \"AngularJS Expressions\" which you can read about here: https://docs.angularjs.org/guide/expression"
281
+ },
282
+ "sortValue": {
283
+ "type": "number",
284
+ "description": "Different augmentations would do different things with this sort value. Leaderboards for example use this when displaying on a page."
285
+ }
286
+ },
287
+ "required": ["displayName", "formatString", "stableID"]
288
+ },
289
+ "DeedKeys": {
290
+ "type": "string"
291
+ },
292
+ "ExpressionSetup": {
293
+ "type": "object",
294
+ "properties": {
295
+ "displayName": {
296
+ "type": "string",
297
+ "description": "What do we call this datum"
298
+ },
299
+ "secondaryName": {
300
+ "type": "string",
301
+ "description": "An optional secondary name for this config. For example, on a leaderboard this is used in the completion sidebar"
302
+ },
303
+ "stableID": {
304
+ "type": ["string", "null"],
305
+ "description": "For a lot of augmentations, this acts as an \"id\" and should be unique and treated as a lower, kebab-case string.\n\nFor a leaderboard:\n- A stable ID has to be in the format of `game-[gameslug]:[your value name]` for a game-based leaderboard (value here likely can be your deedID). The formatting will get validated on puzzle creation, and in TypeScript."
306
+ },
307
+ "order": {
308
+ "type": "string",
309
+ "enum": ["Higher=better", "Lower=better"],
310
+ "description": "Just saying it how it is, for some augmentations, this isn't necessary"
311
+ },
312
+ "deedID": {
313
+ "$ref": "#/definitions/DeedKeys",
314
+ "description": "Sometimes, instead of an expression, you may need to hook up to a deed"
315
+ },
316
+ "formatString": {
317
+ "type": "string",
318
+ "description": "A custom string formatter, slightly based on printf.\n\n- `%+`: Adds a plus sign _only_ to positive numbers\n- `%@`: Takes the value and replaces the token with the value. If a number it is 'toLocaleString(\"en-US\")'ed\n- `%TD`: Takes the text definition for a deed and replaces the token with the value\n- `\"[time]\"`: Converts a number of seconds to a colon-separated time string (must be exact match)"
319
+ },
320
+ "filterExp": {
321
+ "type": "string",
322
+ "description": "An expression string which can stop something from happening. A concrete example: Whether to post to a leaderboard or not. If the expression returns true or > 0 then the entry is considered allowed for the leaderboard."
323
+ },
324
+ "valueExp": {
325
+ "type": "string",
326
+ "description": "An expression string which can be used to generate the value for whatever your config is based on. The API will provide a set of appropriate variables for you to use in this JS-like expression string. They are based on \"AngularJS Expressions\" which you can read about here: https://docs.angularjs.org/guide/expression"
327
+ },
328
+ "sortValue": {
329
+ "type": "number",
330
+ "description": "Different augmentations would do different things with this sort value. Leaderboards for example use this when displaying on a page."
331
+ }
332
+ },
333
+ "required": ["displayName", "formatString"],
334
+ "additionalProperties": false,
335
+ "description": "Data given by either via a puzzle in front-matter, or a game in completion. A general unit of data which can be used to represent a lot of configuration points from the game to the API."
336
+ }
337
+ }
338
+ }
@@ -5,7 +5,15 @@ import path from "node:path"
5
5
  import * as p from "@clack/prompts"
6
6
 
7
7
  import { GameNotFoundError, uploadFiles } from "../util/api.js"
8
- import { type TokenEntry, findTokensForTeam, getTokens, resolveServerForTeam, sourceToURL } from "../util/config.js"
8
+ import {
9
+ defaultSource,
10
+ findTokensForTeam,
11
+ getTokens,
12
+ normalizeSource,
13
+ resolveServerForTeam,
14
+ sourceToURL,
15
+ type TokenEntry,
16
+ } from "../util/config.js"
9
17
  import { createUserGame } from "../util/createGame.js"
10
18
  import { discoverGames, type DiscoveredGame } from "../util/discoverGames.js"
11
19
 
@@ -22,6 +30,7 @@ type GameSuccess = {
22
30
  versionID: string
23
31
  assetsBase: string
24
32
  integrationsChanged: boolean
33
+ gameURL: string | null
25
34
  versionsURL: string | null
26
35
  }
27
36
 
@@ -55,23 +64,26 @@ export const upload = async (dir: string, options: UploadOptions = {}) => {
55
64
  process.exit(1)
56
65
  }
57
66
 
58
- console.log(`Found ${games.length} game(s) under ${rootDir}`)
59
- for (const game of games) {
60
- console.log(` - ${game.puzzmoFile.game.slug} (${path.relative(rootDir, game.distDir) || "."})`)
61
- }
62
- if (discoveryErrors.length) {
63
- console.log(`\n${discoveryErrors.length} puzzmo.json file(s) could not be loaded:`)
64
- for (const err of discoveryErrors) {
65
- console.log(` - ${err.slug ?? path.relative(rootDir, err.puzzmoJsonPath)}`)
66
- for (const e of err.errors) console.log(` ${e}`)
67
+ const multi = games.length + discoveryErrors.length > 1
68
+
69
+ if (multi) {
70
+ console.log(`Found ${plural(games.length, "game")} under ${rootDir}`)
71
+ for (const game of games) {
72
+ console.log(` - ${game.puzzmoFile.game.slug} (${path.relative(rootDir, game.distDir) || "."})`)
73
+ }
74
+ if (discoveryErrors.length) {
75
+ console.log(`\n${plural(discoveryErrors.length, "puzzmo.json file")} could not be loaded:`)
76
+ for (const err of discoveryErrors) {
77
+ console.log(` - ${err.slug ?? path.relative(rootDir, err.puzzmoJsonPath)}`)
78
+ for (const e of err.errors) console.log(` ${e}`)
79
+ }
67
80
  }
68
81
  }
69
82
 
70
83
  const sha = getGitSHA(rootDir) || hashGames(games)
71
84
  const description = getGitMessage(rootDir)
72
85
  const repoURL = getGitRepoURL(rootDir)
73
- if (description) console.log(`\nMessage: ${description}`)
74
- if (repoURL) console.log(`Repo: ${repoURL}`)
86
+ if (description && multi) console.log(`\nMessage: ${description}`)
75
87
 
76
88
  const results: GameResult[] = []
77
89
  for (const err of discoveryErrors) {
@@ -81,7 +93,8 @@ export const upload = async (dir: string, options: UploadOptions = {}) => {
81
93
  for (let i = 0; i < games.length; i++) {
82
94
  const game = games[i]
83
95
  const slug = game.puzzmoFile.game.slug
84
- console.log(`\n[${i + 1}/${games.length}] Uploading ${slug}`)
96
+ const prefix = multi ? `[${i + 1}/${games.length}] ` : ""
97
+ const distLabel = path.relative(rootDir, game.distDir) || "."
85
98
 
86
99
  const teamID = game.puzzmoFile.game.teamID
87
100
  const credential = await resolveServerForTeam(teamID)
@@ -91,23 +104,25 @@ export const upload = async (dir: string, options: UploadOptions = {}) => {
91
104
  matches.length === 0
92
105
  ? `No saved token for team ${teamID}. Run \`puzzmo login <token>\` (use \`--source\` if the token is for a non-default server).`
93
106
  : `Token for team ${teamID} is registered against ${matches.map((m) => m.source).join(", ")} but none of those servers are reachable.`
94
- console.error(` ${message}`)
107
+ console.error(`\n${prefix}Uploading ${slug} from ${distLabel}\n ${message}`)
95
108
  results.push({ ok: false, slug, error: message })
96
109
  continue
97
110
  }
98
111
 
99
112
  const apiURL = sourceToURL(credential.source)
100
- console.log(` Server: ${credential.source}`)
113
+ console.log(`\n${prefix}Uploading ${slug} from ${distLabel}`)
114
+ if (!isDefaultServer(credential.source)) console.log(` Server: ${credential.source}`)
115
+ if (description && !multi) console.log(` Message: ${description}`)
101
116
 
102
117
  try {
103
118
  let result: GameSuccess
104
119
  try {
105
- result = await uploadOneGame(game, { credential, apiURL, sha, description, repoURL, verbose, rootDir })
120
+ result = await uploadOneGame(game, { credential, apiURL, sha, description, repoURL, verbose })
106
121
  } catch (e) {
107
122
  if (!(e instanceof GameNotFoundError)) throw e
108
123
  const created = await maybeCreateMissingGame(e, game, { apiURL, teamAccessToken: credential.token })
109
124
  if (!created) throw e
110
- result = await uploadOneGame(game, { credential, apiURL, sha, description, repoURL, verbose, rootDir })
125
+ result = await uploadOneGame(game, { credential, apiURL, sha, description, repoURL, verbose })
111
126
  }
112
127
  results.push(result)
113
128
  } catch (e) {
@@ -117,7 +132,7 @@ export const upload = async (dir: string, options: UploadOptions = {}) => {
117
132
  }
118
133
  }
119
134
 
120
- printReport(results)
135
+ printSummary(results, multi)
121
136
 
122
137
  const anyFailed = results.some((r) => !r.ok)
123
138
  if (anyFailed) process.exit(1)
@@ -130,22 +145,20 @@ type UploadOneOptions = {
130
145
  description: string | null
131
146
  repoURL: string | null
132
147
  verbose: boolean
133
- rootDir: string
134
148
  }
135
149
 
136
150
  /** Uploads a single discovered game; throws on failure */
137
151
  const uploadOneGame = async (game: DiscoveredGame, opts: UploadOneOptions): Promise<GameSuccess> => {
138
- const { credential, apiURL, sha, description, repoURL, verbose, rootDir } = opts
152
+ const { credential, apiURL, sha, description, repoURL, verbose } = opts
139
153
  const { puzzmoFile, distDir } = game
140
154
  const gameSlug = puzzmoFile.game.slug
141
155
 
142
156
  const files = collectFiles(distDir)
143
157
  if (!files.length) throw new Error(`Dist folder is empty: ${distDir}`)
144
158
 
145
- console.log(` Directory: ${path.relative(rootDir, distDir) || distDir}`)
146
159
  let totalBytes = 0
147
160
  for (const file of files) totalBytes += fs.statSync(file).size
148
- console.log(` ${files.length} file(s), ${formatBytes(totalBytes)} total (sha ${sha.slice(0, 8)})`)
161
+ console.log(` ${plural(files.length, "file")}, ${formatBytes(totalBytes)} (sha ${sha.slice(0, 8)})`)
149
162
 
150
163
  const result = await uploadFiles(
151
164
  apiURL,
@@ -156,15 +169,19 @@ const uploadOneGame = async (game: DiscoveredGame, opts: UploadOneOptions): Prom
156
169
  distDir,
157
170
  puzzmoFile,
158
171
  (batch, totalBatches, uploaded) => {
159
- console.log(` Batch ${batch}/${totalBatches} done (${uploaded} file(s) uploaded)`)
172
+ console.log(` Batch ${batch}/${totalBatches} done (${plural(uploaded, "file")} uploaded)`)
160
173
  },
161
174
  { verbose, description, repoURL },
162
175
  )
163
176
 
164
- console.log(` Done - ${result.versionID}`)
165
177
  if (result.integrationsChanged && result.versionsURL) {
166
- console.log(` Integrations changed — staged on a new upcoming version:`)
178
+ console.log(` Uploaded. Integrations changed — a new version has been staged for your team:`)
167
179
  console.log(` ${result.versionsURL}`)
180
+ } else if (result.gameURL) {
181
+ console.log(` Uploaded — live now for your team at:`)
182
+ console.log(` ${result.gameURL}`)
183
+ } else {
184
+ console.log(` Uploaded.`)
168
185
  }
169
186
  return {
170
187
  ok: true,
@@ -175,22 +192,57 @@ const uploadOneGame = async (game: DiscoveredGame, opts: UploadOneOptions): Prom
175
192
  versionID: result.versionID,
176
193
  assetsBase: result.assetsBase,
177
194
  integrationsChanged: result.integrationsChanged,
195
+ gameURL: result.gameURL,
178
196
  versionsURL: result.versionsURL,
179
197
  }
180
198
  }
181
199
 
182
- /** Prints a final summary of every game's outcome */
183
- const printReport = (results: GameResult[]) => {
184
- console.log(`\nUpload report (${results.length} game${results.length === 1 ? "" : "s"})`)
200
+ /** Prints the closing summary: failure count for all-fail, otherwise the puzzmonaut delivering the success line. */
201
+ const printSummary = (results: GameResult[], multi: boolean) => {
185
202
  const successes = results.filter((r): r is GameSuccess => r.ok)
186
203
  const failures = results.filter((r): r is GameFailure => !r.ok)
187
- for (const r of successes) {
188
- console.log(` OK ${r.slug.padEnd(24)} ${formatBytes(r.totalBytes).padStart(8)} ${r.source.padEnd(20)} ${r.versionID}`)
189
- }
190
- for (const r of failures) {
191
- console.log(` FAIL ${r.slug.padEnd(24)} ${r.error}`)
204
+
205
+ if (successes.length === 0) {
206
+ if (multi) console.log(`\n${plural(failures.length, "game")} failed.`)
207
+ return
192
208
  }
193
- console.log(`\n${successes.length} succeeded, ${failures.length} failed`)
209
+
210
+ const lines: string[] = []
211
+ if (multi && failures.length === 0) lines.push(`${plural(successes.length, "game")} uploaded!`)
212
+ else if (multi) lines.push(`${successes.length} of ${results.length} uploaded, ${failures.length} failed.`)
213
+ else lines.push("Uploaded!")
214
+
215
+ console.log("")
216
+ console.log(puzzmonautSays(lines))
217
+ }
218
+
219
+ const plural = (n: number, singular: string, pluralForm?: string): string => `${n} ${n === 1 ? singular : (pluralForm ?? `${singular}s`)}`
220
+
221
+ const isDefaultServer = (source: string): boolean => normalizeSource(source) === normalizeSource(defaultSource)
222
+
223
+ const yellow = (s: string): string => (process.stdout.isTTY ? `\x1b[33m${s}\x1b[0m` : s)
224
+ const blackOnYellow = (s: string): string => (process.stdout.isTTY ? `\x1b[30;43m${s}\x1b[0m` : s)
225
+
226
+ const puzzmonautLines = [
227
+ ` ${yellow("▟████▙")}`,
228
+ ` ${yellow("██")}${blackOnYellow("▝ ▘ ")} ${yellow("██")}`,
229
+ `${yellow(" ██")}${blackOnYellow(" ▄▖")}${yellow("██")}`,
230
+ ` ${yellow("▝▀▀▀▀▘")}`,
231
+ ]
232
+
233
+ const visualWidth = (s: string): number => s.replace(/\u001b\[[0-9;]*m/g, "").length
234
+
235
+ /** Renders the puzzmonaut with message lines vertically centered to its right. */
236
+ const puzzmonautSays = (messages: string[]): string => {
237
+ const iconWidth = Math.max(...puzzmonautLines.map(visualWidth))
238
+ const startRow = Math.max(0, Math.floor((puzzmonautLines.length - messages.length) / 2))
239
+ return puzzmonautLines
240
+ .map((line, i) => {
241
+ const pad = " ".repeat(iconWidth - visualWidth(line))
242
+ const msg = messages[i - startRow] ?? ""
243
+ return `${line}${pad} ${msg}`.trimEnd()
244
+ })
245
+ .join("\n")
194
246
  }
195
247
 
196
248
  /** Collects all files in a directory recursively */
@@ -285,7 +337,7 @@ const maybeCreateMissingGame = async (
285
337
 
286
338
  try {
287
339
  const created = await createUserGame({ apiURL: opts.apiURL, displayName, teamAccessToken: opts.teamAccessToken })
288
- console.log(` Created game ${created.slug} (${created.id})`)
340
+ console.log(` Created game ${created.slug}`)
289
341
  if (created.slug !== slug) {
290
342
  console.warn(` Server picked slug "${created.slug}" but your puzzmo.json uses "${slug}". Update puzzmo.json before re-uploading.`)
291
343
  return false
package/src/util/api.ts CHANGED
@@ -28,9 +28,23 @@ export class GameNotFoundError extends Error {
28
28
  }
29
29
  }
30
30
 
31
- type InitResponse = { sessionID: string; basePath: string; integrationsChanged?: boolean; versionsURL?: string; error?: string }
31
+ type InitResponse = {
32
+ sessionID: string
33
+ basePath: string
34
+ integrationsChanged?: boolean
35
+ gameURL?: string
36
+ versionsURL?: string
37
+ error?: string
38
+ }
32
39
  type FileResponse = { path: string; error?: string }
33
- type CompleteResponse = { assetsBase: string; versionID: string; integrationsChanged: boolean; versionsURL: string | null; error?: string }
40
+ type CompleteResponse = {
41
+ assetsBase: string
42
+ versionID: string
43
+ integrationsChanged: boolean
44
+ gameURL: string | null
45
+ versionsURL: string | null
46
+ error?: string
47
+ }
34
48
 
35
49
  /** Callback for reporting batch upload progress */
36
50
  export type UploadProgress = (batch: number, totalBatches: number, uploaded: number) => void
@@ -157,7 +171,6 @@ export const uploadFiles = async (
157
171
  if (e instanceof Error && e.message.includes("Game not found:")) throw new GameNotFoundError(gameSlug, e.message)
158
172
  throw e
159
173
  }
160
- if (verbose) console.log(` session: ${init.sessionID}`)
161
174
 
162
175
  // Step 2: Upload files in concurrent batches
163
176
  const fileURL = `${apiURL}/cliUpload/${init.sessionID}/file`
@@ -175,11 +188,12 @@ export const uploadFiles = async (
175
188
  // Step 3: Complete
176
189
  const complete = (await jsonPost(`${apiURL}/cliUpload/${init.sessionID}/complete`, token, {}, "upload complete", verbose)) as Omit<
177
190
  CompleteResponse,
178
- "integrationsChanged" | "versionsURL"
191
+ "integrationsChanged" | "gameURL" | "versionsURL"
179
192
  >
180
193
  return {
181
194
  ...complete,
182
195
  integrationsChanged: !!init.integrationsChanged,
196
+ gameURL: init.gameURL ?? null,
183
197
  versionsURL: init.versionsURL ?? null,
184
198
  }
185
199
  }
@@ -1,5 +1,5 @@
1
1
  {
2
- "$schema": "https://dev.puzzmo.com/schema/puzzmo-file-schema.json",
2
+ "$schema": "./node_modules/@puzzmo/cli/schemas/puzzmo-file-schema.json",
3
3
  "game": {
4
4
  "displayName": "__DISPLAY_NAME__",
5
5
  "slug": "__SLUG__",