arcadible 0.0.1 → 0.1.1
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 +3 -0
- package/bin/arc-default.js +57 -0
- package/bin/arc-deploy.js +117 -0
- package/bin/arc-init.js +196 -0
- package/bin/arc-inspect.js +107 -0
- package/bin/arc-login.js +127 -0
- package/bin/arc-logout.js +58 -0
- package/bin/arc-pack.js +126 -0
- package/bin/arc-validate.js +114 -0
- package/bin/arc-whoami.js +111 -0
- package/bin/arc.js +64 -0
- package/package.json +49 -1
- package/src/action/deploy/tool.js +11 -0
- package/src/action/deploy-git/git.js +23 -0
- package/src/action/deploy-git/release.js +74 -0
- package/src/action/deploy-git/tool.js +11 -0
- package/src/action/init/tool.js +44 -0
- package/src/action/inspect/tool.js +25 -0
- package/src/action/login/flow.js +94 -0
- package/src/action/login/tool.js +16 -0
- package/src/action/logout/tool.js +15 -0
- package/src/action/pack/tool.js +60 -0
- package/src/action/validate/tool.js +39 -0
- package/src/action/whoami/tool.js +15 -0
- package/src/api.js +39 -0
- package/src/cli/deploy.js +17 -0
- package/src/cli/index.js +25 -0
- package/src/cli/init.js +15 -0
- package/src/cli/inspect.js +15 -0
- package/src/cli/login.js +15 -0
- package/src/cli/logout.js +15 -0
- package/src/cli/pack.js +15 -0
- package/src/cli/validate.js +15 -0
- package/src/cli/whoami.js +15 -0
- package/src/config/audience.js +5 -0
- package/src/config/game.js +5 -0
- package/src/config/genre.js +22 -0
- package/src/config/html.js +27 -0
- package/src/config/input.js +14 -0
- package/src/config/orientation.js +14 -0
- package/src/config/uri.js +14 -0
- package/src/config/url.js +17 -0
- package/src/config/visibility.js +5 -0
- package/src/config/workflow.js +5 -0
- package/src/parser/manifest.js +46 -0
- package/src/parser/media.js +96 -0
- package/src/parser/project.js +55 -0
- package/src/parser/readme.js +144 -0
- package/src/prompt/project.js +10 -0
- package/src/prompt/template.js +37 -0
- package/src/schema/game.js +324 -0
- package/src/schema/workflow.js +119 -0
- package/src/user.js +91 -0
- package/src/util/dom.js +27 -0
- package/src/util/log.js +99 -0
- package/src/util/md.js +24 -0
- package/src/util/objs.js +28 -0
- package/src/util/os.js +24 -0
- package/src/util/output.js +46 -0
- package/src/util/promise.js +29 -0
- package/src/util/rc.js +41 -0
- package/src/util/request.js +62 -0
- package/src/util/schema.js +25 -0
- package/src/util/strs.js +21 -0
- package/src/util/time.js +79 -0
- package/src/util/zip.js +59 -0
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
// [import]
|
|
4
|
+
|
|
5
|
+
const path = require("node:path");
|
|
6
|
+
|
|
7
|
+
// [import]
|
|
8
|
+
|
|
9
|
+
const fs = require("fs-extra");
|
|
10
|
+
|
|
11
|
+
// [import]
|
|
12
|
+
|
|
13
|
+
const objs = require("../util/objs");
|
|
14
|
+
|
|
15
|
+
// [use]
|
|
16
|
+
|
|
17
|
+
const extname = path.extname;
|
|
18
|
+
const join = path.join;
|
|
19
|
+
const pathExists = fs.pathExists;
|
|
20
|
+
const pathParse = path.parse;
|
|
21
|
+
const pruneEmpty = objs.pruneEmpty;
|
|
22
|
+
const readdir = fs.promises.readdir;
|
|
23
|
+
|
|
24
|
+
// [declare]
|
|
25
|
+
|
|
26
|
+
const ART = [
|
|
27
|
+
"banner.png",
|
|
28
|
+
"banner_video.mp4",
|
|
29
|
+
"cover.png",
|
|
30
|
+
"cover_video.mp4",
|
|
31
|
+
"icon.png",
|
|
32
|
+
"icon_video.mp4",
|
|
33
|
+
"poster.png",
|
|
34
|
+
"poster_video.mp4",
|
|
35
|
+
"wordmark.svg",
|
|
36
|
+
"wordmark_animated.svg",
|
|
37
|
+
];
|
|
38
|
+
|
|
39
|
+
// [declare]
|
|
40
|
+
|
|
41
|
+
const MEDIA = ".arcadible";
|
|
42
|
+
|
|
43
|
+
// [function]
|
|
44
|
+
|
|
45
|
+
const handleArt = function (exists) {
|
|
46
|
+
return Object.fromEntries(
|
|
47
|
+
ART.map((f, i) => [pathParse(f).name, exists[i] ? join(MEDIA, f) : null]),
|
|
48
|
+
);
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
// [function]
|
|
52
|
+
|
|
53
|
+
const art = function (root) {
|
|
54
|
+
return (game) =>
|
|
55
|
+
Promise.all(ART.map((value) => pathExists(join(root, MEDIA, value))))
|
|
56
|
+
.then(handleArt)
|
|
57
|
+
.then((data) => ({ ...game, ...data }));
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
// [function]
|
|
61
|
+
|
|
62
|
+
const handleGallery = function (entries) {
|
|
63
|
+
return entries
|
|
64
|
+
.filter((f) => extname(f).toLowerCase() === ".png")
|
|
65
|
+
.map((f) => join(MEDIA, "gallery", f))
|
|
66
|
+
.sort();
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
// [function]
|
|
70
|
+
|
|
71
|
+
const gallery = function (root) {
|
|
72
|
+
const dir = join(root, MEDIA, "gallery");
|
|
73
|
+
return (game) =>
|
|
74
|
+
pathExists(dir)
|
|
75
|
+
.then((exists) => (exists ? readdir(dir) : []))
|
|
76
|
+
.then(handleGallery)
|
|
77
|
+
.then((data) => ({ ...game, gallery: data }));
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
// [function]
|
|
81
|
+
|
|
82
|
+
const parse = function (root) {
|
|
83
|
+
return new Promise((resolve, reject) => {
|
|
84
|
+
Promise.resolve({})
|
|
85
|
+
.then(art(root))
|
|
86
|
+
.then(gallery(root))
|
|
87
|
+
.then(pruneEmpty)
|
|
88
|
+
.then((game) => ({ game }))
|
|
89
|
+
.then(resolve)
|
|
90
|
+
.catch(reject);
|
|
91
|
+
});
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
// [export]
|
|
95
|
+
|
|
96
|
+
module.exports = { parse };
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
// [import]
|
|
4
|
+
|
|
5
|
+
const cfggame = require("../config/game");
|
|
6
|
+
const cfgworkflow = require("../config/workflow");
|
|
7
|
+
const manifest = require("./manifest");
|
|
8
|
+
const media = require("./media");
|
|
9
|
+
const promise = require("../util/promise");
|
|
10
|
+
const readme = require("./readme");
|
|
11
|
+
|
|
12
|
+
// [function]
|
|
13
|
+
|
|
14
|
+
const configGame = function (readmeGame, mediaGame, manifestGame) {
|
|
15
|
+
return {
|
|
16
|
+
...cfggame,
|
|
17
|
+
...(readmeGame || {}),
|
|
18
|
+
...(mediaGame || {}),
|
|
19
|
+
...(manifestGame || {}),
|
|
20
|
+
};
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
// [function]
|
|
24
|
+
|
|
25
|
+
const configWorkflow = function (manifestWorkflow) {
|
|
26
|
+
return {
|
|
27
|
+
...cfgworkflow,
|
|
28
|
+
...(manifestWorkflow || {}),
|
|
29
|
+
};
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
// [function]
|
|
33
|
+
|
|
34
|
+
const parse = function (root) {
|
|
35
|
+
const parsers = [
|
|
36
|
+
() => manifest.parse(root),
|
|
37
|
+
() => media.parse(root),
|
|
38
|
+
() => readme.parse(root),
|
|
39
|
+
];
|
|
40
|
+
return promise
|
|
41
|
+
.serial(parsers)
|
|
42
|
+
.then(([manifestData, mediaData, readmeData]) => {
|
|
43
|
+
const game = configGame(
|
|
44
|
+
readmeData.game,
|
|
45
|
+
mediaData.game,
|
|
46
|
+
manifestData.game,
|
|
47
|
+
);
|
|
48
|
+
const workflow = configWorkflow(manifestData.workflow);
|
|
49
|
+
return { game, workflow };
|
|
50
|
+
});
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
// [export]
|
|
54
|
+
|
|
55
|
+
module.exports = { parse };
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
// [import]
|
|
4
|
+
|
|
5
|
+
const path = require("node:path");
|
|
6
|
+
|
|
7
|
+
// [import]
|
|
8
|
+
|
|
9
|
+
const fs = require("fs-extra");
|
|
10
|
+
|
|
11
|
+
// [import]
|
|
12
|
+
|
|
13
|
+
const dom = require("../util/dom");
|
|
14
|
+
const MD = require("../util/md");
|
|
15
|
+
const objs = require("../util/objs");
|
|
16
|
+
const strs = require("../util/strs");
|
|
17
|
+
|
|
18
|
+
// [use]
|
|
19
|
+
|
|
20
|
+
const join = path.join;
|
|
21
|
+
const pruneEmpty = objs.pruneEmpty;
|
|
22
|
+
const readFile = fs.readFile;
|
|
23
|
+
const trimWhitespace = strs.trimWhitespace;
|
|
24
|
+
|
|
25
|
+
// [declare]
|
|
26
|
+
|
|
27
|
+
const README = "README.md";
|
|
28
|
+
|
|
29
|
+
// [function]
|
|
30
|
+
|
|
31
|
+
const splitTitle = function (str) {
|
|
32
|
+
let title = "";
|
|
33
|
+
let shortTitle = "";
|
|
34
|
+
const m = str.match(/^(?<title>\S.*?)(?:\s*\((?<shortTitle>[^)]*)\))?$/u);
|
|
35
|
+
if (m && m.groups.title) {
|
|
36
|
+
title = m.groups.title.trim();
|
|
37
|
+
}
|
|
38
|
+
if (m && m.groups.shortTitle) {
|
|
39
|
+
shortTitle = m.groups.shortTitle.trim();
|
|
40
|
+
}
|
|
41
|
+
return [title, shortTitle];
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
// [function]
|
|
45
|
+
|
|
46
|
+
const extractTitle = function (doc) {
|
|
47
|
+
const elTitle = doc.querySelector("h1");
|
|
48
|
+
let title = "";
|
|
49
|
+
let shortTitle = "";
|
|
50
|
+
if (elTitle) {
|
|
51
|
+
if (elTitle.textContent) {
|
|
52
|
+
[title, shortTitle] = splitTitle(elTitle.textContent);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
return [title, shortTitle].map(trimWhitespace);
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
// [function]
|
|
59
|
+
|
|
60
|
+
const extractTagline = function (doc) {
|
|
61
|
+
const elTagline = doc.querySelector("h2");
|
|
62
|
+
let tagline = "";
|
|
63
|
+
if (elTagline) {
|
|
64
|
+
if (elTagline.textContent) {
|
|
65
|
+
tagline = elTagline.textContent;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
return trimWhitespace(tagline);
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
// [function]
|
|
72
|
+
|
|
73
|
+
const extractBio = function (doc) {
|
|
74
|
+
const elBio = doc.querySelector("h2 + p");
|
|
75
|
+
let bio = "";
|
|
76
|
+
if (elBio) {
|
|
77
|
+
if (elBio.textContent) {
|
|
78
|
+
bio = elBio.textContent;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
return trimWhitespace(bio);
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
// [function]
|
|
85
|
+
|
|
86
|
+
const extractDescription = function (doc) {
|
|
87
|
+
const hrs = doc.querySelectorAll("hr");
|
|
88
|
+
if (hrs.length < 2) {
|
|
89
|
+
return "";
|
|
90
|
+
}
|
|
91
|
+
const first = hrs[0];
|
|
92
|
+
const last = hrs[hrs.length - 1];
|
|
93
|
+
const parts = [];
|
|
94
|
+
let node = first.nextSibling;
|
|
95
|
+
while (node && node !== last) {
|
|
96
|
+
parts.push(node.outerHTML || node.textContent);
|
|
97
|
+
node = node.nextSibling;
|
|
98
|
+
}
|
|
99
|
+
return trimWhitespace(parts.join(""));
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
// [function]
|
|
103
|
+
|
|
104
|
+
const extract = function (html) {
|
|
105
|
+
const doc = new dom.DOM(html).window.document;
|
|
106
|
+
// eslint-disable-next-line camelcase
|
|
107
|
+
const [title, short_title] = extractTitle(doc);
|
|
108
|
+
const tagline = extractTagline(doc);
|
|
109
|
+
const bio = extractBio(doc);
|
|
110
|
+
const description = extractDescription(doc);
|
|
111
|
+
return Object.fromEntries(
|
|
112
|
+
// eslint-disable-next-line camelcase
|
|
113
|
+
Object.entries({ bio, description, short_title, tagline, title }).map(
|
|
114
|
+
([k, v]) => [k, v || null],
|
|
115
|
+
),
|
|
116
|
+
);
|
|
117
|
+
};
|
|
118
|
+
|
|
119
|
+
// [function]
|
|
120
|
+
|
|
121
|
+
const parseReadme = function (buf) {
|
|
122
|
+
try {
|
|
123
|
+
return extract(MD.parse(buf));
|
|
124
|
+
} catch (ex) {
|
|
125
|
+
throw new Error(`Unable to parse ${README}: ${ex.message}`, { cause: ex });
|
|
126
|
+
}
|
|
127
|
+
};
|
|
128
|
+
|
|
129
|
+
// [function]
|
|
130
|
+
|
|
131
|
+
const parse = function (root) {
|
|
132
|
+
return new Promise((resolve, reject) => {
|
|
133
|
+
readFile(join(root, README), "utf8")
|
|
134
|
+
.then(parseReadme)
|
|
135
|
+
.then(pruneEmpty)
|
|
136
|
+
.then((game) => ({ game }))
|
|
137
|
+
.then(resolve)
|
|
138
|
+
.catch(reject);
|
|
139
|
+
});
|
|
140
|
+
};
|
|
141
|
+
|
|
142
|
+
// [export]
|
|
143
|
+
|
|
144
|
+
module.exports = { parse };
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
// [export]
|
|
4
|
+
|
|
5
|
+
module.exports = {
|
|
6
|
+
select: {
|
|
7
|
+
choices: [
|
|
8
|
+
{
|
|
9
|
+
description: "Blank starter template.",
|
|
10
|
+
name: "Blank",
|
|
11
|
+
value: "arcadible/starter",
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
description: "Three.js starter template.",
|
|
15
|
+
name: "Three.js",
|
|
16
|
+
value: "arcadible/starter-threejs",
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
description: "Phaser starter template.",
|
|
20
|
+
name: "Phaser",
|
|
21
|
+
value: "arcadible/starter-phaser",
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
description: "PixiJS starter template.",
|
|
25
|
+
name: "PixiJS",
|
|
26
|
+
value: "arcadible/starter-pixijs",
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
description: "Babylon.js starter template.",
|
|
30
|
+
name: "Babylon.js",
|
|
31
|
+
value: "arcadible/starter-babylonjs",
|
|
32
|
+
},
|
|
33
|
+
],
|
|
34
|
+
default: "arcadible/starter",
|
|
35
|
+
message: "Template",
|
|
36
|
+
},
|
|
37
|
+
};
|
|
@@ -0,0 +1,324 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
// [import]
|
|
4
|
+
|
|
5
|
+
const chalk = require("chalk");
|
|
6
|
+
const z = require("zod");
|
|
7
|
+
|
|
8
|
+
// [import]
|
|
9
|
+
|
|
10
|
+
const cfgaudience = require("../config/audience");
|
|
11
|
+
const cfggenre = require("../config/genre");
|
|
12
|
+
const cfghtml = require("../config/html");
|
|
13
|
+
const cfginput = require("../config/input");
|
|
14
|
+
const cfgorientation = require("../config/orientation");
|
|
15
|
+
const cfgurl = require("../config/url");
|
|
16
|
+
const cfgvisibility = require("../config/visibility");
|
|
17
|
+
const dom = require("../util/dom");
|
|
18
|
+
|
|
19
|
+
// [function]
|
|
20
|
+
|
|
21
|
+
const reference = function (field) {
|
|
22
|
+
return chalk.cyan.underline(`${cfgurl.MANIFEST}#${field}`);
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
// [function]
|
|
26
|
+
|
|
27
|
+
const indent = function (text, spaces = 2) {
|
|
28
|
+
const pad = " ".repeat(spaces);
|
|
29
|
+
return text
|
|
30
|
+
.split("\n")
|
|
31
|
+
.map((line) => pad + line)
|
|
32
|
+
.join("\n");
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
// [function]
|
|
36
|
+
|
|
37
|
+
const message = function (field, msg) {
|
|
38
|
+
return { message: [msg, indent(reference(field))].join("\n") };
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
// [function]
|
|
42
|
+
|
|
43
|
+
const zText = function (field, { max, min }) {
|
|
44
|
+
return z
|
|
45
|
+
.string()
|
|
46
|
+
.min(min)
|
|
47
|
+
.max(max)
|
|
48
|
+
.regex(
|
|
49
|
+
/^[\p{L}0-9 .,!?'"():;-]+$/u,
|
|
50
|
+
message(field, "Contains invalid characters."),
|
|
51
|
+
);
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
// [function]
|
|
55
|
+
|
|
56
|
+
const zPng = function () {
|
|
57
|
+
return z.string();
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
// [function]
|
|
61
|
+
|
|
62
|
+
const zSvg = function () {
|
|
63
|
+
return z.string();
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
// [function]
|
|
67
|
+
|
|
68
|
+
const zMp4 = function () {
|
|
69
|
+
return z.string();
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
// [function]
|
|
73
|
+
|
|
74
|
+
const zVimeo = function () {
|
|
75
|
+
return z
|
|
76
|
+
.string()
|
|
77
|
+
.regex(
|
|
78
|
+
/^https:\/\/(?:www\.)?(?:vimeo\.com|player\.vimeo\.com\/video)\/([0-9]+)(?:[/?#].*)?$/iu,
|
|
79
|
+
);
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
// [function]
|
|
83
|
+
|
|
84
|
+
const zYouTube = function () {
|
|
85
|
+
return z
|
|
86
|
+
.string()
|
|
87
|
+
.regex(
|
|
88
|
+
/^https:\/\/(?:www\.)?(?:youtube\.com\/(?:watch\?v=|embed\/)|youtu\.be\/)([A-Za-z0-9_-]{11})(?:[?&#].*)?$/iu,
|
|
89
|
+
);
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
// [function]
|
|
93
|
+
|
|
94
|
+
const zAudience = function () {
|
|
95
|
+
// const field = "game.audience";
|
|
96
|
+
return z.optional(z.enum(cfgaudience));
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
// [function]
|
|
100
|
+
|
|
101
|
+
const zBanner = function () {
|
|
102
|
+
// const field = "game.banner";
|
|
103
|
+
return z.optional(zPng());
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
// [function]
|
|
107
|
+
|
|
108
|
+
const zBannerVideo = function () {
|
|
109
|
+
// const field = "game.banner_video";
|
|
110
|
+
return z.optional(zMp4());
|
|
111
|
+
};
|
|
112
|
+
|
|
113
|
+
// [function]
|
|
114
|
+
|
|
115
|
+
const zBio = function () {
|
|
116
|
+
const field = "game.bio";
|
|
117
|
+
return z.optional(zText(field, { max: 192, min: 1 }));
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
// [function]
|
|
121
|
+
|
|
122
|
+
const zCover = function () {
|
|
123
|
+
// const field = "game.cover";
|
|
124
|
+
return z.optional(zPng());
|
|
125
|
+
};
|
|
126
|
+
|
|
127
|
+
// [function]
|
|
128
|
+
|
|
129
|
+
const zCoverVideo = function () {
|
|
130
|
+
// const field = "game.cover_video";
|
|
131
|
+
return z.optional(zMp4());
|
|
132
|
+
};
|
|
133
|
+
|
|
134
|
+
// [function]
|
|
135
|
+
|
|
136
|
+
const zDescription = function () {
|
|
137
|
+
const field = "game.description";
|
|
138
|
+
return z.optional(
|
|
139
|
+
z
|
|
140
|
+
.string()
|
|
141
|
+
.min(1)
|
|
142
|
+
.max(4000)
|
|
143
|
+
.refine(
|
|
144
|
+
(str) =>
|
|
145
|
+
str ===
|
|
146
|
+
dom.sanitize(str, {
|
|
147
|
+
ALLOWED_ATTR: cfghtml.ALLOWED_ATTR,
|
|
148
|
+
ALLOWED_TAGS: cfghtml.ALLOWED_TAGS,
|
|
149
|
+
}),
|
|
150
|
+
message(field, "Contains invalid elements."),
|
|
151
|
+
),
|
|
152
|
+
);
|
|
153
|
+
};
|
|
154
|
+
|
|
155
|
+
// [function]
|
|
156
|
+
|
|
157
|
+
const zGallery = function () {
|
|
158
|
+
// const field = "game.gallery";
|
|
159
|
+
return z.optional(z.array(zPng()).min(1).max(12));
|
|
160
|
+
};
|
|
161
|
+
|
|
162
|
+
// [function]
|
|
163
|
+
|
|
164
|
+
const zGenres = function () {
|
|
165
|
+
// const field = "game.genres";
|
|
166
|
+
return z.optional(z.array(z.enum(cfggenre)).max(3));
|
|
167
|
+
};
|
|
168
|
+
|
|
169
|
+
// [function]
|
|
170
|
+
|
|
171
|
+
const zHandle = function () {
|
|
172
|
+
const field = "game.handle";
|
|
173
|
+
return z.optional(
|
|
174
|
+
z
|
|
175
|
+
.string()
|
|
176
|
+
.regex(
|
|
177
|
+
/^[a-z0-9](?:(?![-]{2})[a-z0-9-]){1,22}[a-z0-9]$/u,
|
|
178
|
+
message(field, "Contains invalid characters."),
|
|
179
|
+
),
|
|
180
|
+
);
|
|
181
|
+
};
|
|
182
|
+
|
|
183
|
+
// [function]
|
|
184
|
+
|
|
185
|
+
const zIcon = function () {
|
|
186
|
+
// const field = "game.icon";
|
|
187
|
+
return z.optional(zPng());
|
|
188
|
+
};
|
|
189
|
+
|
|
190
|
+
// [function]
|
|
191
|
+
|
|
192
|
+
const zIconVideo = function () {
|
|
193
|
+
// const field = "game.icon_video";
|
|
194
|
+
return z.optional(zMp4());
|
|
195
|
+
};
|
|
196
|
+
|
|
197
|
+
// [function]
|
|
198
|
+
|
|
199
|
+
const zInputs = function () {
|
|
200
|
+
// const field = "game.inputs";
|
|
201
|
+
return z.optional(z.array(z.enum(cfginput)).max(3));
|
|
202
|
+
};
|
|
203
|
+
|
|
204
|
+
// [function]
|
|
205
|
+
|
|
206
|
+
const zOrientation = function () {
|
|
207
|
+
// const field = "game.orientation";
|
|
208
|
+
return z.optional(z.enum(cfgorientation));
|
|
209
|
+
};
|
|
210
|
+
|
|
211
|
+
// [function]
|
|
212
|
+
|
|
213
|
+
const zPoster = function () {
|
|
214
|
+
// const field = "game.poster";
|
|
215
|
+
return z.optional(zPng());
|
|
216
|
+
};
|
|
217
|
+
|
|
218
|
+
// [function]
|
|
219
|
+
|
|
220
|
+
const zPosterVideo = function () {
|
|
221
|
+
// const field = "game.poster_video";
|
|
222
|
+
return z.optional(zMp4());
|
|
223
|
+
};
|
|
224
|
+
|
|
225
|
+
// [function]
|
|
226
|
+
|
|
227
|
+
const zPrice = function () {
|
|
228
|
+
// const field = "game.price";
|
|
229
|
+
return z.optional(z.int().min(0).max(25));
|
|
230
|
+
};
|
|
231
|
+
|
|
232
|
+
// [function]
|
|
233
|
+
|
|
234
|
+
const zShortTitle = function () {
|
|
235
|
+
const field = "game.short_title";
|
|
236
|
+
return z.optional(zText(field, { max: 16, min: 1 }));
|
|
237
|
+
};
|
|
238
|
+
|
|
239
|
+
// [function]
|
|
240
|
+
|
|
241
|
+
const zTagline = function () {
|
|
242
|
+
const field = "game.tagline";
|
|
243
|
+
return z.optional(zText(field, { max: 96, min: 1 }));
|
|
244
|
+
};
|
|
245
|
+
|
|
246
|
+
// [function]
|
|
247
|
+
|
|
248
|
+
const zTitle = function () {
|
|
249
|
+
const field = "game.title";
|
|
250
|
+
return z.optional(zText(field, { max: 64, min: 1 }));
|
|
251
|
+
};
|
|
252
|
+
|
|
253
|
+
// [function]
|
|
254
|
+
|
|
255
|
+
const zTrailer = function () {
|
|
256
|
+
const field = "game.trailer";
|
|
257
|
+
return z
|
|
258
|
+
.string()
|
|
259
|
+
.max(255)
|
|
260
|
+
.refine(
|
|
261
|
+
(url) =>
|
|
262
|
+
zVimeo().safeParse(url).success || zYouTube().safeParse(url).success,
|
|
263
|
+
message(field, "Must be a YouTube (or Viemo) URL."),
|
|
264
|
+
)
|
|
265
|
+
.optional();
|
|
266
|
+
};
|
|
267
|
+
|
|
268
|
+
// [function]
|
|
269
|
+
|
|
270
|
+
const zVisibility = function () {
|
|
271
|
+
// const field = "game.visibility";
|
|
272
|
+
return z.optional(z.enum(cfgvisibility));
|
|
273
|
+
};
|
|
274
|
+
|
|
275
|
+
// [function]
|
|
276
|
+
|
|
277
|
+
const zWordmark = function () {
|
|
278
|
+
// const field = "game.wordmark";
|
|
279
|
+
return z.optional(zSvg());
|
|
280
|
+
};
|
|
281
|
+
|
|
282
|
+
// [function]
|
|
283
|
+
|
|
284
|
+
const zWordmarkAnimated = function () {
|
|
285
|
+
// const field = "game.wordmark_animated";
|
|
286
|
+
return z.optional(zSvg());
|
|
287
|
+
};
|
|
288
|
+
|
|
289
|
+
// [function]
|
|
290
|
+
|
|
291
|
+
const main = function (value, { root }) {
|
|
292
|
+
/* eslint-disable camelcase */
|
|
293
|
+
return z.object({
|
|
294
|
+
audience: zAudience(),
|
|
295
|
+
banner: zBanner(root),
|
|
296
|
+
banner_video: zBannerVideo(root),
|
|
297
|
+
bio: zBio(),
|
|
298
|
+
cover: zCover(root),
|
|
299
|
+
cover_video: zCoverVideo(root),
|
|
300
|
+
description: zDescription(),
|
|
301
|
+
gallery: zGallery(root),
|
|
302
|
+
genres: zGenres(),
|
|
303
|
+
handle: zHandle(),
|
|
304
|
+
icon: zIcon(root),
|
|
305
|
+
icon_video: zIconVideo(root),
|
|
306
|
+
inputs: zInputs(),
|
|
307
|
+
orientation: zOrientation(),
|
|
308
|
+
poster: zPoster(root),
|
|
309
|
+
poster_video: zPosterVideo(root),
|
|
310
|
+
price: zPrice(),
|
|
311
|
+
short_title: zShortTitle(),
|
|
312
|
+
tagline: zTagline(),
|
|
313
|
+
title: zTitle(),
|
|
314
|
+
trailer: zTrailer(),
|
|
315
|
+
visibility: zVisibility(),
|
|
316
|
+
wordmark: zWordmark(root),
|
|
317
|
+
wordmark_animated: zWordmarkAnimated(root),
|
|
318
|
+
});
|
|
319
|
+
/* eslint-enable camelcase */
|
|
320
|
+
};
|
|
321
|
+
|
|
322
|
+
// [export]
|
|
323
|
+
|
|
324
|
+
module.exports = main;
|