arcadible 0.1.18 → 0.1.20

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.
@@ -30,13 +30,17 @@ const main = function (argv) {
30
30
  yargs(hideBin(argv))
31
31
  .scriptName(CMD)
32
32
  .usage("$0 <command> [options]")
33
- .command("init", "Initialize a project")
34
- .command("validate", "Validate project workspace")
35
- .command("deploy", "Deploy to Arcadible")
36
- .command("inspect", "Inspect project metadata")
33
+ .command("init", "Initialize project")
34
+ .command("inspect", "Inspect project")
35
+ .command("validate", "Validate project")
36
+ .command("build", "Build project")
37
+ .command("pack", "Package project")
38
+ .command("deploy", "Deploy project")
39
+ .command("open", "Open a game's store page")
40
+ .command("play", "Play a game")
37
41
  .command("login", "Log in to Arcadible")
38
- .command("logout", "Log out of Arcadible")
39
42
  .command("whoami", "Show Arcadible account")
43
+ .command("logout", "Log out of Arcadible")
40
44
  .help("help")
41
45
  .alias("help", "h")
42
46
  .version(pkg.version)
package/bin/arc-deploy.js CHANGED
@@ -42,8 +42,8 @@ const SUBCMD = "deploy";
42
42
  // [define]
43
43
 
44
44
  const conf = {
45
- git: false,
46
45
  json: false,
46
+ method: "direct",
47
47
  quiet: false,
48
48
  ...findRc(CMD, SUBCMD, process.argv, ["--cwd", "-C"]),
49
49
  };
@@ -97,7 +97,7 @@ const handler = function ({ json, pb, quiet, sw }) {
97
97
  // [function]
98
98
 
99
99
  const start = function (argv) {
100
- const git = argv.git;
100
+ const git = argv.method === "git";
101
101
  const json = argv.json;
102
102
  const quiet = argv.quiet;
103
103
  const root = resolve(process.cwd(), argv.cwd);
@@ -110,7 +110,7 @@ const start = function (argv) {
110
110
  throw new Error(phrase.issuesFound(count));
111
111
  }
112
112
  sw.stop();
113
- sw = new SpinnerWheel("Checking login... %s");
113
+ sw = new SpinnerWheel("Checking... %s");
114
114
  return whoami({ handler: handler({ json, pb, quiet, sw }) });
115
115
  })
116
116
  .then((current) => {
@@ -211,12 +211,15 @@ const main = function (argv) {
211
211
  return start(
212
212
  yargs(hideBin(argv))
213
213
  .scriptName(`${CMD} ${SUBCMD}`)
214
- .usage("$0 [options]")
215
- .option("git", {
216
- default: conf.git,
217
- describe: "Deploy using Git workflow",
218
- type: "boolean",
219
- })
214
+ .usage("$0 [method] [options]")
215
+ .command("$0 [method]", false, (cli) =>
216
+ cli.positional("method", {
217
+ choices: ["direct", "git"],
218
+ default: conf.method,
219
+ describe: "Deploy method",
220
+ type: "string",
221
+ }),
222
+ )
220
223
  .option("json", {
221
224
  alias: "j",
222
225
  default: conf.json,
package/bin/arc-init.js CHANGED
@@ -73,14 +73,13 @@ const handler = function ({ json, quiet, sw }) {
73
73
  const start = function (argv) {
74
74
  const json = argv.json;
75
75
  const quiet = argv.quiet;
76
- const root = resolve(process.cwd(), argv.cwd);
77
76
  const sw = new SpinnerWheel("Initializing... %s");
78
77
  return init({
79
78
  force: true,
80
79
  handler: handler({ json, quiet, sw }),
81
80
  patch: argv.patch,
82
81
  project: argv.project,
83
- root,
82
+ root: resolve(process.cwd(), argv.cwd),
84
83
  template: argv.template,
85
84
  })
86
85
  .then((project) => {
@@ -17,12 +17,14 @@ const log = require("../src/util/log");
17
17
  const output = require("../src/util/output");
18
18
  const pkg = require("../package.json");
19
19
  const rc = require("../src/util/rc");
20
+ const spinner = require("../src/util/spinner");
20
21
 
21
22
  // [use]
22
23
 
23
24
  const findRc = rc.findRc;
24
25
  const print = output.print;
25
26
  const resolve = path.resolve;
27
+ const SpinnerWheel = spinner.SpinnerWheel;
26
28
 
27
29
  // [declare]
28
30
 
@@ -33,27 +35,46 @@ const SUBCMD = "inspect";
33
35
 
34
36
  const conf = {
35
37
  json: false,
36
- key: "",
38
+ selector: null,
37
39
  ...findRc(CMD, SUBCMD, process.argv, ["--cwd", "-C"]),
38
40
  };
39
41
 
40
42
  // [function]
41
43
 
44
+ const handler = function ({ json, sw }) {
45
+ return {
46
+ onInspectFetch() {
47
+ sw.start(json);
48
+ },
49
+ };
50
+ };
51
+
52
+ // [function]
53
+
42
54
  const start = function (argv) {
43
55
  const json = argv.json;
44
- const key = argv.key;
56
+ const selector = argv.selector;
57
+ const sw = new SpinnerWheel("Loading... %s");
45
58
  return inspect({
46
- key,
59
+ game: null,
60
+ handler: handler({ json, sw }),
47
61
  root: resolve(process.cwd(), argv.cwd),
62
+ selector,
48
63
  })
49
64
  .then((data) => {
50
- print(data, { key, toml: !json });
65
+ if (json) {
66
+ print(data);
67
+ return;
68
+ }
69
+ sw.stop(true);
70
+ print(data, { key: selector, toml: true });
51
71
  })
52
72
  .catch((ex) => {
53
73
  const message = ex.message;
54
74
  if (json) {
55
75
  print({ error: { message } });
56
76
  } else {
77
+ sw.stop(true);
57
78
  log.hd("Inspect aborted.");
58
79
  log.p(message);
59
80
  }
@@ -67,11 +88,11 @@ const main = function (argv) {
67
88
  return start(
68
89
  yargs(hideBin(argv))
69
90
  .scriptName(`${CMD} ${SUBCMD}`)
70
- .usage("$0 [key] [options]")
71
- .command("$0 [key]", false, (cli) =>
72
- cli.positional("key", {
73
- default: conf.key,
74
- describe: "Metadata key",
91
+ .usage("$0 [selector] [options]")
92
+ .command("$0 [selector]", false, (cli) =>
93
+ cli.positional("selector", {
94
+ default: conf.selector,
95
+ describe: "Property selector",
75
96
  type: "string",
76
97
  }),
77
98
  )
package/bin/arc-login.js CHANGED
@@ -4,7 +4,6 @@
4
4
  // [import]
5
5
 
6
6
  const hideBin = require("yargs/helpers").hideBin;
7
- const open = require("open");
8
7
  const qrcode = require("qrcode-terminal");
9
8
  const yargs = require("yargs/yargs");
10
9
 
@@ -14,11 +13,13 @@ const log = require("../src/util/log");
14
13
  const login = require("../src/cli/login");
15
14
  const pkg = require("../package.json");
16
15
  const rc = require("../src/util/rc");
16
+ const shell = require("../src/util/shell");
17
17
  const spinner = require("../src/util/spinner");
18
18
 
19
19
  // [use]
20
20
 
21
21
  const findRc = rc.findRc;
22
+ const launch = shell.launch;
22
23
  const SpinnerWheel = spinner.SpinnerWheel;
23
24
 
24
25
  // [declare]
@@ -77,7 +78,7 @@ const handler = function ({ browser, qrcode: qr, sw }) {
77
78
  if (browser) {
78
79
  log.nlp("Press Enter to open the URL.");
79
80
  onLoginEnter(() => {
80
- open(link).catch(() => {});
81
+ launch(link);
81
82
  });
82
83
  }
83
84
  });
package/bin/arc-logout.js CHANGED
@@ -11,18 +11,32 @@ const yargs = require("yargs/yargs");
11
11
  const log = require("../src/util/log");
12
12
  const logout = require("../src/cli/logout");
13
13
  const pkg = require("../package.json");
14
+ const rc = require("../src/util/rc");
15
+
16
+ // [use]
17
+
18
+ const findRc = rc.findRc;
14
19
 
15
20
  // [declare]
16
21
 
17
22
  const CMD = "arc";
18
23
  const SUBCMD = "logout";
19
24
 
25
+ // [define]
26
+
27
+ const conf = {
28
+ quiet: false,
29
+ ...findRc(CMD, SUBCMD, process.argv, ["--cwd", "-C"]),
30
+ };
31
+
20
32
  // [function]
21
33
 
22
- const start = function () {
34
+ const start = function (argv) {
23
35
  return logout()
24
36
  .then(() => {
25
- log.hs("Logged out.");
37
+ if (!argv.quiet) {
38
+ log.hs("Logged out.");
39
+ }
26
40
  })
27
41
  .catch((ex) => {
28
42
  log.hd("Logout aborted.");
@@ -38,6 +52,12 @@ const main = function (argv) {
38
52
  yargs(hideBin(argv))
39
53
  .scriptName(`${CMD} ${SUBCMD}`)
40
54
  .usage("$0 [options]")
55
+ .option("quiet", {
56
+ alias: "q",
57
+ default: conf.quiet,
58
+ describe: "Output only errors",
59
+ type: "boolean",
60
+ })
41
61
  .help("help")
42
62
  .alias("help", "h")
43
63
  .version(pkg.version)
@@ -0,0 +1,109 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+
4
+ // [import]
5
+
6
+ const path = require("node:path");
7
+
8
+ // [import]
9
+
10
+ const hideBin = require("yargs/helpers").hideBin;
11
+ const yargs = require("yargs/yargs");
12
+
13
+ // [import]
14
+
15
+ const cfguri = require("../src/config/uri");
16
+ const log = require("../src/util/log");
17
+ const open = require("../src/cli/open");
18
+ const phrase = require("../src/phrase");
19
+ const pkg = require("../package.json");
20
+ const rc = require("../src/util/rc");
21
+ const shell = require("../src/util/shell");
22
+
23
+ // [use]
24
+
25
+ const findRc = rc.findRc;
26
+ const launch = shell.launch;
27
+ const resolve = path.resolve;
28
+
29
+ // [declare]
30
+
31
+ const CMD = "arc";
32
+ const SUBCMD = "open";
33
+
34
+ // [define]
35
+
36
+ const conf = {
37
+ browser: false,
38
+ game: "self",
39
+ ...findRc(CMD, SUBCMD, process.argv, ["--cwd", "-C"]),
40
+ };
41
+
42
+ // [function]
43
+
44
+ const start = function (argv) {
45
+ return open({
46
+ game: argv.game,
47
+ root: resolve(process.cwd(), argv.cwd),
48
+ })
49
+ .then((data) => {
50
+ const page = data?.page;
51
+ if (!page) {
52
+ throw new Error(phrase.noGameId());
53
+ }
54
+ launch(
55
+ argv.browser
56
+ ? `${cfguri.HOST_HTTP_WWW}${page}`
57
+ : `${cfguri.HOST_APP_STORE}${page}`,
58
+ );
59
+ })
60
+ .catch((ex) => {
61
+ log.hd("Open aborted.");
62
+ log.p(ex.message);
63
+ process.exit(1);
64
+ });
65
+ };
66
+
67
+ // [function]
68
+
69
+ const main = function (argv) {
70
+ return start(
71
+ yargs(hideBin(argv))
72
+ .scriptName(`${CMD} ${SUBCMD}`)
73
+ .usage("$0 [game] [options]")
74
+ .command("$0 [game]", false, (cli) =>
75
+ cli.positional("game", {
76
+ default: conf.game,
77
+ describe: "Game handle or ID",
78
+ type: "string",
79
+ }),
80
+ )
81
+ .option("browser", {
82
+ default: conf.browser,
83
+ describe: "Open in a web browser",
84
+ type: "boolean",
85
+ })
86
+ .option("cwd", {
87
+ alias: "C",
88
+ default: ".",
89
+ describe: "Set the working directory",
90
+ type: "string",
91
+ })
92
+ .help("help")
93
+ .alias("help", "h")
94
+ .version(pkg.version)
95
+ .alias("version", "v")
96
+ .strict()
97
+ .parse(),
98
+ );
99
+ };
100
+
101
+ // [main]
102
+
103
+ if (require.main === module) {
104
+ main(process.argv);
105
+ }
106
+
107
+ // [export]
108
+
109
+ module.exports = { main };
package/bin/arc-pack.js CHANGED
@@ -12,6 +12,7 @@ const yargs = require("yargs/yargs");
12
12
 
13
13
  // [import]
14
14
 
15
+ const cfgworkflow = require("../src/config/workflow");
15
16
  const log = require("../src/util/log");
16
17
  const output = require("../src/util/output");
17
18
  const pack = require("../src/cli/pack");
@@ -36,9 +37,9 @@ const SUBCMD = "pack";
36
37
  // [define]
37
38
 
38
39
  const conf = {
39
- input: null,
40
+ input: cfgworkflow.deploy_dir,
40
41
  json: false,
41
- output: null,
42
+ output: ".arc/package/game.zip",
42
43
  quiet: false,
43
44
  ...findRc(CMD, SUBCMD, process.argv, ["--cwd", "-C"]),
44
45
  };
@@ -0,0 +1,139 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+
4
+ // [import]
5
+
6
+ const path = require("node:path");
7
+
8
+ // [import]
9
+
10
+ const hideBin = require("yargs/helpers").hideBin;
11
+ const yargs = require("yargs/yargs");
12
+
13
+ // [import]
14
+
15
+ const cfguri = require("../src/config/uri");
16
+ const log = require("../src/util/log");
17
+ const phrase = require("../src/phrase");
18
+ const pkg = require("../package.json");
19
+ const play = require("../src/cli/play");
20
+ const rc = require("../src/util/rc");
21
+ const shell = require("../src/util/shell");
22
+ const spinner = require("../src/util/spinner");
23
+
24
+ // [use]
25
+
26
+ const findRc = rc.findRc;
27
+ const launch = shell.launch;
28
+ const resolve = path.resolve;
29
+ const SpinnerWheel = spinner.SpinnerWheel;
30
+
31
+ // [declare]
32
+
33
+ const CMD = "arc";
34
+ const SUBCMD = "play";
35
+
36
+ // [define]
37
+
38
+ const conf = {
39
+ browser: false,
40
+ game: "self",
41
+ quiet: false,
42
+ release: "production",
43
+ ...findRc(CMD, SUBCMD, process.argv, ["--cwd", "-C"]),
44
+ };
45
+
46
+ // [function]
47
+
48
+ const handler = function ({ quiet, sw }) {
49
+ return {
50
+ onPlayFetch() {
51
+ sw.start(quiet);
52
+ },
53
+ };
54
+ };
55
+
56
+ // [function]
57
+
58
+ const start = function (argv) {
59
+ const sw = new SpinnerWheel("Opening... %s");
60
+ return play({
61
+ game: argv.game,
62
+ handler: handler({ quiet: argv.quiet, sw }),
63
+ release: argv.release,
64
+ root: resolve(process.cwd(), argv.cwd),
65
+ })
66
+ .then((data) => {
67
+ const orientation = data?.orientation;
68
+ const url = data?.url;
69
+ if (!orientation || !url) {
70
+ throw new Error(phrase.noGameId());
71
+ }
72
+ sw.stop(true);
73
+ launch(
74
+ argv.browser ? url : `${cfguri.HOST_APP_PLAY}/${orientation}/${url}`,
75
+ );
76
+ })
77
+ .catch((ex) => {
78
+ sw.stop(true);
79
+ log.hd("Play aborted.");
80
+ log.p(ex.message);
81
+ process.exit(1);
82
+ });
83
+ };
84
+
85
+ // [function]
86
+
87
+ const main = function (argv) {
88
+ return start(
89
+ yargs(hideBin(argv))
90
+ .scriptName(`${CMD} ${SUBCMD}`)
91
+ .usage("$0 [game] [options]")
92
+ .command("$0 [game]", false, (cli) =>
93
+ cli.positional("game", {
94
+ default: conf.game,
95
+ describe: "Game handle or ID",
96
+ type: "string",
97
+ }),
98
+ )
99
+ .option("release", {
100
+ alias: "r",
101
+ default: conf.release,
102
+ describe: "Release channel or version",
103
+ type: "string",
104
+ })
105
+ .option("browser", {
106
+ default: conf.browser,
107
+ describe: "Open in a web browser",
108
+ type: "boolean",
109
+ })
110
+ .option("quiet", {
111
+ alias: "q",
112
+ default: conf.quiet,
113
+ describe: "Output only errors",
114
+ type: "boolean",
115
+ })
116
+ .option("cwd", {
117
+ alias: "C",
118
+ default: ".",
119
+ describe: "Set the working directory",
120
+ type: "string",
121
+ })
122
+ .help("help")
123
+ .alias("help", "h")
124
+ .version(pkg.version)
125
+ .alias("version", "v")
126
+ .strict()
127
+ .parse(),
128
+ );
129
+ };
130
+
131
+ // [main]
132
+
133
+ if (require.main === module) {
134
+ main(process.argv);
135
+ }
136
+
137
+ // [export]
138
+
139
+ module.exports = { main };
@@ -41,7 +41,6 @@ const conf = {
41
41
 
42
42
  const start = function (argv) {
43
43
  const json = argv.json;
44
- const quiet = argv.quiet;
45
44
  return validate({ root: resolve(process.cwd(), argv.cwd) })
46
45
  .then((issues) => {
47
46
  const count = issues.length;
@@ -50,7 +49,7 @@ const start = function (argv) {
50
49
  } else if (count) {
51
50
  log.hd(`${count} ${count === 1 ? "issue" : "issues"} found.`);
52
51
  log.p(issues.map((error) => `✗ ${error}`));
53
- } else if (!quiet) {
52
+ } else if (!argv.quiet) {
54
53
  log.hs("No issues found.");
55
54
  }
56
55
  process.exit(count ? 1 : 0);
package/bin/arc-whoami.js CHANGED
@@ -48,7 +48,7 @@ const handler = function ({ json, sw }) {
48
48
 
49
49
  const start = function (argv) {
50
50
  const json = argv.json;
51
- const sw = new SpinnerWheel("Checking login... %s");
51
+ const sw = new SpinnerWheel("Checking... %s");
52
52
  return whoami({ handler: handler({ json, sw }) })
53
53
  .then((current) => {
54
54
  const profile = current?.profile;
package/package.json CHANGED
@@ -7,8 +7,9 @@
7
7
  "arc-inspect": "bin/arc-inspect.js",
8
8
  "arc-login": "bin/arc-login.js",
9
9
  "arc-logout": "bin/arc-logout.js",
10
+ "arc-open": "bin/arc-open.js",
10
11
  "arc-pack": "bin/arc-pack.js",
11
- "arc-predeploy": "bin/arc-predeploy.js",
12
+ "arc-play": "bin/arc-play.js",
12
13
  "arc-validate": "bin/arc-validate.js",
13
14
  "arc-whoami": "bin/arc-whoami.js"
14
15
  },
@@ -46,7 +47,9 @@
46
47
  "./inspect": "./src/cli/inspect.js",
47
48
  "./login": "./src/cli/login.js",
48
49
  "./logout": "./src/cli/logout.js",
50
+ "./open": "./src/cli/open.js",
49
51
  "./pack": "./src/cli/pack.js",
52
+ "./play": "./src/cli/play.js",
50
53
  "./predeploy": "./src/cli/predeploy.js",
51
54
  "./validate": "./src/cli/validate.js",
52
55
  "./whoami": "./src/cli/whoami.js"
@@ -58,5 +61,5 @@
58
61
  "license": "Apache-2.0",
59
62
  "main": "./src/cli/index.js",
60
63
  "name": "arcadible",
61
- "version": "0.1.18"
64
+ "version": "0.1.20"
62
65
  }
package/src/account.js CHANGED
@@ -71,15 +71,16 @@ const get = function (onRefresh) {
71
71
  }
72
72
  throw ex;
73
73
  })
74
- .then((account) => {
75
- if (!account || !account.session) {
74
+ .then((current) => {
75
+ const session = current?.session;
76
+ if (!session) {
76
77
  return null;
77
78
  }
78
- return expired(account.session)
79
+ return expired(session)
79
80
  ? (onRefresh &&
80
- onRefresh((renew) => (renew ? refresh(account) : null))) ||
81
+ onRefresh((renew) => (renew ? refresh(current) : null))) ||
81
82
  null
82
- : account;
83
+ : current;
83
84
  });
84
85
  };
85
86
 
@@ -0,0 +1,39 @@
1
+ "use strict";
2
+
3
+ // [declare]
4
+
5
+ const ART = [
6
+ "banner",
7
+ "banner_video",
8
+ "cover",
9
+ "cover_video",
10
+ "icon",
11
+ "icon_video",
12
+ "poster",
13
+ "poster_video",
14
+ "wordmark",
15
+ "wordmark_animated",
16
+ ];
17
+
18
+ // [declare]
19
+
20
+ const MEDIA = ".arcadible";
21
+
22
+ // [function]
23
+
24
+ const dehydrate = function (game) {
25
+ for (const key of ART) {
26
+ const media = game[key];
27
+ if (media && typeof media === "object" && media.src) {
28
+ const index = media.src.indexOf(MEDIA);
29
+ if (index !== -1) {
30
+ game[key] = media.src.slice(index);
31
+ }
32
+ }
33
+ }
34
+ return game;
35
+ };
36
+
37
+ // [export]
38
+
39
+ module.exports = { dehydrate };
@@ -6,18 +6,54 @@ const dotProp = require("dot-prop");
6
6
 
7
7
  // [import]
8
8
 
9
+ const api = require("../../api");
10
+ const media = require("./media");
11
+ const phrase = require("../../phrase");
9
12
  const project = require("../../parser/project");
10
13
 
11
14
  // [function]
12
15
 
13
- const inspect = function (proj, key) {
16
+ const select = function (proj, key) {
14
17
  return key ? dotProp.get(proj, key, null) : proj;
15
18
  };
16
19
 
17
20
  // [function]
18
21
 
19
- const main = function ({ key, root }) {
20
- return project(root).then((proj) => inspect(proj, key));
22
+ const inspect = function (id) {
23
+ return api
24
+ .discoverGameBuilds(id, {
25
+ channel: "production",
26
+ select: "manifest",
27
+ })
28
+ .then((builds) => {
29
+ if (!builds.length) {
30
+ throw new Error(phrase.noProductionBuild(id));
31
+ }
32
+ const manifest = builds[0]?.manifest ?? {};
33
+ if (manifest.game) {
34
+ media.dehydrate(manifest.game);
35
+ }
36
+ return manifest;
37
+ });
38
+ };
39
+
40
+ // [function]
41
+
42
+ const main = function ({ game: id, root, selector }, { onInspectFetch }) {
43
+ const local = !id;
44
+ if (onInspectFetch && !local) {
45
+ onInspectFetch({ game: id });
46
+ }
47
+ if (local) {
48
+ return project(root).then((data) => select(data, selector));
49
+ }
50
+ if (id === "self") {
51
+ return project(root)
52
+ .then(({ game }) => game?.handle ?? game?.id)
53
+ .then(inspect)
54
+ .then((data) => select(data, selector));
55
+ }
56
+ return inspect(id).then((data) => select(data, selector));
21
57
  };
22
58
 
23
59
  // [export]
@@ -0,0 +1,24 @@
1
+ "use strict";
2
+
3
+ // [import]
4
+
5
+ const project = require("../../parser/project");
6
+
7
+ // [function]
8
+
9
+ const open = function (id) {
10
+ return id ? { page: `/play/${id}` } : null;
11
+ };
12
+
13
+ // [function]
14
+
15
+ const main = function ({ game: id, root }) {
16
+ if (id === "self") {
17
+ return project(root).then(({ game }) => open(game?.handle ?? game?.id));
18
+ }
19
+ return Promise.resolve(open(id));
20
+ };
21
+
22
+ // [export]
23
+
24
+ module.exports = main;
@@ -0,0 +1,42 @@
1
+ "use strict";
2
+
3
+ // [import]
4
+
5
+ const api = require("../../api");
6
+ const cfguri = require("../../config/uri");
7
+ const project = require("../../parser/project");
8
+
9
+ // [function]
10
+
11
+ const play = function (id, release) {
12
+ if (!id) {
13
+ return Promise.resolve(null);
14
+ }
15
+ const target = release === "production" ? "" : `:${release}`;
16
+ const url = `${cfguri.HOST_HTTP_PLAY}/${id}${target}/`;
17
+ return api
18
+ .discoverGame(id, { select: "orientation" })
19
+ .catch(() => null)
20
+ .then((game) => ({
21
+ orientation: game?.orientation ?? "natural",
22
+ url,
23
+ }));
24
+ };
25
+
26
+ // [function]
27
+
28
+ const main = function ({ game: id, release, root }, { onPlayFetch }) {
29
+ if (onPlayFetch) {
30
+ onPlayFetch({ game: id });
31
+ }
32
+ if (id === "self") {
33
+ return project(root).then(({ game }) =>
34
+ play(game?.handle ?? game?.id, release),
35
+ );
36
+ }
37
+ return play(id, release);
38
+ };
39
+
40
+ // [export]
41
+
42
+ module.exports = main;
package/src/api.js CHANGED
@@ -42,6 +42,18 @@ const postUpload = function (form, opts) {
42
42
 
43
43
  // [function]
44
44
 
45
+ const discoverGame = function (id, opts) {
46
+ return request.get(endpoint(`/discover/games/${id}`), opts);
47
+ };
48
+
49
+ // [function]
50
+
51
+ const discoverGameBuilds = function (id, opts) {
52
+ return request.get(endpoint(`/discover/games/${id}/builds`), opts);
53
+ };
54
+
55
+ // [function]
56
+
45
57
  const gameBuild = function (id, version, opts) {
46
58
  return request.get(endpoint(`/games/${id}/builds/${version}`), opts);
47
59
  };
@@ -49,6 +61,8 @@ const gameBuild = function (id, version, opts) {
49
61
  // [export]
50
62
 
51
63
  module.exports = {
64
+ discoverGame,
65
+ discoverGameBuilds,
52
66
  flow,
53
67
  gameBuild,
54
68
  postAuthRefresh,
package/src/cli/index.js CHANGED
@@ -8,7 +8,9 @@ const init = require("./init");
8
8
  const inspect = require("./inspect");
9
9
  const login = require("./login");
10
10
  const logout = require("./logout");
11
+ const open = require("./open");
11
12
  const pack = require("./pack");
13
+ const play = require("./play");
12
14
  const predeploy = require("./predeploy");
13
15
  const validate = require("./validate");
14
16
  const whoami = require("./whoami");
@@ -22,7 +24,9 @@ module.exports = {
22
24
  inspect,
23
25
  login,
24
26
  logout,
27
+ open,
25
28
  pack,
29
+ play,
26
30
  predeploy,
27
31
  validate,
28
32
  whoami,
@@ -6,8 +6,8 @@ const inspectTool = require("../action/inspect/tool");
6
6
 
7
7
  // [function]
8
8
 
9
- const main = function (conf) {
10
- return inspectTool(conf);
9
+ const main = function ({ handler, ...conf }) {
10
+ return inspectTool(conf, handler);
11
11
  };
12
12
 
13
13
  // [export]
@@ -0,0 +1,15 @@
1
+ "use strict";
2
+
3
+ // [import]
4
+
5
+ const openTool = require("../action/open/tool");
6
+
7
+ // [function]
8
+
9
+ const main = function (conf) {
10
+ return openTool(conf);
11
+ };
12
+
13
+ // [export]
14
+
15
+ module.exports = main;
@@ -0,0 +1,15 @@
1
+ "use strict";
2
+
3
+ // [import]
4
+
5
+ const playTool = require("../action/play/tool");
6
+
7
+ // [function]
8
+
9
+ const main = function ({ handler, ...conf }) {
10
+ return playTool(conf, handler);
11
+ };
12
+
13
+ // [export]
14
+
15
+ module.exports = main;
package/src/config/uri.js CHANGED
@@ -2,13 +2,17 @@
2
2
 
3
3
  // [declare]
4
4
 
5
- const SLD = "arcadible";
5
+ const DOMAIN = "arcadible";
6
+ const PROTOCOL = DOMAIN;
6
7
 
7
8
  // [export]
8
9
 
9
10
  module.exports = {
10
- HOST_HTTP_ACCOUNT: `https://account.${SLD}.com`,
11
- HOST_HTTP_API: `https://api.${SLD}.com`,
12
- HOST_HTTP_DEVELOPER: `https://developer.${SLD}.com`,
13
- HOST_HTTP_WWW: `https://${SLD}.com`,
11
+ HOST_APP_PLAY: `${PROTOCOL}://play`,
12
+ HOST_APP_STORE: `${PROTOCOL}://store`,
13
+ HOST_HTTP_ACCOUNT: `https://account.${DOMAIN}.com`,
14
+ HOST_HTTP_API: `https://api.${DOMAIN}.com`,
15
+ HOST_HTTP_DEVELOPER: `https://developer.${DOMAIN}.com`,
16
+ HOST_HTTP_PLAY: `https://play.${DOMAIN}.com`,
17
+ HOST_HTTP_WWW: `https://${DOMAIN}.com`,
14
18
  };
package/src/config/url.js CHANGED
@@ -4,14 +4,10 @@
4
4
 
5
5
  const cfguri = require("./uri");
6
6
 
7
- // [declare]
8
-
9
- const SLD = "arcadible";
10
-
11
7
  // [export]
12
8
 
13
9
  module.exports = {
14
10
  GETTING_STARTED: `${cfguri.HOST_HTTP_DEVELOPER}/guides/games/getting-started`,
15
11
  LINK: `${cfguri.HOST_HTTP_ACCOUNT}/link`,
16
- MANIFEST: `${cfguri.HOST_HTTP_DEVELOPER}/references/${SLD}-manifest`,
12
+ MANIFEST: `${cfguri.HOST_HTTP_DEVELOPER}/references/arcadible-manifest`,
17
13
  };
@@ -95,7 +95,7 @@ const extractDescription = function (doc) {
95
95
  const parts = [];
96
96
  let node = first.nextSibling;
97
97
  while (node && node !== last) {
98
- parts.push(node.outerHTML || node.textContent);
98
+ parts.push(node.outerHTML ?? node.textContent);
99
99
  node = node.nextSibling;
100
100
  }
101
101
  return trimWhitespace(parts.join(""));
@@ -135,7 +135,7 @@ const findReadme = function (root) {
135
135
  README.map((file) =>
136
136
  pathExists(join(root, file)).then((exists) => (exists ? file : null)),
137
137
  ),
138
- ).then((files) => files.find(Boolean) || null);
138
+ ).then((files) => files.find(Boolean) ?? null);
139
139
  };
140
140
 
141
141
  // [function]
@@ -145,7 +145,7 @@ const main = function (root) {
145
145
  .then((file) => (file ? readFile(join(root, file), "utf8") : null))
146
146
  .then((buf) => (buf === null ? null : parseReadme(buf)))
147
147
  .then(deepCompact)
148
- .then((game) => ({ game: game || null }));
148
+ .then((game) => ({ game: game ?? null }));
149
149
  };
150
150
 
151
151
  // [export]
package/src/phrase.js CHANGED
@@ -74,6 +74,18 @@ const loginFailed = function () {
74
74
 
75
75
  // [function]
76
76
 
77
+ const noGameId = function () {
78
+ return "No game handle or ID.";
79
+ };
80
+
81
+ // [function]
82
+
83
+ const noProductionBuild = function () {
84
+ return "No production build found.";
85
+ };
86
+
87
+ // [function]
88
+
77
89
  const notLoggedIn = function () {
78
90
  return "Not logged in. Run `arc login` to log in.";
79
91
  };
@@ -144,6 +156,8 @@ module.exports = {
144
156
  issuesFound,
145
157
  loginExpired,
146
158
  loginFailed,
159
+ noGameId,
160
+ noProductionBuild,
147
161
  noVideoMetadata,
148
162
  noVideoTrack,
149
163
  notLoggedIn,
@@ -2,7 +2,8 @@
2
2
 
3
3
  // [declare]
4
4
 
5
- const REPO = "arcadible";
5
+ const OWNER = "arcadible";
6
+ const REPO = "starter";
6
7
 
7
8
  // [export]
8
9
 
@@ -10,32 +11,37 @@ module.exports = {
10
11
  select: {
11
12
  choices: [
12
13
  {
13
- description: "Plain JavaScript starter.",
14
- name: "Default",
15
- value: `${REPO}/starter`,
14
+ alias: "blank",
15
+ description: "Blank JavaScript starter.",
16
+ name: "Blank",
17
+ value: `${OWNER}/${REPO}`,
16
18
  },
17
19
  {
20
+ alias: "threejs",
18
21
  description: "Three.js starter.",
19
22
  name: "Three.js",
20
- value: `${REPO}/starter-threejs`,
23
+ value: `${OWNER}/${REPO}-threejs`,
21
24
  },
22
25
  {
26
+ alias: "phaser",
23
27
  description: "Phaser starter.",
24
28
  name: "Phaser",
25
- value: `${REPO}/starter-phaser`,
29
+ value: `${OWNER}/${REPO}-phaser`,
26
30
  },
27
31
  {
32
+ alias: "pixijs",
28
33
  description: "PixiJS starter.",
29
34
  name: "PixiJS",
30
- value: `${REPO}/starter-pixijs`,
35
+ value: `${OWNER}/${REPO}-pixijs`,
31
36
  },
32
37
  {
38
+ alias: "babylonjs",
33
39
  description: "Babylon.js starter.",
34
40
  name: "Babylon.js",
35
- value: `${REPO}/starter-babylonjs`,
41
+ value: `${OWNER}/${REPO}-babylonjs`,
36
42
  },
37
43
  ],
38
- default: `${REPO}/starter`,
44
+ default: `${OWNER}/${REPO}`,
39
45
  message: "Template",
40
46
  },
41
47
  };
@@ -305,7 +305,7 @@ const zId = function () {
305
305
  .string(
306
306
  message(field, [
307
307
  "Must be defined.",
308
- "Run `arc init` to generate a new ID.",
308
+ "Run `arc init` to generate a new game ID.",
309
309
  ]),
310
310
  )
311
311
  .uuid(message(field, ["Must be a valid UUID."]))
@@ -71,7 +71,7 @@ const zDeployDir = function (root, { build }) {
71
71
  (file) => build || existsCheck(root, file),
72
72
  message(field, [
73
73
  "Must exist when no build step is defined.",
74
- "Run `arc inspect workflow` for details.",
74
+ "Run `arc inspect` for details.",
75
75
  ]),
76
76
  );
77
77
  };
package/src/util/http.js CHANGED
@@ -6,10 +6,11 @@ const HttpError = class extends Error {
6
6
 
7
7
  // [constructor]
8
8
 
9
- constructor(status, message) {
9
+ constructor(status, { message, title }) {
10
10
  super(message);
11
- this.name = "HttpError";
12
11
  this.status = status;
12
+ this.name = title;
13
+ this.message = `HttpError: ${this.name} (${this.status})`;
13
14
  }
14
15
  };
15
16
 
@@ -23,8 +23,8 @@ const printJson = function (data) {
23
23
 
24
24
  // [function]
25
25
 
26
- const printToml = function (data, key = "value") {
27
- const field = key.split(".").at(-1);
26
+ const printToml = function (data, key) {
27
+ const field = (key ?? "value").split(".").at(-1);
28
28
  if (data === null) {
29
29
  write(`# ${field} = null`);
30
30
  return;
package/src/util/rc.js CHANGED
@@ -33,7 +33,7 @@ const config = function (cmd, argv, option) {
33
33
  // [function]
34
34
 
35
35
  const findRc = function (cmd, subcmd, argv, option) {
36
- return rc(cmd, {}, { config: config(cmd, argv, option) })[subcmd] || {};
36
+ return rc(cmd, {}, { config: config(cmd, argv, option) })[subcmd] ?? {};
37
37
  };
38
38
 
39
39
  // [export]
@@ -19,7 +19,7 @@ const CLIENT_VERSION = pkg.version;
19
19
  const parse = function (resp) {
20
20
  return resp.json().then((json) => {
21
21
  if (!resp.ok) {
22
- throw new HttpError(resp.status, json.data.message);
22
+ throw new HttpError(resp.status, json.data);
23
23
  }
24
24
  return json.data;
25
25
  });
@@ -0,0 +1,15 @@
1
+ "use strict";
2
+
3
+ // [import]
4
+
5
+ const open = require("open");
6
+
7
+ // [function]
8
+
9
+ const launch = function (uri) {
10
+ open(uri).catch(() => {});
11
+ };
12
+
13
+ // [export]
14
+
15
+ module.exports = { launch };
package/src/util/video.js CHANGED
@@ -50,7 +50,7 @@ const readMp4 = function (file) {
50
50
  let video = null;
51
51
  mp4.onReady = (info) => {
52
52
  const track = info.tracks.find((t) => t.video);
53
- if (!track || !track.video) {
53
+ if (!track?.video) {
54
54
  error = new Error(phrase.noVideoTrack());
55
55
  return;
56
56
  }
@@ -1,2 +0,0 @@
1
- #!/usr/bin/env node
2
- "use strict";