@apollion-dsi/scripts 0.7.7 → 0.8.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.
Files changed (77) hide show
  1. package/CHANGELOG.md +118 -0
  2. package/README.md +73 -0
  3. package/codemods/v4-migrate.mjs +196 -0
  4. package/coverage/clover.xml +123 -0
  5. package/coverage/coverage-final.json +7 -0
  6. package/coverage/lcov-report/base.css +224 -0
  7. package/coverage/lcov-report/block-navigation.js +87 -0
  8. package/coverage/lcov-report/config/env.ts.html +400 -0
  9. package/coverage/lcov-report/config/index.html +146 -0
  10. package/coverage/lcov-report/config/paths.ts.html +442 -0
  11. package/coverage/lcov-report/config/shared.ts.html +211 -0
  12. package/coverage/lcov-report/favicon.png +0 -0
  13. package/coverage/lcov-report/index.html +131 -0
  14. package/coverage/lcov-report/prettify.css +1 -0
  15. package/coverage/lcov-report/prettify.js +2 -0
  16. package/coverage/lcov-report/sort-arrow-sprite.png +0 -0
  17. package/coverage/lcov-report/sorter.js +210 -0
  18. package/coverage/lcov-report/utils/checkRequiredFiles.ts.html +178 -0
  19. package/coverage/lcov-report/utils/formatWebpackMessages.ts.html +214 -0
  20. package/coverage/lcov-report/utils/getPublicUrlOrPath.ts.html +259 -0
  21. package/coverage/lcov-report/utils/index.html +146 -0
  22. package/coverage/lcov.info +236 -0
  23. package/jest.config.js +36 -0
  24. package/lib/command/build.d.ts +14 -0
  25. package/lib/command/build.js +14 -0
  26. package/lib/command/build.js.map +1 -1
  27. package/lib/command/create/helper.js +0 -1
  28. package/lib/command/create/helper.js.map +1 -1
  29. package/lib/command/dev.d.ts +12 -0
  30. package/lib/command/dev.js +12 -0
  31. package/lib/command/dev.js.map +1 -1
  32. package/lib/config/env.d.ts +23 -0
  33. package/lib/config/env.js +23 -0
  34. package/lib/config/env.js.map +1 -1
  35. package/lib/config/paths.d.ts +31 -0
  36. package/lib/config/paths.js +11 -0
  37. package/lib/config/paths.js.map +1 -1
  38. package/lib/config/shared.d.ts +15 -0
  39. package/lib/config/shared.js +1 -0
  40. package/lib/config/shared.js.map +1 -1
  41. package/lib/index.d.ts +8 -0
  42. package/lib/index.js +8 -0
  43. package/lib/index.js.map +1 -1
  44. package/lib/utils/checkRequiredFiles.d.ts +9 -0
  45. package/lib/utils/checkRequiredFiles.js +9 -0
  46. package/lib/utils/checkRequiredFiles.js.map +1 -1
  47. package/lib/utils/formatWebpackMessages.d.ts +13 -0
  48. package/lib/utils/formatWebpackMessages.js +9 -0
  49. package/lib/utils/formatWebpackMessages.js.map +1 -1
  50. package/lib/utils/getPublicUrlOrPath.d.ts +19 -0
  51. package/lib/utils/getPublicUrlOrPath.js +19 -0
  52. package/lib/utils/getPublicUrlOrPath.js.map +1 -1
  53. package/llms.txt +52 -0
  54. package/package.json +9 -5
  55. package/scripts/validate.sh +3 -3
  56. package/src/__tests__/checkRequiredFiles.test.ts +44 -0
  57. package/src/__tests__/env.test.ts +51 -0
  58. package/src/__tests__/formatWebpackMessages.test.ts +42 -0
  59. package/src/__tests__/getPublicUrlOrPath.test.ts +38 -0
  60. package/src/__tests__/paths.test.ts +47 -0
  61. package/src/__tests__/shared.test.ts +14 -0
  62. package/src/command/build.ts +14 -0
  63. package/src/command/create/helper.ts +0 -1
  64. package/src/command/dev.ts +12 -0
  65. package/src/config/env.ts +23 -0
  66. package/src/config/paths.ts +31 -0
  67. package/src/config/shared.ts +15 -0
  68. package/src/index.ts +9 -0
  69. package/src/utils/checkRequiredFiles.ts +9 -0
  70. package/src/utils/formatWebpackMessages.ts +13 -0
  71. package/src/utils/getPublicUrlOrPath.ts +19 -0
  72. package/tsconfig.json +1 -1
  73. package/tsconfig.test.json +14 -0
  74. package/verify-no-install-scripts.js +76 -0
  75. package/.prettierrc.js +0 -1
  76. package/README.MD +0 -91
  77. package/audit-ci.json +0 -5
@@ -1 +1,10 @@
1
+ /**
2
+ * Verify every file in `files` exists on disk. Logs the first missing
3
+ * file to `console.log` (with chalk) and returns `false`; otherwise
4
+ * returns `true`. Used by the build/dev commands to fail fast before
5
+ * touching webpack.
6
+ *
7
+ * @param files Absolute paths to required files (typically `paths.appHtml`,
8
+ * `paths.appIndexJs`).
9
+ */
1
10
  export default function checkRequiredFiles(files: string[]): boolean;
@@ -7,6 +7,15 @@ exports.default = checkRequiredFiles;
7
7
  const fs_1 = __importDefault(require("fs"));
8
8
  const path_1 = __importDefault(require("path"));
9
9
  const chalk_1 = __importDefault(require("chalk"));
