arcadible 0.1.43 → 0.1.44
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/bin/arc-build.js +20 -5
- package/bin/arc-deploy.js +25 -12
- package/bin/arc-pack.js +10 -5
- package/package.json +1 -1
- package/src/action/login/flow.js +5 -2
- package/src/action/pack/tool.js +20 -6
- package/src/action/predeploy/git.js +22 -5
- package/src/action/predeploy/tool-git.js +1 -0
- package/src/action/validate/unknown.js +2 -2
- package/src/config/code.js +25 -10
- package/src/phrase.js +26 -7
- package/src/util/error.js +5 -4
- package/src/util/output.js +22 -9
- package/src/util/request.js +2 -2
- package/src/util/s3.js +2 -2
package/bin/arc-build.js
CHANGED
|
@@ -36,6 +36,7 @@ const relative = path.relative;
|
|
|
36
36
|
const resolve = path.resolve;
|
|
37
37
|
const SpinnerWheel = spinner.SpinnerWheel;
|
|
38
38
|
const warn = output.warn;
|
|
39
|
+
const warning = output.warning;
|
|
39
40
|
|
|
40
41
|
// [declare]
|
|
41
42
|
|
|
@@ -59,6 +60,8 @@ const start = function (argv) {
|
|
|
59
60
|
const root = resolve(process.cwd(), argv.cwd);
|
|
60
61
|
// the project, parsed once for both steps.
|
|
61
62
|
let parsed = null;
|
|
63
|
+
// what --json lists under `warnings`.
|
|
64
|
+
let warnings = [];
|
|
62
65
|
let sw = new SpinnerWheel("Validating... %s");
|
|
63
66
|
sw.start(json || quiet);
|
|
64
67
|
return project(root)
|
|
@@ -66,13 +69,14 @@ const start = function (argv) {
|
|
|
66
69
|
parsed = proj;
|
|
67
70
|
return validate({ project: parsed, root });
|
|
68
71
|
})
|
|
69
|
-
.then((
|
|
70
|
-
const count = issues.length;
|
|
72
|
+
.then((validated) => {
|
|
73
|
+
const count = validated.issues.length;
|
|
74
|
+
warnings = validated.warnings;
|
|
71
75
|
if (count) {
|
|
72
76
|
throw new ArcError(
|
|
73
77
|
cfgcode.VALIDATION_FAILED,
|
|
74
78
|
phrase.issuesFound(count),
|
|
75
|
-
{ data: { issues } },
|
|
79
|
+
{ data: { issues: validated.issues } },
|
|
76
80
|
);
|
|
77
81
|
}
|
|
78
82
|
sw.stop(true);
|
|
@@ -83,7 +87,16 @@ const start = function (argv) {
|
|
|
83
87
|
})
|
|
84
88
|
.then((artifact) => {
|
|
85
89
|
if (json) {
|
|
86
|
-
|
|
90
|
+
const missing = artifact?.missing
|
|
91
|
+
? [
|
|
92
|
+
warning(
|
|
93
|
+
cfgcode.WARNING.DEPLOY_DIR_NOT_BUILT,
|
|
94
|
+
phrase.buildOutputMissing(relative(root, artifact.missing)),
|
|
95
|
+
"workflow.deploy_dir",
|
|
96
|
+
),
|
|
97
|
+
]
|
|
98
|
+
: [];
|
|
99
|
+
print({ artifact, warnings: [...warnings, ...missing] });
|
|
87
100
|
return;
|
|
88
101
|
}
|
|
89
102
|
if (!quiet) {
|
|
@@ -103,7 +116,9 @@ const start = function (argv) {
|
|
|
103
116
|
log.hs("Nothing to do.");
|
|
104
117
|
}
|
|
105
118
|
})
|
|
106
|
-
.catch((ex) =>
|
|
119
|
+
.catch((ex) =>
|
|
120
|
+
abort("Build aborted.", ex, { data: { warnings }, json, sw }),
|
|
121
|
+
);
|
|
107
122
|
};
|
|
108
123
|
|
|
109
124
|
// [function]
|
package/bin/arc-deploy.js
CHANGED
|
@@ -42,6 +42,7 @@ const ProgressBar = progress.ProgressBar;
|
|
|
42
42
|
const resolve = path.resolve;
|
|
43
43
|
const SpinnerWheel = spinner.SpinnerWheel;
|
|
44
44
|
const warn = output.warn;
|
|
45
|
+
const warning = output.warning;
|
|
45
46
|
|
|
46
47
|
// [declare]
|
|
47
48
|
|
|
@@ -65,7 +66,9 @@ const conf = {
|
|
|
65
66
|
|
|
66
67
|
// [function]
|
|
67
68
|
|
|
68
|
-
|
|
69
|
+
// `warnings` collects what --json lists, such as a version that couldn't be
|
|
70
|
+
// checked.
|
|
71
|
+
const handler = function ({ json, pb, quiet, sw, warnings }) {
|
|
69
72
|
return {
|
|
70
73
|
onAccountRefresh(refresh) {
|
|
71
74
|
sw.start(json || quiet);
|
|
@@ -76,7 +79,10 @@ const handler = function ({ json, pb, quiet, sw }) {
|
|
|
76
79
|
pb.start();
|
|
77
80
|
}
|
|
78
81
|
},
|
|
79
|
-
onLogInfo({ level, message }) {
|
|
82
|
+
onLogInfo({ code, level, message }) {
|
|
83
|
+
if (code) {
|
|
84
|
+
warnings.push(warning(code, message));
|
|
85
|
+
}
|
|
80
86
|
if (!json && !quiet) {
|
|
81
87
|
switch (level) {
|
|
82
88
|
case "warn":
|
|
@@ -253,6 +259,8 @@ const start = function (argv) {
|
|
|
253
259
|
// the project, parsed once and given to each step. A build can write files
|
|
254
260
|
// the manifest reads, such as art, so it's parsed again after one runs.
|
|
255
261
|
let parsed = null;
|
|
262
|
+
// what --json lists under `warnings`: arc validate's, then the deploy's.
|
|
263
|
+
const warnings = [];
|
|
256
264
|
let sw = new SpinnerWheel("Validating... %s");
|
|
257
265
|
sw.start(json || quiet);
|
|
258
266
|
return checkTimeout(timeout)
|
|
@@ -261,26 +269,29 @@ const start = function (argv) {
|
|
|
261
269
|
parsed = proj;
|
|
262
270
|
return validate({ project: parsed, root });
|
|
263
271
|
})
|
|
264
|
-
.then((
|
|
265
|
-
const count = issues.length;
|
|
272
|
+
.then((validated) => {
|
|
273
|
+
const count = validated.issues.length;
|
|
274
|
+
warnings.push(...validated.warnings);
|
|
266
275
|
if (count) {
|
|
267
276
|
throw new ArcError(
|
|
268
277
|
cfgcode.VALIDATION_FAILED,
|
|
269
278
|
phrase.issuesFound(count),
|
|
270
|
-
{ data: { issues } },
|
|
279
|
+
{ data: { issues: validated.issues } },
|
|
271
280
|
);
|
|
272
281
|
}
|
|
273
282
|
sw.stop(true);
|
|
274
|
-
warn(warnings, { json, quiet });
|
|
283
|
+
warn(validated.warnings, { json, quiet });
|
|
275
284
|
sw = new SpinnerWheel("Checking... %s");
|
|
276
285
|
// git deploys need no login: anyone who can push to the repository can
|
|
277
286
|
// release, and the Arcadible GitHub App publishes the release. Anyone
|
|
278
287
|
// can wait for it too; the game's owner, logged in, waits among their
|
|
279
288
|
// own releases, which also say when the repository isn't connected.
|
|
280
289
|
if (git) {
|
|
281
|
-
return whoamiIfAny({
|
|
290
|
+
return whoamiIfAny({
|
|
291
|
+
handler: handler({ json, pb, quiet, sw, warnings }),
|
|
292
|
+
});
|
|
282
293
|
}
|
|
283
|
-
return whoami({ handler: handler({ json, pb, quiet, sw }) });
|
|
294
|
+
return whoami({ handler: handler({ json, pb, quiet, sw, warnings }) });
|
|
284
295
|
})
|
|
285
296
|
.then((current) => {
|
|
286
297
|
if (!current && !git) {
|
|
@@ -295,7 +306,7 @@ const start = function (argv) {
|
|
|
295
306
|
predeploy({
|
|
296
307
|
current,
|
|
297
308
|
git,
|
|
298
|
-
handler: handler({ json, pb, quiet, sw }),
|
|
309
|
+
handler: handler({ json, pb, quiet, sw, warnings }),
|
|
299
310
|
project: parsed,
|
|
300
311
|
root,
|
|
301
312
|
}),
|
|
@@ -359,7 +370,7 @@ const start = function (argv) {
|
|
|
359
370
|
artifact,
|
|
360
371
|
current,
|
|
361
372
|
git,
|
|
362
|
-
handler: handler({ json, pb, quiet, sw }),
|
|
373
|
+
handler: handler({ json, pb, quiet, sw, warnings }),
|
|
363
374
|
project: parsed,
|
|
364
375
|
root,
|
|
365
376
|
}),
|
|
@@ -376,7 +387,7 @@ const start = function (argv) {
|
|
|
376
387
|
const shown = { ...deployed };
|
|
377
388
|
delete shown.game;
|
|
378
389
|
delete shown.release;
|
|
379
|
-
const result = git ? shown : { built, ...shown };
|
|
390
|
+
const result = { ...(git ? shown : { built, ...shown }), warnings };
|
|
380
391
|
sw.stop(true);
|
|
381
392
|
if (argv.wait) {
|
|
382
393
|
return waitAndReport(current, deployed, result, {
|
|
@@ -396,7 +407,9 @@ const start = function (argv) {
|
|
|
396
407
|
}
|
|
397
408
|
return null;
|
|
398
409
|
})
|
|
399
|
-
.catch((ex) =>
|
|
410
|
+
.catch((ex) =>
|
|
411
|
+
abort("Deploy aborted.", ex, { data: { warnings }, json, pb, sw }),
|
|
412
|
+
);
|
|
400
413
|
};
|
|
401
414
|
|
|
402
415
|
// [function]
|
package/bin/arc-pack.js
CHANGED
|
@@ -60,6 +60,8 @@ const start = function (argv) {
|
|
|
60
60
|
const root = resolve(process.cwd(), argv.cwd);
|
|
61
61
|
// the project, parsed once for both steps.
|
|
62
62
|
let parsed = null;
|
|
63
|
+
// what --json lists under `warnings`.
|
|
64
|
+
let warnings = [];
|
|
63
65
|
let sw = new SpinnerWheel("Validating... %s");
|
|
64
66
|
sw.start(json || quiet);
|
|
65
67
|
return project(root)
|
|
@@ -67,13 +69,14 @@ const start = function (argv) {
|
|
|
67
69
|
parsed = proj;
|
|
68
70
|
return validate({ project: parsed, root });
|
|
69
71
|
})
|
|
70
|
-
.then((
|
|
71
|
-
const count = issues.length;
|
|
72
|
+
.then((validated) => {
|
|
73
|
+
const count = validated.issues.length;
|
|
74
|
+
warnings = validated.warnings;
|
|
72
75
|
if (count) {
|
|
73
76
|
throw new ArcError(
|
|
74
77
|
cfgcode.VALIDATION_FAILED,
|
|
75
78
|
phrase.issuesFound(count),
|
|
76
|
-
{ data: { issues } },
|
|
79
|
+
{ data: { issues: validated.issues } },
|
|
77
80
|
);
|
|
78
81
|
}
|
|
79
82
|
sw.stop(true);
|
|
@@ -89,7 +92,7 @@ const start = function (argv) {
|
|
|
89
92
|
})
|
|
90
93
|
.then((artifact) => {
|
|
91
94
|
if (json) {
|
|
92
|
-
print({ artifact });
|
|
95
|
+
print({ artifact, warnings });
|
|
93
96
|
return;
|
|
94
97
|
}
|
|
95
98
|
if (!quiet) {
|
|
@@ -98,7 +101,9 @@ const start = function (argv) {
|
|
|
98
101
|
print(artifact, { nl: true, toml: true });
|
|
99
102
|
}
|
|
100
103
|
})
|
|
101
|
-
.catch((ex) =>
|
|
104
|
+
.catch((ex) =>
|
|
105
|
+
abort("Pack aborted.", ex, { data: { warnings }, json, sw }),
|
|
106
|
+
);
|
|
102
107
|
};
|
|
103
108
|
|
|
104
109
|
// [function]
|
package/package.json
CHANGED
package/src/action/login/flow.js
CHANGED
|
@@ -28,7 +28,7 @@ const POLL = {
|
|
|
28
28
|
interval: time.s(15),
|
|
29
29
|
maxDelay: time.s(5),
|
|
30
30
|
timeoutError: () =>
|
|
31
|
-
new ArcError(cfgcode.
|
|
31
|
+
new ArcError(cfgcode.LOGIN_CODE_EXPIRED, phrase.loginCodeExpired()),
|
|
32
32
|
};
|
|
33
33
|
|
|
34
34
|
// [function]
|
|
@@ -73,7 +73,10 @@ const pollFlow = function (value, onLoginPoll) {
|
|
|
73
73
|
case "failed":
|
|
74
74
|
throw new ArcError(cfgcode.LOGIN_FAILED, phrase.loginFailed());
|
|
75
75
|
default:
|
|
76
|
-
throw new ArcError(
|
|
76
|
+
throw new ArcError(
|
|
77
|
+
cfgcode.LOGIN_CODE_EXPIRED,
|
|
78
|
+
phrase.loginCodeExpired(),
|
|
79
|
+
);
|
|
77
80
|
}
|
|
78
81
|
});
|
|
79
82
|
};
|
package/src/action/pack/tool.js
CHANGED
|
@@ -69,15 +69,26 @@ const verifyTotal = function (zip) {
|
|
|
69
69
|
|
|
70
70
|
// [function]
|
|
71
71
|
|
|
72
|
-
|
|
72
|
+
// `deployDir` when the input is deploy_dir, rather than a folder --input
|
|
73
|
+
// named: a missing deploy_dir means the build hasn't written it.
|
|
74
|
+
const pack = function (
|
|
75
|
+
name,
|
|
76
|
+
game,
|
|
77
|
+
{ deployDir, inputPath, mediaPath, outputPath },
|
|
78
|
+
) {
|
|
73
79
|
const zip = new Zip(name);
|
|
74
80
|
return pathExists(inputPath)
|
|
75
81
|
.then((existsInput) => {
|
|
76
82
|
if (!existsInput) {
|
|
77
|
-
throw
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
83
|
+
throw deployDir
|
|
84
|
+
? new ArcError(
|
|
85
|
+
cfgcode.DEPLOY_DIR_MISSING,
|
|
86
|
+
phrase.deployDirMissing(inputPath),
|
|
87
|
+
)
|
|
88
|
+
: new ArcError(
|
|
89
|
+
cfgcode.PATH_NOT_FOUND,
|
|
90
|
+
phrase.unableToFind(inputPath),
|
|
91
|
+
);
|
|
81
92
|
}
|
|
82
93
|
zip.addDir(inputPath);
|
|
83
94
|
return zip;
|
|
@@ -105,8 +116,11 @@ const main = function ({ input, output, ...conf }) {
|
|
|
105
116
|
return given(conf).then(({ game, workflow }) => {
|
|
106
117
|
const name = game.handle ?? game.id;
|
|
107
118
|
const file = output ?? `${OUTPUT}/${name}-v${game.version}.zip`;
|
|
119
|
+
const deployDir = resolve(root, workflow.deploy_dir);
|
|
120
|
+
const inputPath = resolve(root, input ?? workflow.deploy_dir);
|
|
108
121
|
return pack(parse(file).name, game, {
|
|
109
|
-
|
|
122
|
+
deployDir: inputPath === deployDir,
|
|
123
|
+
inputPath,
|
|
110
124
|
mediaPath: resolve(root, MEDIA),
|
|
111
125
|
outputPath: resolve(root, file),
|
|
112
126
|
});
|
|
@@ -77,11 +77,28 @@ const ensureClean = function (root) {
|
|
|
77
77
|
|
|
78
78
|
// [function]
|
|
79
79
|
|
|
80
|
+
// fails with git_remote_missing when there's no origin, and with
|
|
81
|
+
// git_remote_unreachable when it's there but can't be reached.
|
|
80
82
|
const ensureRemote = function (root) {
|
|
81
|
-
return git(root, ["
|
|
82
|
-
(
|
|
83
|
-
|
|
84
|
-
|
|
83
|
+
return git(root, ["remote", "get-url", "origin"])
|
|
84
|
+
.then(
|
|
85
|
+
() => null,
|
|
86
|
+
failWith(cfgcode.GIT_REMOTE_MISSING, phrase.gitRemoteMissing()),
|
|
87
|
+
)
|
|
88
|
+
.then(() => git(root, ["ls-remote", "origin"]))
|
|
89
|
+
.then(
|
|
90
|
+
() => null,
|
|
91
|
+
// git_remote_missing passes through.
|
|
92
|
+
(err) => {
|
|
93
|
+
if (err instanceof ArcError) {
|
|
94
|
+
throw err;
|
|
95
|
+
}
|
|
96
|
+
failWith(
|
|
97
|
+
cfgcode.GIT_REMOTE_UNREACHABLE,
|
|
98
|
+
phrase.gitRemoteUnreachable(),
|
|
99
|
+
)(err);
|
|
100
|
+
},
|
|
101
|
+
);
|
|
85
102
|
};
|
|
86
103
|
|
|
87
104
|
// [function]
|
|
@@ -168,7 +185,7 @@ const hasTagLocal = function (root, tag) {
|
|
|
168
185
|
const hasTagRemote = function (root, tag) {
|
|
169
186
|
return git(root, ["ls-remote", "--tags", "origin", `refs/tags/${tag}`]).then(
|
|
170
187
|
(stdout) => Boolean(stdout.trim()),
|
|
171
|
-
failWith(cfgcode.
|
|
188
|
+
failWith(cfgcode.GIT_REMOTE_UNREACHABLE, phrase.gitRemoteUnreachable()),
|
|
172
189
|
);
|
|
173
190
|
};
|
|
174
191
|
|
|
@@ -57,6 +57,7 @@ const ensurePublishable = function ({ handle, id, version }, handler) {
|
|
|
57
57
|
if (game === null || build === null) {
|
|
58
58
|
if (handler.onLogInfo) {
|
|
59
59
|
handler.onLogInfo({
|
|
60
|
+
code: cfgcode.WARNING.VERSION_UNCHECKED,
|
|
60
61
|
level: "warn",
|
|
61
62
|
message: phrase.versionUnchecked(version),
|
|
62
63
|
});
|
|
@@ -11,7 +11,7 @@ const workflow = require("../../schema/workflow");
|
|
|
11
11
|
// [use]
|
|
12
12
|
|
|
13
13
|
const closest = strs.closest;
|
|
14
|
-
const
|
|
14
|
+
const WARNING = cfgcode.WARNING;
|
|
15
15
|
|
|
16
16
|
// [function]
|
|
17
17
|
|
|
@@ -29,7 +29,7 @@ const known = function (root) {
|
|
|
29
29
|
// it's reported without failing, with the name it might have meant.
|
|
30
30
|
const warning = function (path, message, near) {
|
|
31
31
|
return {
|
|
32
|
-
code:
|
|
32
|
+
code: WARNING.FIELD_UNKNOWN,
|
|
33
33
|
details: near ? [`Did you mean: ${near}?`] : [],
|
|
34
34
|
link: null,
|
|
35
35
|
message,
|
package/src/config/code.js
CHANGED
|
@@ -8,24 +8,26 @@
|
|
|
8
8
|
|
|
9
9
|
// the CLI's own codes.
|
|
10
10
|
const CLI = {
|
|
11
|
-
|
|
11
|
+
API_REFUSED: "api_refused",
|
|
12
|
+
API_UNREACHABLE: "api_unreachable",
|
|
12
13
|
ARGUMENT_INVALID: "argument_invalid",
|
|
13
14
|
BUILD_FAILED: "build_failed",
|
|
15
|
+
DEPLOY_DIR_MISSING: "deploy_dir_missing",
|
|
14
16
|
GAME_EXISTS: "game_exists",
|
|
15
17
|
GAME_ID_MISSING: "game_id_missing",
|
|
16
18
|
GAME_NOT_DEPLOYED: "game_not_deployed",
|
|
17
19
|
GAME_NOT_FOUND: "game_not_found",
|
|
18
|
-
|
|
20
|
+
GIT_REMOTE_MISSING: "git_remote_missing",
|
|
21
|
+
GIT_REMOTE_UNREACHABLE: "git_remote_unreachable",
|
|
19
22
|
GIT_REPO_MISSING: "git_repo_missing",
|
|
20
23
|
GIT_TAG_CREATE_FAILED: "git_tag_create_failed",
|
|
21
24
|
GIT_TAG_EXISTS: "git_tag_exists",
|
|
22
25
|
GIT_TAG_PUSH_FAILED: "git_tag_push_failed",
|
|
23
26
|
GIT_UNCOMMITTED: "git_uncommitted",
|
|
24
27
|
LOCKFILE_MISSING: "lockfile_missing",
|
|
25
|
-
|
|
28
|
+
LOGIN_CODE_EXPIRED: "login_code_expired",
|
|
26
29
|
LOGIN_FAILED: "login_failed",
|
|
27
30
|
MANIFEST_MISSING: "manifest_missing",
|
|
28
|
-
NETWORK_ERROR: "network_error",
|
|
29
31
|
NOT_LOGGED_IN: "not_logged_in",
|
|
30
32
|
PACKAGE_FILE_TOO_LARGE: "package_file_too_large",
|
|
31
33
|
PACKAGE_INDEX_MISSING: "package_index_missing",
|
|
@@ -48,24 +50,26 @@ const CLI = {
|
|
|
48
50
|
// thing wherever it appears: GAME_UNAVAILABLE, INTERNAL, REPO_NOT_CONNECTED,
|
|
49
51
|
// and VERSION_EXISTS are the CLI's too.
|
|
50
52
|
const RELEASE = {
|
|
51
|
-
|
|
52
|
-
EXPIRED: "expired",
|
|
53
|
+
BUILD_RATE_LIMITED: "build_rate_limited",
|
|
53
54
|
GAME_LIMIT_REACHED: "game_limit_reached",
|
|
54
55
|
GAME_MISMATCH: "game_mismatch",
|
|
55
56
|
GAME_UNAVAILABLE: "game_unavailable",
|
|
57
|
+
GITHUB_APP_NOT_INSTALLED: "github_app_not_installed",
|
|
56
58
|
INTERNAL: "internal",
|
|
57
59
|
MANIFEST_INVALID: "manifest_invalid",
|
|
58
|
-
|
|
60
|
+
RELEASE_EXPIRED: "release_expired",
|
|
59
61
|
REPO_NOT_CONNECTED: "repo_not_connected",
|
|
60
62
|
VERSION_EXISTS: "version_exists",
|
|
63
|
+
VERSION_MISMATCH: "version_mismatch",
|
|
61
64
|
ZIP_INVALID: "zip_invalid",
|
|
65
|
+
ZIP_MISSING: "zip_missing",
|
|
62
66
|
ZIP_TOO_LARGE: "zip_too_large",
|
|
63
67
|
};
|
|
64
68
|
// the Arcadible check's own codes on GitHub, for a `git` release that fails
|
|
65
|
-
// before there's a release (the queue publisher
|
|
69
|
+
// before there's a release (the queue publisher and subscriber Lambdas). `arc deploy git`
|
|
66
70
|
// checks for workflow_missing before it pushes.
|
|
67
71
|
const GITHUB = {
|
|
68
|
-
|
|
72
|
+
GIT_TAG_INVALID: "git_tag_invalid",
|
|
69
73
|
WORKFLOW_MISSING: "workflow_missing",
|
|
70
74
|
};
|
|
71
75
|
// an `arc validate` issue's codes, named for the rule it breaks; the field
|
|
@@ -76,7 +80,6 @@ const ISSUE = {
|
|
|
76
80
|
DESCRIPTION_RULES_MISSING: "description_rules_missing",
|
|
77
81
|
DUPLICATE: "duplicate",
|
|
78
82
|
EMPTY: "empty",
|
|
79
|
-
FIELD_UNKNOWN: "field_unknown",
|
|
80
83
|
INDEX_MISSING: "index_missing",
|
|
81
84
|
INVALID: "invalid",
|
|
82
85
|
MARKDOWN_INVALID: "markdown_invalid",
|
|
@@ -93,6 +96,14 @@ const ISSUE = {
|
|
|
93
96
|
UUID_INVALID: "uuid_invalid",
|
|
94
97
|
VERSION_INVALID: "version_invalid",
|
|
95
98
|
};
|
|
99
|
+
// a warning's codes: what's reported without failing, in an issue's shape.
|
|
100
|
+
// they follow the same rules, and share the Errors page, so no warning code
|
|
101
|
+
// is also an error or issue code.
|
|
102
|
+
const WARNING = {
|
|
103
|
+
DEPLOY_DIR_NOT_BUILT: "deploy_dir_not_built",
|
|
104
|
+
FIELD_UNKNOWN: "field_unknown",
|
|
105
|
+
VERSION_UNCHECKED: "version_unchecked",
|
|
106
|
+
};
|
|
96
107
|
// every error code, for checking one exists.
|
|
97
108
|
const ALL = new Set([
|
|
98
109
|
...Object.values(CLI),
|
|
@@ -101,6 +112,8 @@ const ALL = new Set([
|
|
|
101
112
|
]);
|
|
102
113
|
// every issue code.
|
|
103
114
|
const ISSUES = new Set(Object.values(ISSUE));
|
|
115
|
+
// every warning code.
|
|
116
|
+
const WARNINGS = new Set(Object.values(WARNING));
|
|
104
117
|
|
|
105
118
|
// [export]
|
|
106
119
|
|
|
@@ -113,4 +126,6 @@ module.exports = {
|
|
|
113
126
|
ISSUE,
|
|
114
127
|
ISSUES,
|
|
115
128
|
RELEASE,
|
|
129
|
+
WARNING,
|
|
130
|
+
WARNINGS,
|
|
116
131
|
};
|
package/src/phrase.js
CHANGED
|
@@ -101,6 +101,15 @@ const cmdValidate = function () {
|
|
|
101
101
|
|
|
102
102
|
// [function]
|
|
103
103
|
|
|
104
|
+
const deployDirMissing = function (dir) {
|
|
105
|
+
return blocks(
|
|
106
|
+
`Unable to find deploy_dir: ${dir}`,
|
|
107
|
+
"Run `arc build`, or set deploy_dir to the folder your build writes.",
|
|
108
|
+
);
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
// [function]
|
|
112
|
+
|
|
104
113
|
const docAttrInvalid = function (tag, attr, value) {
|
|
105
114
|
return `Value '${value}' is not valid for the '${attr}' attribute on the '${tag}' tag.`;
|
|
106
115
|
};
|
|
@@ -207,8 +216,17 @@ const gitChangesPresent = function () {
|
|
|
207
216
|
|
|
208
217
|
const gitRemoteMissing = function () {
|
|
209
218
|
return blocks(
|
|
210
|
-
"
|
|
211
|
-
"
|
|
219
|
+
"No Git remote 'origin'.",
|
|
220
|
+
"Add the game's GitHub repository as origin.",
|
|
221
|
+
);
|
|
222
|
+
};
|
|
223
|
+
|
|
224
|
+
// [function]
|
|
225
|
+
|
|
226
|
+
const gitRemoteUnreachable = function () {
|
|
227
|
+
return blocks(
|
|
228
|
+
"Unable to reach Git remote 'origin'.",
|
|
229
|
+
"Check your connection, and that you can access it.",
|
|
212
230
|
);
|
|
213
231
|
};
|
|
214
232
|
|
|
@@ -357,8 +375,8 @@ const issuesFound = function (count) {
|
|
|
357
375
|
|
|
358
376
|
// [function]
|
|
359
377
|
|
|
360
|
-
const
|
|
361
|
-
return "Login
|
|
378
|
+
const loginCodeExpired = function () {
|
|
379
|
+
return "Login code expired.";
|
|
362
380
|
};
|
|
363
381
|
|
|
364
382
|
// [function]
|
|
@@ -469,10 +487,9 @@ const packageUncompressedTooLarge = function (size) {
|
|
|
469
487
|
// and where to see it.
|
|
470
488
|
// `studio` is the game's builds in Studio, for its owner; anyone else can't
|
|
471
489
|
// open it.
|
|
472
|
-
const releaseFailed = function ({ message
|
|
490
|
+
const releaseFailed = function ({ message }, studio) {
|
|
473
491
|
return blocks(
|
|
474
492
|
(message ?? "").split(/(?<=\.)\s+/u).join("\n"),
|
|
475
|
-
`Reason: ${reason}.`,
|
|
476
493
|
...(studio ? [[`${TITLE} Studio:`, studio]] : []),
|
|
477
494
|
);
|
|
478
495
|
};
|
|
@@ -767,6 +784,7 @@ module.exports = {
|
|
|
767
784
|
buildSubmitted,
|
|
768
785
|
cmdInit,
|
|
769
786
|
cmdInspect,
|
|
787
|
+
deployDirMissing,
|
|
770
788
|
docAttrInvalid,
|
|
771
789
|
docAttrUnallowed,
|
|
772
790
|
docCommentUnallowed,
|
|
@@ -783,6 +801,7 @@ module.exports = {
|
|
|
783
801
|
gameUnavailable,
|
|
784
802
|
gitChangesPresent,
|
|
785
803
|
gitRemoteMissing,
|
|
804
|
+
gitRemoteUnreachable,
|
|
786
805
|
gitRepoMissing,
|
|
787
806
|
gitTagCreateFailed,
|
|
788
807
|
gitTagPushFailed,
|
|
@@ -799,7 +818,7 @@ module.exports = {
|
|
|
799
818
|
imageWidthMin,
|
|
800
819
|
issuesAfterBuild,
|
|
801
820
|
issuesFound,
|
|
802
|
-
|
|
821
|
+
loginCodeExpired,
|
|
803
822
|
loginFailed,
|
|
804
823
|
noGameId,
|
|
805
824
|
noLockFile,
|
package/src/util/error.js
CHANGED
|
@@ -32,14 +32,15 @@ const ArcError = class extends Error {
|
|
|
32
32
|
|
|
33
33
|
// [function]
|
|
34
34
|
|
|
35
|
-
// the code a failure reports: its own,
|
|
36
|
-
// refused, or internal for
|
|
35
|
+
// the code a failure reports: its own, api_refused for a request the API
|
|
36
|
+
// refused, or internal for a failure on Arcadible's side (a 5xx) and for
|
|
37
|
+
// anything else, which is a bug in the CLI.
|
|
37
38
|
const codeOf = function (ex) {
|
|
38
39
|
if (ex instanceof ArcError) {
|
|
39
40
|
return ex.code;
|
|
40
41
|
}
|
|
41
|
-
if (ex instanceof HttpError) {
|
|
42
|
-
return cfgcode.
|
|
42
|
+
if (ex instanceof HttpError && !(ex.status >= 500)) {
|
|
43
|
+
return cfgcode.API_REFUSED;
|
|
43
44
|
}
|
|
44
45
|
return cfgcode.INTERNAL;
|
|
45
46
|
};
|
package/src/util/output.js
CHANGED
|
@@ -66,7 +66,7 @@ const print = function (data, { key, nl, toml } = {}) {
|
|
|
66
66
|
// release that failed. `nl` puts a blank line before the heading, after
|
|
67
67
|
// output the command has already printed, such as arc login's link.
|
|
68
68
|
// `code` is a failed release's reason, which the API may add to, so it isn't
|
|
69
|
-
// checked
|
|
69
|
+
// checked.
|
|
70
70
|
const abort = function (
|
|
71
71
|
heading,
|
|
72
72
|
ex,
|
|
@@ -74,12 +74,15 @@ const abort = function (
|
|
|
74
74
|
) {
|
|
75
75
|
const message = ex.message;
|
|
76
76
|
const status = ex.status;
|
|
77
|
+
const shown = code ?? codeOf(ex);
|
|
78
|
+
const link = `${cfgurl.ERRORS}#${shown}`;
|
|
77
79
|
if (json) {
|
|
78
80
|
print({
|
|
79
81
|
...ex.data,
|
|
80
82
|
...data,
|
|
81
83
|
error: {
|
|
82
|
-
code:
|
|
84
|
+
code: shown,
|
|
85
|
+
link,
|
|
83
86
|
message,
|
|
84
87
|
...(status ? { status } : {}),
|
|
85
88
|
},
|
|
@@ -97,12 +100,7 @@ const abort = function (
|
|
|
97
100
|
log.hd(heading);
|
|
98
101
|
}
|
|
99
102
|
log.pd(message);
|
|
100
|
-
|
|
101
|
-
log.nlpd([
|
|
102
|
-
phrase.errorCode(codeOf(ex)),
|
|
103
|
-
chalk.cyan.underline(`${cfgurl.ERRORS}#${codeOf(ex)}`),
|
|
104
|
-
]);
|
|
105
|
-
}
|
|
103
|
+
log.nlpd([phrase.errorCode(shown), chalk.cyan.underline(link)]);
|
|
106
104
|
}
|
|
107
105
|
process.exit(1);
|
|
108
106
|
};
|
|
@@ -119,6 +117,21 @@ const warn = function (warnings, { json, quiet } = {}) {
|
|
|
119
117
|
warnings.forEach((each) => log.pw(`⚠ ${schema.print(each)}`));
|
|
120
118
|
};
|
|
121
119
|
|
|
120
|
+
// [function]
|
|
121
|
+
|
|
122
|
+
// a warning of the command's own, in an issue's shape, as --json lists it
|
|
123
|
+
// under `warnings` beside arc validate's: its code, and the link to it on
|
|
124
|
+
// the Errors page. `path` is the field it's about, if any.
|
|
125
|
+
const warning = function (code, message, path = null) {
|
|
126
|
+
return {
|
|
127
|
+
code,
|
|
128
|
+
details: [],
|
|
129
|
+
link: `${cfgurl.ERRORS}#${code}`,
|
|
130
|
+
message,
|
|
131
|
+
path,
|
|
132
|
+
};
|
|
133
|
+
};
|
|
134
|
+
|
|
122
135
|
// [export]
|
|
123
136
|
|
|
124
|
-
module.exports = { abort, print, printJson, printToml, warn };
|
|
137
|
+
module.exports = { abort, print, printJson, printToml, warn, warning };
|
package/src/util/request.js
CHANGED
|
@@ -53,7 +53,7 @@ const parse = function (resp) {
|
|
|
53
53
|
|
|
54
54
|
// sends a request to a full URL. `headers` are added to the client's own, and
|
|
55
55
|
// a form is sent as JSON. A request that gets no response, such as when
|
|
56
|
-
// offline, rejects as
|
|
56
|
+
// offline, rejects as api_unreachable.
|
|
57
57
|
const send = function (method, url, form, headers = {}) {
|
|
58
58
|
const all = {
|
|
59
59
|
[`X-${CLIENT}-Client-Id`]: ID,
|
|
@@ -66,7 +66,7 @@ const send = function (method, url, form, headers = {}) {
|
|
|
66
66
|
headers: all,
|
|
67
67
|
method,
|
|
68
68
|
}).then(parse, (ex) => {
|
|
69
|
-
throw new ArcError(cfgcode.
|
|
69
|
+
throw new ArcError(cfgcode.API_UNREACHABLE, phrase.unableToReach(), {
|
|
70
70
|
cause: ex,
|
|
71
71
|
});
|
|
72
72
|
});
|
package/src/util/s3.js
CHANGED
|
@@ -32,7 +32,7 @@ const requestOpts = function (size) {
|
|
|
32
32
|
// [function]
|
|
33
33
|
|
|
34
34
|
// puts the file to the upload link, and resolves once S3 accepts it. A
|
|
35
|
-
// request that gets no response rejects as
|
|
35
|
+
// request that gets no response rejects as api_unreachable; a file that can't
|
|
36
36
|
// be read rejects with its own error.
|
|
37
37
|
const upload = function (url, { path, size }, onProgress) {
|
|
38
38
|
return new Promise((resolve, reject) => {
|
|
@@ -49,7 +49,7 @@ const upload = function (url, { path, size }, onProgress) {
|
|
|
49
49
|
req.on("error", (ex) => {
|
|
50
50
|
reject(
|
|
51
51
|
readError ??
|
|
52
|
-
new ArcError(cfgcode.
|
|
52
|
+
new ArcError(cfgcode.API_UNREACHABLE, phrase.unableToReach(), {
|
|
53
53
|
cause: ex,
|
|
54
54
|
}),
|
|
55
55
|
);
|