arcadible 0.0.1 → 0.1.0

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/package.json CHANGED
@@ -1,5 +1,42 @@
1
1
  {
2
+ "bin": {
3
+ "arc": "bin/arc.js",
4
+ "arc-check": "bin/arc-check.js",
5
+ "arc-default": "bin/arc-default.js",
6
+ "arc-deploy": "bin/arc-deploy.js",
7
+ "arc-inspect": "bin/arc-inspect.js",
8
+ "arc-pack": "bin/arc-pack.js"
9
+ },
10
+ "dependencies": {
11
+ "@iarna/toml": "^2.2.5",
12
+ "adm-zip": "^0.5.16",
13
+ "chalk": "^4.1.2",
14
+ "dompurify": "^3.3.1",
15
+ "fs-extra": "^11.3.2",
16
+ "image-size": "^2.0.2",
17
+ "jsdom": "^27.3.0",
18
+ "marked": "^17.0.1",
19
+ "mp4box": "^2.3.0",
20
+ "rc": "^1.2.8",
21
+ "yargs": "^17.7.2",
22
+ "zod": "^4.1.13"
23
+ },
24
+ "description": "The Arcadible command-line interface.",
25
+ "engines": {
26
+ "node": ">=24.11.1"
27
+ },
28
+ "exports": {
29
+ "./check": "./src/cmd/check.js",
30
+ "./deploy": "./src/cmd/deploy.js",
31
+ "./inspect": "./src/cmd/inspect.js",
32
+ "./pack": "./src/cmd/pack.js"
33
+ },
34
+ "keywords": [
35
+ "arcadible",
36
+ "cli"
37
+ ],
2
38
  "license": "Apache-2.0",
39
+ "main": "./src/cmd/index.js",
3
40
  "name": "arcadible",
4
- "version": "0.0.1"
41
+ "version": "0.1.0"
5
42
  }
