sku 12.3.2 → 12.4.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.
@@ -0,0 +1,152 @@
1
+ const { cwd } = require('../lib/cwd');
2
+ const { findRootSync } = require('@manypkg/find-root');
3
+ const { getCommand, INSTALL_PAGE } = require('@antfu/ni');
4
+
5
+ const { sync: which } = require('which');
6
+ const skuArgs = require('../config/args');
7
+
8
+ /** @typedef {'yarn' | 'pnpm' | 'npm'} SupportedPackageManager */
9
+
10
+ /** @type {Array<SupportedPackageManager>} */
11
+ const supportedPackageManagers = ['yarn', 'pnpm', 'npm'];
12
+
13
+ /**
14
+ * @param {SupportedPackageManager} commandName
15
+ * @returns {SupportedPackageManager | null}
16
+ */
17
+ const detectPackageManagerCommand = (commandName) =>
18
+ which(commandName, { nothrow: true }) ? commandName : null;
19
+
20
+ const detectPackageManager = () =>
21
+ detectPackageManagerCommand('yarn') ||
22
+ detectPackageManagerCommand('pnpm') ||
23
+ 'npm';
24
+
25
+ /**
26
+ * Get the package manager and root directory of the project. If the project does not have a
27
+ * project manager configured, a supported package manager will be detected in your `PATH`, and
28
+ * `rootDir` will be `null`.
29
+ * @returns {{packageManager: SupportedPackageManager, rootDir: string | null}}
30
+ */
31
+ const getPackageManager = () => {
32
+ let _packageManager = skuArgs?.packageManager;
33
+
34
+ try {
35
+ const {
36
+ tool: { type: foundPackageManager },
37
+ rootDir,
38
+ } = findRootSync(cwd());
39
+
40
+ if (!supportedPackageManagers.includes(foundPackageManager)) {
41
+ throw new Error('Unsupported package manager found');
42
+ }
43
+
44
+ _packageManager ||= foundPackageManager;
45
+
46
+ return { packageManager: _packageManager, rootDir };
47
+ } catch {
48
+ _packageManager ||= detectPackageManager();
49
+
50
+ return { packageManager: _packageManager, rootDir: null };
51
+ }
52
+ };
53
+
54
+ const { rootDir, packageManager } = getPackageManager();
55
+
56
+ const isYarn = packageManager === 'yarn';
57
+ const isPnpm = packageManager === 'pnpm';
58
+ const isNpm = packageManager === 'npm';
59
+
60
+ /**
61
+ * @param {string} scriptName
62
+ */
63
+ const getRunCommand = (scriptName) =>
64
+ getCommand(packageManager, 'run', [scriptName]);
65
+
66
+ /**
67
+ * @param {string[]} args
68
+ */
69
+ const getExecuteCommand = (args) => getCommand(packageManager, 'execute', args);
70
+
71
+ /** @type {Record<SupportedPackageManager, string[]>} */
72
+ const regularLoglevelArgsByPackageManager = {
73
+ // Yarn doesn't have a loglevel flag
74
+ yarn: [],
75
+ pnpm: ['--loglevel', 'error'],
76
+ npm: ['--loglevel', 'error'],
77
+ };
78
+
79
+ /** @type {Record<SupportedPackageManager, string[]>} */
80
+ const verboseLoglevelArgsByPackageManager = {
81
+ yarn: ['--verbose'],
82
+ pnpm: ['--loglevel', 'info'],
83
+ npm: ['--loglevel', 'verbose'],
84
+ };
85
+
86
+ /**
87
+ * @param {'verbose' | 'regular'} logLevel
88
+ */
89
+ const resolveLogLevelArgs = (logLevel) => {
90
+ if (logLevel === 'verbose') {
91
+ return verboseLoglevelArgsByPackageManager[packageManager];
92
+ }
93
+
94
+ return regularLoglevelArgsByPackageManager[packageManager];
95
+ };
96
+
97
+ /**
98
+ * @typedef {object} GetAddCommandOptions
99
+ * @property {'dev' | 'prod'} type
100
+ * @property {'verbose' | 'regular' | undefined} logLevel
101
+ * @property {boolean} exact
102
+ * @property {string[]} deps
103
+ * @param {GetAddCommandOptions} options
104
+ */
105
+ const getAddCommand = ({ type, logLevel, deps, exact }) => {
106
+ const args = [];
107
+
108
+ const addingDevDeps = type === 'dev';
109
+
110
+ if (addingDevDeps) {
111
+ const devDepFlag = isYarn ? '--dev' : `--save-dev`;
112
+ args.push(devDepFlag);
113
+ }
114
+
115
+ if (exact) {
116
+ const exactFlag = isYarn ? '--exact' : '--save-exact';
117
+ args.push(exactFlag);
118
+ }
119
+
120
+ if (logLevel) {
121
+ args.push(...resolveLogLevelArgs(logLevel));
122
+ }
123
+
124
+ args.push(...deps);
125
+
126
+ return getCommand(packageManager, 'add', args);
127
+ };
128
+
129
+ const getInstallCommand = () => getCommand(packageManager, 'install', []);
130
+
131
+ const getWhyCommand = () => {
132
+ const whyCommand = isPnpm ? 'why -r' : 'why';
133
+
134
+ return `${packageManager} ${whyCommand}`;
135
+ };
136
+
137
+ const getPackageManagerInstallPage = () => INSTALL_PAGE[packageManager];
138
+
139
+ module.exports = {
140
+ supportedPackageManagers,
141
+ rootDir,
142
+ packageManager,
143
+ isYarn,
144
+ isPnpm,
145
+ isNpm,
146
+ getRunCommand,
147
+ getExecuteCommand,
148
+ getAddCommand,
149
+ getInstallCommand,
150
+ getWhyCommand,
151
+ getPackageManagerInstallPage,
152
+ };
package/lib/parseArgs.js CHANGED
@@ -36,6 +36,10 @@ const optionDefinitions = [
36
36
  name: 'environment',
37
37
  type: String,
38
38
  },
