@puzzmo/cli 1.0.30 → 1.0.32
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/README.md +4 -4
- package/lib/commands/upload.d.ts +1 -1
- package/lib/commands/upload.js +2 -1
- package/lib/commands/upload.js.map +1 -1
- package/lib/index.js +9 -6
- package/lib/index.js.map +1 -1
- package/lib/util/api.js +42 -15
- package/lib/util/api.js.map +1 -1
- package/package.json +1 -1
- package/src/commands/upload.ts +2 -1
- package/src/index.ts +9 -6
- package/src/util/api.ts +58 -21
package/README.md
CHANGED
|
@@ -18,15 +18,15 @@ Save a CLI auth token. Generate one from studio.puzzmo.com.
|
|
|
18
18
|
puzzmo login pzt-your-token-here
|
|
19
19
|
```
|
|
20
20
|
|
|
21
|
-
### `puzzmo upload <
|
|
21
|
+
### `puzzmo upload <dir>`
|
|
22
22
|
|
|
23
|
-
Upload a game build directory to Puzzmo.
|
|
23
|
+
Upload a game build directory to Puzzmo. The game slug is read from `puzzmo.json` in the build directory.
|
|
24
24
|
|
|
25
25
|
```bash
|
|
26
|
-
puzzmo upload
|
|
26
|
+
puzzmo upload dist/
|
|
27
27
|
```
|
|
28
28
|
|
|
29
|
-
The command collects all files in the directory, computes a SHA from git (or file contents), and uploads them in batches.
|
|
29
|
+
The command collects all files in the directory, validates the `puzzmo.json`, computes a SHA from git (or file contents), and uploads them in batches.
|
|
30
30
|
|
|
31
31
|
### `puzzmo game create [token]`
|
|
32
32
|
|
package/lib/commands/upload.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
/** Uploads game build artifacts to Puzzmo */
|
|
2
|
-
export declare const upload: (
|
|
2
|
+
export declare const upload: (dir: string) => Promise<void>;
|
package/lib/commands/upload.js
CHANGED
|
@@ -44,7 +44,7 @@ const formatBytes = (bytes) => {
|
|
|
44
44
|
return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
|
|
45
45
|
};
|
|
46
46
|
/** Uploads game build artifacts to Puzzmo */
|
|
47
|
-
export const upload = async (
|
|
47
|
+
export const upload = async (dir) => {
|
|
48
48
|
const token = getToken();
|
|
49
49
|
if (!token) {
|
|
50
50
|
console.error("Not logged in. Run `puzzmo login <token>` or set PUZZMO_TOKEN.");
|
|
@@ -83,6 +83,7 @@ export const upload = async (gameSlug, dir) => {
|
|
|
83
83
|
process.exit(1);
|
|
84
84
|
}
|
|
85
85
|
const puzzmoFile = validation.data;
|
|
86
|
+
const gameSlug = puzzmoFile.game.slug;
|
|
86
87
|
// Determine SHA
|
|
87
88
|
const sha = getGitSHA() || hashFiles(files);
|
|
88
89
|
console.log(`\nUploading ${gameSlug} (${sha.slice(0, 8)})`);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"upload.js","sourceRoot":"","sources":["../../src/commands/upload.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAA;AAC7C,OAAO,MAAM,MAAM,aAAa,CAAA;AAChC,OAAO,EAAE,MAAM,SAAS,CAAA;AACxB,OAAO,IAAI,MAAM,WAAW,CAAA;AAE5B,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAA;AAC5C,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAA;AACvD,OAAO,EAAE,kBAAkB,EAAE,MAAM,+BAA+B,CAAA;AAElE,oDAAoD;AACpD,MAAM,YAAY,GAAG,CAAC,GAAW,EAAY,EAAE,CAAC;IAC9C,MAAM,OAAO,GAAG,EAAE,CAAC,WAAW,CAAC,GAAG,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAA;IAC5D,MAAM,KAAK,GAAa,EAAE,CAAA;IAC1B,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;QAC5B,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,CAAC,CAAA;QACvC,IAAI,KAAK,CAAC,WAAW,EAAE;YAAE,KAAK,CAAC,IAAI,CAAC,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC,CAAA;;YACrD,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;IACvB,CAAC;IACD,OAAO,KAAK,CAAA;AAAA,CACb,CAAA;AAED,kFAAkF;AAClF,MAAM,SAAS,GAAG,GAAkB,EAAE,CAAC;IACrC,IAAI,CAAC;QACH,OAAO,QAAQ,CAAC,4BAA4B,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC,CAAC,IAAI,EAAE,CAAA;IAC7E,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAA;IACb,CAAC;AAAA,CACF,CAAA;AAED,8DAA8D;AAC9D,MAAM,SAAS,GAAG,CAAC,SAAmB,EAAU,EAAE,CAAC;IACjD,MAAM,IAAI,GAAG,MAAM,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAA;IACxC,KAAK,MAAM,EAAE,IAAI,SAAS,CAAC,IAAI,EAAE,EAAE,CAAC;QAClC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,YAAY,CAAC,EAAE,CAAC,CAAC,CAAA;IAClC,CAAC;IACD,OAAO,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAA;AAAA,CACvC,CAAA;AAED,sDAAsD;AACtD,MAAM,WAAW,GAAG,CAAC,KAAa,EAAU,EAAE,CAAC;IAC7C,IAAI,KAAK,GAAG,IAAI;QAAE,OAAO,GAAG,KAAK,IAAI,CAAA;IACrC,IAAI,KAAK,GAAG,IAAI,GAAG,IAAI;QAAE,OAAO,GAAG,CAAC,KAAK,GAAG,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAA;IACjE,OAAO,GAAG,CAAC,KAAK,GAAG,CAAC,IAAI,GAAG,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAA;AAAA,CAClD,CAAA;AAED,6CAA6C;AAC7C,MAAM,CAAC,MAAM,MAAM,GAAG,KAAK,EAAE,
|
|
1
|
+
{"version":3,"file":"upload.js","sourceRoot":"","sources":["../../src/commands/upload.ts"],"names":[],"mappings":"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"}
|
package/lib/index.js
CHANGED
|
@@ -10,7 +10,7 @@ const printUsage = () => {
|
|
|
10
10
|
puzzmo login <token> Save a CLI auth token
|
|
11
11
|
puzzmo game create [token] Create a new Puzzmo game project
|
|
12
12
|
|
|
13
|
-
puzzmo upload <
|
|
13
|
+
puzzmo upload <dir> Upload game build from <dir> (slug from puzzmo.json)
|
|
14
14
|
puzzmo validate [dir] Validate puzzmo.json in a directory (default: .)
|
|
15
15
|
puzzmo migrate List and select migration skills from dev.puzzmo.com`);
|
|
16
16
|
};
|
|
@@ -26,13 +26,12 @@ const run = async () => {
|
|
|
26
26
|
break;
|
|
27
27
|
}
|
|
28
28
|
case "upload": {
|
|
29
|
-
const
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
console.error("Usage: puzzmo upload <gameSlug> <dir>");
|
|
29
|
+
const dir = args[0];
|
|
30
|
+
if (!dir) {
|
|
31
|
+
console.error("Usage: puzzmo upload <dir>");
|
|
33
32
|
process.exit(1);
|
|
34
33
|
}
|
|
35
|
-
await upload(
|
|
34
|
+
await upload(dir);
|
|
36
35
|
break;
|
|
37
36
|
}
|
|
38
37
|
case "game": {
|
|
@@ -61,6 +60,10 @@ const run = async () => {
|
|
|
61
60
|
};
|
|
62
61
|
run().catch((err) => {
|
|
63
62
|
console.error(err.message || err);
|
|
63
|
+
if (err && err.cause) {
|
|
64
|
+
const cause = err.cause;
|
|
65
|
+
console.error(`Caused by: ${cause instanceof Error ? cause.message : cause}`);
|
|
66
|
+
}
|
|
64
67
|
process.exit(1);
|
|
65
68
|
});
|
|
66
69
|
//# sourceMappingURL=index.js.map
|
package/lib/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAA;AAC3C,OAAO,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAA;AAC7C,OAAO,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAA;AACjD,OAAO,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAA;AACtD,OAAO,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAA;AAE/C,MAAM,CAAC,OAAO,EAAE,GAAG,IAAI,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAA;AAEhD,MAAM,UAAU,GAAG,GAAG,EAAE,CAAC;IACvB,OAAO,CAAC,GAAG,CAAC;;;;;;uFAMyE,CAAC,CAAA;AAAA,CACvF,CAAA;AAED,MAAM,GAAG,GAAG,KAAK,IAAI,EAAE,CAAC;IACtB,QAAQ,OAAO,EAAE,CAAC;QAChB,KAAK,OAAO,EAAE,CAAC;YACb,MAAM,KAAK,GAAG,IAAI,CAAC,CAAC,CAAC,CAAA;YACrB,IAAI,CAAC,KAAK,EAAE,CAAC;gBACX,OAAO,CAAC,KAAK,CAAC,6BAA6B,CAAC,CAAA;gBAC5C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;YACjB,CAAC;YACD,KAAK,CAAC,KAAK,CAAC,CAAA;YACZ,MAAK;QACP,CAAC;QACD,KAAK,QAAQ,EAAE,CAAC;YACd,MAAM,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAA;AAC3C,OAAO,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAA;AAC7C,OAAO,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAA;AACjD,OAAO,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAA;AACtD,OAAO,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAA;AAE/C,MAAM,CAAC,OAAO,EAAE,GAAG,IAAI,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAA;AAEhD,MAAM,UAAU,GAAG,GAAG,EAAE,CAAC;IACvB,OAAO,CAAC,GAAG,CAAC;;;;;;uFAMyE,CAAC,CAAA;AAAA,CACvF,CAAA;AAED,MAAM,GAAG,GAAG,KAAK,IAAI,EAAE,CAAC;IACtB,QAAQ,OAAO,EAAE,CAAC;QAChB,KAAK,OAAO,EAAE,CAAC;YACb,MAAM,KAAK,GAAG,IAAI,CAAC,CAAC,CAAC,CAAA;YACrB,IAAI,CAAC,KAAK,EAAE,CAAC;gBACX,OAAO,CAAC,KAAK,CAAC,6BAA6B,CAAC,CAAA;gBAC5C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;YACjB,CAAC;YACD,KAAK,CAAC,KAAK,CAAC,CAAA;YACZ,MAAK;QACP,CAAC;QACD,KAAK,QAAQ,EAAE,CAAC;YACd,MAAM,GAAG,GAAG,IAAI,CAAC,CAAC,CAAC,CAAA;YACnB,IAAI,CAAC,GAAG,EAAE,CAAC;gBACT,OAAO,CAAC,KAAK,CAAC,4BAA4B,CAAC,CAAA;gBAC3C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;YACjB,CAAC;YACD,MAAM,MAAM,CAAC,GAAG,CAAC,CAAA;YACjB,MAAK;QACP,CAAC;QACD,KAAK,MAAM,EAAE,CAAC;YACZ,MAAM,CAAC,UAAU,EAAE,GAAG,OAAO,CAAC,GAAG,IAAI,CAAA;YACrC,IAAI,UAAU,KAAK,QAAQ,EAAE,CAAC;gBAC5B,MAAM,UAAU,CAAC,OAAO,CAAC,CAAA;YAC3B,CAAC;iBAAM,CAAC;gBACN,OAAO,CAAC,KAAK,CAAC,0GAA0G,CAAC,CAAA;gBACzH,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;YACjB,CAAC;YACD,MAAK;QACP,CAAC;QACD,KAAK,UAAU,EAAE,CAAC;YAChB,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,CAAA;YACxB,MAAK;QACP,CAAC;QACD,KAAK,SAAS,EAAE,CAAC;YACf,MAAM,OAAO,EAAE,CAAA;YACf,MAAK;QACP,CAAC;QACD;YACE,UAAU,EAAE,CAAA;YACZ,MAAK;IACT,CAAC;AAAA,CACF,CAAA;AAED,GAAG,EAAE,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC;IACnB,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,IAAI,GAAG,CAAC,CAAA;IACjC,IAAI,GAAG,IAAI,GAAG,CAAC,KAAK,EAAE,CAAC;QACrB,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,CAAA;QACvB,OAAO,CAAC,KAAK,CAAC,cAAc,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,EAAE,CAAC,CAAA;IAC/E,CAAC;IACD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;AAAA,CAChB,CAAC,CAAA"}
|
package/lib/util/api.js
CHANGED
|
@@ -2,40 +2,67 @@ import fs from "node:fs";
|
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
import { getAPIURL } from "./config.js";
|
|
4
4
|
const BATCH_SIZE = 10;
|
|
5
|
+
/** Wraps fetch to surface the underlying network cause (DNS, ECONNREFUSED, TLS, etc.) */
|
|
6
|
+
const fetchWithContext = async (url, init, step) => {
|
|
7
|
+
try {
|
|
8
|
+
return await fetch(url, init);
|
|
9
|
+
}
|
|
10
|
+
catch (e) {
|
|
11
|
+
const cause = e.cause;
|
|
12
|
+
const causeMsg = cause instanceof Error ? cause.message : cause ? String(cause) : e.message;
|
|
13
|
+
throw new Error(`Network error during ${step} (${url}): ${causeMsg}`);
|
|
14
|
+
}
|
|
15
|
+
};
|
|
16
|
+
/** Reads a response body, parsing JSON when possible and including status + body in errors */
|
|
17
|
+
const readResponse = async (res, url, step) => {
|
|
18
|
+
const text = await res.text();
|
|
19
|
+
let json;
|
|
20
|
+
try {
|
|
21
|
+
json = text ? JSON.parse(text) : {};
|
|
22
|
+
}
|
|
23
|
+
catch {
|
|
24
|
+
if (!res.ok) {
|
|
25
|
+
const snippet = text.slice(0, 200).replace(/\s+/g, " ").trim();
|
|
26
|
+
throw new Error(`Server error during ${step} (${res.status} ${res.statusText} from ${url}): ${snippet || "no body"}`);
|
|
27
|
+
}
|
|
28
|
+
throw new Error(`Invalid JSON response during ${step} (${url}): ${text.slice(0, 200)}`);
|
|
29
|
+
}
|
|
30
|
+
if (!res.ok) {
|
|
31
|
+
const serverMsg = json.error || res.statusText || "Unknown error";
|
|
32
|
+
throw new Error(`Server error during ${step} (${res.status} from ${url}): ${serverMsg}`);
|
|
33
|
+
}
|
|
34
|
+
return json;
|
|
35
|
+
};
|
|
5
36
|
/** Sends a JSON POST request */
|
|
6
|
-
const jsonPost = async (url, token, body) => {
|
|
7
|
-
const res = await
|
|
37
|
+
const jsonPost = async (url, token, body, step) => {
|
|
38
|
+
const res = await fetchWithContext(url, {
|
|
8
39
|
method: "POST",
|
|
9
40
|
headers: { Authorization: `Bearer ${token}`, "Content-Type": "application/json" },
|
|
10
41
|
body: JSON.stringify(body),
|
|
11
|
-
});
|
|
12
|
-
|
|
13
|
-
if (!res.ok)
|
|
14
|
-
throw new Error(`Server error (${res.status}): ${json.error || "Unknown error"}`);
|
|
15
|
-
return json;
|
|
42
|
+
}, step);
|
|
43
|
+
return readResponse(res, url, step);
|
|
16
44
|
};
|
|
17
45
|
/** Uploads a single file as raw binary with filename in query param */
|
|
18
46
|
const uploadFile = async (url, token, filePath, baseDir) => {
|
|
19
47
|
const relativePath = path.relative(baseDir, filePath);
|
|
20
48
|
const content = fs.readFileSync(filePath);
|
|
21
|
-
const
|
|
49
|
+
const step = `file upload (${relativePath})`;
|
|
50
|
+
const fullURL = `${url}?name=${encodeURIComponent(relativePath)}`;
|
|
51
|
+
const res = await fetchWithContext(fullURL, {
|
|
22
52
|
method: "POST",
|
|
23
53
|
headers: {
|
|
24
54
|
Authorization: `Bearer ${token}`,
|
|
25
55
|
"Content-Type": "application/octet-stream",
|
|
26
56
|
},
|
|
27
57
|
body: content,
|
|
28
|
-
});
|
|
29
|
-
|
|
30
|
-
if (!res.ok)
|
|
31
|
-
throw new Error(`Server error (${res.status}): ${json.error || "Unknown error"}`);
|
|
32
|
-
return json;
|
|
58
|
+
}, step);
|
|
59
|
+
return (await readResponse(res, fullURL, step));
|
|
33
60
|
};
|
|
34
61
|
/** Multi-step upload: init -> batched file uploads -> complete */
|
|
35
62
|
export const uploadFiles = async (token, gameSlug, sha, filePaths, baseDir, puzzmoFile, onProgress) => {
|
|
36
63
|
const apiURL = getAPIURL();
|
|
37
64
|
// Step 1: Init session (includes puzzmo.json metadata)
|
|
38
|
-
const init = (await jsonPost(`${apiURL}/cliUpload`, token, { gameSlug, sha, puzzmoFile }));
|
|
65
|
+
const init = (await jsonPost(`${apiURL}/cliUpload`, token, { gameSlug, sha, puzzmoFile }, "upload init"));
|
|
39
66
|
// Step 2: Upload files in concurrent batches
|
|
40
67
|
const fileURL = `${apiURL}/cliUpload/${init.sessionID}/file`;
|
|
41
68
|
const totalBatches = Math.ceil(filePaths.length / BATCH_SIZE);
|
|
@@ -48,6 +75,6 @@ export const uploadFiles = async (token, gameSlug, sha, filePaths, baseDir, puzz
|
|
|
48
75
|
onProgress?.(batchNum, totalBatches, totalUploaded);
|
|
49
76
|
}
|
|
50
77
|
// Step 3: Complete
|
|
51
|
-
return (await jsonPost(`${apiURL}/cliUpload/${init.sessionID}/complete`, token, {}));
|
|
78
|
+
return (await jsonPost(`${apiURL}/cliUpload/${init.sessionID}/complete`, token, {}, "upload complete"));
|
|
52
79
|
};
|
|
53
80
|
//# sourceMappingURL=api.js.map
|
package/lib/util/api.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"api.js","sourceRoot":"","sources":["../../src/util/api.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAA;AACxB,OAAO,IAAI,MAAM,WAAW,CAAA;AAE5B,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;AAYvC,MAAM,UAAU,GAAG,EAAE,CAAA;AASrB,
|
|
1
|
+
{"version":3,"file":"api.js","sourceRoot":"","sources":["../../src/util/api.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
package/src/commands/upload.ts
CHANGED
|
@@ -45,7 +45,7 @@ const formatBytes = (bytes: number): string => {
|
|
|
45
45
|
}
|
|
46
46
|
|
|
47
47
|
/** Uploads game build artifacts to Puzzmo */
|
|
48
|
-
export const upload = async (
|
|
48
|
+
export const upload = async (dir: string) => {
|
|
49
49
|
const token = getToken()
|
|
50
50
|
if (!token) {
|
|
51
51
|
console.error("Not logged in. Run `puzzmo login <token>` or set PUZZMO_TOKEN.")
|
|
@@ -87,6 +87,7 @@ export const upload = async (gameSlug: string, dir: string) => {
|
|
|
87
87
|
process.exit(1)
|
|
88
88
|
}
|
|
89
89
|
const puzzmoFile = validation.data
|
|
90
|
+
const gameSlug = puzzmoFile.game.slug
|
|
90
91
|
|
|
91
92
|
// Determine SHA
|
|
92
93
|
const sha = getGitSHA() || hashFiles(files)
|
package/src/index.ts
CHANGED
|
@@ -13,7 +13,7 @@ const printUsage = () => {
|
|
|
13
13
|
puzzmo login <token> Save a CLI auth token
|
|
14
14
|
puzzmo game create [token] Create a new Puzzmo game project
|
|
15
15
|
|
|
16
|
-
puzzmo upload <
|
|
16
|
+
puzzmo upload <dir> Upload game build from <dir> (slug from puzzmo.json)
|
|
17
17
|
puzzmo validate [dir] Validate puzzmo.json in a directory (default: .)
|
|
18
18
|
puzzmo migrate List and select migration skills from dev.puzzmo.com`)
|
|
19
19
|
}
|
|
@@ -30,13 +30,12 @@ const run = async () => {
|
|
|
30
30
|
break
|
|
31
31
|
}
|
|
32
32
|
case "upload": {
|
|
33
|
-
const
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
console.error("Usage: puzzmo upload <gameSlug> <dir>")
|
|
33
|
+
const dir = args[0]
|
|
34
|
+
if (!dir) {
|
|
35
|
+
console.error("Usage: puzzmo upload <dir>")
|
|
37
36
|
process.exit(1)
|
|
38
37
|
}
|
|
39
|
-
await upload(
|
|
38
|
+
await upload(dir)
|
|
40
39
|
break
|
|
41
40
|
}
|
|
42
41
|
case "game": {
|
|
@@ -65,5 +64,9 @@ const run = async () => {
|
|
|
65
64
|
|
|
66
65
|
run().catch((err) => {
|
|
67
66
|
console.error(err.message || err)
|
|
67
|
+
if (err && err.cause) {
|
|
68
|
+
const cause = err.cause
|
|
69
|
+
console.error(`Caused by: ${cause instanceof Error ? cause.message : cause}`)
|
|
70
|
+
}
|
|
68
71
|
process.exit(1)
|
|
69
72
|
})
|
package/src/util/api.ts
CHANGED
|
@@ -22,34 +22,71 @@ type CompleteResponse = { assetsBase: string; versionID: string; error?: string
|
|
|
22
22
|
/** Callback for reporting batch upload progress */
|
|
23
23
|
export type UploadProgress = (batch: number, totalBatches: number, uploaded: number) => void
|
|
24
24
|
|
|
25
|
-
/**
|
|
26
|
-
const
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
25
|
+
/** Wraps fetch to surface the underlying network cause (DNS, ECONNREFUSED, TLS, etc.) */
|
|
26
|
+
const fetchWithContext = async (url: string, init: RequestInit, step: string): Promise<Response> => {
|
|
27
|
+
try {
|
|
28
|
+
return await fetch(url, init)
|
|
29
|
+
} catch (e) {
|
|
30
|
+
const cause = (e as { cause?: unknown }).cause
|
|
31
|
+
const causeMsg = cause instanceof Error ? cause.message : cause ? String(cause) : (e as Error).message
|
|
32
|
+
throw new Error(`Network error during ${step} (${url}): ${causeMsg}`)
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/** Reads a response body, parsing JSON when possible and including status + body in errors */
|
|
37
|
+
const readResponse = async (res: Response, url: string, step: string) => {
|
|
38
|
+
const text = await res.text()
|
|
39
|
+
let json: unknown
|
|
40
|
+
try {
|
|
41
|
+
json = text ? JSON.parse(text) : {}
|
|
42
|
+
} catch {
|
|
43
|
+
if (!res.ok) {
|
|
44
|
+
const snippet = text.slice(0, 200).replace(/\s+/g, " ").trim()
|
|
45
|
+
throw new Error(`Server error during ${step} (${res.status} ${res.statusText} from ${url}): ${snippet || "no body"}`)
|
|
46
|
+
}
|
|
47
|
+
throw new Error(`Invalid JSON response during ${step} (${url}): ${text.slice(0, 200)}`)
|
|
48
|
+
}
|
|
49
|
+
if (!res.ok) {
|
|
50
|
+
const serverMsg = (json as { error?: string }).error || res.statusText || "Unknown error"
|
|
51
|
+
throw new Error(`Server error during ${step} (${res.status} from ${url}): ${serverMsg}`)
|
|
52
|
+
}
|
|
34
53
|
return json
|
|
35
54
|
}
|
|
36
55
|
|
|
56
|
+
/** Sends a JSON POST request */
|
|
57
|
+
const jsonPost = async (url: string, token: string, body: object, step: string) => {
|
|
58
|
+
const res = await fetchWithContext(
|
|
59
|
+
url,
|
|
60
|
+
{
|
|
61
|
+
method: "POST",
|
|
62
|
+
headers: { Authorization: `Bearer ${token}`, "Content-Type": "application/json" },
|
|
63
|
+
body: JSON.stringify(body),
|
|
64
|
+
},
|
|
65
|
+
step,
|
|
66
|
+
)
|
|
67
|
+
return readResponse(res, url, step)
|
|
68
|
+
}
|
|
69
|
+
|
|
37
70
|
/** Uploads a single file as raw binary with filename in query param */
|
|
38
71
|
const uploadFile = async (url: string, token: string, filePath: string, baseDir: string): Promise<FileResponse> => {
|
|
39
72
|
const relativePath = path.relative(baseDir, filePath)
|
|
40
73
|
const content = fs.readFileSync(filePath)
|
|
74
|
+
const step = `file upload (${relativePath})`
|
|
41
75
|
|
|
42
|
-
const
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
76
|
+
const fullURL = `${url}?name=${encodeURIComponent(relativePath)}`
|
|
77
|
+
const res = await fetchWithContext(
|
|
78
|
+
fullURL,
|
|
79
|
+
{
|
|
80
|
+
method: "POST",
|
|
81
|
+
headers: {
|
|
82
|
+
Authorization: `Bearer ${token}`,
|
|
83
|
+
"Content-Type": "application/octet-stream",
|
|
84
|
+
},
|
|
85
|
+
body: content,
|
|
47
86
|
},
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
if (!res.ok) throw new Error(`Server error (${res.status}): ${(json as any).error || "Unknown error"}`)
|
|
52
|
-
return json as FileResponse
|
|
87
|
+
step,
|
|
88
|
+
)
|
|
89
|
+
return (await readResponse(res, fullURL, step)) as FileResponse
|
|
53
90
|
}
|
|
54
91
|
|
|
55
92
|
/** Multi-step upload: init -> batched file uploads -> complete */
|
|
@@ -65,7 +102,7 @@ export const uploadFiles = async (
|
|
|
65
102
|
const apiURL = getAPIURL()
|
|
66
103
|
|
|
67
104
|
// Step 1: Init session (includes puzzmo.json metadata)
|
|
68
|
-
const init = (await jsonPost(`${apiURL}/cliUpload`, token, { gameSlug, sha, puzzmoFile })) as InitResponse
|
|
105
|
+
const init = (await jsonPost(`${apiURL}/cliUpload`, token, { gameSlug, sha, puzzmoFile }, "upload init")) as InitResponse
|
|
69
106
|
|
|
70
107
|
// Step 2: Upload files in concurrent batches
|
|
71
108
|
const fileURL = `${apiURL}/cliUpload/${init.sessionID}/file`
|
|
@@ -81,5 +118,5 @@ export const uploadFiles = async (
|
|
|
81
118
|
}
|
|
82
119
|
|
|
83
120
|
// Step 3: Complete
|
|
84
|
-
return (await jsonPost(`${apiURL}/cliUpload/${init.sessionID}/complete`, token, {})) as CompleteResponse
|
|
121
|
+
return (await jsonPost(`${apiURL}/cliUpload/${init.sessionID}/complete`, token, {}, "upload complete")) as CompleteResponse
|
|
85
122
|
}
|