sku 12.4.11 → 12.5.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 +60 -0
- package/README.md +13 -5
- package/config/typescript/tsconfig.js +7 -3
- package/config/webpack/plugins/createHtmlRenderPlugin.js +1 -1
- package/config/webpack/utils/resolvePackage.js +2 -1
- package/context/defaultCompilePackages.js +65 -39
- package/entry/server/index.js +6 -12
- package/lib/allocatePort.js +2 -1
- package/lib/buildFileUtils.js +16 -6
- package/lib/configure.js +13 -16
- package/lib/copyDirContents.js +1 -0
- package/lib/createServer.js +1 -0
- package/lib/cwd.js +1 -0
- package/lib/env.js +1 -0
- package/lib/exists.js +1 -0
- package/lib/getSiteForHost.js +1 -0
- package/lib/install.js +2 -0
- package/lib/isCI.js +1 -0
- package/lib/isCompilePackage.js +1 -0
- package/lib/isEmptyDir.js +21 -0
- package/lib/parseArgs.js +53 -65
- package/lib/parseArgs.test.js +30 -5
- package/lib/routeMatcher.js +1 -0
- package/lib/runBin.js +3 -2
- package/lib/runTsc.js +1 -0
- package/lib/runVocab.js +1 -0
- package/lib/storybook.js +1 -0
- package/lib/suggestScript.js +1 -0
- package/lib/toPosixPath.test.js +4 -0
- package/lib/validateLessFiles.js +9 -3
- package/lib/validatePeerDeps.js +34 -22
- package/package.json +10 -9
- package/scripts/build-storybook.js +2 -2
- package/scripts/build.js +2 -2
- package/scripts/init.js +19 -18
- package/tsconfig.json +0 -4
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,65 @@
|
|
|
1
1
|
# sku
|
|
2
2
|
|
|
3
|
+
## 12.5.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Remove `rimraf` dependency in favour of Node.js's `rm` ([#961](https://github.com/seek-oss/sku/pull/961))
|
|
8
|
+
|
|
9
|
+
- Unpin and bump `@pmmmwh/react-refresh-webpack-plugin` ([#959](https://github.com/seek-oss/sku/pull/959))
|
|
10
|
+
|
|
11
|
+
- Ensure all sku-generated gitignored files are present in `.prettierignore` and `.eslintignore` too ([#957](https://github.com/seek-oss/sku/pull/957))
|
|
12
|
+
|
|
13
|
+
Consumers should notice a few new files being added to the sku-managed sections within `.prettierignore` and `.eslintignore` the next time a `sku` command is run:
|
|
14
|
+
|
|
15
|
+
```diff
|
|
16
|
+
# managed by sku
|
|
17
|
+
*.less.d.ts
|
|
18
|
+
+.eslintcache
|
|
19
|
+
+.eslintrc
|
|
20
|
+
+.prettierrc
|
|
21
|
+
.storybook/main.js
|
|
22
|
+
coverage/
|
|
23
|
+
dist-storybook/
|
|
24
|
+
dist/
|
|
25
|
+
report/
|
|
26
|
+
# end managed by sku
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
These changes should be committed to your repo.
|
|
30
|
+
|
|
31
|
+
- Disable peer dependency validation for PNPM ([#952](https://github.com/seek-oss/sku/pull/952))
|
|
32
|
+
|
|
33
|
+
The method we currently use to validate peer dependencies and warn users about duplicate package is not compatible with how PNPM organizes dependencies in `node_modules`. This feature has been disabled for PNPM repos until further notice.
|
|
34
|
+
|
|
35
|
+
- Replace `memoizee` dependency with `nano-memoize` ([#953](https://github.com/seek-oss/sku/pull/953))
|
|
36
|
+
|
|
37
|
+
- Replace `fast-glob` with `fdir` and `picomatch` ([#952](https://github.com/seek-oss/sku/pull/952))
|
|
38
|
+
|
|
39
|
+
- Replace `validate-npm-package-name` dependency with a regexp ([#954](https://github.com/seek-oss/sku/pull/954))
|
|
40
|
+
|
|
41
|
+
- Improve performance of peer dependency validation ([#952](https://github.com/seek-oss/sku/pull/952))
|
|
42
|
+
|
|
43
|
+
Peer dependency validation shoould now complete within a few seconds, rather than a few minutes.
|
|
44
|
+
|
|
45
|
+
## 12.5.0
|
|
46
|
+
|
|
47
|
+
### Minor Changes
|
|
48
|
+
|
|
49
|
+
- Update TypeScript to 5.3 ([#938](https://github.com/seek-oss/sku/pull/938))
|
|
50
|
+
|
|
51
|
+
This release includes breaking changes. See the [TypeScript 5.3 announcement] for more information.
|
|
52
|
+
|
|
53
|
+
[TypeScript 5.3 announcement]: https://devblogs.microsoft.com/typescript/announcing-typescript-5-3/
|
|
54
|
+
|
|
55
|
+
### Patch Changes
|
|
56
|
+
|
|
57
|
+
- Remove `empty-dir` dependency ([#935](https://github.com/seek-oss/sku/pull/935))
|
|
58
|
+
|
|
59
|
+
- Replace `command-line-args` with `minimist` for parsing CLI arguments ([#940](https://github.com/seek-oss/sku/pull/940))
|
|
60
|
+
|
|
61
|
+
- Emit incremental TypeScript build info for faster subsequent type checking ([#938](https://github.com/seek-oss/sku/pull/938))
|
|
62
|
+
|
|
3
63
|
## 12.4.11
|
|
4
64
|
|
|
5
65
|
### Patch Changes
|
package/README.md
CHANGED
|
@@ -6,7 +6,8 @@
|
|
|
6
6
|
|
|
7
7
|
Front-end development toolkit, powered by [Webpack](https://webpack.js.org/), [Babel](https://babeljs.io/), [Vanilla Extract](https://vanilla-extract.style/), [CSS Modules](https://github.com/css-modules/css-modules), [Less](http://lesscss.org/), [ESLint](http://eslint.org/), [Prettier](https://prettier.io/), [Jest](https://facebook.github.io/jest/) and [Storybook](https://storybook.js.org/).
|
|
8
8
|
|
|
9
|
-
Quickly get up and running with a zero-config development environment, or optionally add minimal config when needed.
|
|
9
|
+
Quickly get up and running with a zero-config development environment, or optionally add minimal config when needed.
|
|
10
|
+
Designed for usage with [braid-design-system](https://github.com/seek-oss/braid-design-system), although this isn't a requirement.
|
|
10
11
|
|
|
11
12
|
This tool is heavily inspired by other work, most notably:
|
|
12
13
|
|
|
@@ -14,13 +15,19 @@ This tool is heavily inspired by other work, most notably:
|
|
|
14
15
|
- [insin/nwb](https://github.com/insin/nwb)
|
|
15
16
|
- [NYTimes/kyt](https://github.com/NYTimes/kyt)
|
|
16
17
|
|
|
17
|
-
|
|
18
|
+
> [!WARNING]
|
|
19
|
+
> While this software is open source, its primary purpose is to improve consistency, cross-team collaboration and code quality at SEEK.
|
|
20
|
+
> As a result, it’s likely that this tool may not exactly suit your needs, or may be overkill for your use case.
|
|
21
|
+
> It may be worth considering alternatives such as [Vite] or [Parcel].
|
|
22
|
+
|
|
23
|
+
[Vite]: https://vitejs.dev/
|
|
24
|
+
[Parcel]: https://parceljs.org/
|
|
18
25
|
|
|
19
26
|
## Getting Started
|
|
20
27
|
|
|
21
28
|
Create a new project and start a local development environment:
|
|
22
29
|
|
|
23
|
-
```
|
|
30
|
+
```sh
|
|
24
31
|
$ npx sku init my-app
|
|
25
32
|
$ cd my-app
|
|
26
33
|
$ yarn start
|
|
@@ -30,7 +37,7 @@ By default, a new project's dependencies will be installed with the first suppor
|
|
|
30
37
|
Package managers are detected in the following order: `yarn` -> `pnpm` -> `npm`.
|
|
31
38
|
This can be overridden via the `--packageManager` flag:
|
|
32
39
|
|
|
33
|
-
```
|
|
40
|
+
```sh
|
|
34
41
|
$ pnpm dlx sku init --packageManager pnpm my-app
|
|
35
42
|
$ cd my-app
|
|
36
43
|
$ pnpm start
|
|
@@ -40,7 +47,8 @@ $ pnpm start
|
|
|
40
47
|
|
|
41
48
|
## Contributing
|
|
42
49
|
|
|
43
|
-
Refer to [CONTRIBUTING.md](/CONTRIBUTING.md).
|
|
50
|
+
Refer to [CONTRIBUTING.md](/CONTRIBUTING.md).
|
|
51
|
+
If you're planning to change the public API, please [open a new issue](https://github.com/seek-oss/sku/issues/new).
|
|
44
52
|
|
|
45
53
|
## License
|
|
46
54
|
|
|
@@ -4,11 +4,15 @@ const { rootResolution, tsconfigDecorator } = require('../../context');
|
|
|
4
4
|
module.exports = () => {
|
|
5
5
|
const config = {
|
|
6
6
|
compilerOptions: {
|
|
7
|
-
//
|
|
8
|
-
// otherwise it would emit a bunch of useless JS/JSX files in your project.
|
|
9
|
-
// We emit compiled JavaScript into `dist` via webpack + Babel, not tsc.
|
|
7
|
+
// Don't compile anything, only perform type checking
|
|
10
8
|
noEmit: true,
|
|
11
9
|
|
|
10
|
+
// Emit build information for faster subsequent type checking
|
|
11
|
+
incremental: true,
|
|
12
|
+
// Emit build information to `node_modules` to avoid bloating the project root
|
|
13
|
+
// and ignore files
|
|
14
|
+
outDir: 'node_modules',
|
|
15
|
+
|
|
12
16
|
// Fixes https://github.com/cypress-io/cypress/issues/1087
|
|
13
17
|
skipLibCheck: true,
|
|
14
18
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
const path = require('node:path');
|
|
2
|
-
const memoize = require('
|
|
2
|
+
const { default: memoize } = require('nano-memoize');
|
|
3
3
|
const debug = require('debug')('sku:resolvePackage');
|
|
4
4
|
const { cwd } = require('../../../lib/cwd');
|
|
5
5
|
|
|
@@ -37,6 +37,7 @@ const createPackageResolver = (fs, resolve) => {
|
|
|
37
37
|
*
|
|
38
38
|
* Throws if a package is listed in the project's dependencies and cannot be resolved.
|
|
39
39
|
*/
|
|
40
|
+
/** @param {string} packageName */
|
|
40
41
|
function resolvePackage(packageName) {
|
|
41
42
|
try {
|
|
42
43
|
// First, try to use require.resolve to find the package.
|
|
@@ -1,57 +1,83 @@
|
|
|
1
1
|
const { posix: path } = require('node:path');
|
|
2
2
|
const chalk = require('chalk');
|
|
3
|
-
const
|
|
3
|
+
const { fdir: Fdir } = require('fdir');
|
|
4
4
|
|
|
5
|
-
const { cwd
|
|
5
|
+
const { cwd } = require('../lib/cwd');
|
|
6
6
|
const toPosixPath = require('../lib/toPosixPath');
|
|
7
7
|
|
|
8
8
|
const { rootDir, isPnpm } = require('../lib/packageManager');
|
|
9
|
+
const debug = require('debug')('sku:compilePackages');
|
|
9
10
|
|
|
10
11
|
/** @type {string[]} */
|
|
11
12
|
let detectedCompilePackages = [];
|
|
12
13
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
14
|
+
// If there's no rootDir, we're either inside `sku init`, or we can't determine the user's
|
|
15
|
+
// package manager. In either case, we can't correctly detect compile packages.
|
|
16
|
+
if (rootDir) {
|
|
17
|
+
try {
|
|
18
|
+
let crawler = new Fdir();
|
|
16
19
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
'.',
|
|
24
|
-
pnpmVirtualStorePath,
|
|
25
|
-
);
|
|
26
|
-
const pnpmVirtualStoreGlob = path.join(
|
|
27
|
-
pnpmVirtualStoreRelativePath,
|
|
28
|
-
'@seek*/node_modules/@seek/*/package.json',
|
|
29
|
-
);
|
|
20
|
+
if (isPnpm) {
|
|
21
|
+
// Follow symlinks inside node_modules into the pnpm virtual store
|
|
22
|
+
crawler = crawler.withSymlinks().withRelativePaths();
|
|
23
|
+
} else {
|
|
24
|
+
crawler = crawler.withBasePath();
|
|
25
|
+
}
|
|
30
26
|
|
|
31
|
-
|
|
32
|
-
|
|
27
|
+
const seekDependencyGlob = '**/@seek/*/package.json';
|
|
28
|
+
|
|
29
|
+
let results = crawler
|
|
30
|
+
.glob(seekDependencyGlob)
|
|
31
|
+
.crawl('./node_modules/@seek')
|
|
32
|
+
.sync();
|
|
33
|
+
|
|
34
|
+
if (isPnpm) {
|
|
35
|
+
const pnpmVirtualStorePath = path.join(
|
|
36
|
+
toPosixPath(rootDir),
|
|
37
|
+
'node_modules/.pnpm',
|
|
38
|
+
);
|
|
39
|
+
|
|
40
|
+
const pnpmVirtualStoreRelativePath = path.relative(
|
|
41
|
+
'.',
|
|
42
|
+
pnpmVirtualStorePath,
|
|
43
|
+
);
|
|
33
44
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
45
|
+
const pnpmVirtualStoreResults = new Fdir()
|
|
46
|
+
.withRelativePaths()
|
|
47
|
+
.glob(seekDependencyGlob)
|
|
48
|
+
.crawl(pnpmVirtualStoreRelativePath)
|
|
49
|
+
.sync();
|
|
50
|
+
|
|
51
|
+
results.push(...pnpmVirtualStoreResults);
|
|
52
|
+
|
|
53
|
+
// All results will be relative to the virtual store directory, so we need
|
|
54
|
+
// to prepend the relative path from the current directory to the virtual store
|
|
55
|
+
results = results.map((file) =>
|
|
56
|
+
path.join(pnpmVirtualStoreRelativePath, file),
|
|
57
|
+
);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
detectedCompilePackages = results
|
|
61
|
+
.map((packagePath) => {
|
|
62
|
+
const packageJson = require(path.join(cwd(), packagePath));
|
|
63
|
+
|
|
64
|
+
return {
|
|
65
|
+
isCompilePackage: Boolean(packageJson.skuCompilePackage),
|
|
66
|
+
packageName: packageJson.name,
|
|
67
|
+
};
|
|
68
|
+
})
|
|
69
|
+
.filter(({ isCompilePackage }) => isCompilePackage)
|
|
70
|
+
.map(({ packageName }) => packageName);
|
|
71
|
+
} catch (e) {
|
|
72
|
+
console.log(
|
|
73
|
+
chalk.red`Warning: Failed to detect compile packages. Contact #sku-support.`,
|
|
74
|
+
);
|
|
75
|
+
console.error(e);
|
|
76
|
+
}
|
|
53
77
|
}
|
|
54
78
|
|
|
79
|
+
debug(detectedCompilePackages);
|
|
80
|
+
|
|
55
81
|
module.exports = [
|
|
56
82
|
'sku',
|
|
57
83
|
'braid-design-system',
|
package/entry/server/index.js
CHANGED
|
@@ -1,20 +1,14 @@
|
|
|
1
1
|
import fs from 'node:fs';
|
|
2
2
|
import http from 'node:http';
|
|
3
3
|
import https from 'node:https';
|
|
4
|
-
import commandLineArgs from 'command-line-args';
|
|
5
4
|
import { app, onStart } from './server';
|
|
5
|
+
import minimist from 'minimist';
|
|
6
6
|
|
|
7
|
-
const { port } =
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
type: Number,
|
|
13
|
-
defaultValue: __SKU_DEFAULT_SERVER_PORT__, // eslint-disable-line no-undef
|
|
14
|
-
},
|
|
15
|
-
],
|
|
16
|
-
{ partial: true },
|
|
17
|
-
);
|
|
7
|
+
const { port } = minimist(process.argv.slice(2), {
|
|
8
|
+
alias: { p: 'port' },
|
|
9
|
+
// eslint-disable-next-line no-undef
|
|
10
|
+
default: { port: __SKU_DEFAULT_SERVER_PORT__ },
|
|
11
|
+
});
|
|
18
12
|
|
|
19
13
|
const startCallback = () => {
|
|
20
14
|
console.log('Server started on port', port);
|
package/lib/allocatePort.js
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
|
+
// @ts-check
|
|
1
2
|
const { yellow, bold } = require('chalk');
|
|
2
3
|
const getPort = require('get-port');
|
|
3
4
|
const debug = require('debug')('sku:allocatePort');
|
|
4
5
|
|
|
5
6
|
/**
|
|
6
|
-
* @param {{ port?: number, host?: string }}
|
|
7
|
+
* @param {{ port?: number, host?: string }} options
|
|
7
8
|
*/
|
|
8
9
|
const allocatePort = async ({ port, host }) => {
|
|
9
10
|
debug(`Finding available port with request for ${port}`);
|
package/lib/buildFileUtils.js
CHANGED
|
@@ -1,12 +1,15 @@
|
|
|
1
|
+
// @ts-check
|
|
1
2
|
const path = require('node:path');
|
|
2
3
|
const fs = require('node:fs/promises');
|
|
3
|
-
const {
|
|
4
|
+
const { fdir: Fdir } = require('fdir');
|
|
4
5
|
|
|
5
6
|
const { paths } = require('../context');
|
|
6
7
|
const exists = require('./exists');
|
|
7
8
|
const copyDirContents = require('./copyDirContents');
|
|
8
9
|
|
|
9
|
-
const cleanTargetDirectory = () =>
|
|
10
|
+
const cleanTargetDirectory = async () => {
|
|
11
|
+
fs.rm(paths.target, { recursive: true, force: true });
|
|
12
|
+
};
|
|
10
13
|
|
|
11
14
|
const copyPublicFiles = async () => {
|
|
12
15
|
if (await exists(paths.public)) {
|
|
@@ -18,14 +21,21 @@ const ensureTargetDirectory = async () => {
|
|
|
18
21
|
await fs.mkdir(paths.target, { recursive: true });
|
|
19
22
|
};
|
|
20
23
|
|
|
21
|
-
const
|
|
22
|
-
const
|
|
23
|
-
|
|
24
|
+
const cleanStaticRenderEntry = async () => {
|
|
25
|
+
const files = await new Fdir()
|
|
26
|
+
.withBasePath()
|
|
27
|
+
.filter((file) => file.endsWith('render.js'))
|
|
28
|
+
.crawl(paths.target)
|
|
29
|
+
.withPromise();
|
|
30
|
+
|
|
31
|
+
for (const file of files) {
|
|
32
|
+
await fs.rm(file);
|
|
33
|
+
}
|
|
24
34
|
};
|
|
25
35
|
|
|
26
36
|
module.exports = {
|
|
27
37
|
cleanTargetDirectory,
|
|
28
38
|
copyPublicFiles,
|
|
29
39
|
ensureTargetDirectory,
|
|
30
|
-
|
|
40
|
+
cleanStaticRenderEntry,
|
|
31
41
|
};
|
package/lib/configure.js
CHANGED
|
@@ -32,28 +32,23 @@ const writeFileToCWD = async (fileName, content, { banner = true } = {}) => {
|
|
|
32
32
|
};
|
|
33
33
|
|
|
34
34
|
module.exports = async () => {
|
|
35
|
-
// Ignore
|
|
35
|
+
// Ignore target directories
|
|
36
|
+
const webpackTargetDirectory = addSep(
|
|
37
|
+
paths.target.replace(addSep(cwd()), ''),
|
|
38
|
+
);
|
|
39
|
+
const storybookTargetDirectory = addSep(
|
|
40
|
+
paths.storybookTarget.replace(addSep(cwd()), ''),
|
|
41
|
+
);
|
|
42
|
+
|
|
36
43
|
const gitIgnorePatterns = [
|
|
44
|
+
// Ignore webpack bundle report output
|
|
37
45
|
addSep(bundleReportFolder),
|
|
38
46
|
addSep(coverageFolder),
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
const lintIgnorePatterns = [
|
|
42
|
-
addSep(bundleReportFolder),
|
|
43
|
-
addSep(coverageFolder),
|
|
44
|
-
'*.less.d.ts',
|
|
47
|
+
webpackTargetDirectory,
|
|
48
|
+
storybookTargetDirectory,
|
|
45
49
|
storybookMainConfigPath,
|
|
46
50
|
];
|
|
47
51
|
|
|
48
|
-
// Ignore webpack target directories
|
|
49
|
-
const targetDirectory = addSep(paths.target.replace(addSep(cwd()), ''));
|
|
50
|
-
const storybookTargetDirectory = addSep(
|
|
51
|
-
paths.storybookTarget.replace(addSep(cwd()), ''),
|
|
52
|
-
);
|
|
53
|
-
|
|
54
|
-
gitIgnorePatterns.push(targetDirectory, storybookTargetDirectory);
|
|
55
|
-
lintIgnorePatterns.push(targetDirectory, storybookTargetDirectory);
|
|
56
|
-
|
|
57
52
|
// Generate ESLint configuration
|
|
58
53
|
const eslintConfigFilename = '.eslintrc';
|
|
59
54
|
const eslintCacheFilename = '.eslintcache';
|
|
@@ -71,6 +66,8 @@ module.exports = async () => {
|
|
|
71
66
|
});
|
|
72
67
|
gitIgnorePatterns.push(prettierConfigFilename);
|
|
73
68
|
|
|
69
|
+
const lintIgnorePatterns = [...gitIgnorePatterns, '*.less.d.ts'];
|
|
70
|
+
|
|
74
71
|
if (languages) {
|
|
75
72
|
const generatedVocabFileGlob = '**/*.vocab/index.ts';
|
|
76
73
|
gitIgnorePatterns.push(generatedVocabFileGlob);
|
package/lib/copyDirContents.js
CHANGED
package/lib/createServer.js
CHANGED
package/lib/cwd.js
CHANGED
package/lib/env.js
CHANGED
package/lib/exists.js
CHANGED
package/lib/getSiteForHost.js
CHANGED
package/lib/install.js
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
|
+
// @ts-check
|
|
1
2
|
const { getAddCommand } = require('./packageManager');
|
|
2
3
|
|
|
3
4
|
const spawn = require('cross-spawn');
|
|
4
5
|
|
|
5
6
|
/**
|
|
6
7
|
* @param {import("../lib/packageManager").GetAddCommandOptions} options
|
|
8
|
+
* @returns {Promise<void>}
|
|
7
9
|
*/
|
|
8
10
|
module.exports = ({ deps, type, logLevel, exact = true }) =>
|
|
9
11
|
new Promise((resolve, reject) => {
|
package/lib/isCI.js
CHANGED
package/lib/isCompilePackage.js
CHANGED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
const { statSync, readdirSync } = require('node:fs');
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Returns whether the given directory is empty, throwing if the path is not a directory
|
|
6
|
+
* @typedef {import('fs').PathLike} PathLike
|
|
7
|
+
* @param {PathLike} path A path to a directory
|
|
8
|
+
*/
|
|
9
|
+
const isEmptyDir = (path) => {
|
|
10
|
+
const isDirectory = statSync(path).isDirectory();
|
|
11
|
+
|
|
12
|
+
if (!isDirectory) {
|
|
13
|
+
throw new Error(`${path} is not a directory`);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const files = readdirSync(path);
|
|
17
|
+
|
|
18
|
+
return files.length === 0;
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
module.exports = { isEmptyDir };
|
package/lib/parseArgs.js
CHANGED
|
@@ -1,75 +1,61 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
const optionDefinitions = [
|
|
4
|
-
{
|
|
5
|
-
name: 'script',
|
|
6
|
-
defaultOption: true,
|
|
7
|
-
},
|
|
8
|
-
{
|
|
9
|
-
name: 'env',
|
|
10
|
-
alias: 'e',
|
|
11
|
-
type: String,
|
|
12
|
-
defaultValue: 'production',
|
|
13
|
-
},
|
|
14
|
-
{
|
|
15
|
-
name: 'tenant',
|
|
16
|
-
alias: 't',
|
|
17
|
-
type: String,
|
|
18
|
-
defaultValue: '',
|
|
19
|
-
},
|
|
20
|
-
{
|
|
21
|
-
name: 'build',
|
|
22
|
-
alias: 'b',
|
|
23
|
-
type: String,
|
|
24
|
-
},
|
|
25
|
-
{
|
|
26
|
-
name: 'config',
|
|
27
|
-
alias: 'c',
|
|
28
|
-
type: String,
|
|
29
|
-
},
|
|
30
|
-
{
|
|
31
|
-
name: 'debug',
|
|
32
|
-
alias: 'D',
|
|
33
|
-
type: Boolean,
|
|
34
|
-
},
|
|
35
|
-
{
|
|
36
|
-
name: 'environment',
|
|
37
|
-
type: String,
|
|
38
|
-
},
|
|
39
|
-
{
|
|
40
|
-
name: 'packageManager',
|
|
41
|
-
type: String,
|
|
42
|
-
},
|
|
43
|
-
{
|
|
44
|
-
name: 'port',
|
|
45
|
-
type: Number,
|
|
46
|
-
},
|
|
47
|
-
{
|
|
48
|
-
name: 'site',
|
|
49
|
-
type: String,
|
|
50
|
-
},
|
|
51
|
-
{
|
|
52
|
-
name: 'stats',
|
|
53
|
-
type: String,
|
|
54
|
-
},
|
|
55
|
-
];
|
|
1
|
+
// @ts-check
|
|
2
|
+
const minimist = require('minimist');
|
|
56
3
|
|
|
57
4
|
/**
|
|
58
5
|
* Supports parsing args that look like:
|
|
59
6
|
* [/path/to/node/node, /path/to/sku, scriptName, arg1, arg2]
|
|
60
7
|
*
|
|
61
|
-
* @param {string[]}
|
|
8
|
+
* @param {string[]} processArgv - should look like process.argv
|
|
62
9
|
*/
|
|
63
|
-
module.exports = (
|
|
64
|
-
|
|
10
|
+
module.exports = (processArgv) => {
|
|
11
|
+
/**
|
|
12
|
+
* @type {string[]}
|
|
13
|
+
*/
|
|
14
|
+
const unknown = [];
|
|
15
|
+
|
|
16
|
+
// We are tracking unknown arguments ourselves, so we ignore `minimist`'s unknown property `_`
|
|
17
|
+
const { _, ...options } = minimist(
|
|
65
18
|
// The first 2 items in process.argv are /path/to/node and /path/to/sku.
|
|
66
|
-
// We need the first arg we give to
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
19
|
+
// We need the first arg we give to minimist to be the script name.
|
|
20
|
+
processArgv.slice(2),
|
|
21
|
+
{
|
|
22
|
+
string: [
|
|
23
|
+
'env',
|
|
24
|
+
'tenant',
|
|
25
|
+
'build',
|
|
26
|
+
'config',
|
|
27
|
+
'environment',
|
|
28
|
+
'packageManager',
|
|
29
|
+
'site',
|
|
30
|
+
'stats',
|
|
31
|
+
],
|
|
32
|
+
default: {
|
|
33
|
+
env: 'production',
|
|
34
|
+
tenant: '',
|
|
35
|
+
},
|
|
36
|
+
alias: {
|
|
37
|
+
e: 'env',
|
|
38
|
+
t: 'tenant',
|
|
39
|
+
b: 'build',
|
|
40
|
+
c: 'config',
|
|
41
|
+
D: 'debug',
|
|
42
|
+
},
|
|
43
|
+
boolean: [
|
|
44
|
+
'debug',
|
|
45
|
+
// Passed to Vocab in the `translations` script
|
|
46
|
+
'delete-unused-keys',
|
|
47
|
+
],
|
|
48
|
+
// `minimist` does not push unknown flags to `_` even if this function returns `true`, so we
|
|
49
|
+
// need to track them ourselves
|
|
50
|
+
unknown: (arg) => {
|
|
51
|
+
unknown.push(arg);
|
|
71
52
|
|
|
72
|
-
|
|
53
|
+
return true;
|
|
54
|
+
},
|
|
55
|
+
},
|
|
56
|
+
);
|
|
57
|
+
|
|
58
|
+
const [script, ...argv] = unknown;
|
|
73
59
|
|
|
74
60
|
// Backwards compatibility for unnamed build name argument, to be deprecated
|
|
75
61
|
const buildName = () => {
|
|
@@ -78,11 +64,13 @@ module.exports = (args) => {
|
|
|
78
64
|
} else if (argv.length) {
|
|
79
65
|
return argv[0];
|
|
80
66
|
}
|
|
81
|
-
|
|
67
|
+
|
|
68
|
+
return undefined;
|
|
82
69
|
};
|
|
83
70
|
|
|
84
71
|
return {
|
|
85
72
|
...options,
|
|
73
|
+
script,
|
|
86
74
|
buildName: script === 'start' ? buildName() : null,
|
|
87
75
|
env: script === 'start' ? 'development' : options.env,
|
|
88
76
|
argv,
|
package/lib/parseArgs.test.js
CHANGED
|
@@ -1,20 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @jest-environment node
|
|
3
|
+
*/
|
|
4
|
+
|
|
1
5
|
const parseArgs = require('./parseArgs');
|
|
2
6
|
|
|
3
|
-
describe('
|
|
4
|
-
test('sku
|
|
5
|
-
const { script, argv, env } = parseArgs([
|
|
7
|
+
describe('parseArgs', () => {
|
|
8
|
+
test('sku script with short and long flag', () => {
|
|
9
|
+
const { script, argv, env, config } = parseArgs([
|
|
6
10
|
'/path/to/node',
|
|
7
11
|
'/path/to/bin/sku',
|
|
8
12
|
'lint',
|
|
9
13
|
'-e',
|
|
10
14
|
'test',
|
|
15
|
+
'--config',
|
|
16
|
+
'custom.sku.config.ts',
|
|
11
17
|
]);
|
|
18
|
+
|
|
12
19
|
expect(script).toEqual('lint');
|
|
13
20
|
expect(argv).toEqual([]);
|
|
14
21
|
expect(env).toEqual('test');
|
|
22
|
+
expect(config).toEqual('custom.sku.config.ts');
|
|
15
23
|
});
|
|
16
24
|
|
|
17
|
-
test('sku
|
|
25
|
+
test('sku script with flag and argument', () => {
|
|
18
26
|
const { script, argv, env } = parseArgs([
|
|
19
27
|
'/path/to/node',
|
|
20
28
|
'/path/to/bin/sku',
|
|
@@ -23,15 +31,32 @@ describe('arg parsing', () => {
|
|
|
23
31
|
'-e',
|
|
24
32
|
'test',
|
|
25
33
|
]);
|
|
34
|
+
|
|
26
35
|
expect(script).toEqual('lint');
|
|
27
36
|
expect(argv).toEqual(['src/components/**']);
|
|
28
37
|
expect(env).toEqual('test');
|
|
29
38
|
});
|
|
30
39
|
|
|
40
|
+
test('sku script with argument, known flag and unknown flag', () => {
|
|
41
|
+
const { script, argv, env } = parseArgs([
|
|
42
|
+
'/path/to/node',
|
|
43
|
+
'/path/to/bin/sku',
|
|
44
|
+
'test',
|
|
45
|
+
'-e',
|
|
46
|
+
'test',
|
|
47
|
+
'testFilter',
|
|
48
|
+
'--someJestFlag',
|
|
49
|
+
]);
|
|
50
|
+
|
|
51
|
+
expect(script).toEqual('test');
|
|
52
|
+
expect(argv).toEqual(['testFilter', '--someJestFlag']);
|
|
53
|
+
expect(env).toEqual('test');
|
|
54
|
+
});
|
|
55
|
+
|
|
31
56
|
test('debug', () => {
|
|
32
57
|
expect(
|
|
33
58
|
parseArgs(['/path/to/node', '/path/to/bin/sku', 'build']).debug,
|
|
34
|
-
).
|
|
59
|
+
).toBe(false);
|
|
35
60
|
|
|
36
61
|
expect(
|
|
37
62
|
parseArgs(['/path/to/node', '/path/to/bin/sku', '-D', 'build']).debug,
|
package/lib/routeMatcher.js
CHANGED
package/lib/runBin.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
// @ts-check
|
|
1
2
|
const path = require('node:path');
|
|
2
3
|
const spawn = require('cross-spawn');
|
|
3
4
|
|
|
@@ -45,13 +46,13 @@ const spawnPromise = (commandPath, args, options) => {
|
|
|
45
46
|
*/
|
|
46
47
|
|
|
47
48
|
/**
|
|
48
|
-
* @param {Options}
|
|
49
|
+
* @param {Options} options
|
|
49
50
|
*/
|
|
50
51
|
const runBin = ({ packageName, binName, args, options }) =>
|
|
51
52
|
spawnPromise(resolveBin(packageName, binName), args, options);
|
|
52
53
|
|
|
53
54
|
/**
|
|
54
|
-
* @param {Options}
|
|
55
|
+
* @param {Options} options
|
|
55
56
|
*/
|
|
56
57
|
const startBin = ({ packageName, binName, args, options }) => {
|
|
57
58
|
const childProcess = spawn(resolveBin(packageName, binName), args, options);
|
package/lib/runTsc.js
CHANGED
package/lib/runVocab.js
CHANGED
package/lib/storybook.js
CHANGED
package/lib/suggestScript.js
CHANGED
package/lib/toPosixPath.test.js
CHANGED
package/lib/validateLessFiles.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
const fs = require('node:fs');
|
|
2
|
-
const path = require('node:path');
|
|
3
|
-
const glob = require('fast-glob');
|
|
4
2
|
const chalk = require('chalk');
|
|
3
|
+
const { fdir: Fdir } = require('fdir');
|
|
5
4
|
|
|
6
5
|
const printBanner = require('./banner');
|
|
7
6
|
const exists = require('./exists');
|
|
@@ -14,11 +13,18 @@ module.exports = async () => {
|
|
|
14
13
|
const lessFileGlobResults = await Promise.all(
|
|
15
14
|
srcPathsExist
|
|
16
15
|
.filter((srcPath) => srcPath && fs.statSync(srcPath).isDirectory())
|
|
17
|
-
.map(async (srcPath) =>
|
|
16
|
+
.map(async (srcPath) =>
|
|
17
|
+
new Fdir()
|
|
18
|
+
.filter((file) => file.endsWith('.less'))
|
|
19
|
+
.crawl(srcPath)
|
|
20
|
+
.withPromise(),
|
|
21
|
+
),
|
|
18
22
|
);
|
|
23
|
+
|
|
19
24
|
const srcHasLessFiles = lessFileGlobResults.some(
|
|
20
25
|
(fileArray) => fileArray.length > 0,
|
|
21
26
|
);
|
|
27
|
+
|
|
22
28
|
if (srcHasLessFiles) {
|
|
23
29
|
printBanner('warning', 'LESS styles detected', [
|
|
24
30
|
`Support for ${chalk.bold('LESS')} has been deprecated.`,
|
package/lib/validatePeerDeps.js
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
const { getWhyCommand } = require('./packageManager');
|
|
1
|
+
const { getWhyCommand, isPnpm } = require('./packageManager');
|
|
2
2
|
|
|
3
3
|
const { readFile } = require('node:fs/promises');
|
|
4
|
-
const
|
|
4
|
+
const { fdir: Fdir } = require('fdir');
|
|
5
5
|
const semver = require('semver');
|
|
6
6
|
const chalk = require('chalk');
|
|
7
7
|
|
|
8
8
|
const banner = require('./banner');
|
|
9
9
|
const track = require('../telemetry');
|
|
10
|
-
const {
|
|
10
|
+
const { getPathFromCwd } = require('../lib/cwd');
|
|
11
11
|
const { paths } = require('../context');
|
|
12
12
|
|
|
13
13
|
/**
|
|
@@ -21,30 +21,42 @@ const asyncMap = (list, fn) => {
|
|
|
21
21
|
const singletonPackages = ['@vanilla-extract/css'];
|
|
22
22
|
|
|
23
23
|
module.exports = async () => {
|
|
24
|
+
if (isPnpm) {
|
|
25
|
+
// pnpm doesn't nest dependencies in the same way as yarn or npm, so the method used below won't
|
|
26
|
+
// work for detecting duplicate packages
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
|
|
24
30
|
try {
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
31
|
+
/** @type {string[]} */
|
|
32
|
+
const duplicatePackages = [];
|
|
33
|
+
const packagesToCheck = [...paths.compilePackages, ...singletonPackages];
|
|
34
|
+
|
|
35
|
+
const packagePatterns = packagesToCheck.map((packageName) => [
|
|
36
|
+
packageName,
|
|
37
|
+
`node_modules/${packageName}/package.json`,
|
|
38
|
+
]);
|
|
39
|
+
|
|
40
|
+
const patterns = packagePatterns.map(([, pattern]) => pattern);
|
|
41
|
+
|
|
42
|
+
const results = await new Fdir()
|
|
43
|
+
.withBasePath()
|
|
44
|
+
.filter((file) => patterns.some((pattern) => file.endsWith(pattern)))
|
|
45
|
+
.crawl('./node_modules')
|
|
46
|
+
.withPromise();
|
|
47
|
+
|
|
48
|
+
for (const [packageName, pattern] of packagePatterns) {
|
|
49
|
+
const resultsForPackage = results.filter((result) =>
|
|
50
|
+
result.endsWith(pattern),
|
|
39
51
|
);
|
|
40
52
|
|
|
41
|
-
if (
|
|
53
|
+
if (resultsForPackage.length > 1) {
|
|
42
54
|
const messages = [
|
|
43
55
|
chalk`Multiple copies of {bold ${packageName}} are present in node_modules. This is likely to cause errors, but even if it works, it will probably result in an unnecessarily large bundle size.`,
|
|
44
56
|
];
|
|
45
57
|
|
|
46
58
|
messages.push(
|
|
47
|
-
|
|
59
|
+
resultsForPackage
|
|
48
60
|
.map((depLocation) => {
|
|
49
61
|
const { version } = require(getPathFromCwd(depLocation));
|
|
50
62
|
|
|
@@ -64,14 +76,14 @@ module.exports = async () => {
|
|
|
64
76
|
compile_package: packageName,
|
|
65
77
|
});
|
|
66
78
|
banner('error', 'Error: Duplicate packages detected', messages);
|
|
67
|
-
}
|
|
68
79
|
|
|
69
|
-
|
|
80
|
+
duplicatePackages.push(...resultsForPackage);
|
|
81
|
+
}
|
|
70
82
|
}
|
|
71
83
|
|
|
72
84
|
const compilePackages = new Map();
|
|
73
85
|
|
|
74
|
-
await asyncMap(
|
|
86
|
+
await asyncMap(duplicatePackages, async (p) => {
|
|
75
87
|
const contents = await readFile(getPathFromCwd(p), {
|
|
76
88
|
encoding: 'utf8',
|
|
77
89
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sku",
|
|
3
|
-
"version": "12.
|
|
3
|
+
"version": "12.5.1",
|
|
4
4
|
"description": "Front-end development toolkit, powered by Webpack, Babel, CSS Modules, Less and Jest",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"bin": {
|
|
@@ -39,7 +39,7 @@
|
|
|
39
39
|
"@loadable/server": "^5.14.0",
|
|
40
40
|
"@loadable/webpack-plugin": "^5.14.0",
|
|
41
41
|
"@manypkg/find-root": "^2.2.0",
|
|
42
|
-
"@pmmmwh/react-refresh-webpack-plugin": "0.5.
|
|
42
|
+
"@pmmmwh/react-refresh-webpack-plugin": "^0.5.12",
|
|
43
43
|
"@storybook/builder-webpack5": "^7.0.17",
|
|
44
44
|
"@storybook/cli": "^7.0.17",
|
|
45
45
|
"@storybook/react": "^7.0.17",
|
|
@@ -64,7 +64,6 @@
|
|
|
64
64
|
"browserslist": "^4.16.1",
|
|
65
65
|
"browserslist-config-seek": "^2.1.0",
|
|
66
66
|
"chalk": "^4.1.0",
|
|
67
|
-
"command-line-args": "^5.1.1",
|
|
68
67
|
"cross-spawn": "^7.0.3",
|
|
69
68
|
"css-loader": "^6.7.1",
|
|
70
69
|
"css-modules-typescript-loader": "4.0.1",
|
|
@@ -74,7 +73,6 @@
|
|
|
74
73
|
"dedent": "^1.5.1",
|
|
75
74
|
"didyoumean2": "^6.0.1",
|
|
76
75
|
"ejs": "^3.1.8",
|
|
77
|
-
"empty-dir": "^3.0.0",
|
|
78
76
|
"ensure-gitignore": "^1.1.2",
|
|
79
77
|
"env-ci": "^7.0.0",
|
|
80
78
|
"esbuild": "^0.19.7",
|
|
@@ -84,8 +82,8 @@
|
|
|
84
82
|
"eslint-config-seek": "^12.0.1",
|
|
85
83
|
"exception-formatter": "^2.1.2",
|
|
86
84
|
"express": "^4.16.3",
|
|
87
|
-
"fast-glob": "^3.2.5",
|
|
88
85
|
"fastest-validator": "^1.9.0",
|
|
86
|
+
"fdir": "^6.1.1",
|
|
89
87
|
"find-up": "^5.0.0",
|
|
90
88
|
"get-port": "^5.0.0",
|
|
91
89
|
"hostile": "^1.3.3",
|
|
@@ -97,17 +95,18 @@
|
|
|
97
95
|
"less": "^4.1.0",
|
|
98
96
|
"less-loader": "^12.0.0",
|
|
99
97
|
"lint-staged": "^11.1.1",
|
|
100
|
-
"memoizee": "^0.4.15",
|
|
101
98
|
"mini-css-extract-plugin": "^2.6.1",
|
|
99
|
+
"minimist": "^1.2.8",
|
|
100
|
+
"nano-memoize": "^3.0.16",
|
|
102
101
|
"node-html-parser": "^6.1.1",
|
|
103
102
|
"open": "^7.3.1",
|
|
104
103
|
"path-to-regexp": "^6.2.0",
|
|
104
|
+
"picomatch": "^3.0.1",
|
|
105
105
|
"postcss": "^8.4.0",
|
|
106
106
|
"postcss-loader": "^8.0.0",
|
|
107
107
|
"prettier": "^2.8.8",
|
|
108
108
|
"pretty-ms": "^7.0.1",
|
|
109
109
|
"react-refresh": "^0.14.0",
|
|
110
|
-
"rimraf": "^5.0.0",
|
|
111
110
|
"selfsigned": "^2.1.1",
|
|
112
111
|
"semver": "^7.3.4",
|
|
113
112
|
"serialize-javascript": "^6.0.0",
|
|
@@ -115,8 +114,7 @@
|
|
|
115
114
|
"svgo-loader": "^4.0.0",
|
|
116
115
|
"terser-webpack-plugin": "^5.1.4",
|
|
117
116
|
"tree-kill": "^1.2.1",
|
|
118
|
-
"typescript": "~5.
|
|
119
|
-
"validate-npm-package-name": "^5.0.0",
|
|
117
|
+
"typescript": "~5.3.0",
|
|
120
118
|
"webpack": "^5.52.0",
|
|
121
119
|
"webpack-bundle-analyzer": "^4.6.1",
|
|
122
120
|
"webpack-dev-server": "^5.0.2",
|
|
@@ -128,7 +126,10 @@
|
|
|
128
126
|
},
|
|
129
127
|
"devDependencies": {
|
|
130
128
|
"@types/cross-spawn": "^6.0.3",
|
|
129
|
+
"@types/debug": "^4.1.12",
|
|
131
130
|
"@types/express": "^4.17.11",
|
|
131
|
+
"@types/minimist": "^1.2.5",
|
|
132
|
+
"@types/picomatch": "^2.3.3",
|
|
132
133
|
"@types/react": "^18.2.3",
|
|
133
134
|
"@types/react-dom": "^18.2.3",
|
|
134
135
|
"@types/which": "^3.0.0",
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// First, ensure the build is running in production mode
|
|
2
2
|
process.env.NODE_ENV = 'production';
|
|
3
3
|
|
|
4
|
-
const {
|
|
4
|
+
const { rm } = require('node:fs/promises');
|
|
5
5
|
const { argv, config } = require('../config/args');
|
|
6
6
|
const gracefulSpawn = require('../lib/gracefulSpawn');
|
|
7
7
|
const { storybookTarget } = require('../context');
|
|
@@ -11,7 +11,7 @@ const { setUpStorybookConfigDirectory } = require('../lib/storybook');
|
|
|
11
11
|
|
|
12
12
|
(async () => {
|
|
13
13
|
await runVocabCompile();
|
|
14
|
-
await
|
|
14
|
+
await rm(storybookTarget, { recursive: true, force: true });
|
|
15
15
|
await setUpStorybookConfigDirectory();
|
|
16
16
|
|
|
17
17
|
argv.push('build');
|
package/scripts/build.js
CHANGED
|
@@ -10,7 +10,7 @@ const {
|
|
|
10
10
|
copyPublicFiles,
|
|
11
11
|
cleanTargetDirectory,
|
|
12
12
|
ensureTargetDirectory,
|
|
13
|
-
|
|
13
|
+
cleanStaticRenderEntry,
|
|
14
14
|
} = require('../lib/buildFileUtils');
|
|
15
15
|
const { run } = require('../lib/runWebpack');
|
|
16
16
|
const createHtmlRenderPlugin = require('../config/webpack/plugins/createHtmlRenderPlugin');
|
|
@@ -31,7 +31,7 @@ const { runVocabCompile } = require('../lib/runVocab');
|
|
|
31
31
|
}),
|
|
32
32
|
),
|
|
33
33
|
);
|
|
34
|
-
await
|
|
34
|
+
await cleanStaticRenderEntry();
|
|
35
35
|
await copyPublicFiles();
|
|
36
36
|
|
|
37
37
|
const timeTaken = performance.now();
|
package/scripts/init.js
CHANGED
|
@@ -10,8 +10,7 @@ const {
|
|
|
10
10
|
const chalk = require('chalk');
|
|
11
11
|
const fs = require('node:fs/promises');
|
|
12
12
|
const { posix: path } = require('node:path');
|
|
13
|
-
const
|
|
14
|
-
const validatePackageName = require('validate-npm-package-name');
|
|
13
|
+
const { isEmptyDir } = require('../lib/isEmptyDir');
|
|
15
14
|
const dedent = require('dedent');
|
|
16
15
|
const { setCwd } = require('../lib/cwd');
|
|
17
16
|
const prettierWrite = require('../lib/runPrettier').write;
|
|
@@ -21,7 +20,7 @@ const install = require('../lib/install');
|
|
|
21
20
|
const banner = require('../lib/banner');
|
|
22
21
|
const toPosixPath = require('../lib/toPosixPath');
|
|
23
22
|
const trace = require('debug')('sku:init');
|
|
24
|
-
const
|
|
23
|
+
const { fdir: Fdir } = require('fdir');
|
|
25
24
|
const ejs = require('ejs');
|
|
26
25
|
|
|
27
26
|
const args = require('../config/args');
|
|
@@ -48,6 +47,11 @@ const getTemplateFileDestinationFromRoot =
|
|
|
48
47
|
return path.join(projectRoot, filePathRelativeToTemplate);
|
|
49
48
|
};
|
|
50
49
|
|
|
50
|
+
// Copied from `package-name-regex@4.0.0`
|
|
51
|
+
// See https://github.com/dword-design/package-name-regex/blob/acae7d482b1d03379003899df4d484238625364d/src/index.js#L1-L2
|
|
52
|
+
const packageNameRegex =
|
|
53
|
+
/^(@[a-z0-9-~][a-z0-9-._~]*\/)?[a-z0-9-~][a-z0-9-._~]*$/;
|
|
54
|
+
|
|
51
55
|
(async () => {
|
|
52
56
|
const projectName = args.argv[0];
|
|
53
57
|
|
|
@@ -89,21 +93,16 @@ const getTemplateFileDestinationFromRoot =
|
|
|
89
93
|
'braid-design-system',
|
|
90
94
|
].sort();
|
|
91
95
|
|
|
92
|
-
const
|
|
93
|
-
validForNewPackages,
|
|
94
|
-
errors = [],
|
|
95
|
-
warnings = [],
|
|
96
|
-
} = validatePackageName(appName);
|
|
96
|
+
const isValidPackageName = packageNameRegex.test(appName);
|
|
97
97
|
|
|
98
|
-
if (!
|
|
98
|
+
if (!isValidPackageName) {
|
|
99
99
|
console.error(dedent`
|
|
100
|
-
Could not create a project called ${chalk.red(
|
|
101
|
-
|
|
100
|
+
Could not create a project called ${chalk.red(
|
|
101
|
+
`"${appName}"`,
|
|
102
|
+
)} because of npm naming restrictions. \
|
|
103
|
+
Please see https://docs.npmjs.com/cli/configuring-npm/package-json for package name rules.
|
|
102
104
|
`);
|
|
103
105
|
|
|
104
|
-
const results = [...errors, ...warnings];
|
|
105
|
-
results.forEach((result) => console.error(chalk.red(` * ${result}`)));
|
|
106
|
-
|
|
107
106
|
process.exit(1);
|
|
108
107
|
}
|
|
109
108
|
|
|
@@ -125,7 +124,7 @@ const getTemplateFileDestinationFromRoot =
|
|
|
125
124
|
|
|
126
125
|
await fs.mkdir(projectName, { recursive: true });
|
|
127
126
|
|
|
128
|
-
if (!
|
|
127
|
+
if (!isEmptyDir(root)) {
|
|
129
128
|
console.log(`The directory ${chalk.green(projectName)} is not empty.`);
|
|
130
129
|
process.exit(1);
|
|
131
130
|
}
|
|
@@ -152,9 +151,11 @@ const getTemplateFileDestinationFromRoot =
|
|
|
152
151
|
process.chdir(root);
|
|
153
152
|
|
|
154
153
|
const templateDirectory = path.join(toPosixPath(__dirname), '../template');
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
154
|
+
|
|
155
|
+
const templateFiles = await new Fdir()
|
|
156
|
+
.withBasePath()
|
|
157
|
+
.crawl(templateDirectory)
|
|
158
|
+
.withPromise();
|
|
158
159
|
|
|
159
160
|
const getTemplateFileDestination = getTemplateFileDestinationFromRoot(
|
|
160
161
|
root,
|
package/tsconfig.json
DELETED