39
+ {
40
+ name: 'packageManager',
41
+ type: String,
42
+ },
39
43
  {
40
44
  name: 'port',
41
45
  type: Number,
package/lib/runESLint.js CHANGED
@@ -17,6 +17,7 @@ const runESLint = async ({ fix = false, paths }) => {
17
17
  extensions,
18
18
  useEslintrc: false,
19
19
  fix,
20
+ cache: true,
20
21
  });
21
22
  const checkAll = typeof paths === 'undefined';
22
23
  /* Whitelist the file extensions that our ESLint setup currently supports */
@@ -20,7 +20,7 @@ const runPrettier = async ({ write, listDifferent, paths }) => {
20
20
  chalk.cyan(`${write ? 'Formatting' : 'Checking'} code with Prettier`),
21
21
  );
22
22
 
23
- const prettierArgs = ['--config', prettierConfigPath];
23
+ const prettierArgs = ['--config', prettierConfigPath, '--cache'];
24
24
 
25
25
  if (write) {
26
26
  prettierArgs.push('--write');
@@ -69,7 +69,7 @@ const runPrettier = async ({ write, listDifferent, paths }) => {
69
69
  'Error: The file(s) listed above failed the prettier check',
70
70
  ),
71
71
  );
72
- await suggestScript('format');
72
+ suggestScript('format');
73
73
  } else {
74
74
  console.error(
75
75
  chalk.red('Error: Prettier check exited with exit code', exitCode),
package/lib/storybook.js CHANGED
@@ -1,70 +1,35 @@
1
1
  const path = require('path');
2
-
3
- const { paths } = require('../context');
4
2
  const fs = require('fs/promises');
5
3
  const debug = require('debug');
6
- const glob = require('fast-glob');
7
4
 
8
5
  const log = debug('sku:storybook');
9
6
 
10
- const previewFileName = 'preview.{js,ts,tsx}';
11
-
12
- const previewFileAbsolutePath = path.join(
13
- path.dirname(paths.appSkuConfigPath),
14
- '.storybook',
15
- previewFileName,
16
- );
17
-
18
- /**
19
- * This function first cleans up any existing preview.{js,ts,tsx} files in the provided storybook config directory.
20
- * This includes any potentially dangling symlinks.
21
- * Then it looks for a `.storybook/preview.{js,ts,tsx}` file relative to the sku config.
22
- * If 1 file is found, a symlink pointing to it is created in the provided storybook config directory.
23
- * Does nothing if 0 or >1 files are found.
24
- *
25
- * @param {string} storybookConfigDirectory The path to the storybook config directory
26
- */
27
- const setUpStorybookPreviewFile = async (storybookConfigDirectory) => {
28
- const symlinkFileAsbolutePath = path.join(
29
- storybookConfigDirectory,
30
- previewFileName,
31
- );
32
- const symlinkFiles = await glob(symlinkFileAsbolutePath, {
33
- dot: true,
34
- onlyFiles: false, // Required to find dangling symlinks
35
- });
36
-
37
- // Clean up any existing files in the storybook config folder so we have a clean slate
38
- for (const symlinkFile of symlinkFiles) {
39
- await fs.unlink(symlinkFile);
40
- log(`Cleaning up exising file ${symlinkFile}.`);
41
- }
7
+ const managedConfigBanner = require('./managedConfigBanner');
42
8
 
43
- const previewFiles = await glob(previewFileAbsolutePath);
9
+ // Since this config will be in the user's project, we can use ESM
10
+ // Spread `storybookConfig` to prevent warning
11
+ // https://github.com/storybookjs/storybook/issues/23675
12
+ const mainConfigFileContents = `${managedConfigBanner}
13
+ import storybookConfig from 'sku/config/storybook';
44
14
 
45
- if (previewFiles.length > 1) {
46
- console.error(
47
- 'Multiple storybook preview files found. Please only define a single preview file.',
48
- );
49
- console.error(previewFiles);
15
+ export default { ...storybookConfig };
16
+ `;
50
17
 
51
- return;
52
- }
18
+ const storybookMainConfigPath = '.storybook/main.js';
19
+ const storybookConfigDirectory = path.dirname(storybookMainConfigPath);
53
20
 
54
- const previewFile = previewFiles?.[0];
55
-
56
- if (previewFile) {
57
- const previewFileExtension = path.extname(previewFile);
58
- const symlinkFile = path.join(
21
+ const setUpStorybookConfigDirectory = async () => {
22
+ await fs.mkdir(storybookConfigDirectory, { recursive: true });
23
+ log(
24
+ `Created '${path.resolve(
59
25
  storybookConfigDirectory,
60
- `preview${previewFileExtension}`,
61
- );
62
-
63
- log(`Found preview file at ${previewFile}`);
64
- log(`Creating symlink from ${symlinkFile} to ${previewFile}`);
26
+ )}' directory if it didn't exist`,
27
+ );
65
28
 
66
- await fs.symlink(previewFile, symlinkFile);
67
- }
29
+ await fs.writeFile(storybookMainConfigPath, mainConfigFileContents);
30
+ log(
31
+ `Wrote storybook config file to '${path.resolve(storybookMainConfigPath)}'`,
32
+ );
68
33
  };
69
34
 
70
- module.exports = { setUpStorybookPreviewFile };
35
+ module.exports = { setUpStorybookConfigDirectory, storybookMainConfigPath };
@@ -1,14 +1,17 @@
1
- const exists = require('./exists');
1
+ const { getRunCommand, getExecuteCommand } = require('./packageManager');
2
+
2
3
  const chalk = require('chalk');
3
- const { getPathFromCwd, requireFromCwd } = require('./cwd');
4
+ const { requireFromCwd } = require('./cwd');
4
5
 
5
6
  /**
6
- * @param {scriptContents} string
7
+ * @param {string} scriptContents
8
+ * @returns {string | undefined}
7
9
  */
8
- const findPackageScript = (scriptContents) => {
10
+ const findPackageScriptName = (scriptContents) => {
9
11
  let pkg;
12
+
10
13
  try {
11
- pkg = requireFromCwd('package.json');
14
+ pkg = requireFromCwd('./package.json');
12
15
  } catch (err) {
13
16
  pkg = { scripts: {} };
14
17
  }
@@ -29,31 +32,24 @@ const findPackageScript = (scriptContents) => {
29
32
  * @param {string} scriptName
30
33
  * @param {Options | undefined} options
31
34
  */
32
- const getSuggestedScript = async (scriptName, options = { sudo: false }) => {
33
- let script = options.sudo ? 'sudo ' : '';
34
- const isYarnProject = await exists(getPathFromCwd('yarn.lock'));
35
+ const getSuggestedScript = (scriptName, options = { sudo: false }) => {
36
+ const packageScriptName = findPackageScriptName(`sku ${scriptName}`);
35
37
 
36
- try {
37
- const packageScript = findPackageScript(`sku ${scriptName}`);
38
+ const command = packageScriptName
39
+ ? getRunCommand(packageScriptName)
40
+ : getExecuteCommand(['sku', scriptName]);
38
41
 
39
- if (packageScript) {
40
- script += `${isYarnProject ? 'yarn' : 'npm run'} ${packageScript}`;
41
- } else {
42
- script += `${isYarnProject ? 'yarn' : 'npx'} sku ${scriptName}`;
43
- }
44
- } catch (err) {
45
- script += `npx sku ${scriptName}`;
46
- }
42
+ const sudoPrefix = options.sudo ? 'sudo ' : '';
47
43
 
48
- return script;
44
+ return `${sudoPrefix}${command}`;
49
45
  };
50
46
 
51
47
  /**
52
48
  * @param {string} scriptName
53
49
  * @param {Options | undefined} options
54
50
  */
55
- const suggestScript = async (scriptName, options) => {
56
- const suggestedScript = await getSuggestedScript(scriptName, options);
51
+ const suggestScript = (scriptName, options) => {
52
+ const suggestedScript = getSuggestedScript(scriptName, options);
57
53
 
58
54
  console.log(
59
55
  chalk.blue(`To fix this issue, run '${chalk.bold(suggestedScript)}'`),
@@ -62,5 +58,4 @@ const suggestScript = async (scriptName, options) => {
62
58
 
63
59
  module.exports = {
64
60
  suggestScript,
65
- getSuggestedScript,
66
61
  };
@@ -1,3 +1,5 @@
1
+ const { getWhyCommand } = require('./packageManager');
2
+
1
3
  const { readFile } = require('fs/promises');
2
4
  const glob = require('fast-glob');
3
5
  const semver = require('semver');
@@ -5,7 +7,6 @@ const chalk = require('chalk');
5
7
 
6
8
  const banner = require('./banner');
7
9
  const track = require('../telemetry');
8
- const detectYarn = require('./detectYarn');
9
10
  const { cwd, getPathFromCwd } = require('../lib/cwd');
10
11
  const { paths } = require('../context');
11
12
 
@@ -55,11 +56,9 @@ module.exports = async () => {
55
56
  .join('\n'),
56
57
  );
57
58
 
58
- if (detectYarn()) {
59
- messages.push(
60
- chalk`Try running "{blue.bold yarn why} {bold ${packageName}}" to diagnose the issue`,
61
- );
62
- }
59
+ messages.push(
60
+ chalk`Try running "{blue.bold ${getWhyCommand()}} {bold ${packageName}}" to diagnose the issue`,
61
+ );
63
62
 
64
63
  track.count('duplicate_compile_package', {
65
64
  compile_package: packageName,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sku",
3
- "version": "12.3.2",
3
+ "version": "12.4.0",
4
4
  "description": "Front-end development toolkit, powered by Webpack, Babel, CSS Modules, Less and Jest",
5
5
  "main": "index.js",
6
6
  "bin": {
@@ -25,6 +25,7 @@
25
25
  "react": "^16.14.0 || ^17.0.0 || ^18.0.0"
26
26
  },
27
27
  "dependencies": {
28
+ "@antfu/ni": "^0.21.8",
28
29
  "@babel/core": "^7.21.8",
29
30
  "@babel/plugin-transform-react-constant-elements": "^7.21.3",
30
31
  "@babel/plugin-transform-react-inline-elements": "^7.21.0",
@@ -38,7 +39,7 @@
38
39
  "@loadable/server": "^5.14.0",
39
40
  "@loadable/webpack-plugin": "^5.14.0",
40
41
  "@manypkg/find-root": "^2.2.0",
41
- "@pmmmwh/react-refresh-webpack-plugin": "0.5.10",
42
+ "@pmmmwh/react-refresh-webpack-plugin": "0.5.11",
42
43
  "@storybook/builder-webpack5": "^7.0.17",
43
44
  "@storybook/cli": "^7.0.17",
44
45
  "@storybook/react": "^7.0.17",
@@ -96,7 +97,6 @@
96
97
  "less": "^4.1.0",
97
98
  "less-loader": "^11.1.3",
98
99
  "lint-staged": "^11.1.1",
99
- "lodash": "^4.17.21",
100
100
  "memoizee": "^0.4.15",
101
101
  "mini-css-extract-plugin": "^2.6.1",
102
102
  "node-emoji": "^2.1.0",
@@ -108,7 +108,6 @@
108
108
  "prettier": "^2.8.8",
109
109
  "pretty-ms": "^7.0.1",
110
110
  "react-refresh": "^0.14.0",
111
- "require-from-string": "^2.0.2",
112
111
  "rimraf": "^5.0.0",
113
112
  "selfsigned": "^2.1.1",
114
113
  "semver": "^7.3.4",
@@ -116,15 +115,15 @@
116
115
  "serve-handler": "^6.1.3",
117
116
  "svgo-loader": "^4.0.0",
118
117
  "terser-webpack-plugin": "^5.1.4",
119
- "traverse": "^0.6.6",
120
118
  "tree-kill": "^1.2.1",
121
- "typescript": "~5.1.0",
119
+ "typescript": "~5.2.0",
122
120
  "validate-npm-package-name": "^5.0.0",
123
121
  "webpack": "^5.52.0",
124
122
  "webpack-bundle-analyzer": "^4.6.1",
125
- "webpack-dev-server": "4.11.1",
123
+ "webpack-dev-server": "^4.15.1",
126
124
  "webpack-merge": "^5.8.0",
127
125
  "webpack-node-externals": "^3.0.0",
126
+ "which": "^4.0.0",
128
127
  "wrap-ansi": "^7.0.0",
129
128
  "x-default-browser": "^0.5.0"
130
129
  },
@@ -133,15 +132,14 @@
133
132
  "@types/express": "^4.17.11",
134
133
  "@types/react": "^18.2.3",
135
134
  "@types/react-dom": "^18.2.3",
135
+ "@types/which": "^3.0.0",
136
136
  "@vanilla-extract/css": "^1.0.0",
137
137
  "@vocab/react": "^1.0.1",
138
- "assert": "^2.0.0",
139
138
  "braid-design-system": "^32.0.0",
140
139
  "react": "^18.2.0",
141
140
  "react-dom": "^18.2.0",
142
141
  "react-helmet": "^6.1.0",
143
- "react-router-dom": "^5.2.0",
144
- "webpack-cli": "^5.0.0"
142
+ "react-router-dom": "^5.2.0"
145
143
  },
146
144
  "scripts": {
147
145
  "postinstall": "node ./scripts/postinstall.js"
@@ -1,29 +1,26 @@
1
1
  // First, ensure the build is running in production mode
2
2
  process.env.NODE_ENV = 'production';
3
3
 
4
- const path = require('path');
5
4
  const { rimraf } = require('rimraf');
6
- const { argv } = require('../config/args');
5
+ const { argv, config } = require('../config/args');
7
6
  const gracefulSpawn = require('../lib/gracefulSpawn');
8
7
  const { storybookTarget } = require('../context');
9
8
  const buildStorybookPath = require.resolve('@storybook/cli/bin/index');
10
- const configDir = path.resolve(__dirname, '../config/storybook/build');
11
9
  const { runVocabCompile } = require('../lib/runVocab');
12
- const { setUpStorybookPreviewFile } = require('../lib/storybook');
10
+ const { setUpStorybookConfigDirectory } = require('../lib/storybook');
13
11
 
14
12
  (async () => {
15
13
  await runVocabCompile();
16
14
  await rimraf(storybookTarget);
17
- await setUpStorybookPreviewFile(configDir);
15
+ await setUpStorybookConfigDirectory();
18
16
 
19
17
  argv.push('build');
20
- argv.push('--config-dir', configDir);
21
18
  argv.push('--output-dir', storybookTarget);
22
19
  argv.push('--quiet');
23
20
 
24
21
  const storybookProcess = gracefulSpawn(buildStorybookPath, argv, {
25
22
  stdio: 'inherit',
26
- env: process.env,
23
+ env: { ...process.env, SKU_CONFIG: config },
27
24
  });
28
25
 
29
26
  storybookProcess.on('exit', (exitCode) => {
package/scripts/init.js CHANGED
@@ -1,5 +1,12 @@
1
1
  #!/usr/bin/env node
2
2
 
3
+ const {
4
+ packageManager,
5
+ getRunCommand,
6
+ getPackageManagerInstallPage,
7
+ getInstallCommand,
8
+ } = require('../lib/packageManager');
9
+
3
10
  const chalk = require('chalk');
4
11
  const fs = require('fs/promises');
5
12
  const { posix: path } = require('path');
@@ -7,7 +14,6 @@ const emptyDir = require('empty-dir');
7
14
  const validatePackageName = require('validate-npm-package-name');
8
15
  const dedent = require('dedent');
9
16
  const { setCwd } = require('../lib/cwd');
10
- const detectYarn = require('../lib/detectYarn');
11
17
  const prettierWrite = require('../lib/runPrettier').write;
12
18
  const esLintFix = require('../lib/runESLint').fix;
13
19
  const configure = require('../lib/configure');
@@ -69,8 +75,6 @@ const getTemplateFileDestinationFromRoot =
69
75
  process.exit(1);
70
76
  }
71
77
 
72
- const verbose = args.argv.indexOf('--verbose') >= 0;
73
-
74
78
  const root = path.resolve(projectName);
75
79
  setCwd(root);
76
80
 
@@ -147,8 +151,6 @@ const getTemplateFileDestinationFromRoot =
147
151
  await fs.writeFile(path.join(root, 'package.json'), packageJsonString);
148
152
  process.chdir(root);
149
153
 
150
- const useYarn = detectYarn();
151
-
152
154
  const templateDirectory = path.join(toPosixPath(__dirname), '../template');
153
155
  const templateFiles = await glob(`${templateDirectory}/**/*`, {
154
156
  onlyFiles: true,
@@ -159,33 +161,27 @@ const getTemplateFileDestinationFromRoot =
159
161
  templateDirectory,
160
162
  );
161
163
 
164
+ const templateData = {
165
+ appName,
166
+ gettingStartedDocs: dedent`
167
+ First of all, make sure you've installed [${packageManager}](${getPackageManagerInstallPage()}).
168
+
169
+ Then, install dependencies:
170
+
171
+ \`\`\`sh
172
+ $ ${getInstallCommand()}
173
+ \`\`\`
174
+ `,
175
+ startScript: getRunCommand('start'),
176
+ testScript: getRunCommand('test'),
177
+ lintScript: getRunCommand('lint'),
178
+ formatScript: getRunCommand('format'),
179
+ buildScript: getRunCommand('build'),
180
+ };
181
+
162
182
  await Promise.all(
163
183
  templateFiles.map(async (file) => {
164
- const fileContents = await ejs.renderFile(file, {
165
- appName,
166
- gettingStartedDocs: useYarn
167
- ? dedent`
168
- First of all, make sure you've installed [Yarn](https://yarnpkg.com).
169
-
170
- Then, install dependencies:
171
-
172
- \`\`\`bash
173
- $ yarn
174
- \`\`\`
175
- `
176
- : dedent`
177
- Install dependencies:
178
-
179
- \`\`\`bash
180
- $ npm install
181
- \`\`\`
182
- `,
183
- startScript: useYarn ? 'yarn start' : 'npm start',
184
- testScript: useYarn ? 'yarn test' : 'npm test',
185
- lintScript: useYarn ? 'yarn lint' : 'npm run lint',
186
- formatScript: useYarn ? 'yarn format' : 'npm run format',
187
- buildScript: useYarn ? 'yarn build' : 'npm run build',
188
- });
184
+ const fileContents = await ejs.renderFile(file, templateData);
189
185
  const destination = getTemplateFileDestination(file);
190
186
 
191
187
  // Ensure folders exist before writing files to them
@@ -203,7 +199,11 @@ const getTemplateFileDestinationFromRoot =
203
199
  '@types/react-dom',
204
200
  ];
205
201
 
206
- console.log('Installing packages. This might take a couple of minutes.');
202
+ console.log(
203
+ `Installing packages with ${chalk.bold(
204
+ packageManager,
205
+ )}. This might take a couple of minutes.`,
206
+ );
207
207
  console.log(
208
208
  `Installing ${deps
209
209
  .concat(devDeps)
@@ -212,8 +212,15 @@ const getTemplateFileDestinationFromRoot =
212
212
  );
213
213
  console.log();
214
214
 
215
- await install({ deps, verbose, useYarn });
216
- await install({ deps: devDeps, type: 'dev', exact: false, verbose, useYarn });
215
+ const logLevel = args.argv.indexOf('--verbose') >= 0 ? 'verbose' : 'regular';
216
+
217
+ await install({ deps, logLevel });
218
+ await install({
219
+ deps: devDeps,
220
+ type: 'dev',
221
+ logLevel,
222
+ exact: false,
223
+ });
217
224
 
218
225
  await configure();
219
226
  await esLintFix();
@@ -221,7 +228,7 @@ const getTemplateFileDestinationFromRoot =
221
228
 
222
229
  const nextSteps = [
223
230
  `${chalk.cyan('cd')} ${projectName}`,
224
- `${chalk.cyan('yarn start')}`,
231
+ `${chalk.cyan(getRunCommand('start'))}`,
225
232
  ]
226
233
  .filter(Boolean)
227
234
  .join('\n');
package/scripts/serve.js CHANGED
@@ -2,7 +2,6 @@ const path = require('path');
2
2
  const exists = require('../lib/exists');
3
3
  const express = require('express');
4
4
  const handler = require('serve-handler');
5
- const flatMap = require('lodash/flatMap');
6
5
  const { blue, bold, underline, red } = require('chalk');
7
6
  const didYouMean = require('didyoumean2').default;
8
7
 
@@ -94,7 +93,7 @@ const preferredSite = args.site;
94
93
 
95
94
  const site = getSiteForHost(hostname, preferredSite) || '';
96
95
 
97
- const rewrites = flatMap(routes, (route) =>
96
+ const rewrites = routes.flatMap((route) =>
98
97
  getValidLanguagesForRoute(route).map((lang) => {
99
98
  const langRoute = getRouteWithLanguage(route.route, lang);
100
99
 
@@ -3,7 +3,6 @@ process.env.NODE_ENV = 'development';
3
3
  const path = require('path');
4
4
  const WebpackDevServer = require('webpack-dev-server');
5
5
  const webpack = require('webpack');
6
- const { once } = require('lodash');
7
6
  const onDeath = require('death');
8
7
  const { blue, underline } = require('chalk');
9
8
  const debug = require('debug')('sku:start');
@@ -29,6 +28,20 @@ const hot = process.env.SKU_HOT !== 'false';
29
28
  const pluginName = 'sku-start-ssr';
30
29
  const localhost = '0.0.0.0';
31
30
 
31
+ const once = (fn) => {
32
+ let called = false;
33
+ let result;
34
+
35
+ return (...fnArgs) => {
36
+ if (!called) {
37
+ result = fn(...fnArgs);
38
+ called = true;
39
+ }
40
+
41
+ return result;
42
+ };
43
+ };
44
+
32
45
  (async () => {
33
46
  await watchVocabCompile();
34
47