arcadible 0.1.9 → 0.1.11

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,13 @@ 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")
33
35
  .command("deploy", "Deploy to Arcadible")
34
- .command("validate", "Validate workspace")
35
36
  .command("inspect", "Inspect project metadata")
36
- .command("init", "Initialize a project")
37
- .command("whoami", "Show current Arcadible account")
38
37
  .command("login", "Log in to Arcadible")
39
38
  .command("logout", "Log out of Arcadible")
39
+ .command("whoami", "Show Arcadible account")
40
40
  .help("help")
41
41
  .alias("help", "h")
42
42
  .version(pkg.version)
package/bin/arc-deploy.js CHANGED
@@ -18,6 +18,7 @@ const output = require("../src/util/output");
18
18
  const pkg = require("../package.json");
19
19
  const rc = require("../src/util/rc");
20
20
  const validate = require("../src/cli/validate");
21
+ const whoami = require("../src/cli/whoami");
21
22
 
22
23
  // [use]
23
24
 
@@ -60,6 +61,12 @@ const handler = function ({ json, quiet }) {
60
61
  log.p(`• ${message}`);
61
62
  }
62
63
  },
64
+ onRefresh(refresh) {
65
+ if (!json) {
66
+ log.p("Checking login...");
67
+ }
68
+ return refresh(true);
69
+ },
63
70
  };
64
71
  };
65
72
 
