arcadible 0.1.46 → 0.1.47

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
@@ -75,5 +75,5 @@
75
75
  "scripts": {
76
76
  "test": "node --test \"test/**/*.test.js\""
77
77
  },
78
- "version": "0.1.46"
78
+ "version": "0.1.47"
79
79
  }
@@ -38,6 +38,9 @@ const MAIN = "index.html";
38
38
  const MANIFEST = cfgfile.PACKAGED;
39
39
  const MEDIA = cfgfile.MEDIA;
40
40
  const OUTPUT = `.${TOOL}/package`;
41
+ // the folder every build's origin keeps for Arcadible's own files, such as
42
+ // the script games include, in any letter case.
43
+ const RESERVED = cfgproduct.handle;
41
44
 
42
45
  // [declare]
43
46
 
@@ -45,6 +48,17 @@ const SIZE_PARTIAL = cfglimit.ZIP_SIZE;
45
48
 
46
49
  // [function]
47
50
 
51
+ // the build's folder named like the reserved one, if it has one.
52
+ const findReserved = function (zip) {
53
+ const folder = zip
54
+ .entries()
55
+ .map((entry) => entry.name.split("/"))
56
+ .find((parts) => parts.length > 1 && parts[0].toLowerCase() === RESERVED);
57
+ return folder?.[0];
58
+ };
59
+
60
+ // [function]
61
+
48
62
  // the files' own limits come first, since they name what to fix, such as
49
63
  // the one file over 64 MB that makes the zip too large.
50
64
  const verifyPartial = function (zip) {
@@ -54,6 +68,13 @@ const verifyPartial = function (zip) {
54
68
  phrase.packageIndexMissing(MAIN),
55
69
  );
56
70
  }
71
+ const reserved = findReserved(zip);
72
+ if (reserved) {
73
+ throw new ArcError(
74
+ cfgcode.PACKAGE_PATH_RESERVED,
75
+ phrase.packagePathReserved(reserved),
76
+ );
77
+ }
57
78
  limits.check(zip.entries());
58
79
  if (zip.stat().size > SIZE_PARTIAL) {
59
80
  throw new ArcError(
@@ -31,6 +31,7 @@ const CLI = {
31
31
  NOT_LOGGED_IN: "not_logged_in",
32
32
  PACKAGE_FILE_TOO_LARGE: "package_file_too_large",
33
33
  PACKAGE_INDEX_MISSING: "package_index_missing",
34
+ PACKAGE_PATH_RESERVED: "package_path_reserved",
34
35
  PACKAGE_TOO_LARGE: "package_too_large",
35
36
  PACKAGE_TOO_MANY_FILES: "package_too_many_files",
36
37
  PACKAGE_UNCOMPRESSED_TOO_LARGE: "package_uncompressed_too_large",
package/src/phrase.js CHANGED
@@ -566,6 +566,15 @@ const packageFileTooLarge = function (file, size) {
566
566
 
567
567
  // [function]
568
568
 
569
+ const packagePathReserved = function (folder) {
570
+ return blocks(
571
+ `'${folder}/' is reserved for ${TITLE}.`,
572
+ "Rename the folder, and the paths that load from it.",
573
+ );
574
+ };
575
+
576
+ // [function]
577
+
569
578
  const packageTooLarge = function (size) {
570
579
  return blocks(
571
580
  `Package is larger than ${size} MB.`,
@@ -957,6 +966,7 @@ module.exports = {
957
966
  opened,
958
967
  packageFileTooLarge,
959
968
  packageIndexMissing,
969
+ packagePathReserved,
960
970
  packageTooLarge,
961
971
  packageTooManyFiles,
962
972
  packageUncompressedTooLarge,
@@ -13,6 +13,7 @@ const fs = require("fs-extra");
13
13
  const isAbsolute = path.isAbsolute;
14
14
  const join = path.join;
15
15
  const pathExistsSync = fs.pathExistsSync; // eslint-disable-line no-sync
16
+ const readdirSync = fs.readdirSync; // eslint-disable-line no-sync
16
17
  const relative = path.relative;
17
18
  const resolve = path.resolve;
18
19
 
@@ -71,6 +72,19 @@ const lacksFiles = function (root, target, names) {
71
72
  return names.every((name) => !exists(join(root, target), name));
72
73
  };
73
74
 
75
+ // [function]
76
+
77
+ // whether an existing `target` lacks a folder named `name` at its root, in any
78
+ // letter case, since a build's paths are case-sensitive once it's served.
79
+ const lacksFolder = function (root, target, name) {
80
+ if (!exists(root, target)) {
81
+ return true;
82
+ }
83
+ return !readdirSync(join(root, target), { withFileTypes: true }).some(
84
+ (entry) => entry.isDirectory() && entry.name.toLowerCase() === name,
85
+ );
86
+ };
87
+
74
88
  // [export]
75
89
 
76
90
  module.exports = {
@@ -81,4 +95,5 @@ module.exports = {
81
95
  isRelative,
82
96
  isRoot,
83
97
  lacksFiles,
98
+ lacksFolder,
84
99
  };
@@ -25,6 +25,7 @@ const isInsideCheck = check.isInside;
25
25
  const isRelativeCheck = check.isRelative;
26
26
  const isRootCheck = check.isRoot;
27
27
  const lacksFilesCheck = check.lacksFiles;
28
+ const lacksFolderCheck = check.lacksFolder;
28
29
 
29
30
  // [declare]
30
31
 
@@ -32,6 +33,9 @@ const message = schemaMessage.messages("workflow");
32
33
  const MEDIA = cfgfile.MEDIA;
33
34
  const INDEX = "index.html";
34
35
  const RESERVED = [cfgfile.PACKAGED, MEDIA];
36
+ // the folder every build's origin keeps for Arcadible's own files, such as
37
+ // the script games include. arc pack checks it again after the build.
38
+ const RESERVED_FOLDER = cfgproduct.handle;
35
39
 
36
40
  // [function]
37
41
 
@@ -119,6 +123,16 @@ const zDeployDir = function (root, { build }) {
119
123
  ISSUE.PATH_INVALID,
120
124
  ),
121
125
  abort: true,
126
+ })
127
+ .refine((file) => lacksFolderCheck(root, file, RESERVED_FOLDER), {
128
+ ...message(
129
+ field,
130
+ [
131
+ `Must not have an ${RESERVED_FOLDER} folder at its root, in any letter case. It's reserved for ${cfgproduct.title}'s own files.`,
132
+ ],
133
+ ISSUE.PATH_INVALID,
134
+ ),
135
+ abort: true,
122
136
  });
123
137
  };
124
138