@apollion-dsi/scripts 0.7.7 → 0.8.1
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/CHANGELOG.md +127 -0
- package/README.md +73 -0
- package/codemods/v4-migrate.mjs +196 -0
- package/coverage/clover.xml +123 -0
- package/coverage/coverage-final.json +7 -0
- package/coverage/lcov-report/base.css +224 -0
- package/coverage/lcov-report/block-navigation.js +87 -0
- package/coverage/lcov-report/config/env.ts.html +400 -0
- package/coverage/lcov-report/config/index.html +146 -0
- package/coverage/lcov-report/config/paths.ts.html +442 -0
- package/coverage/lcov-report/config/shared.ts.html +211 -0
- package/coverage/lcov-report/favicon.png +0 -0
- package/coverage/lcov-report/index.html +131 -0
- package/coverage/lcov-report/prettify.css +1 -0
- package/coverage/lcov-report/prettify.js +2 -0
- package/coverage/lcov-report/sort-arrow-sprite.png +0 -0
- package/coverage/lcov-report/sorter.js +210 -0
- package/coverage/lcov-report/utils/checkRequiredFiles.ts.html +178 -0
- package/coverage/lcov-report/utils/formatWebpackMessages.ts.html +214 -0
- package/coverage/lcov-report/utils/getPublicUrlOrPath.ts.html +259 -0
- package/coverage/lcov-report/utils/index.html +146 -0
- package/coverage/lcov.info +236 -0
- package/jest.config.js +36 -0
- package/lib/command/build.d.ts +14 -0
- package/lib/command/build.js +14 -0
- package/lib/command/build.js.map +1 -1
- package/lib/command/create/helper.js +0 -1
- package/lib/command/create/helper.js.map +1 -1
- package/lib/command/dev.d.ts +12 -0
- package/lib/command/dev.js +12 -0
- package/lib/command/dev.js.map +1 -1
- package/lib/command/test.js +2 -5
- package/lib/command/test.js.map +1 -1
- package/lib/config/env.d.ts +23 -0
- package/lib/config/env.js +23 -0
- package/lib/config/env.js.map +1 -1
- package/lib/config/paths.d.ts +31 -0
- package/lib/config/paths.js +11 -0
- package/lib/config/paths.js.map +1 -1
- package/lib/config/shared.d.ts +15 -0
- package/lib/config/shared.js +1 -0
- package/lib/config/shared.js.map +1 -1
- package/lib/config/webpack.config.js +6 -7
- package/lib/config/webpack.config.js.map +1 -1
- package/lib/index.d.ts +8 -0
- package/lib/index.js +8 -0
- package/lib/index.js.map +1 -1
- package/lib/utils/checkRequiredFiles.d.ts +9 -0
- package/lib/utils/checkRequiredFiles.js +9 -0
- package/lib/utils/checkRequiredFiles.js.map +1 -1
- package/lib/utils/formatWebpackMessages.d.ts +13 -0
- package/lib/utils/formatWebpackMessages.js +9 -0
- package/lib/utils/formatWebpackMessages.js.map +1 -1
- package/lib/utils/getPublicUrlOrPath.d.ts +19 -0
- package/lib/utils/getPublicUrlOrPath.js +19 -0
- package/lib/utils/getPublicUrlOrPath.js.map +1 -1
- package/llms.txt +52 -0
- package/package.json +11 -6
- package/scripts/validate.sh +3 -3
- package/src/__tests__/checkRequiredFiles.test.ts +44 -0
- package/src/__tests__/env.test.ts +51 -0
- package/src/__tests__/formatWebpackMessages.test.ts +42 -0
- package/src/__tests__/getPublicUrlOrPath.test.ts +38 -0
- package/src/__tests__/paths.test.ts +47 -0
- package/src/__tests__/shared.test.ts +14 -0
- package/src/command/build.ts +14 -0
- package/src/command/create/helper.ts +0 -1
- package/src/command/dev.ts +12 -0
- package/src/command/test.ts +2 -2
- package/src/config/env.ts +23 -0
- package/src/config/paths.ts +31 -0
- package/src/config/shared.ts +15 -0
- package/src/config/webpack.config.js +6 -7
- package/src/index.ts +9 -0
- package/src/utils/checkRequiredFiles.ts +9 -0
- package/src/utils/formatWebpackMessages.ts +13 -0
- package/src/utils/getPublicUrlOrPath.ts +19 -0
- package/tsconfig.json +1 -1
- package/tsconfig.test.json +14 -0
- package/verify-no-install-scripts.js +76 -0
- package/.prettierrc.js +0 -1
- package/README.MD +0 -91
- package/audit-ci.json +0 -5
package/src/command/build.ts
CHANGED
|
@@ -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,
|
package/src/command/dev.ts
CHANGED
|
@@ -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/command/test.ts
CHANGED
|
@@ -10,7 +10,7 @@ require('../config/env');
|
|
|
10
10
|
|
|
11
11
|
import { execSync } from 'child_process';
|
|
12
12
|
|
|
13
|
-
import
|
|
13
|
+
import { run as jestRun } from 'jest-cli';
|
|
14
14
|
|
|
15
15
|
const argv = process.argv.slice(2);
|
|
16
16
|
|
|
@@ -30,4 +30,4 @@ if (!process.env.CI && argv.indexOf('--watchAll') === -1 && argv.indexOf('--watc
|
|
|
30
30
|
argv.push(hasSourceControl ? '--watch' : '--watchAll');
|
|
31
31
|
}
|
|
32
32
|
|
|
33
|
-
|
|
33
|
+
jestRun(argv);
|
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.
|
package/src/config/paths.ts
CHANGED
|
@@ -3,22 +3,42 @@ import path from 'path';
|
|
|
3
3
|
|
|
4
4
|
import getPublicUrlOrPath from '../utils/getPublicUrlOrPath';
|
|
5
5
|
|
|
6
|
+
/**
|
|
7
|
+
* Resolved filesystem locations the build/dev/test commands operate on.
|
|
8
|
+
* Every entry is an absolute path computed from the consumer app root.
|
|
9
|
+
*/
|
|
6
10
|
export type AppPaths = {
|
|
11
|
+
/** `.env` file the consumer app reads from. Suffixed variants (`.env.local`, `.env.<NODE_ENV>`) are derived from this. */
|
|
7
12
|
dotenv: string;
|
|
13
|
+
/** Consumer app root (= the directory containing `package.json`). */
|
|
8
14
|
appPath: string;
|
|
15
|
+
/** Output directory for production bundles. Honors `scriptsrc.js#output`, defaults to `build/`. */
|
|
9
16
|
appBuild: string;
|
|
17
|
+
/** Directory copied verbatim into `appBuild` during production builds. */
|
|
10
18
|
appPublic: string;
|
|
19
|
+
/** Entry HTML used as the webpack `HtmlWebpackPlugin` template. */
|
|
11
20
|
appHtml: string;
|
|
21
|
+
/** Resolved JS/TS entry under `src/` (extension picked by `moduleFileExtensions`). */
|
|
12
22
|
appIndexJs: string;
|
|
23
|
+
/** Consumer app `src/` root. */
|
|
13
24
|
appSrc: string;
|
|
25
|
+
/** Optional consumer-provided override file (`scriptsrc.js`). */
|
|
14
26
|
appCustomConfig: string;
|
|
27
|
+
/** Consumer app `tsconfig.json`. */
|
|
15
28
|
appTsConfig: string;
|
|
29
|
+
/** Consumer `yarn.lock` — drives "use yarn?" detection. */
|
|
16
30
|
yarnLockFile: string;
|
|
31
|
+
/** Optional `src/setupTests.{ts,tsx,js}` resolved with the same extension precedence. */
|
|
17
32
|
testsSetup: string;
|
|
33
|
+
/** Optional `src/setupProxy.js`. */
|
|
18
34
|
proxySetup: string;
|
|
35
|
+
/** Consumer `node_modules/`. */
|
|
19
36
|
appNodeModules: string;
|
|
37
|
+
/** Consumer `package.json`. */
|
|
20
38
|
appPackageJson: string;
|
|
39
|
+
/** Public URL (or absolute pathname in dev) derived from env + homepage — see {@link getPublicUrlOrPath}. */
|
|
21
40
|
publicUrlOrPath: string;
|
|
41
|
+
/** Source extensions tried (in order) when resolving JS/TS entries. */
|
|
22
42
|
moduleFileExtensions: string[];
|
|
23
43
|
};
|
|
24
44
|
|
|
@@ -36,6 +56,17 @@ export const moduleFileExtensions = [
|
|
|
36
56
|
'jsx',
|
|
37
57
|
];
|
|
38
58
|
|
|
59
|
+
/**
|
|
60
|
+
* Build the {@link AppPaths} object for the consumer app rooted at `basePath`.
|
|
61
|
+
*
|
|
62
|
+
* Reads (synchronously, at call time):
|
|
63
|
+
* - `<basePath>/package.json` — for `homepage`.
|
|
64
|
+
* - `<basePath>/scriptsrc.js` — if present, for `output` override.
|
|
65
|
+
* - `process.env.NODE_ENV`, `process.env.PUBLIC_URL` — drive public-url resolution.
|
|
66
|
+
*
|
|
67
|
+
* @param basePath Defaults to `process.cwd()`. Pass an explicit path in tests
|
|
68
|
+
* to point at a fixture without changing the working dir.
|
|
69
|
+
*/
|
|
39
70
|
export function createAppPaths(basePath: string = process.cwd()): AppPaths {
|
|
40
71
|
const appDirectory = fs.realpathSync(basePath);
|
|
41
72
|
const resolveApp = (relativePath) => path.resolve(appDirectory, relativePath);
|
package/src/config/shared.ts
CHANGED
|
@@ -1,20 +1,35 @@
|
|
|
1
1
|
import { Configuration } from 'webpack';
|
|
2
2
|
|
|
3
|
+
/**
|
|
4
|
+
* Shape of the optional `scriptsrc.js` consumer apps drop next to their
|
|
5
|
+
* `package.json` to override CLI defaults. Every field is optional —
|
|
6
|
+
* unset keys fall back to {@link defaultDevConfig}.
|
|
7
|
+
*/
|
|
3
8
|
export type CustomConfigType = {
|
|
9
|
+
/** Dev server port. Default `3000`. `choosePort` will increment if busy. */
|
|
4
10
|
port?: number;
|
|
11
|
+
/** Dev server host. Default `'0.0.0.0'` (listens on all interfaces). */
|
|
5
12
|
host?: string;
|
|
13
|
+
/** HTML `<title>` injected via `HtmlWebpackPlugin`. */
|
|
6
14
|
head?: HeadConfigType;
|
|
15
|
+
/** Constants exposed to the bundle via `DefinePlugin`. Stringified for you. */
|
|
7
16
|
constants?: Record<string, string>;
|
|
17
|
+
/** Arbitrary i18n config object — opaque to the CLI, forwarded to consumer code. */
|
|
8
18
|
i18nConfig?: Record<string, any>;
|
|
19
|
+
/** Enable React Refresh in dev. Default `true`. */
|
|
9
20
|
useFastRefresh?: boolean;
|
|
21
|
+
/** Relay compiler artifact dir (used by `babel-plugin-relay`). */
|
|
10
22
|
relayArtifactDirectory?: string;
|
|
23
|
+
/** Last-mile escape hatch: receives the resolved webpack config and must return one. */
|
|
11
24
|
configureWebpack?: (config: Configuration, env: 'development' | 'production' | 'test') => Configuration;
|
|
12
25
|
};
|
|
13
26
|
|
|
27
|
+
/** `<head>` overrides — only `title` is consumed today. */
|
|
14
28
|
export type HeadConfigType = {
|
|
15
29
|
title: string;
|
|
16
30
|
};
|
|
17
31
|
|
|
32
|
+
/** Defaults merged into every `CustomConfigType` consumer override. */
|
|
18
33
|
export const defaultDevConfig = {
|
|
19
34
|
port: 3000,
|
|
20
35
|
host: '0.0.0.0',
|
|
@@ -7,7 +7,7 @@ import ModuleNotFoundPlugin from '../utils/ModuleNotFoundPlugin';
|
|
|
7
7
|
import ModuleScopePlugin from '../utils/ModuleScopePlugin';
|
|
8
8
|
import ReactRefreshWebpackPlugin from '@pmmmwh/react-refresh-webpack-plugin';
|
|
9
9
|
import CaseSensitivePathsPlugin from 'case-sensitive-paths-webpack-plugin';
|
|
10
|
-
import
|
|
10
|
+
import { GitRevisionPlugin as GitRevisionPluginCtor } from 'git-revision-webpack-plugin';
|
|
11
11
|
import HtmlWebpackPlugin from 'html-webpack-plugin';
|
|
12
12
|
import resolve from 'resolve';
|
|
13
13
|
import TerserPlugin from 'terser-webpack-plugin';
|
|
@@ -21,7 +21,7 @@ import modules from './modules';
|
|
|
21
21
|
export default (webpackEnv, paths, options = {}) => {
|
|
22
22
|
const appPackageJson = require(paths.appPackageJson);
|
|
23
23
|
|
|
24
|
-
const GitRevisionPlugin = new
|
|
24
|
+
const GitRevisionPlugin = new GitRevisionPluginCtor({ branch: true });
|
|
25
25
|
|
|
26
26
|
const shouldInlineRuntimeChunk = process.env.INLINE_RUNTIME_CHUNK !== 'false';
|
|
27
27
|
|
|
@@ -64,7 +64,9 @@ export default (webpackEnv, paths, options = {}) => {
|
|
|
64
64
|
output: {
|
|
65
65
|
path: isEnvProduction ? paths.appBuild : undefined,
|
|
66
66
|
pathinfo: isEnvDevelopment,
|
|
67
|
-
filename: isEnvProduction
|
|
67
|
+
filename: isEnvProduction
|
|
68
|
+
? 'static/js/[name].[contenthash:8].js'
|
|
69
|
+
: isEnvDevelopment && 'static/js/[name].bundle.js',
|
|
68
70
|
chunkFilename: isEnvProduction
|
|
69
71
|
? 'static/js/[name].[contenthash:8].chunk.js'
|
|
70
72
|
: isEnvDevelopment && 'static/js/[name].chunk.js',
|
|
@@ -138,10 +140,7 @@ export default (webpackEnv, paths, options = {}) => {
|
|
|
138
140
|
tls: false,
|
|
139
141
|
child_process: false,
|
|
140
142
|
},
|
|
141
|
-
plugins: [
|
|
142
|
-
new ModuleScopePlugin(paths.appSrc, [paths.appPackageJson]),
|
|
143
|
-
new TsconfigPathsPlugin(),
|
|
144
|
-
],
|
|
143
|
+
plugins: [new ModuleScopePlugin(paths.appSrc, [paths.appPackageJson]), new TsconfigPathsPlugin()],
|
|
145
144
|
},
|
|
146
145
|
module: {
|
|
147
146
|
strictExportPresence: true,
|
package/src/index.ts
CHANGED
|
@@ -1,3 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Public API of `@apollion-dsi/scripts` — the CRA-style CLI consumed by
|
|
3
|
+
* Apollion-based clients (Jovian, DEX-Aggregator, Fanaticofc). Detailed
|
|
4
|
+
* usage lives in {@link README.md}; this barrel only re-exports the
|
|
5
|
+
* three entry points consumer apps need.
|
|
6
|
+
*
|
|
7
|
+
* @packageDocumentation
|
|
8
|
+
*/
|
|
9
|
+
|
|
1
10
|
export { createAppPaths, AppPaths } from './config/paths';
|
|
2
11
|
export { createDevServer } from './command/dev';
|
|
3
12
|
export { createProductionBuild } from './command/build';
|
|
@@ -3,6 +3,15 @@ import path from 'path';
|
|
|
3
3
|
|
|
4
4
|
import chalk from 'chalk';
|
|
5
5
|
|
|
6
|
+
/**
|
|
7
|
+
* Verify every file in `files` exists on disk. Logs the first missing
|
|
8
|
+
* file to `console.log` (with chalk) and returns `false`; otherwise
|
|
9
|
+
* returns `true`. Used by the build/dev commands to fail fast before
|
|
10
|
+
* touching webpack.
|
|
11
|
+
*
|
|
12
|
+
* @param files Absolute paths to required files (typically `paths.appHtml`,
|
|
13
|
+
* `paths.appIndexJs`).
|
|
14
|
+
*/
|
|
6
15
|
export default function checkRequiredFiles(files: string[]): boolean {
|
|
7
16
|
let currentFilePath: string | undefined;
|
|
8
17
|
try {
|
|
@@ -1,3 +1,7 @@
|
|
|
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[];
|
|
@@ -23,6 +27,15 @@ function toString(item: unknown): string {
|
|
|
23
27
|
return String(item);
|
|
24
28
|
}
|
|
25
29
|
|
|
30
|
+
/**
|
|
31
|
+
* Coerce webpack's `stats.toJson({ warnings, errors })` shape into a
|
|
32
|
+
* plain `{ errors, warnings }` of strings. Tolerates `null`, arrays of
|
|
33
|
+
* objects with `{ message, moduleName }`, raw primitives, or anything
|
|
34
|
+
* else (falls back to `JSON.stringify` / `String()`).
|
|
35
|
+
*
|
|
36
|
+
* @param json Output of `stats.toJson({ warnings: true, errors: true })`
|
|
37
|
+
* or any partially-shaped equivalent.
|
|
38
|
+
*/
|
|
26
39
|
export default function formatWebpackMessages(json: any): FormattedMessages {
|
|
27
40
|
const errors = Array.isArray(json?.errors) ? json.errors.map(toString) : [];
|
|
28
41
|
const warnings = Array.isArray(json?.warnings) ? json.warnings.map(toString) : [];
|
|
@@ -1,5 +1,24 @@
|
|
|
1
1
|
import { URL } from 'url';
|
|
2
2
|
|
|
3
|
+
/**
|
|
4
|
+
* Compute the absolute base URL (or path) every bundled asset is served from.
|
|
5
|
+
*
|
|
6
|
+
* Precedence: `envPublicUrl` → `homepage` → `'/'`.
|
|
7
|
+
*
|
|
8
|
+
* In **development**, absolute URLs collapse to their pathname so the
|
|
9
|
+
* dev-server doesn't try to fetch from a different origin; relative
|
|
10
|
+
* homepages (starting with `.`) collapse to `'/'` for the same reason.
|
|
11
|
+
*
|
|
12
|
+
* In **production**, the full URL (or pathname when only `homepage` is
|
|
13
|
+
* set) is preserved so CDN-rooted bundles resolve correctly.
|
|
14
|
+
*
|
|
15
|
+
* Adapted from `react-scripts` — semantics kept identical to ease migration.
|
|
16
|
+
*
|
|
17
|
+
* @param isEnvDevelopment `true` when `NODE_ENV === 'development'`.
|
|
18
|
+
* @param homepage `package.json#homepage` (project-level).
|
|
19
|
+
* @param envPublicUrl `process.env.PUBLIC_URL` (per-invocation override).
|
|
20
|
+
* @returns A trailing-slash-normalized URL or absolute path.
|
|
21
|
+
*/
|
|
3
22
|
export default function getPublicUrlOrPath(
|
|
4
23
|
isEnvDevelopment: boolean,
|
|
5
24
|
homepage: string | undefined,
|
package/tsconfig.json
CHANGED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
{
|
|
2
|
+
"extends": "./tsconfig.json",
|
|
3
|
+
"include": ["src", "src/__tests__"],
|
|
4
|
+
"exclude": [],
|
|
5
|
+
"compilerOptions": {
|
|
6
|
+
"noEmit": true,
|
|
7
|
+
"module": "commonjs",
|
|
8
|
+
"moduleResolution": "node",
|
|
9
|
+
"esModuleInterop": true,
|
|
10
|
+
"isolatedModules": false,
|
|
11
|
+
"noImplicitAny": false,
|
|
12
|
+
"types": ["jest", "node"]
|
|
13
|
+
}
|
|
14
|
+
}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* verify-no-install-scripts — supply-chain hardening (threat-model E2).
|
|
4
|
+
*
|
|
5
|
+
* Blocks `@apollion-dsi/*` workspaces from declaring lifecycle scripts that
|
|
6
|
+
* **run on consumer install** of the published package — the attack vector
|
|
7
|
+
* for malicious npm postinstall (event-stream / ua-parser-js precedent).
|
|
8
|
+
*
|
|
9
|
+
* **Strictly blocked (consumer-install-time):**
|
|
10
|
+
* preinstall, install, postinstall
|
|
11
|
+
*
|
|
12
|
+
* **Allowed with caution (publish-time only — npm 7+ does NOT run these on
|
|
13
|
+
* consumer install):** prepare, prepublish, prepublishOnly, postpublish.
|
|
14
|
+
* These are legitimate for `yarn build` style workflows but still appear in
|
|
15
|
+
* the published tarball. Audit in PR review for any code that fetches
|
|
16
|
+
* remote resources or mutates the working tree.
|
|
17
|
+
*
|
|
18
|
+
* Exit 0 on clean, exit 1 if any forbidden hook found.
|
|
19
|
+
*
|
|
20
|
+
* @see ADR-006 §3.8 boundary B2 (anti-postinstall policy)
|
|
21
|
+
* @see ADR-006 §8.5 risk #7 (E2 NPM postinstall lateral)
|
|
22
|
+
* @see PRD-002 §S5
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
const fs = require('node:fs');
|
|
26
|
+
const path = require('node:path');
|
|
27
|
+
|
|
28
|
+
const FORBIDDEN_HOOKS = ['preinstall', 'install', 'postinstall'];
|
|
29
|
+
|
|
30
|
+
const REPO_ROOT = process.argv[2]
|
|
31
|
+
? path.resolve(process.argv[2])
|
|
32
|
+
: path.resolve(__dirname, '..', '..');
|
|
33
|
+
|
|
34
|
+
const PACKAGES_DIR = path.join(REPO_ROOT, 'packages');
|
|
35
|
+
|
|
36
|
+
function findPackageJsons() {
|
|
37
|
+
const out = [];
|
|
38
|
+
if (!fs.existsSync(PACKAGES_DIR)) return out;
|
|
39
|
+
for (const name of fs.readdirSync(PACKAGES_DIR)) {
|
|
40
|
+
const pkgPath = path.join(PACKAGES_DIR, name, 'package.json');
|
|
41
|
+
if (fs.existsSync(pkgPath)) out.push(pkgPath);
|
|
42
|
+
}
|
|
43
|
+
return out;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function scan(pkgPath) {
|
|
47
|
+
const data = JSON.parse(fs.readFileSync(pkgPath, 'utf8'));
|
|
48
|
+
const name = data.name ?? '<unknown>';
|
|
49
|
+
const scripts = data.scripts ?? {};
|
|
50
|
+
const violations = FORBIDDEN_HOOKS.filter((hook) => Object.prototype.hasOwnProperty.call(scripts, hook));
|
|
51
|
+
return { name, pkgPath, violations };
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function main() {
|
|
55
|
+
const results = findPackageJsons().map(scan);
|
|
56
|
+
const bad = results.filter((r) => r.violations.length > 0);
|
|
57
|
+
|
|
58
|
+
if (bad.length === 0) {
|
|
59
|
+
console.log(`✓ verify-no-install-scripts: ${results.length} package.json clean (no forbidden lifecycle hooks)`);
|
|
60
|
+
process.exit(0);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
console.error('✗ verify-no-install-scripts: forbidden lifecycle hooks found:');
|
|
64
|
+
for (const r of bad) {
|
|
65
|
+
console.error(` ${r.name} (${path.relative(REPO_ROOT, r.pkgPath)})`);
|
|
66
|
+
for (const hook of r.violations) {
|
|
67
|
+
console.error(` - ${hook}: ${r.violations.length === 1 ? '' : ''}`);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
console.error('');
|
|
71
|
+
console.error(' ADR-006 §3.8 boundary B2 + §8.5 risk E2 forbid install-time scripts');
|
|
72
|
+
console.error(' in @apollion-dsi/* workspaces to mitigate supply-chain attack vector.');
|
|
73
|
+
process.exit(1);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
main();
|
package/.prettierrc.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
module.exports = require('@apollion-dsi/eslint-config/prettier.config');
|
package/README.MD
DELETED
|
@@ -1,91 +0,0 @@
|
|
|
1
|
-
# Apollion Scripts
|
|
2
|
-
|
|
3
|
-
Interface de linha de comando, contendo o template para iniciar, desenvolver e fazer o build de uma aplicação com Apollion Design System.
|
|
4
|
-
|
|
5
|
-
## Desenvolvimento
|
|
6
|
-
|
|
7
|
-
### Criando um novo projeto
|
|
8
|
-
|
|
9
|
-
Você pode iniciar um novo projeto usando a nossa `CLI` com o comando a seguir:
|
|
10
|
-
|
|
11
|
-
```bash
|
|
12
|
-
$ npx @captalys-platform/scripts create project-name
|
|
13
|
-
$ cd project-name
|
|
14
|
-
$ yarn start
|
|
15
|
-
# ou
|
|
16
|
-
$ npm start
|
|
17
|
-
```
|
|
18
|
-
|
|
19
|
-
Você não precisa instalar ou configurar ferramentas como `webpack` e `babel`, ambos já vem configurados para que você possa focar no código. Além disso o template inclui `eslint`, `prettier`, `jest`, `commitLint` e `Typescript`. O template tem a seguinte estrutura:
|
|
20
|
-
|
|
21
|
-
```
|
|
22
|
-
project-name
|
|
23
|
-
├── node_modules
|
|
24
|
-
├── package.json
|
|
25
|
-
├── tsconfig.json
|
|
26
|
-
├── jest.config.js
|
|
27
|
-
├── commitlint.config.js
|
|
28
|
-
├── .eslintrc.js
|
|
29
|
-
├── .editorconfig.js
|
|
30
|
-
├── .gitignore
|
|
31
|
-
├── .prettierrc.js
|
|
32
|
-
├── public
|
|
33
|
-
│ ├── index.html
|
|
34
|
-
└── src
|
|
35
|
-
├── index.tsx
|
|
36
|
-
├── App.tsx
|
|
37
|
-
├── App.test.tsx
|
|
38
|
-
```
|
|
39
|
-
|
|
40
|
-
### Projetos existentes
|
|
41
|
-
|
|
42
|
-
1. Para projetos existentes, você pode usar nossa `CLI` da seguinte forma (na raiz do projeto)
|
|
43
|
-
|
|
44
|
-
```bash
|
|
45
|
-
$ npm install @captalys-platform/scripts --save-dev
|
|
46
|
-
# ou
|
|
47
|
-
$ yarn add @captalys-platform/scripts --dev
|
|
48
|
-
```
|
|
49
|
-
|
|
50
|
-
2. Você deve atualizar o campo `scripts` do `package.json`
|
|
51
|
-
|
|
52
|
-
```json
|
|
53
|
-
{
|
|
54
|
-
"scripts": {
|
|
55
|
-
"dev": "scripts dev",
|
|
56
|
-
"build": "scripts build",
|
|
57
|
-
"test": "scripts test"
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
```
|
|
61
|
-
|
|
62
|
-
3. Para a aplicação funcionar é necessário utilizar a estrutura de pasta a seguir
|
|
63
|
-
|
|
64
|
-
```
|
|
65
|
-
project-name
|
|
66
|
-
├── package.json
|
|
67
|
-
├── public
|
|
68
|
-
│ ├── index.html
|
|
69
|
-
└── src
|
|
70
|
-
├── index.tsx
|
|
71
|
-
```
|
|
72
|
-
|
|
73
|
-
## Comandos
|
|
74
|
-
|
|
75
|
-
Estes são os comandos disponíveis no nosso template
|
|
76
|
-
|
|
77
|
-
- `yarn start` ou `npm start`
|
|
78
|
-
|
|
79
|
-
Roda o projeto em um servidor de desenvolvimento, com reload automático, em http://localhost:3000/.
|
|
80
|
-
|
|
81
|
-
- `yarn build` ou `npm build`
|
|
82
|
-
|
|
83
|
-
Cria o projeto para ser distribuído para produção, na pasta **build**.
|
|
84
|
-
|
|
85
|
-
- `yarn test` ou `npm test`
|
|
86
|
-
|
|
87
|
-
Roda os testes com `jest --watch` nos arquivos alterados a partir do ultimo commit.
|
|
88
|
-
|
|
89
|
-
## Licença
|
|
90
|
-
|
|
91
|
-
© 2021 Captalys - Todos os direitos reservados.
|