10
+ /**
11
+ * Verify every file in `files` exists on disk. Logs the first missing
12
+ * file to `console.log` (with chalk) and returns `false`; otherwise
13
+ * returns `true`. Used by the build/dev commands to fail fast before
14
+ * touching webpack.
15
+ *
16
+ * @param files Absolute paths to required files (typically `paths.appHtml`,
17
+ * `paths.appIndexJs`).
18
+ */
10
19
  function checkRequiredFiles(files) {
11
20
  let currentFilePath;
12
21
  try {
@@ -1 +1 @@
1
- {"version":3,"file":"checkRequiredFiles.js","sourceRoot":"","sources":["../../src/utils/checkRequiredFiles.ts"],"names":[],"mappings":";;;;;AAKA,qCAgBC;AArBD,4CAAoB;AACpB,gDAAwB;AAExB,kDAA0B;AAE1B,SAAwB,kBAAkB,CAAC,KAAe;IACxD,IAAI,eAAmC,CAAC;IACxC,IAAI,CAAC;QACH,KAAK,CAAC,OAAO,CAAC,CAAC,QAAQ,EAAE,EAAE;YACzB,eAAe,GAAG,QAAQ,CAAC;YAC3B,YAAE,CAAC,UAAU,CAAC,QAAQ,EAAE,YAAE,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;QAC7C,CAAC,CAAC,CAAC;QACH,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,OAAO,GAAG,eAAe,CAAC,CAAC,CAAC,cAAI,CAAC,OAAO,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QACrE,MAAM,QAAQ,GAAG,eAAe,CAAC,CAAC,CAAC,cAAI,CAAC,QAAQ,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QACvE,OAAO,CAAC,GAAG,CAAC,eAAK,CAAC,GAAG,CAAC,iCAAiC,CAAC,CAAC,CAAC;QAC1D,OAAO,CAAC,GAAG,CAAC,KAAK,eAAK,CAAC,GAAG,CAAC,MAAM,CAAC,KAAK,eAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;QAC/D,OAAO,CAAC,GAAG,CAAC,KAAK,eAAK,CAAC,GAAG,CAAC,aAAa,CAAC,KAAK,eAAK,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;QACrE,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"checkRequiredFiles.js","sourceRoot":"","sources":["../../src/utils/checkRequiredFiles.ts"],"names":[],"mappings":";;;;;AAcA,qCAgBC;AA9BD,4CAAoB;AACpB,gDAAwB;AAExB,kDAA0B;AAE1B;;;;;;;;GAQG;AACH,SAAwB,kBAAkB,CAAC,KAAe;IACxD,IAAI,eAAmC,CAAC;IACxC,IAAI,CAAC;QACH,KAAK,CAAC,OAAO,CAAC,CAAC,QAAQ,EAAE,EAAE;YACzB,eAAe,GAAG,QAAQ,CAAC;YAC3B,YAAE,CAAC,UAAU,CAAC,QAAQ,EAAE,YAAE,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;QAC7C,CAAC,CAAC,CAAC;QACH,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,OAAO,GAAG,eAAe,CAAC,CAAC,CAAC,cAAI,CAAC,OAAO,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QACrE,MAAM,QAAQ,GAAG,eAAe,CAAC,CAAC,CAAC,cAAI,CAAC,QAAQ,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QACvE,OAAO,CAAC,GAAG,CAAC,eAAK,CAAC,GAAG,CAAC,iCAAiC,CAAC,CAAC,CAAC;QAC1D,OAAO,CAAC,GAAG,CAAC,KAAK,eAAK,CAAC,GAAG,CAAC,MAAM,CAAC,KAAK,eAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;QAC/D,OAAO,CAAC,GAAG,CAAC,KAAK,eAAK,CAAC,GAAG,CAAC,aAAa,CAAC,KAAK,eAAK,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;QACrE,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC"}
@@ -1,5 +1,18 @@
1
+ /**
2
+ * Normalized result of {@link formatWebpackMessages} — `errors` and
3
+ * `warnings` are always string arrays (empty if absent in the input).
4
+ */
1
5
  export type FormattedMessages = {
2
6
  errors: string[];
3
7
  warnings: string[];
4
8
  };
9
+ /**
10
+ * Coerce webpack's `stats.toJson({ warnings, errors })` shape into a
11
+ * plain `{ errors, warnings }` of strings. Tolerates `null`, arrays of
12
+ * objects with `{ message, moduleName }`, raw primitives, or anything
13
+ * else (falls back to `JSON.stringify` / `String()`).
14
+ *
15
+ * @param json Output of `stats.toJson({ warnings: true, errors: true })`
16
+ * or any partially-shaped equivalent.
17
+ */
5
18
  export default function formatWebpackMessages(json: any): FormattedMessages;
@@ -24,6 +24,15 @@ function toString(item) {
24
24
  }
25
25
  return String(item);
26
26
  }
27
+ /**
28
+ * Coerce webpack's `stats.toJson({ warnings, errors })` shape into a
29
+ * plain `{ errors, warnings }` of strings. Tolerates `null`, arrays of
30
+ * objects with `{ message, moduleName }`, raw primitives, or anything
31
+ * else (falls back to `JSON.stringify` / `String()`).
32
+ *
33
+ * @param json Output of `stats.toJson({ warnings: true, errors: true })`
34
+ * or any partially-shaped equivalent.
35
+ */
27
36
  function formatWebpackMessages(json) {
28
37
  const errors = Array.isArray(json?.errors) ? json.errors.map(toString) : [];
29
38
  const warnings = Array.isArray(json?.warnings) ? json.warnings.map(toString) : [];
@@ -1 +1 @@
1
- {"version":3,"file":"formatWebpackMessages.js","sourceRoot":"","sources":["../../src/utils/formatWebpackMessages.ts"],"names":[],"mappings":";;AAyBA,wCAIC;AAxBD,SAAS,QAAQ,CAAC,IAAa;IAC7B,IAAI,IAAI,IAAI,IAAI;QAAE,OAAO,EAAE,CAAC;IAC5B,IAAI,OAAO,IAAI,KAAK,QAAQ;QAAE,OAAO,IAAI,CAAC;IAC1C,IAAI,OAAO,IAAI,KAAK,QAAQ,EAAE,CAAC;QAC7B,MAAM,OAAO,GAAG,IAAW,CAAC;QAC5B,IAAI,OAAO,OAAO,CAAC,OAAO,KAAK,QAAQ,EAAE,CAAC;YACxC,IAAI,MAAM,GAAG,EAAE,CAAC;YAChB,IAAI,OAAO,CAAC,UAAU;gBAAE,MAAM,IAAI,MAAM,OAAO,CAAC,UAAU,MAAM,CAAC;YACjE,MAAM,IAAI,OAAO,CAAC,OAAO,CAAC;YAC1B,OAAO,MAAM,CAAC;QAChB,CAAC;QACD,IAAI,CAAC;YACH,OAAO,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;QACjC,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,MAAM,CAAC,OAAO,CAAC,CAAC;QACzB,CAAC;IACH,CAAC;IACD,OAAO,MAAM,CAAC,IAAI,CAAC,CAAC;AACtB,CAAC;AAED,SAAwB,qBAAqB,CAAC,IAAS;IACrD,MAAM,MAAM,GAAG,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IAC5E,MAAM,QAAQ,GAAG,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IAClF,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC;AAC9B,CAAC"}
1
+ {"version":3,"file":"formatWebpackMessages.js","sourceRoot":"","sources":["../../src/utils/formatWebpackMessages.ts"],"names":[],"mappings":";;AAsCA,wCAIC;AAjCD,SAAS,QAAQ,CAAC,IAAa;IAC7B,IAAI,IAAI,IAAI,IAAI;QAAE,OAAO,EAAE,CAAC;IAC5B,IAAI,OAAO,IAAI,KAAK,QAAQ;QAAE,OAAO,IAAI,CAAC;IAC1C,IAAI,OAAO,IAAI,KAAK,QAAQ,EAAE,CAAC;QAC7B,MAAM,OAAO,GAAG,IAAW,CAAC;QAC5B,IAAI,OAAO,OAAO,CAAC,OAAO,KAAK,QAAQ,EAAE,CAAC;YACxC,IAAI,MAAM,GAAG,EAAE,CAAC;YAChB,IAAI,OAAO,CAAC,UAAU;gBAAE,MAAM,IAAI,MAAM,OAAO,CAAC,UAAU,MAAM,CAAC;YACjE,MAAM,IAAI,OAAO,CAAC,OAAO,CAAC;YAC1B,OAAO,MAAM,CAAC;QAChB,CAAC;QACD,IAAI,CAAC;YACH,OAAO,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;QACjC,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,MAAM,CAAC,OAAO,CAAC,CAAC;QACzB,CAAC;IACH,CAAC;IACD,OAAO,MAAM,CAAC,IAAI,CAAC,CAAC;AACtB,CAAC;AAED;;;;;;;;GAQG;AACH,SAAwB,qBAAqB,CAAC,IAAS;IACrD,MAAM,MAAM,GAAG,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IAC5E,MAAM,QAAQ,GAAG,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IAClF,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC;AAC9B,CAAC"}
@@ -1 +1,20 @@
1
+ /**
2
+ * Compute the absolute base URL (or path) every bundled asset is served from.
3
+ *
4
+ * Precedence: `envPublicUrl` → `homepage` → `'/'`.
5
+ *
6
+ * In **development**, absolute URLs collapse to their pathname so the
7
+ * dev-server doesn't try to fetch from a different origin; relative
8
+ * homepages (starting with `.`) collapse to `'/'` for the same reason.
9
+ *
10
+ * In **production**, the full URL (or pathname when only `homepage` is
11
+ * set) is preserved so CDN-rooted bundles resolve correctly.
12
+ *
13
+ * Adapted from `react-scripts` — semantics kept identical to ease migration.
14
+ *
15
+ * @param isEnvDevelopment `true` when `NODE_ENV === 'development'`.
16
+ * @param homepage `package.json#homepage` (project-level).
17
+ * @param envPublicUrl `process.env.PUBLIC_URL` (per-invocation override).
18
+ * @returns A trailing-slash-normalized URL or absolute path.
19
+ */
1
20
  export default function getPublicUrlOrPath(isEnvDevelopment: boolean, homepage: string | undefined, envPublicUrl: string | undefined): string;
@@ -2,6 +2,25 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.default = getPublicUrlOrPath;
4
4
  const url_1 = require("url");
5
+ /**
6
+ * Compute the absolute base URL (or path) every bundled asset is served from.
7
+ *
8
+ * Precedence: `envPublicUrl` → `homepage` → `'/'`.
9
+ *
10
+ * In **development**, absolute URLs collapse to their pathname so the
11
+ * dev-server doesn't try to fetch from a different origin; relative
12
+ * homepages (starting with `.`) collapse to `'/'` for the same reason.
13
+ *
14
+ * In **production**, the full URL (or pathname when only `homepage` is
15
+ * set) is preserved so CDN-rooted bundles resolve correctly.
16
+ *
17
+ * Adapted from `react-scripts` — semantics kept identical to ease migration.
18
+ *
19
+ * @param isEnvDevelopment `true` when `NODE_ENV === 'development'`.
20
+ * @param homepage `package.json#homepage` (project-level).
21
+ * @param envPublicUrl `process.env.PUBLIC_URL` (per-invocation override).
22
+ * @returns A trailing-slash-normalized URL or absolute path.
23
+ */
5
24
  function getPublicUrlOrPath(isEnvDevelopment, homepage, envPublicUrl) {
6
25
  const stubDomain = 'https://create-react-app.dev';
7
26
  if (envPublicUrl) {
@@ -1 +1 @@
1
- {"version":3,"file":"getPublicUrlOrPath.js","sourceRoot":"","sources":["../../src/utils/getPublicUrlOrPath.ts"],"names":[],"mappings":";;AAEA,qCAoCC;AAtCD,6BAA0B;AAE1B,SAAwB,kBAAkB,CACxC,gBAAyB,EACzB,QAA4B,EAC5B,YAAgC;IAEhC,MAAM,UAAU,GAAG,8BAA8B,CAAC;IAElD,IAAI,YAAY,EAAE,CAAC;QACjB,IAAI,UAAU,GAAG,YAAY,CAAC;QAC9B,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,GAAG,CAAC;YAAE,UAAU,IAAI,GAAG,CAAC;QACjD,IAAI,CAAC;YACH,MAAM,cAAc,GAAG,IAAI,SAAG,CAAC,UAAU,EAAE,UAAU,CAAC,CAAC;YACvD,OAAO,gBAAgB,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC;QACtG,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,UAAU,CAAC;QACpB,CAAC;IACH,CAAC;IAED,IAAI,QAAQ,EAAE,CAAC;QACb,IAAI,UAAU,GAAG,QAAQ,CAAC;QAC1B,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,GAAG,CAAC;YAAE,UAAU,IAAI,GAAG,CAAC;QACjD,IAAI,CAAC;YACH,MAAM,qBAAqB,GAAG,IAAI,SAAG,CAAC,UAAU,EAAE,UAAU,CAAC,CAAC,QAAQ,CAAC;YACvE,OAAO,gBAAgB;gBACrB,CAAC,CAAC,UAAU,CAAC,UAAU,CAAC,GAAG,CAAC;oBAC1B,CAAC,CAAC,GAAG;oBACL,CAAC,CAAC,qBAAqB;gBACzB,CAAC,CAAC,UAAU,CAAC,UAAU,CAAC,GAAG,CAAC;oBAC1B,CAAC,CAAC,UAAU;oBACZ,CAAC,CAAC,qBAAqB,CAAC;QAC9B,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,UAAU,CAAC;QACpB,CAAC;IACH,CAAC;IAED,OAAO,GAAG,CAAC;AACb,CAAC"}
1
+ {"version":3,"file":"getPublicUrlOrPath.js","sourceRoot":"","sources":["../../src/utils/getPublicUrlOrPath.ts"],"names":[],"mappings":";;AAqBA,qCAoCC;AAzDD,6BAA0B;AAE1B;;;;;;;;;;;;;;;;;;GAkBG;AACH,SAAwB,kBAAkB,CACxC,gBAAyB,EACzB,QAA4B,EAC5B,YAAgC;IAEhC,MAAM,UAAU,GAAG,8BAA8B,CAAC;IAElD,IAAI,YAAY,EAAE,CAAC;QACjB,IAAI,UAAU,GAAG,YAAY,CAAC;QAC9B,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,GAAG,CAAC;YAAE,UAAU,IAAI,GAAG,CAAC;QACjD,IAAI,CAAC;YACH,MAAM,cAAc,GAAG,IAAI,SAAG,CAAC,UAAU,EAAE,UAAU,CAAC,CAAC;YACvD,OAAO,gBAAgB,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC;QACtG,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,UAAU,CAAC;QACpB,CAAC;IACH,CAAC;IAED,IAAI,QAAQ,EAAE,CAAC;QACb,IAAI,UAAU,GAAG,QAAQ,CAAC;QAC1B,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,GAAG,CAAC;YAAE,UAAU,IAAI,GAAG,CAAC;QACjD,IAAI,CAAC;YACH,MAAM,qBAAqB,GAAG,IAAI,SAAG,CAAC,UAAU,EAAE,UAAU,CAAC,CAAC,QAAQ,CAAC;YACvE,OAAO,gBAAgB;gBACrB,CAAC,CAAC,UAAU,CAAC,UAAU,CAAC,GAAG,CAAC;oBAC1B,CAAC,CAAC,GAAG;oBACL,CAAC,CAAC,qBAAqB;gBACzB,CAAC,CAAC,UAAU,CAAC,UAAU,CAAC,GAAG,CAAC;oBAC1B,CAAC,CAAC,UAAU;oBACZ,CAAC,CAAC,qBAAqB,CAAC;QAC9B,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,UAAU,CAAC;QACpB,CAAC;IACH,CAAC;IAED,OAAO,GAAG,CAAC;AACb,CAAC"}
package/llms.txt ADDED
@@ -0,0 +1,52 @@
1
+ # Apollion DS — @apollion-dsi/scripts
2
+
3
+ Apollion's CRA-style CLI. Hides webpack 5 + Babel 7 + Jest 30 + TS 6
4
+ behind four commands: `create`, `dev`, `build`, `test`.
5
+
6
+ **Package:** `@apollion-dsi/scripts`. **Repo:**
7
+ `github.com/apollion-ds/apollion`. **Bin:** `scripts` (from
8
+ `lib/bin.js`).
9
+
10
+ ## Commands
11
+
12
+ | `scripts <cmd>` | Effect |
13
+ |---|---|
14
+ | `create <name>` | Scaffold a new project from the template |
15
+ | `dev` | webpack-dev-server + HMR (react-refresh) at :3000 |
16
+ | `build` | Production bundle to `build/` |
17
+ | `test` | Jest 30 in watch mode against changed files |
18
+
19
+ Use via `package.json#scripts`:
20
+
21
+ ```json
22
+ { "scripts": { "dev": "scripts dev", "build": "scripts build", "test": "scripts test" } }
23
+ ```
24
+
25
+ ## Stack (hidden from consumer)
26
+
27
+ - webpack 5 + Babel 7 (`preset-env`, `preset-react`, `preset-typescript`)
28
+ - `babel-plugin-relay` + `babel-plugin-styled-components`
29
+ - `react-refresh` for HMR
30
+ - Jest 30 + ts-jest + `@testing-library/react`
31
+ - Peer: **TypeScript 6.x**
32
+
33
+ ## Invariants
34
+
35
+ * **Yarn only** (consumer template uses Yarn 4 Berry).
36
+ * **No webpack config exposed.** If you need a config escape hatch,
37
+ open a ROADMAP entry — the point of this package is to not have one.
38
+ * **TypeScript 6 strict** in the template — non-negotiable.
39
+
40
+ ## Files
41
+
42
+ - `lib/bin.js` — CLI entry (resolved by `package.json#bin`).
43
+ - `lib/index.js` — programmatic entry.
44
+ - `src/` — TS sources.
45
+ - `scripts/validate.sh` — workspace `validate` step.
46
+
47
+ ## Not in scope
48
+
49
+ - Generic React boilerplate (template é opinionated p/ Apollion).
50
+ - Storybook setup (use `@apollion-dsi/core` Storybook diretamente).
51
+ - Monorepo orchestration (consumer monorepos usam yarn workspaces
52
+ diretamente).
package/package.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@apollion-dsi/scripts",
3
- "version": "0.7.7",
3
+ "version": "0.8.0",
4
4
  "description": "Apollion Framework CLI",
5
5
  "main": "lib/index.js",
6
6
  "bin": "lib/bin.js",
7
7
  "scripts": {
8
8
  "prepare": "yarn build",
9
- "audit-dependencies": "audit-ci --config audit-ci.json",
9
+ "audit-dependencies": "yarn npm audit --severity moderate --no-deprecations",
10
10
  "lint": "eslint src --quiet",
11
11
  "lint:full": "eslint src",
12
12
  "lint:fix": "eslint src --fix",
@@ -15,13 +15,16 @@
15
15
  "format": "yarn prettier --write",
16
16
  "validate": "./scripts/validate.sh",
17
17
  "test": "yarn validate",
18
+ "test:watch": "jest --watch",
19
+ "coverage": "jest --coverage",
20
+ "validate:tests": "jest --coverage",
18
21
  "build": "tsc -p ."
19
22
  },
20
23
  "keywords": [],
21
24
  "author": "Apollion DS Team",
22
25
  "license": "ISC",
23
26
  "dependencies": {
24
- "@apollion-dsi/eslint-config": "0.6.0",
27
+ "@apollion-dsi/eslint-config": "0.7.0",
25
28
  "@babel/core": "7.29.0",
26
29
  "@babel/preset-env": "7.29.5",
27
30
  "@babel/preset-react": "7.28.5",
@@ -29,6 +32,7 @@
29
32
  "@pmmmwh/react-refresh-webpack-plugin": "0.6.2",
30
33
  "@testing-library/jest-dom": "6.9.1",
31
34
  "@testing-library/react": "16.3.2",
35
+ "babel-jest": "^30.4.1",
32
36
  "babel-loader": "10.1.1",
33
37
  "babel-plugin-named-asset-import": "0.3.8",
34
38
  "babel-plugin-relay": "20.1.1",
@@ -50,11 +54,12 @@
50
54
  "inquirer": "13.4.3",
51
55
  "jest": "30.4.2",
52
56
  "jest-cli": "30.4.2",
57
+ "jest-environment-node": "^30.4.1",
53
58
  "react-refresh": "0.18.0",
54
59
  "resolve": "1.22.12",
55
60
  "semver": "7.8.0",
56
61
  "terser-webpack-plugin": "5.6.0",
57
- "ts-jest": "29.4.9",
62
+ "ts-jest": "^29.4.11",
58
63
  "tsconfig-paths-webpack-plugin": "4.2.0",
59
64
  "update-notifier": "7.3.1",
60
65
  "validate-npm-package-name": "8.0.0",
@@ -68,7 +73,6 @@
68
73
  "devDependencies": {
69
74
  "@testing-library/dom": "10.4.1",
70
75
  "@types/jest": "30.0.0",
71
- "audit-ci": "7.1.0",
72
76
  "eslint": "9.29.0",
73
77
  "npm-run-all": "4.1.5",
74
78
  "prettier": "3.8.3",
@@ -4,13 +4,13 @@ BRANCH=$(git symbolic-ref --short HEAD)
4
4
 
5
5
  if [ "$BRANCH" = "main" ]; then
6
6
  echo "Validating on production"
7
- npm-run-all --parallel check-types prettier lint && yarn build
7
+ npm-run-all --parallel check-types prettier lint && yarn validate:tests && yarn build
8
8
 
9
9
  elif [ "$BRANCH" = "staging" ]; then
10
10
  echo "Validating on staging"
11
- npm-run-all --parallel check-types prettier lint && yarn build
11
+ npm-run-all --parallel check-types prettier lint && yarn validate:tests && yarn build
12
12
 
13
13
  else
14
14
  echo "Validating on development"
15
- npm-run-all --parallel check-types prettier lint
15
+ npm-run-all --parallel check-types prettier lint && yarn validate:tests
16
16
  fi
@@ -0,0 +1,44 @@
1
+ import fs from 'fs';
2
+ import os from 'os';
3
+ import path from 'path';
4
+
5
+ import checkRequiredFiles from '../utils/checkRequiredFiles';
6
+
7
+ describe('checkRequiredFiles', () => {
8
+ let tmpDir: string;
9
+ let logSpy: jest.SpyInstance;
10
+
11
+ beforeEach(() => {
12
+ tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'apollion-scripts-'));
13
+ logSpy = jest.spyOn(console, 'log').mockImplementation(() => undefined);
14
+ });
15
+
16
+ afterEach(() => {
17
+ fs.rmSync(tmpDir, { recursive: true, force: true });
18
+ logSpy.mockRestore();
19
+ });
20
+
21
+ it('returns true when every file exists', () => {
22
+ const fileA = path.join(tmpDir, 'a.txt');
23
+ const fileB = path.join(tmpDir, 'b.txt');
24
+ fs.writeFileSync(fileA, '');
25
+ fs.writeFileSync(fileB, '');
26
+
27
+ expect(checkRequiredFiles([fileA, fileB])).toBe(true);
28
+ expect(logSpy).not.toHaveBeenCalled();
29
+ });
30
+
31
+ it('returns false and logs the missing file when one is absent', () => {
32
+ const present = path.join(tmpDir, 'present.txt');
33
+ const missing = path.join(tmpDir, 'missing.txt');
34
+ fs.writeFileSync(present, '');
35
+
36
+ expect(checkRequiredFiles([present, missing])).toBe(false);
37
+ const logs = logSpy.mock.calls.flat().join(' ');
38
+ expect(logs).toContain('missing.txt');
39
+ });
40
+
41
+ it('returns true for an empty list', () => {
42
+ expect(checkRequiredFiles([])).toBe(true);
43
+ });
44
+ });
@@ -0,0 +1,51 @@
1
+ import getClientEnvironment, { getEnviroment } from '../config/env';
2
+
3
+ describe('getClientEnvironment', () => {
4
+ const savedEnv = { ...process.env };
5
+ afterEach(() => {
6
+ process.env = { ...savedEnv };
7
+ });
8
+
9
+ it('exposes REACT_APP_* vars in raw and stringified', () => {
10
+ process.env.REACT_APP_API_URL = 'https://api.example.com';
11
+ process.env.SECRET_KEY = 'leak-me-not';
12
+ process.env.NODE_ENV = 'production';
13
+
14
+ const result = getClientEnvironment('/public/', { useFastRefresh: false });
15
+ const raw = result.raw as Record<string, unknown>;
16
+
17
+ expect(raw.REACT_APP_API_URL).toBe('https://api.example.com');
18
+ expect(raw.PUBLIC_URL).toBe('/public/');
19
+ expect(raw.NODE_ENV).toBe('production');
20
+ expect(raw.FAST_REFRESH).toBe(false);
21
+
22
+ expect(raw).not.toHaveProperty('SECRET_KEY');
23
+ expect((result.stringified['process.env'] as Record<string, string>).PUBLIC_URL).toBe('"/public/"');
24
+ });
25
+
26
+ it('defaults NODE_ENV to "development" when unset', () => {
27
+ delete process.env.NODE_ENV;
28
+ const result = getClientEnvironment('/', { useFastRefresh: true });
29
+ expect(result.raw.NODE_ENV).toBe('development');
30
+ expect(result.raw.FAST_REFRESH).toBe(true);
31
+ });
32
+ });
33
+
34
+ describe('getEnviroment', () => {
35
+ const savedEnv = { ...process.env };
36
+ afterEach(() => {
37
+ process.env = { ...savedEnv };
38
+ });
39
+
40
+ it('throws when NODE_ENV is unset', () => {
41
+ delete process.env.NODE_ENV;
42
+ expect(() => getEnviroment({ dotenv: '/tmp/nonexistent.env' } as never)).toThrow(
43
+ /NODE_ENV environment variable is required/,
44
+ );
45
+ });
46
+
47
+ it('completes silently when no dotenv files exist', () => {
48
+ process.env.NODE_ENV = 'test';
49
+ expect(() => getEnviroment({ dotenv: '/tmp/definitely-missing.env' } as never)).not.toThrow();
50
+ });
51
+ });
@@ -0,0 +1,42 @@
1
+ import formatWebpackMessages from '../utils/formatWebpackMessages';
2
+
3
+ describe('formatWebpackMessages', () => {
4
+ it('returns empty arrays when the input has no errors or warnings', () => {
5
+ expect(formatWebpackMessages(null)).toEqual({ errors: [], warnings: [] });
6
+ expect(formatWebpackMessages({})).toEqual({ errors: [], warnings: [] });
7
+ expect(formatWebpackMessages({ errors: 'not-array' })).toEqual({ errors: [], warnings: [] });
8
+ });
9
+
10
+ it('coerces string entries verbatim', () => {
11
+ expect(formatWebpackMessages({ errors: ['boom'], warnings: ['ouch'] })).toEqual({
12
+ errors: ['boom'],
13
+ warnings: ['ouch'],
14
+ });
15
+ });
16
+
17
+ it('prefixes object messages with their moduleName', () => {
18
+ expect(
19
+ formatWebpackMessages({
20
+ errors: [{ moduleName: 'src/a.ts', message: 'syntax error' }],
21
+ warnings: [{ message: 'unused export' }],
22
+ }),
23
+ ).toEqual({
24
+ errors: ['in src/a.ts\n\nsyntax error'],
25
+ warnings: ['unused export'],
26
+ });
27
+ });
28
+
29
+ it('stringifies unknown object shapes', () => {
30
+ expect(formatWebpackMessages({ errors: [{ code: 42 }] })).toEqual({
31
+ errors: ['{"code":42}'],
32
+ warnings: [],
33
+ });
34
+ });
35
+
36
+ it('coerces primitives to string', () => {
37
+ expect(formatWebpackMessages({ errors: [42, true] })).toEqual({
38
+ errors: ['42', 'true'],
39
+ warnings: [],
40
+ });
41
+ });
42
+ });
@@ -0,0 +1,38 @@
1
+ import getPublicUrlOrPath from '../utils/getPublicUrlOrPath';
2
+
3
+ describe('getPublicUrlOrPath', () => {
4
+ describe('with envPublicUrl', () => {
5
+ it('returns the URL with trailing slash in production', () => {
6
+ expect(getPublicUrlOrPath(false, undefined, 'https://cdn.example.com/app')).toBe('https://cdn.example.com/app/');
7
+ });
8
+
9
+ it('returns absolute pathname in development for absolute URL', () => {
10
+ expect(getPublicUrlOrPath(true, undefined, 'https://cdn.example.com/app/')).toBe('/app/');
11
+ });
12
+
13
+ it('returns root in development when URL starts with "."', () => {
14
+ expect(getPublicUrlOrPath(true, undefined, './nested/')).toBe('/');
15
+ });
16
+ });
17
+
18
+ describe('with homepage only', () => {
19
+ it('returns the pathname in production for absolute homepage', () => {
20
+ expect(getPublicUrlOrPath(false, 'https://example.com/app/', undefined)).toBe('/app/');
21
+ });
22
+
23
+ it('returns root in development for absolute homepage', () => {
24
+ expect(getPublicUrlOrPath(true, 'https://example.com/app', undefined)).toBe('/app/');
25
+ });
26
+
27
+ it('returns relative homepage in production when starting with "."', () => {
28
+ expect(getPublicUrlOrPath(false, './app/', undefined)).toBe('./app/');
29
+ });
30
+ });
31
+
32
+ describe('with neither', () => {
33
+ it('returns root', () => {
34
+ expect(getPublicUrlOrPath(true, undefined, undefined)).toBe('/');
35
+ expect(getPublicUrlOrPath(false, undefined, undefined)).toBe('/');
36
+ });
37
+ });
38
+ });
@@ -0,0 +1,47 @@
1
+ import fs from 'fs';
2
+ import os from 'os';
3
+ import path from 'path';
4
+
5
+ describe('createAppPaths', () => {
6
+ let tmpDir: string;
7
+ let savedCwd: string;
8
+
9
+ beforeEach(() => {
10
+ tmpDir = fs.realpathSync(fs.mkdtempSync(path.join(os.tmpdir(), 'apollion-scripts-paths-')));
11
+ fs.writeFileSync(path.join(tmpDir, 'package.json'), JSON.stringify({ name: 'fixture', homepage: '/app/' }));
12
+ fs.writeFileSync(path.join(tmpDir, 'scriptsrc.js'), 'module.exports = { output: "dist" };');
13
+ fs.mkdirSync(path.join(tmpDir, 'src'));
14
+ fs.writeFileSync(path.join(tmpDir, 'src', 'index.tsx'), '// fixture entry');
15
+ fs.writeFileSync(path.join(tmpDir, 'src', 'setupTests.ts'), '// fixture setup');
16
+ savedCwd = process.cwd();
17
+ });
18
+
19
+ afterEach(() => {
20
+ process.chdir(savedCwd);
21
+ fs.rmSync(tmpDir, { recursive: true, force: true });
22
+ jest.resetModules();
23
+ });
24
+
25
+ it('resolves every well-known path against the supplied base', () => {
26
+ process.chdir(tmpDir);
27
+ const { createAppPaths } = require('../config/paths');
28
+ const result = createAppPaths(tmpDir);
29
+
30
+ expect(result.appPath).toBe(tmpDir);
31
+ expect(result.appPackageJson).toBe(path.join(tmpDir, 'package.json'));
32
+ expect(result.appBuild).toBe(path.join(tmpDir, 'dist'));
33
+ expect(result.appHtml).toBe(path.join(tmpDir, 'public/index.html'));
34
+ expect(result.appIndexJs).toBe(path.join(tmpDir, 'src/index.tsx'));
35
+ expect(result.testsSetup).toBe(path.join(tmpDir, 'src/setupTests.ts'));
36
+ expect(result.moduleFileExtensions).toContain('tsx');
37
+ expect(result.publicUrlOrPath).toBe('/app/');
38
+ });
39
+
40
+ it('falls back to a `.js` extension when no source file matches', () => {
41
+ fs.rmSync(path.join(tmpDir, 'src', 'index.tsx'));
42
+ process.chdir(tmpDir);
43
+ const { createAppPaths } = require('../config/paths');
44
+ const result = createAppPaths(tmpDir);
45
+ expect(result.appIndexJs).toBe(path.join(tmpDir, 'src/index.js'));
46
+ });
47
+ });
@@ -0,0 +1,14 @@
1
+ import { defaultDevConfig } from '../config/shared';
2
+
3
+ describe('defaultDevConfig', () => {
4
+ it('exposes the expected dev defaults', () => {
5
+ expect(defaultDevConfig).toEqual({
6
+ port: 3000,
7
+ host: '0.0.0.0',
8
+ head: { title: 'Apollion' },
9
+ constants: {},
10
+ i18nConfig: {},
11
+ useFastRefresh: true,
12
+ });
13
+ });
14
+ });
@@ -95,6 +95,20 @@ function build(config: Configuration, previousFileSizes: unknown) {
95
95
  });
96
96
  }
97
97
 
98
+ /**
99
+ * Run a one-shot webpack production build for the consumer app at `paths`.
100
+ *
101
+ * Side effects:
102
+ * - Sets `process.env.BABEL_ENV` / `NODE_ENV` to `'production'`.
103
+ * - Empties `paths.appBuild` and copies `paths.appPublic` into it.
104
+ * - On failure: prints the formatted error and exits with code 1
105
+ * (or merely warns when `TSC_COMPILE_ON_ERROR=true`).
106
+ * - On `process.env.CI`-truthy runs, treats any webpack warning as a hard error.
107
+ *
108
+ * @param paths Resolved app paths — typically `createAppPaths()`.
109
+ * @param userConfig Optional override. Merged on top of {@link defaultDevConfig}.
110
+ * Pass `configureWebpack` here to mutate the final webpack config.
111
+ */
98
112
  export async function createProductionBuild(
99
113
  paths: AppPaths,
100
114
  userConfig: CustomConfigType = defaultDevConfig,
@@ -18,7 +18,6 @@ export const templateDependencies = [
18
18
  '@types/react-dom',
19
19
  '@types/react-router-dom',
20
20
  'styled-components',
21
- '@types/styled-components',
22
21
  '@apollion-dsi/core',
23
22
  '@apollion-dsi/scripts',
24
23
  '@apollion-dsi/eslint-config',
@@ -22,6 +22,18 @@ import createDevServerConfig from '../config/webpackDevServer.config';
22
22
  import checkRequiredFiles from '../utils/checkRequiredFiles';
23
23
  import { choosePort, createCompiler, prepareProxy, prepareUrls } from '../utils/WebpackDevServerUtils';
24
24
 
25
+ /**
26
+ * Boot a webpack-dev-server for the consumer app described by `paths`.
27
+ *
28
+ * Side effects:
29
+ * - Sets `process.env.BABEL_ENV` / `NODE_ENV` to `'development'`.
30
+ * - Picks an available port starting at `userConfig.port ?? 3000`.
31
+ * - Registers `SIGINT`/`SIGTERM` handlers that stop the server and exit.
32
+ *
33
+ * @param paths Resolved app paths — typically `createAppPaths()`.
34
+ * @param userConfig Optional override. Merged on top of {@link defaultDevConfig}.
35
+ * Pass `configureWebpack` here to mutate the final webpack config.
36
+ */
25
37
  export async function createDevServer(paths: AppPaths, userConfig: CustomConfigType = defaultDevConfig) {
26
38
  const useCustomConfig = fs.existsSync(paths.appCustomConfig);
27
39
 
package/src/config/env.ts CHANGED
@@ -3,6 +3,16 @@ import path from 'path';
3
3
 
4
4
  import { CustomConfigType } from './shared';
5
5
 
6
+ /**
7
+ * Load environment variables from `.env*` files in cascading order
8
+ * (`.env.<NODE_ENV>.local`, `.env.local`, `.env.<NODE_ENV>`, `.env`)
9
+ * and prepend the consumer's `NODE_PATH` entries with absolute paths.
10
+ *
11
+ * **Throws** when `process.env.NODE_ENV` is unset — required so the
12
+ * cascade can pick the right file. Skips `.env.local` for `NODE_ENV=test`.
13
+ *
14
+ * @param paths `AppPaths` (only `paths.dotenv` is read).
15
+ */
6
16
  export function getEnviroment(paths) {
7
17
  const { NODE_ENV, ENV } = process.env;
8
18
 
@@ -43,6 +53,19 @@ export function getEnviroment(paths) {
43
53
  .join(path.delimiter);
44
54
  }
45
55
 
56
+ /**
57
+ * Pick the `REACT_APP_*` subset of `process.env`, augment it with the
58
+ * fixed `NODE_ENV`/`PUBLIC_URL`/`WDS_SOCKET_*`/`FAST_REFRESH` keys, and
59
+ * return both the raw object (for runtime consumers) and a stringified
60
+ * form ready for webpack's `DefinePlugin`.
61
+ *
62
+ * **Security:** vars NOT prefixed with `REACT_APP_` (e.g. `SECRET_KEY`)
63
+ * are excluded — this is the boundary that prevents server-only secrets
64
+ * from leaking into the client bundle.
65
+ *
66
+ * @param publicUrl `paths.publicUrlOrPath` — exposed as `PUBLIC_URL`.
67
+ * @param config Resolved `CustomConfigType` (only `useFastRefresh` is read).
68
+ */
46
69
  export default function getClientEnvironment(publicUrl: string, config: CustomConfigType) {
47
70
  // Grab NODE_ENV and REACT_APP_* environment variables and prepare them to be
48
71
  // injected into the application via DefinePlugin in webpack configuration.