@@ -69,7 +76,13 @@ const start = function (argv) {
69
76
  const json = argv.json;
70
77
  const quiet = argv.quiet;
71
78
  const root = resolve(process.cwd(), argv.cwd);
72
- return validate({ root })
79
+ return whoami({ handler: handler({ json, quiet }) })
80
+ .then((current) => {
81
+ if (!current || !current.profile) {
82
+ throw new Error("Not logged in. Run `arc login` to log in.");
83
+ }
84
+ return validate({ root });
85
+ })
73
86
  .then((issues) => {
74
87
  const valid = !issues.length;
75
88
  if (!valid) {
@@ -112,7 +125,7 @@ const main = function (argv) {
112
125
  .usage("$0 [options]")
113
126
  .option("git", {
114
127
  default: conf.git,
115
- describe: "Deploy through Git",
128
+ describe: "Deploy using Git workflow",
116
129
  type: "boolean",
117
130
  })
118
131
  .option("json", {
package/bin/arc-init.js CHANGED
@@ -82,14 +82,18 @@ const start = function (argv) {
82
82
  }
83
83
  if (!quiet) {
84
84
  log.hsnl("Initialized.");
85
+ log.h("Getting started:");
86
+ log.pnl(cfgurl.GETTING_STARTED);
85
87
  log.h("Next steps:");
86
- log.pnl(
87
- [data.path === root ? null : `cd ${dir}`, "npm install", "arc deploy"]
88
+ log.p(
89
+ [
90
+ data.path === root ? null : `cd ${dir}`,
91
+ "arc login",
92
+ "arc deploy (or: arc deploy --git)",
93
+ ]
88
94
  .filter(Boolean)
89
- .join(" && "),
95
+ .map((step, i) => `${i + 1}. ${step}`),
90
96
  );
91
- log.h("Getting started:");
92
- log.p(cfgurl.GETTING_STARTED);
93
97
  }
94
98
  // degit sometimes hangs
95
99
  process.exit(0);
@@ -149,7 +153,7 @@ const main = function (argv) {
149
153
  .option("yes", {
150
154
  alias: "y",
151
155
  default: conf.yes,
152
- describe: "Answer prompts using default values",
156
+ describe: "Accept all prompt defaults",
153
157
  type: "boolean",
154
158
  })
155
159
  .option("json", {
package/package.json CHANGED
@@ -51,5 +51,5 @@
51
51
  "license": "Apache-2.0",
52
52
  "main": "./src/cli/index.js",
53
53
  "name": "arcadible",
54
- "version": "0.1.9"
54
+ "version": "0.1.11"
55
55
  }
@@ -17,7 +17,7 @@ const os = require("./util/os");
17
17
  // [use]
18
18
 
19
19
  const configDir = os.configDir;
20
- const deepCompact = objs.deepCompact;
20
+ const deepSort = objs.deepSort;
21
21
  const join = path.join;
22
22
  const mkdir = fs.promises.mkdir;
23
23
  const readFile = fs.promises.readFile;
@@ -27,7 +27,7 @@ const writeFile = fs.promises.writeFile;
27
27
  // [declare]
28
28
 
29
29
  const CMD = "arc";
30
- const FILE = "user.json";
30
+ const FILE = "account.json";
31
31
 
32
32
  // [define]
33
33
 
@@ -42,20 +42,22 @@ const expired = function (session) {
42
42
 
43
43
  // [function]
44
44
 
45
- const save = function (user) {
45
+ const save = function (account) {
46
46
  return mkdir(dir, { recursive: true })
47
47
  .then(() =>
48
- writeFile(file, JSON.stringify(deepCompact(user), null, 2), "utf8"),
48
+ writeFile(file, JSON.stringify(deepSort(account), null, 2), "utf8"),
49
49
  )
50
- .then(() => user);
50
+ .then(() => account);
51
51
  };
52
52
 
53
53
  // [function]
54
54
 
55
- const refresh = function ({ session, ...user }) {
55
+ const refresh = function ({ session, ...account }) {
56
56
  const form = new FormData();
57
57
  form.append("refresh_token", session.refresh_token);
58
- return api.authRefresh(form).then((data) => save({ ...user, session: data }));
58
+ return api
59
+ .authRefresh(form)
60
+ .then((data) => save({ ...account, session: data }));
59
61
  };
60
62
 
61
63
  // [function]
@@ -69,13 +71,13 @@ const get = function ({ onRefresh }) {
69
71
  }
70
72
  throw ex;
71
73
  })
72
- .then((user) => {
73
- if (!user || !user.session) {
74
+ .then((account) => {
75
+ if (!account || !account.session) {
74
76
  return null;
75
77
  }
76
- return expired(user.session)
77
- ? onRefresh((renew) => (renew ? refresh(user) : null))
78
- : user;
78
+ return expired(account.session)
79
+ ? onRefresh((renew) => (renew ? refresh(account) : null))
80
+ : account;
79
81
  });
80
82
  };
81
83
 
@@ -44,7 +44,7 @@ const ensureRepo = function (root, cb) {
44
44
  const ensureRemote = function (root, cb) {
45
45
  const message = [
46
46
  "Unable to access Git remote 'origin'.",
47
- "Ensure the remote exists and you have permission to access it.",
47
+ "Ensure the remote 'origin' exists and you have permission to access it.",
48
48
  ];
49
49
  git(root, ["ls-remote", "origin"], (err) => {
50
50
  if (err) {
@@ -8,7 +8,10 @@ const path = require("node:path");
8
8
  // [import]
9
9
 
10
10
  const fs = require("fs-extra");
11
- const TOML = require("@iarna/toml");
11
+
12
+ // [import]
13
+
14
+ const TOML = require("../../util/toml");
12
15
 
13
16
  // [use]
14
17
 
@@ -37,14 +40,10 @@ const parseToml = function (buf) {
37
40
  // [function]
38
41
 
39
42
  const pickVersion = function (version, envVersion) {
40
- switch (true) {
41
- case Boolean(version):
42
- return { version };
43
- case Boolean(envVersion):
44
- return {};
45
- default:
46
- return { version: "0.1.0" };
43
+ if (version) {
44
+ return { version };
47
45
  }
46
+ return envVersion ? {} : { version: "0.1.0" };
48
47
  };
49
48
 
50
49
  // [function]
@@ -57,7 +56,7 @@ const readManifest = function (file) {
57
56
 
58
57
  // [function]
59
58
 
60
- const prepareGame = function (envVersion, game = {}) {
59
+ const patchGame = function (envVersion, game = {}) {
61
60
  const { id, version, ...rest } = game;
62
61
  return {
63
62
  id: id ?? randomUUID(),
@@ -81,7 +80,7 @@ const prepare = function (dest, envVersion) {
81
80
  const file = join(dest, MANIFEST);
82
81
  return readManifest(file).then((manifest) => {
83
82
  const { game, ...rest } = manifest;
84
- const next = { game: prepareGame(envVersion, game), ...rest };
83
+ const next = { game: patchGame(envVersion, game), ...rest };
85
84
  if (shouldWrite(manifest, next)) {
86
85
  return writeFile(file, TOML.stringify(next), "utf8");
87
86
  }
@@ -16,7 +16,7 @@ const resolve = path.resolve;
16
16
 
17
17
  // [function]
18
18
 
19
- const inferVersion = function (root) {
19
+ const detectVersion = function (root) {
20
20
  return env(root).then(({ game }) => game?.version ?? null);
21
21
  };
22
22
 
@@ -28,10 +28,10 @@ const init = function () {
28
28
 
29
29
  // [function]
30
30
 
31
- const main = function ({ project, root }) {
31
+ const main = function ({ force, project, root, template }, handler) {
32
32
  const dest = resolve(root, project);
33
- return init()
34
- .then(() => inferVersion(dest))
33
+ return init(dest, { force, template }, handler)
34
+ .then(() => detectVersion(dest))
35
35
  .then((version) => prepare(dest, version))
36
36
  .then(() => ({ path: dest }));
37
37
  };
@@ -34,13 +34,13 @@ const removeLicense = function (dest) {
34
34
 
35
35
  // [function]
36
36
 
37
- const inferVersion = function (root) {
37
+ const detectVersion = function (root) {
38
38
  return env(root).then(({ game }) => game?.version ?? null);
39
39
  };
40
40
 
41
41
  // [function]
42
42
 
43
- const init = function (src, dest, { onBegin, onInfo }) {
43
+ const scaffold = function (src, dest, { onBegin, onInfo }) {
44
44
  onBegin({ dest, src });
45
45
  return degit(src, { cache: false, force: true, verbose: false })
46
46
  .on("info", onInfo)
@@ -49,19 +49,22 @@ const init = function (src, dest, { onBegin, onInfo }) {
49
49
 
50
50
  // [function]
51
51
 
52
+ const init = function (dest, { force, template }, handler) {
53
+ return pathExists(dest).then((exists) => {
54
+ if (exists && !force) {
55
+ throw new Error("Directory already exists. Use `--force` to overwrite.");
56
+ }
57
+ return scaffold(template, dest, handler);
58
+ });
59
+ };
60
+
61
+ // [function]
62
+
52
63
  const main = function ({ force, project, root, template }, handler) {
53
64
  const dest = resolve(root, project);
54
- return pathExists(dest)
55
- .then((exists) => {
56
- if (exists && !force) {
57
- throw new Error(
58
- "Directory already exists. Use `--force` to overwrite.",
59
- );
60
- }
61
- return init(template, dest, handler);
62
- })
65
+ return init(dest, { force, template }, handler)
63
66
  .then(() => removeLicense(dest))
64
- .then(() => inferVersion(dest))
67
+ .then(() => detectVersion(dest))
65
68
  .then((version) => prepare(dest, version))
66
69
  .then(() => ({ path: dest }));
67
70
  };
@@ -2,13 +2,13 @@
2
2
 
3
3
  // [import]
4
4
 
5
+ const account = require("../../account");
5
6
  const flow = require("./flow");
6
- const user = require("../../user");
7
7
 
8
8
  // [function]
9
9
 
10
10
  const main = function (conf, handler) {
11
- return flow(handler).then(user.save);
11
+ return flow(handler).then(account.save);
12
12
  };
13
13
 
14
14
  // [export]
@@ -2,12 +2,12 @@
2
2
 
3
3
  // [import]
4
4
 
5
- const user = require("../../user");
5
+ const account = require("../../account");
6
6
 
7
7
  // [function]
8
8
 
9
9
  const main = function () {
10
- return user.remove();
10
+ return account.remove();
11
11
  };
12
12
 
13
13
  // [export]
@@ -2,12 +2,12 @@
2
2
 
3
3
  // [import]
4
4
 
5
- const user = require("../../user");
5
+ const account = require("../../account");
6
6
 
7
7
  // [function]
8
8
 
9
9
  const main = function (conf, handler) {
10
- return user.get(handler);
10
+ return account.get(handler);
11
11
  };
12
12
 
13
13
  // [export]
package/src/parser/env.js CHANGED
@@ -37,10 +37,10 @@ const parseJson = function (buf) {
37
37
 
38
38
  // [function]
39
39
 
40
- const extract = function (pkg) {
40
+ const extract = function (conf) {
41
41
  /* eslint-disable camelcase */
42
- const game = { version: pkg.version };
43
- const workflow = { build: pkg.scripts?.build ?? "" };
42
+ const game = { version: conf.version };
43
+ const workflow = { build: conf.scripts?.build ?? "" };
44
44
  /* eslint-enable camelcase */
45
45
  return deepCompact({ game, workflow });
46
46
  };
@@ -52,7 +52,7 @@ const main = function (root) {
52
52
  return pathExists(file)
53
53
  .then((exists) => (exists ? readFile(file, "utf8") : null))
54
54
  .then((buf) => (buf === null ? {} : parseJson(buf)))
55
- .then((pkg) => (Object.keys(pkg).length ? extract(pkg) : {}));
55
+ .then((conf) => (Object.keys(conf).length ? extract(conf) : {}));
56
56
  };
57
57
 
58
58
  // [export]
@@ -7,10 +7,15 @@ const path = require("node:path");
7
7
  // [import]
8
8
 
9
9
  const fs = require("fs-extra");
10
- const TOML = require("@iarna/toml");
10
+
11
+ // [import]
12
+
13
+ const objs = require("../util/objs");
14
+ const TOML = require("../util/toml");
11
15
 
12
16
  // [use]
13
17
 
18
+ const deepCompact = objs.deepCompact;
14
19
  const join = path.join;
15
20
  const pathExists = fs.pathExists;
16
21
  const readFile = fs.readFile;
@@ -33,11 +38,18 @@ const parseToml = function (buf) {
33
38
 
34
39
  // [function]
35
40
 
41
+ const extract = function (conf) {
42
+ return deepCompact(conf);
43
+ };
44
+
45
+ // [function]
46
+
36
47
  const main = function (root) {
37
48
  const file = join(root, MANIFEST);
38
49
  return pathExists(file)
39
50
  .then((exists) => (exists ? readFile(file, "utf8") : null))
40
- .then((buf) => (buf === null ? {} : parseToml(buf)));
51
+ .then((buf) => (buf === null ? {} : parseToml(buf)))
52
+ .then((conf) => (Object.keys(conf).length ? extract(conf) : {}));
41
53
  };
42
54
 
43
55
  // [export]
@@ -10,8 +10,8 @@ module.exports = {
10
10
  select: {
11
11
  choices: [
12
12
  {
13
- description: "Blank starter.",
14
- name: "Blank",
13
+ description: "Zero-build static starter.",
14
+ name: "Default",
15
15
  value: `${REPO}/starter`,
16
16
  },
17
17
  {
@@ -301,7 +301,12 @@ const zIconVideo = function (root) {
301
301
  const zId = function () {
302
302
  const field = "id";
303
303
  return z
304
- .string()
304
+ .string(
305
+ message(field, [
306
+ "Must be a valid UUID.",
307
+ "Run `arc init` to generate a new game ID.",
308
+ ]),
309
+ )
305
310
  .uuid(message(field, ["Must be a valid UUID."]))
306
311
  .refine(
307
312
  (value) => value === value.toLowerCase(),
@@ -389,7 +394,7 @@ const zTrailer = function () {
389
394
  .refine(
390
395
  (url) =>
391
396
  zVimeo().safeParse(url).success || zYouTube().safeParse(url).success,
392
- message(field, ["Must be a YouTube (or Vimeo) URL."]),
397
+ message(field, ["Must be a YouTube or Vimeo URL."]),
393
398
  )
394
399
  .optional();
395
400
  };
@@ -399,10 +404,15 @@ const zTrailer = function () {
399
404
  const zVersion = function () {
400
405
  const field = "version";
401
406
  return z
402
- .string()
407
+ .string(
408
+ message(field, [
409
+ "Must be valid semver.",
410
+ "A version is required unless one can be derived.",
411
+ ]),
412
+ )
403
413
  .refine(
404
414
  (value) => validSemver(value) !== null,
405
- message(field, ["Must be a valid semver."]),
415
+ message(field, ["Must be valid semver."]),
406
416
  );
407
417
  };
408
418
 
@@ -61,7 +61,7 @@ const zDeployDir = function (root, { build }) {
61
61
  )
62
62
  .refine(
63
63
  (file) => isOutCheck(root, file),
64
- message(field, ["Must be within the project."]),
64
+ message(field, ["Must be within the project directory."]),
65
65
  )
66
66
  .refine(
67
67
  (file) => isReservedCheck(root, file, MEDIA),
@@ -70,8 +70,8 @@ const zDeployDir = function (root, { build }) {
70
70
  .refine(
71
71
  (file) => build || existsCheck(root, file),
72
72
  message(field, [
73
- "Must exist if there is no build step.",
74
- "Run `arc inspect workflow.deploy_dir` for its value.",
73
+ "Must exist when there is no build step.",
74
+ "Run `arc inspect workflow.deploy_dir` for details.",
75
75
  ]),
76
76
  );
77
77
  };
package/src/util/delay.js CHANGED
@@ -46,7 +46,7 @@ const poll = function (
46
46
  }
47
47
  const elapsed = Date.now() - started;
48
48
  if (elapsed >= timeout) {
49
- throw new Error("Timed out.");
49
+ throw new Error("Operation timed out.");
50
50
  }
51
51
  return wait(backoff(elapsed, delay, factor, interval, maxDelay), next);
52
52
  });
@@ -2,11 +2,8 @@
2
2
 
3
3
  // [import]
4
4
 
5
- const TOML = require("@iarna/toml");
6
-
7
- // [import]
8
-
9
5
  const objs = require("./objs");
6
+ const TOML = require("./toml");
10
7
 
11
8
  // [use]
12
9
 
@@ -35,7 +32,7 @@ const printToml = function (data, key = "value") {
35
32
  try {
36
33
  write(TOML.stringify(deepSort(data)));
37
34
  } catch (ex) {
38
- write(TOML.stringify({ [field]: data }));
35
+ write(TOML.stringify(deepSort({ [field]: data })));
39
36
  }
40
37
  };
41
38
 
@@ -0,0 +1,14 @@
1
+ "use strict";
2
+
3
+ // [import]
4
+
5
+ const TOML = require("@iarna/toml");
6
+
7
+ // [use]
8
+
9
+ const parse = TOML.parse;
10
+ const stringify = TOML.stringify;
11
+
12
+ // [export]
13
+
14
+ module.exports = { parse, stringify };
package/src/util/video.js CHANGED
@@ -57,7 +57,7 @@ const readMp4 = function (file) {
57
57
  };
58
58
  };
59
59
  mp4.onError = function (mod, msg) {
60
- error = new Error(`MP4Box(${mod}): ${msg}`);
60
+ error = new Error(msg);
61
61
  };
62
62
  const buffer = data.buffer.slice(
63
63
  data.byteOffset,
@@ -70,7 +70,7 @@ const readMp4 = function (file) {
70
70
  throw error;
71
71
  }
72
72
  if (!video) {
73
- throw new Error("MP4 metadata not available.");
73
+ throw new Error("No video metadata found.");
74
74
  }
75
75
  return video;
76
76
  };