arcadible 0.1.44 → 0.1.46
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 +9 -17
- package/bin/arc-deploy.js +20 -36
- package/bin/arc-init.js +6 -16
- package/bin/arc-inspect.js +3 -7
- package/bin/arc-login.js +5 -5
- package/bin/arc-logout.js +4 -8
- package/bin/arc-open.js +7 -20
- package/bin/arc-pack.js +4 -14
- package/bin/arc-play.js +6 -20
- package/bin/arc-validate.js +8 -17
- package/bin/arc-whoami.js +5 -9
- package/bin/arc.js +7 -2
- package/package.json +1 -1
- package/src/account.js +5 -5
- package/src/action/build/tool.js +8 -15
- package/src/action/deploy/tool-git.js +1 -6
- package/src/action/deploy/wait.js +5 -11
- package/src/action/init/manifest.js +9 -37
- package/src/action/login/flow.js +3 -10
- package/src/action/open/tool.js +4 -3
- package/src/action/pack/limits.js +4 -6
- package/src/action/pack/tool.js +9 -5
- package/src/action/play/tool.js +6 -6
- package/src/action/predeploy/ac.js +34 -31
- package/src/action/predeploy/git.js +4 -4
- package/src/action/predeploy/pm.js +1 -1
- package/src/action/predeploy/published.js +4 -4
- package/src/action/predeploy/tool-git.js +10 -10
- package/src/action/validate/unknown.js +11 -10
- package/src/config/code.js +1 -1
- package/src/config/file.js +23 -0
- package/src/config/limit.js +21 -0
- package/src/parser/env.js +0 -2
- package/src/parser/manifest.js +15 -13
- package/src/parser/media.js +9 -11
- package/src/parser/project.js +31 -9
- package/src/parser/self.js +27 -0
- package/src/phrase.js +175 -43
- package/src/schema/game.js +65 -42
- package/src/schema/workflow.js +7 -8
- package/src/util/argv.js +27 -1
- package/src/util/command.js +18 -0
- package/src/util/delay.js +5 -21
- package/src/util/doc.js +4 -13
- package/src/util/links.js +17 -2
- package/src/util/media.js +2 -2
- package/src/util/objs.js +8 -1
- package/src/util/output.js +24 -2
- package/src/util/rc.js +2 -2
- package/src/util/request.js +1 -1
- package/src/util/s3.js +1 -1
- package/src/util/schema.js +9 -3
- package/src/util/uris.js +1 -1
- package/src/util/zip.js +2 -2
- package/src/config/doc.js +0 -7
package/src/phrase.js
CHANGED
|
@@ -32,6 +32,13 @@ const waited = function (seconds) {
|
|
|
32
32
|
|
|
33
33
|
// [function]
|
|
34
34
|
|
|
35
|
+
// a command's heading when it fails: `Deploy aborted.`
|
|
36
|
+
const aborted = function (command) {
|
|
37
|
+
return `${command[0].toUpperCase()}${command.slice(1)} aborted.`;
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
// [function]
|
|
41
|
+
|
|
35
42
|
// a build that exited with `code`, or was stopped by `signal`, with what it
|
|
36
43
|
// wrote to stderr.
|
|
37
44
|
const buildFailed = function ({ code, signal, stderr }) {
|
|
@@ -71,12 +78,30 @@ const buildSubmitted = function (version, channel, built) {
|
|
|
71
78
|
|
|
72
79
|
// [function]
|
|
73
80
|
|
|
81
|
+
const buildSucceeded = function () {
|
|
82
|
+
return "Built.";
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
// [function]
|
|
86
|
+
|
|
87
|
+
const cmdBuild = function () {
|
|
88
|
+
return `\`${TOOL} build\``;
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
// [function]
|
|
92
|
+
|
|
74
93
|
const cmdDeploy = function () {
|
|
75
94
|
return `\`${TOOL} deploy\``;
|
|
76
95
|
};
|
|
77
96
|
|
|
78
97
|
// [function]
|
|
79
98
|
|
|
99
|
+
const cmdDeployGit = function () {
|
|
100
|
+
return `\`${TOOL} deploy git\``;
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
// [function]
|
|
104
|
+
|
|
80
105
|
const cmdInit = function () {
|
|
81
106
|
return `\`${TOOL} init\``;
|
|
82
107
|
};
|
|
@@ -104,12 +129,18 @@ const cmdValidate = function () {
|
|
|
104
129
|
const deployDirMissing = function (dir) {
|
|
105
130
|
return blocks(
|
|
106
131
|
`Unable to find deploy_dir: ${dir}`,
|
|
107
|
-
|
|
132
|
+
`Run ${cmdBuild()}, or set deploy_dir to the folder your build writes.`,
|
|
108
133
|
);
|
|
109
134
|
};
|
|
110
135
|
|
|
111
136
|
// [function]
|
|
112
137
|
|
|
138
|
+
const didYouMean = function (near) {
|
|
139
|
+
return `Did you mean: ${near}?`;
|
|
140
|
+
};
|
|
141
|
+
|
|
142
|
+
// [function]
|
|
143
|
+
|
|
113
144
|
const docAttrInvalid = function (tag, attr, value) {
|
|
114
145
|
return `Value '${value}' is not valid for the '${attr}' attribute on the '${tag}' tag.`;
|
|
115
146
|
};
|
|
@@ -140,20 +171,22 @@ const docMediaMissing = function (src) {
|
|
|
140
171
|
|
|
141
172
|
// [function]
|
|
142
173
|
|
|
143
|
-
|
|
144
|
-
|
|
174
|
+
// a description media src that isn't written as the gallery's path to it,
|
|
175
|
+
// such as `./.arcadible/gallery/x.png`: Arcadible matches it as written.
|
|
176
|
+
const docMediaPath = function (src, gallery) {
|
|
177
|
+
return `Must be written as ${gallery}/<file>: ${src}`;
|
|
145
178
|
};
|
|
146
179
|
|
|
147
180
|
// [function]
|
|
148
181
|
|
|
149
|
-
const
|
|
150
|
-
return `
|
|
182
|
+
const docMediaType = function (src) {
|
|
183
|
+
return `Must be a PNG or MP4 file: ${src}`;
|
|
151
184
|
};
|
|
152
185
|
|
|
153
186
|
// [function]
|
|
154
187
|
|
|
155
|
-
const
|
|
156
|
-
return
|
|
188
|
+
const docTagUnallowed = function (tag) {
|
|
189
|
+
return `Tag '${tag}' is not permitted.`;
|
|
157
190
|
};
|
|
158
191
|
|
|
159
192
|
// [function]
|
|
@@ -165,8 +198,11 @@ const errorCode = function (code) {
|
|
|
165
198
|
|
|
166
199
|
// [function]
|
|
167
200
|
|
|
168
|
-
const
|
|
169
|
-
return
|
|
201
|
+
const gameHandleTaken = function (handle) {
|
|
202
|
+
return blocks(
|
|
203
|
+
`Handle taken: ${handle}`,
|
|
204
|
+
"Choose another handle in arcadible.toml.",
|
|
205
|
+
);
|
|
170
206
|
};
|
|
171
207
|
|
|
172
208
|
// [function]
|
|
@@ -180,8 +216,76 @@ const gameNotDeployed = function (game) {
|
|
|
180
216
|
|
|
181
217
|
// [function]
|
|
182
218
|
|
|
219
|
+
const initialized = function () {
|
|
220
|
+
return "Initialized.";
|
|
221
|
+
};
|
|
222
|
+
|
|
223
|
+
// [function]
|
|
224
|
+
|
|
225
|
+
// the heading of arc validate's list of issues, warnings, or references:
|
|
226
|
+
// `2 issues:`
|
|
227
|
+
const listed = function (count, noun) {
|
|
228
|
+
return `${count} ${noun}${count === 1 ? "" : "s"}:`;
|
|
229
|
+
};
|
|
230
|
+
|
|
231
|
+
// [function]
|
|
232
|
+
|
|
233
|
+
const loggedIn = function () {
|
|
234
|
+
return "Logged in.";
|
|
235
|
+
};
|
|
236
|
+
|
|
237
|
+
// [function]
|
|
238
|
+
|
|
239
|
+
const loggedOut = function () {
|
|
240
|
+
return "Logged out.";
|
|
241
|
+
};
|
|
242
|
+
|
|
243
|
+
// [function]
|
|
244
|
+
|
|
245
|
+
const loggingIn = function () {
|
|
246
|
+
return "Logging in...";
|
|
247
|
+
};
|
|
248
|
+
|
|
249
|
+
// [function]
|
|
250
|
+
|
|
251
|
+
const noAccount = function () {
|
|
252
|
+
return "Not logged in.";
|
|
253
|
+
};
|
|
254
|
+
|
|
255
|
+
// [function]
|
|
256
|
+
|
|
257
|
+
const noIssuesFound = function () {
|
|
258
|
+
return "No issues found.";
|
|
259
|
+
};
|
|
260
|
+
|
|
261
|
+
// [function]
|
|
262
|
+
|
|
263
|
+
const nothingToDo = function () {
|
|
264
|
+
return "Nothing to do.";
|
|
265
|
+
};
|
|
266
|
+
|
|
267
|
+
// [function]
|
|
268
|
+
|
|
269
|
+
const packed = function () {
|
|
270
|
+
return "Packed.";
|
|
271
|
+
};
|
|
272
|
+
|
|
273
|
+
// [function]
|
|
274
|
+
|
|
275
|
+
const pressEnterToOpen = function () {
|
|
276
|
+
return "Press Enter to open the URL.";
|
|
277
|
+
};
|
|
278
|
+
|
|
279
|
+
// [function]
|
|
280
|
+
|
|
281
|
+
const releaseFailedHeading = function () {
|
|
282
|
+
return "Release failed.";
|
|
283
|
+
};
|
|
284
|
+
|
|
285
|
+
// [function]
|
|
286
|
+
|
|
183
287
|
// origin isn't the game's connected repository: none is, or another is.
|
|
184
|
-
const
|
|
288
|
+
const repoNotConnected = function (game, repo, url) {
|
|
185
289
|
return blocks(`${repo} isn't ${game}'s repository on ${TITLE}.`, [
|
|
186
290
|
`The game's owner connects it in ${TITLE} Studio, on the game's Repository tab, and connects it again if it was renamed on GitHub:`,
|
|
187
291
|
url,
|
|
@@ -205,7 +309,7 @@ const gameUnavailable = function (id) {
|
|
|
205
309
|
|
|
206
310
|
// [function]
|
|
207
311
|
|
|
208
|
-
const
|
|
312
|
+
const gitUncommitted = function () {
|
|
209
313
|
return blocks(
|
|
210
314
|
"Uncommitted changes found.",
|
|
211
315
|
"Commit, stash, or discard them first.",
|
|
@@ -232,12 +336,12 @@ const gitRemoteUnreachable = function () {
|
|
|
232
336
|
|
|
233
337
|
// [function]
|
|
234
338
|
|
|
235
|
-
const
|
|
339
|
+
const manifestMissing = function (file, dir, found) {
|
|
236
340
|
return blocks(
|
|
237
341
|
dir === "." ? `No ${file} in this directory.` : `No ${file} in ${dir}.`,
|
|
238
342
|
found
|
|
239
|
-
? `The project is in \`${found}\`: run
|
|
240
|
-
:
|
|
343
|
+
? `The project is in \`${found}\`: run ${TOOL} there, or pass \`-C ${found}\`.`
|
|
344
|
+
: `Run ${TOOL} in the project's directory, or pass \`-C\`, or start a project with ${cmdInit()}.`,
|
|
241
345
|
);
|
|
242
346
|
};
|
|
243
347
|
|
|
@@ -245,8 +349,8 @@ const noManifest = function (file, dir, found) {
|
|
|
245
349
|
|
|
246
350
|
const projectNotRepoRoot = function (prefix) {
|
|
247
351
|
return blocks(
|
|
248
|
-
|
|
249
|
-
|
|
352
|
+
`${cmdDeployGit()} releases the project at the repository's root, and this one is in ${prefix}.`,
|
|
353
|
+
`Deploy it with ${cmdDeploy()}, or give it a repository of its own.`,
|
|
250
354
|
);
|
|
251
355
|
};
|
|
252
356
|
|
|
@@ -279,7 +383,7 @@ const gitTagPushFailed = function (version) {
|
|
|
279
383
|
|
|
280
384
|
// [function]
|
|
281
385
|
|
|
282
|
-
const
|
|
386
|
+
const gitTagExists = function (version) {
|
|
283
387
|
return blocks(
|
|
284
388
|
`Git tag for v${version} already exists, here or on origin.`,
|
|
285
389
|
"Bump the version.",
|
|
@@ -387,16 +491,16 @@ const loginFailed = function () {
|
|
|
387
491
|
|
|
388
492
|
// [function]
|
|
389
493
|
|
|
390
|
-
const
|
|
494
|
+
const gameIdMissing = function () {
|
|
391
495
|
return blocks(
|
|
392
496
|
"No game handle or ID.",
|
|
393
|
-
`Pass one, or run ${cmdInit()}
|
|
497
|
+
`Pass one, or run it in a project after ${cmdInit()} has added an ID.`,
|
|
394
498
|
);
|
|
395
499
|
};
|
|
396
500
|
|
|
397
501
|
// [function]
|
|
398
502
|
|
|
399
|
-
const
|
|
503
|
+
const lockfileMissing = function () {
|
|
400
504
|
return blocks("No lockfile found.", [
|
|
401
505
|
"Install your dependencies to create one.",
|
|
402
506
|
"Then commit it.",
|
|
@@ -411,7 +515,7 @@ const noProductionRelease = function () {
|
|
|
411
515
|
|
|
412
516
|
// [function]
|
|
413
517
|
|
|
414
|
-
const
|
|
518
|
+
const templateMissing = function () {
|
|
415
519
|
return blocks("No template chosen.", [
|
|
416
520
|
"Pass `--template <user/repo>`.",
|
|
417
521
|
"Or pass `--yes` for the blank starter.",
|
|
@@ -421,7 +525,7 @@ const noTemplate = function () {
|
|
|
421
525
|
// [function]
|
|
422
526
|
|
|
423
527
|
const notLoggedIn = function () {
|
|
424
|
-
return blocks(
|
|
528
|
+
return blocks(noAccount(), `Run ${cmdLogin()} to log in.`);
|
|
425
529
|
};
|
|
426
530
|
|
|
427
531
|
// [function]
|
|
@@ -450,7 +554,7 @@ const openToContinue = function () {
|
|
|
450
554
|
|
|
451
555
|
// [function]
|
|
452
556
|
|
|
453
|
-
const
|
|
557
|
+
const packageIndexMissing = function (file) {
|
|
454
558
|
return `Package is missing '${file}'.`;
|
|
455
559
|
};
|
|
456
560
|
|
|
@@ -619,12 +723,6 @@ const templateUnavailable = function (template) {
|
|
|
619
723
|
|
|
620
724
|
// [function]
|
|
621
725
|
|
|
622
|
-
const timedOut = function () {
|
|
623
|
-
return "Timed out.";
|
|
624
|
-
};
|
|
625
|
-
|
|
626
|
-
// [function]
|
|
627
|
-
|
|
628
726
|
const unableToFind = function (file) {
|
|
629
727
|
return `Unable to find: ${file}`;
|
|
630
728
|
};
|
|
@@ -638,7 +736,7 @@ const unableToOpen = function () {
|
|
|
638
736
|
// [function]
|
|
639
737
|
|
|
640
738
|
const unableToParse = function (file, message) {
|
|
641
|
-
return blocks(`Unable to parse ${file}.`, message);
|
|
739
|
+
return blocks(`Unable to parse ${file}.`, message.trim());
|
|
642
740
|
};
|
|
643
741
|
|
|
644
742
|
// [function]
|
|
@@ -652,6 +750,18 @@ const unableToReach = function () {
|
|
|
652
750
|
|
|
653
751
|
// [function]
|
|
654
752
|
|
|
753
|
+
const unknownField = function () {
|
|
754
|
+
return "Unknown field.";
|
|
755
|
+
};
|
|
756
|
+
|
|
757
|
+
// [function]
|
|
758
|
+
|
|
759
|
+
const unknownTable = function () {
|
|
760
|
+
return "Unknown table.";
|
|
761
|
+
};
|
|
762
|
+
|
|
763
|
+
// [function]
|
|
764
|
+
|
|
655
765
|
const uploadFailed = function (status) {
|
|
656
766
|
return `Upload failed with status ${status}.`;
|
|
657
767
|
};
|
|
@@ -667,6 +777,12 @@ const uploadRateLimited = function (version) {
|
|
|
667
777
|
|
|
668
778
|
// [function]
|
|
669
779
|
|
|
780
|
+
const waitTimedOut = function () {
|
|
781
|
+
return "Wait timed out.";
|
|
782
|
+
};
|
|
783
|
+
|
|
784
|
+
// [function]
|
|
785
|
+
|
|
670
786
|
const workflowMissing = function (file) {
|
|
671
787
|
return blocks(
|
|
672
788
|
`No release workflow found: ${file}`,
|
|
@@ -684,7 +800,7 @@ const versionPrerelease = function (version) {
|
|
|
684
800
|
|
|
685
801
|
// a version that's already published, with what is, so the developer knows
|
|
686
802
|
// what to bump to.
|
|
687
|
-
const
|
|
803
|
+
const versionExists = function (version, { next, production, staging }) {
|
|
688
804
|
const latest = [
|
|
689
805
|
production ? `Production: ${production}` : null,
|
|
690
806
|
staging ? `Staging: ${staging}` : null,
|
|
@@ -777,35 +893,38 @@ const videoWidthMin = function (width) {
|
|
|
777
893
|
// [export]
|
|
778
894
|
|
|
779
895
|
module.exports = {
|
|
896
|
+
aborted,
|
|
780
897
|
buildFailed,
|
|
781
898
|
buildOutputMissing,
|
|
782
899
|
buildPublishing,
|
|
783
900
|
buildPublishingGit,
|
|
784
901
|
buildSubmitted,
|
|
902
|
+
buildSucceeded,
|
|
785
903
|
cmdInit,
|
|
786
904
|
cmdInspect,
|
|
787
905
|
deployDirMissing,
|
|
906
|
+
didYouMean,
|
|
788
907
|
docAttrInvalid,
|
|
789
908
|
docAttrUnallowed,
|
|
790
909
|
docCommentUnallowed,
|
|
791
910
|
docMediaElement,
|
|
792
911
|
docMediaMissing,
|
|
912
|
+
docMediaPath,
|
|
793
913
|
docMediaType,
|
|
794
914
|
docTagUnallowed,
|
|
795
|
-
docUnsupported,
|
|
796
915
|
errorCode,
|
|
797
|
-
|
|
916
|
+
gameHandleTaken,
|
|
917
|
+
gameIdMissing,
|
|
798
918
|
gameNotDeployed,
|
|
799
919
|
gameNotFound,
|
|
800
|
-
gameRepoMissing,
|
|
801
920
|
gameUnavailable,
|
|
802
|
-
gitChangesPresent,
|
|
803
921
|
gitRemoteMissing,
|
|
804
922
|
gitRemoteUnreachable,
|
|
805
923
|
gitRepoMissing,
|
|
806
924
|
gitTagCreateFailed,
|
|
925
|
+
gitTagExists,
|
|
807
926
|
gitTagPushFailed,
|
|
808
|
-
|
|
927
|
+
gitUncommitted,
|
|
809
928
|
httpError,
|
|
810
929
|
imageAspect,
|
|
811
930
|
imageFound,
|
|
@@ -816,30 +935,40 @@ module.exports = {
|
|
|
816
935
|
imageUnsupported,
|
|
817
936
|
imageWidthMax,
|
|
818
937
|
imageWidthMin,
|
|
938
|
+
initialized,
|
|
819
939
|
issuesAfterBuild,
|
|
820
940
|
issuesFound,
|
|
941
|
+
listed,
|
|
942
|
+
lockfileMissing,
|
|
943
|
+
loggedIn,
|
|
944
|
+
loggedOut,
|
|
945
|
+
loggingIn,
|
|
821
946
|
loginCodeExpired,
|
|
822
947
|
loginFailed,
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
948
|
+
manifestMissing,
|
|
949
|
+
noAccount,
|
|
950
|
+
noIssuesFound,
|
|
826
951
|
noProductionRelease,
|
|
827
|
-
noTemplate,
|
|
828
952
|
noVideoMetadata,
|
|
829
953
|
noVideoTrack,
|
|
830
954
|
notLoggedIn,
|
|
955
|
+
nothingToDo,
|
|
831
956
|
openToContinue,
|
|
832
957
|
opened,
|
|
833
|
-
packageFileMissing,
|
|
834
958
|
packageFileTooLarge,
|
|
959
|
+
packageIndexMissing,
|
|
835
960
|
packageTooLarge,
|
|
836
961
|
packageTooManyFiles,
|
|
837
962
|
packageUncompressedTooLarge,
|
|
963
|
+
packed,
|
|
964
|
+
pressEnterToOpen,
|
|
838
965
|
projectNotRepoRoot,
|
|
839
966
|
releaseFailed,
|
|
967
|
+
releaseFailedHeading,
|
|
840
968
|
releasePublished,
|
|
841
969
|
releaseTimedOut,
|
|
842
970
|
releaseWaiting,
|
|
971
|
+
repoNotConnected,
|
|
843
972
|
sessionExpired,
|
|
844
973
|
sizeB,
|
|
845
974
|
sizeGb,
|
|
@@ -851,17 +980,19 @@ module.exports = {
|
|
|
851
980
|
starterPixiJs,
|
|
852
981
|
starterThreeJs,
|
|
853
982
|
tagPushed,
|
|
983
|
+
templateMissing,
|
|
854
984
|
templateUnavailable,
|
|
855
|
-
timedOut,
|
|
856
985
|
timeoutInvalid,
|
|
857
986
|
unableToFind,
|
|
858
987
|
unableToOpen,
|
|
859
988
|
unableToParse,
|
|
860
989
|
unableToReach,
|
|
990
|
+
unknownField,
|
|
991
|
+
unknownTable,
|
|
861
992
|
uploadFailed,
|
|
862
993
|
uploadRateLimited,
|
|
994
|
+
versionExists,
|
|
863
995
|
versionPrerelease,
|
|
864
|
-
versionPublished,
|
|
865
996
|
versionRelease,
|
|
866
997
|
versionUnchecked,
|
|
867
998
|
videoAspect,
|
|
@@ -875,5 +1006,6 @@ module.exports = {
|
|
|
875
1006
|
videoUnsupported,
|
|
876
1007
|
videoWidthMax,
|
|
877
1008
|
videoWidthMin,
|
|
1009
|
+
waitTimedOut,
|
|
878
1010
|
workflowMissing,
|
|
879
1011
|
};
|
package/src/schema/game.js
CHANGED
|
@@ -14,13 +14,12 @@ const z = require("zod");
|
|
|
14
14
|
const cfgai = require("../config/ai");
|
|
15
15
|
const cfgaudience = require("../config/audience");
|
|
16
16
|
const cfgcode = require("../config/code");
|
|
17
|
-
const
|
|
17
|
+
const cfgfile = require("../config/file");
|
|
18
18
|
const cfggenre = require("../config/genre");
|
|
19
19
|
const cfghtml = require("../config/html");
|
|
20
20
|
const cfgimage = require("../config/image");
|
|
21
21
|
const cfginput = require("../config/input");
|
|
22
22
|
const cfgorientation = require("../config/orientation");
|
|
23
|
-
const cfgproduct = require("../config/product");
|
|
24
23
|
const cfgvideo = require("../config/video");
|
|
25
24
|
const cfgvisibility = require("../config/visibility");
|
|
26
25
|
const chars = require("../util/chars");
|
|
@@ -38,6 +37,7 @@ const cleanSemver = semver.clean;
|
|
|
38
37
|
const docCheck = check.doc;
|
|
39
38
|
const existsCheck = check.exists;
|
|
40
39
|
const extname = path.extname;
|
|
40
|
+
const posixDirname = path.posix.dirname;
|
|
41
41
|
const ISSUE = cfgcode.ISSUE;
|
|
42
42
|
const imageCheck = check.image;
|
|
43
43
|
const invalidChars = chars.invalid;
|
|
@@ -51,13 +51,12 @@ const videoCheck = check.video;
|
|
|
51
51
|
|
|
52
52
|
// [declare]
|
|
53
53
|
|
|
54
|
-
const HANDLE = cfgproduct.handle;
|
|
55
54
|
const message = schemaMessage.messages("game");
|
|
56
55
|
|
|
57
56
|
// [declare]
|
|
58
57
|
|
|
59
|
-
const GALLERY =
|
|
60
|
-
const MEDIA =
|
|
58
|
+
const GALLERY = cfgfile.GALLERY;
|
|
59
|
+
const MEDIA = cfgfile.MEDIA;
|
|
61
60
|
|
|
62
61
|
// [declare]
|
|
63
62
|
|
|
@@ -144,15 +143,16 @@ const required = function (field, lines) {
|
|
|
144
143
|
// [function]
|
|
145
144
|
|
|
146
145
|
// a list of distinct values. Without a max, its length is up to the values.
|
|
147
|
-
const zSet = function (field, schema, { max
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
)
|
|
146
|
+
const zSet = function (field, schema, { max, min }) {
|
|
147
|
+
const list = z.array(schema).min(min, atLeast(field, min, "element"));
|
|
148
|
+
return (
|
|
149
|
+
max
|
|
150
|
+
? list.max(max, message(field, [`Must not exceed: ${max} elements`]))
|
|
151
|
+
: list
|
|
152
|
+
).refine(
|
|
153
|
+
(items) => new Set(items).size === items.length,
|
|
154
|
+
message(field, ["Must not contain duplicate elements."], ISSUE.DUPLICATE),
|
|
155
|
+
);
|
|
156
156
|
};
|
|
157
157
|
|
|
158
158
|
// [function]
|
|
@@ -174,11 +174,17 @@ const zSetBasefile = function (field, schema, { max, min }) {
|
|
|
174
174
|
|
|
175
175
|
// [function]
|
|
176
176
|
|
|
177
|
+
// a string of `min` to `max` characters, counted as Arcadible counts them: a
|
|
178
|
+
// character outside the Basic Multilingual Plane, such as an emoji, is one,
|
|
179
|
+
// though JavaScript's length counts it as two.
|
|
177
180
|
const zString = function (field, char, { max, min }) {
|
|
178
181
|
return z
|
|
179
182
|
.string()
|
|
180
183
|
.min(min, { ...atLeast(field, min, "character"), abort: min === 1 })
|
|
181
|
-
.
|
|
184
|
+
.refine(
|
|
185
|
+
(str) => [...str].length <= max,
|
|
186
|
+
message(field, [`Must not exceed: ${max} characters`], ISSUE.TOO_LONG),
|
|
187
|
+
)
|
|
182
188
|
.superRefine((str, ctx) => {
|
|
183
189
|
const invalid = invalidChars(str, char);
|
|
184
190
|
if (invalid.length) {
|
|
@@ -197,8 +203,12 @@ const zString = function (field, char, { max, min }) {
|
|
|
197
203
|
|
|
198
204
|
// [function]
|
|
199
205
|
|
|
206
|
+
// plain text, which can't be only spaces.
|
|
200
207
|
const zText = function (field, opts) {
|
|
201
|
-
return zString(field, /[\p{L}0-9 .,!?'"():;-]/u, opts)
|
|
208
|
+
return zString(field, /[\p{L}0-9 .,!?'"():;-]/u, opts).refine(
|
|
209
|
+
(str) => str.trim() !== "",
|
|
210
|
+
message(field, ["Must not be blank."], ISSUE.EMPTY),
|
|
211
|
+
);
|
|
202
212
|
};
|
|
203
213
|
|
|
204
214
|
// [function]
|
|
@@ -206,7 +216,7 @@ const zText = function (field, opts) {
|
|
|
206
216
|
const zHtml = function (field, root, { max, min, ...opts }) {
|
|
207
217
|
const char = /[\p{L}\p{M}\p{N}\p{P}\p{S}\p{Zs}\r\n]/u;
|
|
208
218
|
return zString(field, char, { max, min }).superRefine((str, ctx) => {
|
|
209
|
-
const issues = docCheck(root, str,
|
|
219
|
+
const issues = docCheck(root, str, opts);
|
|
210
220
|
if (issues.length) {
|
|
211
221
|
ctx.addIssue({
|
|
212
222
|
code: "custom",
|
|
@@ -284,27 +294,34 @@ const zMp4 = function (field, root, opts) {
|
|
|
284
294
|
const zPngMp4 = function (field, root, optsPng, optsMp4) {
|
|
285
295
|
const pngSchema = zPng(field, root, optsPng);
|
|
286
296
|
const mp4Schema = zMp4(field, root, optsMp4);
|
|
287
|
-
return z
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
297
|
+
return z
|
|
298
|
+
.string()
|
|
299
|
+
.min(1, { ...atLeast(field, 1), abort: true })
|
|
300
|
+
.superRefine((file, ctx) => {
|
|
301
|
+
const ext = extname(file);
|
|
302
|
+
let schema = null;
|
|
303
|
+
if (Object.hasOwn(cfgimage, ext)) {
|
|
304
|
+
schema = pngSchema;
|
|
305
|
+
}
|
|
306
|
+
if (Object.hasOwn(cfgvideo, ext)) {
|
|
307
|
+
schema = mp4Schema;
|
|
308
|
+
}
|
|
309
|
+
if (!schema) {
|
|
310
|
+
ctx.addIssue({
|
|
311
|
+
code: "custom",
|
|
312
|
+
...message(
|
|
313
|
+
field,
|
|
314
|
+
["Must be a PNG or MP4 file."],
|
|
315
|
+
ISSUE.MEDIA_INVALID,
|
|
316
|
+
),
|
|
317
|
+
});
|
|
318
|
+
return;
|
|
319
|
+
}
|
|
320
|
+
const result = schema.safeParse(file);
|
|
321
|
+
if (!result.success) {
|
|
322
|
+
result.error.issues.forEach((issue) => ctx.addIssue(issue));
|
|
323
|
+
}
|
|
324
|
+
});
|
|
308
325
|
};
|
|
309
326
|
|
|
310
327
|
// [function]
|
|
@@ -383,6 +400,10 @@ const checkSrc = function (root, src, tag) {
|
|
|
383
400
|
) {
|
|
384
401
|
return false;
|
|
385
402
|
}
|
|
403
|
+
// the store page finds it by the gallery's path, exactly.
|
|
404
|
+
if (posixDirname(src) !== GALLERY) {
|
|
405
|
+
return phrase.docMediaPath(src, GALLERY);
|
|
406
|
+
}
|
|
386
407
|
return existsCheck(root, src) || phrase.docMediaMissing(src);
|
|
387
408
|
};
|
|
388
409
|
|
|
@@ -465,6 +486,7 @@ const zId = function () {
|
|
|
465
486
|
.string(
|
|
466
487
|
required(field, [`Run ${phrase.cmdInit()} to generate a new game ID.`]),
|
|
467
488
|
)
|
|
489
|
+
.min(1, { ...atLeast(field, 1), abort: true })
|
|
468
490
|
.uuid(message(field, ["Must be a valid UUID."]))
|
|
469
491
|
.refine(
|
|
470
492
|
(value) => value === value.toLowerCase(),
|
|
@@ -542,10 +564,11 @@ const zVersion = function () {
|
|
|
542
564
|
.string(
|
|
543
565
|
required(field, ["A version is required unless one can be derived."]),
|
|
544
566
|
)
|
|
545
|
-
.
|
|
546
|
-
|
|
547
|
-
message(field, ["Must be valid semver."], ISSUE.VERSION_INVALID),
|
|
548
|
-
|
|
567
|
+
.min(1, { ...atLeast(field, 1), abort: true })
|
|
568
|
+
.refine((value) => validSemver(value) !== null, {
|
|
569
|
+
...message(field, ["Must be valid semver."], ISSUE.VERSION_INVALID),
|
|
570
|
+
abort: true,
|
|
571
|
+
})
|
|
549
572
|
.refine(
|
|
550
573
|
// lowercase too, since the database refuses an uppercase prerelease.
|
|
551
574
|
(value) => cleanSemver(value) === value && value === value.toLowerCase(),
|
package/src/schema/workflow.js
CHANGED
|
@@ -7,14 +7,17 @@ const z = require("zod");
|
|
|
7
7
|
// [import]
|
|
8
8
|
|
|
9
9
|
const cfgcode = require("../config/code");
|
|
10
|
+
const cfgfile = require("../config/file");
|
|
10
11
|
const cfgproduct = require("../config/product");
|
|
11
12
|
const check = require("./check/workflow");
|
|
13
|
+
const commands = require("../util/command");
|
|
12
14
|
const phrase = require("../phrase");
|
|
13
15
|
const schemaMessage = require("./message");
|
|
14
16
|
|
|
15
17
|
// [use]
|
|
16
18
|
|
|
17
19
|
const avoidsCheck = check.avoids;
|
|
20
|
+
const buildCommand = commands.buildCommand;
|
|
18
21
|
const ISSUE = cfgcode.ISSUE;
|
|
19
22
|
const existsCheck = check.exists;
|
|
20
23
|
const hasFileCheck = check.hasFile;
|
|
@@ -25,20 +28,16 @@ const lacksFilesCheck = check.lacksFiles;
|
|
|
25
28
|
|
|
26
29
|
// [declare]
|
|
27
30
|
|
|
28
|
-
const HANDLE = cfgproduct.handle;
|
|
29
31
|
const message = schemaMessage.messages("workflow");
|
|
30
|
-
const MEDIA =
|
|
32
|
+
const MEDIA = cfgfile.MEDIA;
|
|
31
33
|
const INDEX = "index.html";
|
|
32
|
-
const RESERVED = [
|
|
34
|
+
const RESERVED = [cfgfile.PACKAGED, MEDIA];
|
|
33
35
|
|
|
34
36
|
// [function]
|
|
35
37
|
|
|
36
|
-
// whether `build` runs anything
|
|
37
|
-
// trims and drops blank ones (action/build/tool.js).
|
|
38
|
+
// whether `build` runs anything, as `arc build` runs it.
|
|
38
39
|
const hasBuild = function (build) {
|
|
39
|
-
return
|
|
40
|
-
.flat()
|
|
41
|
-
.some((cmd) => typeof cmd === "string" && cmd.trim() !== "");
|
|
40
|
+
return buildCommand(build) !== "";
|
|
42
41
|
};
|
|
43
42
|
|
|
44
43
|
// [function]
|