@@ -0,0 +1,26 @@
1
+ "use strict";
2
+
3
+ // [import]
4
+
5
+ const cmdCheck = require("../cmd-check");
6
+ const log = require("../util/log");
7
+ const project = require("../project");
8
+
9
+ // [function]
10
+
11
+ const main = function (conf) {
12
+ project
13
+ .parse(conf.root)
14
+ .then(({ game, workflow }) => {
15
+ cmdCheck(conf, workflow, game);
16
+ })
17
+ .catch((ex) => {
18
+ log.hd("Check aborted.");
19
+ log.pdnl(ex.message);
20
+ process.exit(1);
21
+ });
22
+ };
23
+
24
+ // [export]
25
+
26
+ module.exports = main;
@@ -0,0 +1,22 @@
1
+ "use strict";
2
+
3
+ // [import]
4
+
5
+ const cmdDeploy = require("../cmd-deploy");
6
+ const log = require("../util/log");
7
+
8
+ // [function]
9
+
10
+ const main = function (conf) {
11
+ try {
12
+ cmdDeploy(conf);
13
+ } catch (ex) {
14
+ log.hd("Deploy aborted.");
15
+ log.pdnl(ex.message);
16
+ process.exit(1);
17
+ }
18
+ };
19
+
20
+ // [export]
21
+
22
+ module.exports = main;
@@ -0,0 +1,12 @@
1
+ "use strict";
2
+
3
+ // [import]
4
+
5
+ const check = require("./check");
6
+ const deploy = require("./deploy");
7
+ const inspect = require("./inspect");
8
+ const pack = require("./pack");
9
+
10
+ // [export]
11
+
12
+ module.exports = { check, deploy, inspect, pack };
@@ -0,0 +1,26 @@
1
+ "use strict";
2
+
3
+ // [import]
4
+
5
+ const cmdInspect = require("../cmd-inspect");
6
+ const log = require("../util/log");
7
+ const project = require("../project");
8
+
9
+ // [function]
10
+
11
+ const main = function (conf) {
12
+ project
13
+ .parse(conf.root)
14
+ .then(({ game, workflow }) => {
15
+ cmdInspect(conf, workflow, game);
16
+ })
17
+ .catch((ex) => {
18
+ log.hd("Inspect aborted.");
19
+ log.pdnl(ex.message);
20
+ process.exit(1);
21
+ });
22
+ };
23
+
24
+ // [export]
25
+
26
+ module.exports = main;
@@ -0,0 +1,24 @@
1
+ "use strict";
2
+
3
+ // [import]
4
+
5
+ const cmdPack = require("../cmd-pack");
6
+ const log = require("../util/log");
7
+ const project = require("../project");
8
+
9
+ // [function]
10
+
11
+ const main = function (conf) {
12
+ project
13
+ .parse(conf.root)
14
+ .then(({ game, workflow }) => cmdPack(conf, workflow, game))
15
+ .catch((ex) => {
16
+ log.hd("Pack aborted.");
17
+ log.pdnl(ex.message);
18
+ process.exit(1);
19
+ });
20
+ };
21
+
22
+ // [export]
23
+
24
+ module.exports = main;
@@ -0,0 +1,57 @@
1
+ "use strict";
2
+
3
+ // [import]
4
+
5
+ const gameSchema = require("../schema/game");
6
+ const log = require("../util/log");
7
+ const workflowSchema = require("../schema/workflow");
8
+
9
+ // [declare]
10
+
11
+ const SUCCESS = ["Workspace and manifest are well-formed."];
12
+
13
+ // [function]
14
+
15
+ const formatError = function (schema, zodError) {
16
+ return zodError.issues.map((issue) => {
17
+ const field = issue.path.join(".") || "value";
18
+ return `✖ ${schema}.${field}: ${issue.message}`;
19
+ });
20
+ };
21
+
22
+ // [function]
23
+
24
+ const checkGame = function (root, game) {
25
+ const schema = gameSchema(root, game).safeParse(game);
26
+ if (!schema.success) {
27
+ log.hd("Check failed.");
28
+ log.pdnl(formatError("game", schema.error));
29
+ process.exit(1);
30
+ }
31
+ };
32
+
33
+ // [function]
34
+
35
+ const checkWorkflow = function (root, workflow) {
36
+ const schema = workflowSchema(root, workflow).safeParse(workflow);
37
+ if (!schema.success) {
38
+ log.hd("Check failed.");
39
+ log.pdnl(formatError("workflow", schema.error));
40
+ process.exit(1);
41
+ }
42
+ };
43
+
44
+ // [function]
45
+
46
+ const main = function ({ quiet, root }, workflow, game) {
47
+ checkGame(root, game);
48
+ checkWorkflow(root, workflow);
49
+ if (!quiet) {
50
+ log.hs("Check Passed.");
51
+ log.pnl(SUCCESS);
52
+ }
53
+ };
54
+
55
+ // [export]
56
+
57
+ module.exports = main;
@@ -0,0 +1,43 @@
1
+ "use strict";
2
+
3
+ // [import]
4
+
5
+ const arc = require("../util/arc");
6
+ const git = require("../util/git");
7
+ const log = require("../util/log");
8
+
9
+ // [declare]
10
+
11
+ const SUCCESS = [
12
+ "Await an email from Arcadible confirming a successful release.",
13
+ ];
14
+
15
+ // [function]
16
+
17
+ const main = function ({ pre, preId, quiet, root }) {
18
+ if (!quiet) {
19
+ log.h("Attempting to deploy…");
20
+ }
21
+ git.isDirty(root, (dirty) => {
22
+ if (dirty) {
23
+ log.hd("Deploy aborted.");
24
+ log.pdnl("Git working directory is not clean.");
25
+ process.exit(1);
26
+ }
27
+ arc.deploy(root, { pre, preId }, (err, tag) => {
28
+ if (err) {
29
+ log.hd("Deploy aborted.");
30
+ log.pdnl(err.message);
31
+ process.exit(1);
32
+ }
33
+ if (!quiet) {
34
+ log.hs(`Deploy initiated for ${tag}.`);
35
+ log.pnl(SUCCESS);
36
+ }
37
+ });
38
+ });
39
+ };
40
+
41
+ // [export]
42
+
43
+ module.exports = main;
@@ -0,0 +1,53 @@
1
+ "use strict";
2
+
3
+ // [import]
4
+
5
+ const TOML = require("@iarna/toml");
6
+
7
+ // [function]
8
+
9
+ const write = function (data) {
10
+ process.stdout.write(data.trim().concat("\n"));
11
+ };
12
+
13
+ // [function]
14
+
15
+ const printJson = function (data) {
16
+ write(JSON.stringify(data, null, 2));
17
+ };
18
+
19
+ // [function]
20
+
21
+ const printToml = function (data) {
22
+ write(TOML.stringify(data));
23
+ };
24
+
25
+ // [function]
26
+
27
+ const print = function (data, json) {
28
+ if (json) {
29
+ printJson(data);
30
+ } else {
31
+ printToml(data);
32
+ }
33
+ };
34
+
35
+ // [function]
36
+
37
+ const main = function ({ json, topic }, workflow, game) {
38
+ switch (topic) {
39
+ case "manifest:game":
40
+ print({ game }, json);
41
+ break;
42
+ case "manifest:workflow":
43
+ print({ workflow }, json);
44
+ break;
45
+ default:
46
+ print({ game, workflow }, json);
47
+ break;
48
+ }
49
+ };
50
+
51
+ // [export]
52
+
53
+ module.exports = main;
@@ -0,0 +1,83 @@
1
+ "use strict";
2
+
3
+ // [import]
4
+
5
+ const path = require("node:path");
6
+
7
+ // [import]
8
+
9
+ const fs = require("fs-extra");
10
+ const TOML = require("@iarna/toml");
11
+
12
+ // [import]
13
+
14
+ const Zip = require("../util/zip");
15
+
16
+ // [use]
17
+
18
+ const pathExists = fs.pathExists;
19
+ const pathParse = path.parse;
20
+ const resolve = path.resolve;
21
+
22
+ // [declare]
23
+
24
+ const MANIFEST = "arcadible.json";
25
+ const MEDIA = ".arcadible";
26
+
27
+ // [function]
28
+
29
+ const write = function (data) {
30
+ process.stdout.write(data.trim().concat("\n"));
31
+ };
32
+
33
+ // [function]
34
+
35
+ const printJson = function (data) {
36
+ write(JSON.stringify(data, null, 2));
37
+ };
38
+
39
+ // [function]
40
+
41
+ const printToml = function (data) {
42
+ write(TOML.stringify(data));
43
+ };
44
+
45
+ // [function]
46
+
47
+ const print = function (data, json) {
48
+ if (json) {
49
+ printJson(data);
50
+ } else {
51
+ printToml(data);
52
+ }
53
+ };
54
+
55
+ // [function]
56
+
57
+ const main = function (conf, workflow, game) {
58
+ const { json, out, quiet, root } = conf;
59
+ const { deploy_dir: deployDir } = workflow;
60
+ const pathDeployDir = resolve(root, deployDir);
61
+ const pathMediaDir = resolve(root, MEDIA);
62
+ const zip = new Zip(pathParse(out).name);
63
+ return Promise.all([
64
+ pathExists(pathDeployDir),
65
+ pathExists(pathMediaDir),
66
+ ]).then(([existsDeployDir, existsMediaDir]) => {
67
+ if (existsDeployDir) {
68
+ zip.addDir(pathDeployDir);
69
+ }
70
+ if (existsMediaDir) {
71
+ zip.addDir(pathMediaDir, MEDIA);
72
+ }
73
+ zip.addJson(MANIFEST, { game });
74
+ zip.write(resolve(root, out));
75
+ if (!quiet) {
76
+ print(zip.stat(), json);
77
+ }
78
+ });
79
+ };
80
+
81
+ // [export]
82
+
83
+ module.exports = main;
@@ -0,0 +1,5 @@
1
+ "use strict";
2
+
3
+ // [export]
4
+
5
+ module.exports = ["everyone", "mature"];
@@ -0,0 +1,5 @@
1
+ "use strict";
2
+
3
+ // [export]
4
+
5
+ module.exports = {};
@@ -0,0 +1,22 @@
1
+ "use strict";
2
+
3
+ // [export]
4
+
5
+ module.exports = [
6
+ "action",
7
+ "adventure",
8
+ "arcade",
9
+ "board",
10
+ "card",
11
+ "casino",
12
+ "casual",
13
+ "music",
14
+ "puzzle",
15
+ "racing",
16
+ "rpg",
17
+ "simulation",
18
+ "sports",
19
+ "strategy",
20
+ "trivia",
21
+ "word",
22
+ ];
@@ -0,0 +1,14 @@
1
+ "use strict";
2
+
3
+ // [export]
4
+
5
+ module.exports = [
6
+ "gamepad",
7
+ "gamepad-motion",
8
+ "keyboard",
9
+ "keyboard-mouse",
10
+ "motion",
11
+ "mouse",
12
+ "touch",
13
+ "touch-motion",
14
+ ];
@@ -0,0 +1,14 @@
1
+ "use strict";
2
+
3
+ // [export]
4
+
5
+ module.exports = [
6
+ "any",
7
+ "natural",
8
+ "portrait",
9
+ "portrait-primary",
10
+ "portrait-secondary",
11
+ "landscape",
12
+ "landscape-primary",
13
+ "landscape-secondary",
14
+ ];
@@ -0,0 +1,5 @@
1
+ "use strict";
2
+
3
+ // [export]
4
+
5
+ module.exports = ["private", "unlisted", "public"];
@@ -0,0 +1,5 @@
1
+ "use strict";
2
+
3
+ // [export]
4
+
5
+ module.exports = {};
@@ -0,0 +1,46 @@
1
+ "use strict";
2
+
3
+ // [import]
4
+
5
+ const path = require("node:path");
6
+
7
+ // [import]
8
+
9
+ const fs = require("fs-extra");
10
+ const TOML = require("@iarna/toml");
11
+
12
+ // [use]
13
+
14
+ const join = path.join;
15
+ const readFile = fs.readFile;
16
+
17
+ // [declare]
18
+
19
+ const MANIFEST = "arcadible.toml";
20
+
21
+ // [function]
22
+
23
+ const parseToml = function (buf) {
24
+ try {
25
+ return TOML.parse(buf);
26
+ } catch (ex) {
27
+ throw new Error(`Unable to parse ${MANIFEST}: ${ex.message}`, {
28
+ cause: ex,
29
+ });
30
+ }
31
+ };
32
+
33
+ // [function]
34
+
35
+ const parse = function (root) {
36
+ return new Promise((resolve, reject) => {
37
+ readFile(join(root, MANIFEST), "utf8")
38
+ .then(parseToml)
39
+ .then(resolve)
40
+ .catch(reject);
41
+ });
42
+ };
43
+
44
+ // [export]
45
+
46
+ module.exports = { parse };
package/src/media.js ADDED
@@ -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 };
package/src/project.js ADDED
@@ -0,0 +1,62 @@
1
+ "use strict";
2
+
3
+ // [import]
4
+
5
+ const gameConfig = require("./config/game");
6
+ const manifest = require("./manifest");
7
+ const media = require("./media");
8
+ const promise = require("./util/promise");
9
+ const readme = require("./readme");
10
+ const workflowConfig = require("./config/workflow");
11
+
12
+ // [function]
13
+
14
+ const parseManifest = function (root) {
15
+ return () => manifest.parse(root);
16
+ };
17
+
18
+ // [function]
19
+
20
+ const parseMedia = function (root) {
21
+ return () => media.parse(root);
22
+ };
23
+
24
+ // [function]
25
+
26
+ const parseReadme = function (root) {
27
+ return () => readme.parse(root);
28
+ };
29
+
30
+ // [function]
31
+
32
+ const confGame = function (readmeGame, mediaGame, manifestGame) {
33
+ return {
34
+ ...gameConfig,
35
+ ...(readmeGame || {}),
36
+ ...(mediaGame || {}),
37
+ ...(manifestGame || {}),
38
+ };
39
+ };
40
+
41
+ // [function]
42
+
43
+ const confWorkflow = function (manifestWorkflow) {
44
+ return { ...workflowConfig, ...(manifestWorkflow || {}) };
45
+ };
46
+
47
+ // [function]
48
+
49
+ const parse = function (root) {
50
+ const parsers = [parseManifest, parseMedia, parseReadme];
51
+ return promise
52
+ .serial(parsers.map((fn) => fn(root)))
53
+ .then(([manifestData, mediaData, readmeData]) => {
54
+ const game = confGame(readmeData.game, mediaData.game, manifestData.game);
55
+ const workflow = confWorkflow(manifestData.workflow);
56
+ return { game, workflow };
57
+ });
58
+ };
59
+
60
+ // [export]
61
+
62
+ module.exports = { parse };