sku 11.0.3 → 11.2.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 CHANGED
@@ -1,5 +1,69 @@
1
1
  # sku
2
2
 
3
+ ## 11.2.1
4
+
5
+ ### Patch Changes
6
+
7
+ - Fix loading of TS config files that use node builtins or external dependencies. ([#657](https://github.com/seek-oss/sku/pull/657))
8
+
9
+ ## 11.2.0
10
+
11
+ ### Minor Changes
12
+
13
+ - Config files can now be in TypeScript ([#655](https://github.com/seek-oss/sku/pull/655))
14
+
15
+ Previously, projects were configured using a `sku.config.js` file, which exported a config object.
16
+ As most projects at SEEK are now TypeScript based, having a JS config file makes it impossible to reuse any of your production code in the config (e.g. routes).
17
+
18
+ This change makes it possible to use a TypeScript config file, by default `sku.config.ts`.
19
+ The easiest way to migrate is to change the module exports to a default export:
20
+
21
+ ```diff
22
+ - // sku.config.js
23
+ + // sku.config.ts
24
+ - module.exports = {
25
+ + export default {
26
+ clientEntry: 'src/client.tsx',
27
+ // ...
28
+ }
29
+ ```
30
+
31
+ But sku also now exports a type for the config object, to make it easier to setup and understand the configuration options.
32
+
33
+ ```diff
34
+ + import type { SkuConfig } from 'sku';
35
+ +
36
+ - module.exports = {
37
+ + const config: SkuConfig = {
38
+ clientEntry: 'src/client.tsx',
39
+ // ...
40
+ }
41
+ +
42
+ + export default config;
43
+ ```
44
+
45
+ `sku init` will now create TypeScript config files by default.
46
+
47
+ ### Patch Changes
48
+
49
+ - Ensure translations are available when running storybook ([#638](https://github.com/seek-oss/sku/pull/638))
50
+
51
+ ## 11.1.0
52
+
53
+ ### Minor Changes
54
+
55
+ - Include node_modules in node builds ([#651](https://github.com/seek-oss/sku/pull/651))
56
+
57
+ Previously, sku would only compile code within your src folder, plus any compile packages, for builds targetting the node environment. While this results in faster builds, it can sometimes lead to incorrect versions of packages being resolved due to clashing version range requirements. All node_modules will now included in the compilation by default, ensuring the correct package version is always required.
58
+
59
+ The old behaviour can be re-enabled via the new `externalizeNodeModules` config.
60
+
61
+ ## 11.0.4
62
+
63
+ ### Patch Changes
64
+
65
+ - Correct exclusion of `removeViewBox` svgo plugin ([#647](https://github.com/seek-oss/sku/pull/647))
66
+
3
67
  ## 11.0.3
4
68
 
5
69
  ### Patch Changes
@@ -1,7 +1,19 @@
1
1
  const { cwd, getPathFromCwd } = require('../../lib/cwd');
2
2
  const { paths, rootResolution } = require('../../context');
3
+ const path = require('path');
3
4
 
4
5
  module.exports = () => {
6
+ const includePaths = paths.src;
7
+
8
+ if (paths.appSkuConfigPath && paths.appSkuConfigPath.endsWith('.ts')) {
9
+ // If the config file is in TypeScript, it needs to be included in the tsconfig
10
+ includePaths.push(paths.appSkuConfigPath);
11
+ } else {
12
+ // If it isn't, the placeholder file needs to be included so we don't break JS only projects.
13
+ // See the comments in placeholder.ts
14
+ includePaths.push(path.join(__dirname, '../../lib/placeholder.ts'));
15
+ }
16
+
5
17
  const config = {
6
18
  compilerOptions: {
7
19
  // This flag allows tsc to be invoked directly by VS Code (via Cmd+Shift+B),
@@ -21,7 +33,7 @@ module.exports = () => {
21
33
  lib: ['dom', 'es2015'],
22
34
  target: 'es5',
23
35
  },
24
- include: paths.src,
36
+ include: includePaths,
25
37
  exclude: [getPathFromCwd('node_modules')],
26
38
  };
27
39
 
@@ -9,7 +9,7 @@ module.exports = function getWebpackCacheSettings({ isDevServer }) {
9
9
  return {
10
10
  type: 'filesystem',
11
11
  buildDependencies: {
12
- config: [paths.appSkuConfigPath],
12
+ config: paths.appSkuConfigPath ? [paths.appSkuConfigPath] : [],
13
13
  },
14
14
  };
15
15
  }
@@ -143,8 +143,10 @@ const makeSvgLoaders = () => [
143
143
  plugins: [
144
144
  {
145
145
  name: 'preset-default',
146
- overrides: {
147
- removeViewBox: false,
146
+ params: {
147
+ overrides: {
148
+ removeViewBox: false,
149
+ },
148
150
  },
149
151
  },
150
152
  {
@@ -16,7 +16,6 @@ const { VocabWebpackPlugin } = require('@vocab/webpack');
16
16
 
17
17
  const utils = require('./utils');
18
18
  const { cwd } = require('../../lib/cwd');
19
- const isTypeScript = require('../../lib/isTypeScript');
20
19
 
21
20
  const renderEntry = require.resolve('../../entry/render');
22
21
  const libraryRenderEntry = require.resolve('../../entry/libraryRender');
@@ -39,6 +38,7 @@ const {
39
38
  cspExtraScriptSrcHosts,
40
39
  rootResolution,
41
40
  skipPackageCompatibilityCompilation,
41
+ externalizeNodeModules,
42
42
  } = config;
43
43
 
44
44
  // port is only required for dev builds
@@ -235,7 +235,7 @@ const makeWebpackConfig = ({
235
235
  browserslist: supportedBrowsers,
236
236
  mode: webpackMode,
237
237
  libraryName,
238
- generateCSSTypes: isTypeScript,
238
+ generateCSSTypes: true,
239
239
  displayNamesProd,
240
240
  removeAssertionsInProduction: !isIntegration,
241
241
  MiniCssExtractPlugin,
@@ -268,19 +268,21 @@ const makeWebpackConfig = ({
268
268
  // render will run within the same process
269
269
  target: `browserslist:${nodeTarget}`,
270
270
  externals: [
271
- // Don't bundle or transpile non-compiled packages
272
- nodeExternals({
273
- allowlist: [
274
- 'classnames', // Workaround for https://github.com/JedWatson/classnames/issues/240
271
+ // Don't bundle or transpile non-compiled packages if externalizeNodeModules is enabled
272
+ externalizeNodeModules
273
+ ? nodeExternals({
274
+ allowlist: [
275
+ 'classnames', // Workaround for https://github.com/JedWatson/classnames/issues/240
275
276
 
276
- // webpack-node-externals compares the `import` or `require` expression to this list,
277
- // not the package name, so we map each packageName to a pattern. This ensures it
278
- // matches when importing a file within a package e.g. import { Text } from 'seek-style-guide/react'.
279
- ...paths.compilePackages.map(
280
- (packageName) => new RegExp(`^(${packageName})`),
281
- ),
282
- ],
283
- }),
277
+ // webpack-node-externals compares the `import` or `require` expression to this list,
278
+ // not the package name, so we map each packageName to a pattern. This ensures it
279
+ // matches when importing a file within a package e.g. import { Text } from 'seek-style-guide/react'.
280
+ ...paths.compilePackages.map(
281
+ (packageName) => new RegExp(`^(${packageName})`),
282
+ ),
283
+ ],
284
+ })
285
+ : {},
284
286
  ],
285
287
  output: {
286
288
  path: paths.target,
@@ -16,7 +16,6 @@ const args = require('../args');
16
16
  const { bundleAnalyzerPlugin } = require('./plugins/bundleAnalyzer');
17
17
  const utils = require('./utils');
18
18
  const { cwd } = require('../../lib/cwd');
19
- const isTypeScript = require('../../lib/isTypeScript');
20
19
  const {
21
20
  paths,
22
21
  env,
@@ -30,6 +29,7 @@ const {
30
29
  useDevServerMiddleware,
31
30
  rootResolution,
32
31
  skipPackageCompatibilityCompilation,
32
+ externalizeNodeModules,
33
33
  } = require('../../context');
34
34
  const { getVocabConfig } = require('../vocab/vocab');
35
35
  const statsConfig = require('./statsConfig');
@@ -188,7 +188,7 @@ const makeWebpackConfig = ({
188
188
  hot,
189
189
  include: internalInclude,
190
190
  compilePackages: paths.compilePackages,
191
- generateCSSTypes: isTypeScript,
191
+ generateCSSTypes: true,
192
192
  browserslist: supportedBrowsers,
193
193
  mode: webpackMode,
194
194
  displayNamesProd,
@@ -225,17 +225,20 @@ const makeWebpackConfig = ({
225
225
  {
226
226
  __sku_alias__webpackStats: `commonjs ./${webpackStatsFilename}`,
227
227
  },
228
- nodeExternals({
229
- modulesDir: findUp.sync('node_modules'), // Allow usage within project subdirectories (required for tests)
230
- allowlist: [
231
- // webpack-node-externals compares the `import` or `require` expression to this list,
232
- // not the package name, so we map each packageName to a pattern. This ensures it
233
- // matches when importing a file within a package e.g. import { Text } from 'seek-style-guide/react'.
234
- ...paths.compilePackages.map(
235
- (packageName) => new RegExp(`^(${packageName})`),
236
- ),
237
- ],
238
- }),
228
+ // Don't bundle or transpile non-compiled packages if externalizeNodeModules is enabled
229
+ externalizeNodeModules
230
+ ? nodeExternals({
231
+ modulesDir: findUp.sync('node_modules'), // Allow usage within project subdirectories (required for tests)
232
+ allowlist: [
233
+ // webpack-node-externals compares the `import` or `require` expression to this list,
234
+ // not the package name, so we map each packageName to a pattern. This ensures it
235
+ // matches when importing a file within a package e.g. import { Text } from 'seek-style-guide/react'.
236
+ ...paths.compilePackages.map(
237
+ (packageName) => new RegExp(`^(${packageName})`),
238
+ ),
239
+ ],
240
+ })
241
+ : {},
239
242
  ],
240
243
  resolve: {
241
244
  alias: {
@@ -190,4 +190,7 @@ module.exports = validator.compile({
190
190
  persistentCache: {
191
191
  type: 'boolean',
192
192
  },
193
+ externalizeNodeModules: {
194
+ type: 'boolean',
195
+ },
193
196
  });
@@ -45,4 +45,5 @@ module.exports = {
45
45
  languages: null,
46
46
  skipPackageCompatibilityCompilation: [],
47
47
  persistentCache: true,
48
+ externalizeNodeModules: false,
48
49
  };
package/context/index.js CHANGED
@@ -1,6 +1,7 @@
1
1
  const fs = require('fs');
2
2
  const path = require('path');
3
3
  const chalk = require('chalk');
4
+ const { register } = require('esbuild-register/dist/node');
4
5
  const { getPathFromCwd } = require('../lib/cwd');
5
6
  const args = require('../config/args');
6
7
  const defaultSkuConfig = require('./defaultSkuConfig');
@@ -9,11 +10,37 @@ const validateConfig = require('./validateConfig');
9
10
  const defaultCompilePackages = require('./defaultCompilePackages');
10
11
  const isCompilePackage = require('../lib/isCompilePackage');
11
12
 
12
- const appSkuConfigPath = getPathFromCwd(args.config);
13
+ const getSkuConfig = () => {
14
+ let appSkuConfigPath;
15
+ const tsPath = getPathFromCwd('sku.config.ts');
16
+ const jsPath = getPathFromCwd('sku.config.js');
17
+
18
+ if (args.config) {
19
+ appSkuConfigPath = getPathFromCwd(args.config);
20
+ } else if (fs.existsSync(tsPath)) {
21
+ appSkuConfigPath = tsPath;
22
+ } else if (fs.existsSync(jsPath)) {
23
+ appSkuConfigPath = jsPath;
24
+ } else {
25
+ return {
26
+ appSkuConfig: {},
27
+ appSkuConfigPath: null,
28
+ };
29
+ }
30
+
31
+ const { unregister } = register({ target: 'node14' });
32
+
33
+ const newConfig = require(appSkuConfigPath);
34
+
35
+ unregister();
36
+
37
+ return {
38
+ appSkuConfig: newConfig.default || newConfig,
39
+ appSkuConfigPath,
40
+ };
41
+ };
13
42
 
14
- const appSkuConfig = fs.existsSync(appSkuConfigPath)
15
- ? require(appSkuConfigPath)
16
- : {};
43
+ const { appSkuConfig, appSkuConfigPath } = getSkuConfig();
17
44
 
18
45
  const skuConfig = {
19
46
  ...defaultSkuConfig,
@@ -171,4 +198,5 @@ module.exports = {
171
198
  skipPackageCompatibilityCompilation:
172
199
  skuConfig.skipPackageCompatibilityCompilation,
173
200
  persistentCache: skuConfig.persistentCache,
201
+ externalizeNodeModules: skuConfig.externalizeNodeModules,
174
202
  };
@@ -1,29 +1,35 @@
1
1
  # Configuration
2
2
 
3
- If you need to configure sku, first create a `sku.config.js` file in your project root:
3
+ If you need to configure sku, first create a `sku.config.ts` file in your project root:
4
4
 
5
5
  ```bash
6
- $ touch sku.config.js
6
+ $ touch sku.config.ts
7
7
  ```
8
8
 
9
9
  While sku has a zero configuration mode, the equivalent manual configuration would look like this:
10
10
 
11
- ```js
12
- module.exports = {
11
+ ```ts
12
+ import type { SkuConfig } from 'sku';
13
+
14
+ const skuConfig: SkuConfig = {
13
15
  clientEntry: 'src/client.js',
14
16
  renderEntry: 'src/render.js',
15
17
  public: 'src/public',
16
18
  publicPath: '/',
17
19
  target: 'dist',
18
20
  };
21
+
22
+ export default skuConfig;
19
23
  ```
20
24
 
21
25
  If you need to specify a different config file you can do so with the `--config` parameter.
22
26
 
23
27
  ```bash
24
- $ sku start --config sku.custom.config.js
28
+ $ sku start --config sku.custom.config.ts
25
29
  ```
26
30
 
31
+ Config files can use either TypeScript or JavaScript.
32
+
27
33
  ## clientEntry
28
34
 
29
35
  type `string`
@@ -117,6 +123,24 @@ const config = {
117
123
  };
118
124
  ```
119
125
 
126
+ ## devServerMiddleware
127
+
128
+ type `string`
129
+
130
+ Path to a file in your project that exports a function that can receive the Express server.
131
+
132
+ This can be used to extend to the dev server middleware.
133
+
134
+ Example:
135
+
136
+ ```js
137
+ module.exports = app => {
138
+ app.get('/mock-api', (req, res) => {
139
+ ...
140
+ })
141
+ }
142
+ ```
143
+
120
144
  ## displayNamesProd
121
145
 
122
146
  type `boolean`
@@ -143,23 +167,13 @@ Default: `[]`
143
167
 
144
168
  An array of environments the app supports. Apps should have one environment for local development plus one for each environment they're deployed to. Use this value to drive app config (e.g. `analyticsEnabled` or `apiEndpoint`). See [static-rendering](./docs/static-rendering.md) for more info.
145
169
 
146
- ## skipPackageCompatibilityCompilation
147
-
148
- type `Array<string>`
149
-
150
- Default: `[]`
151
-
152
- When running `sku build`, sku will compile all your external packages (`node_modules`) through `@babel/preset-env`. This is to ensure external packages satisfy the browser support policy. However, this can cause very slow builds when large packages are processed. The `skipPackageCompatibilityCompilation` option allows you to pass a list of trusted packages to skip this behaviour.
170
+ ## externalizeNodeModules
153
171
 
154
- > Note: `react` & `react-dom` are skipped by default.
172
+ type `boolean`
155
173
 
156
- Example:
174
+ Default: `false`
157
175
 
158
- ```js
159
- const config = {
160
- skipPackageCompatibilityCompilation: ['@bloat/very-large-package', 'lodash'],
161
- };
162
- ```
176
+ By default, sku compiles all node_modules in builds that target node. Setting this option to `true` will instead externalize all node_modules, excluding `compilePackages`.
163
177
 
164
178
  ## hosts
165
179
 
@@ -169,6 +183,14 @@ Default: `['localhost']`
169
183
 
170
184
  An array of custom hosts the app can be served off when running `sku start`. You must have configured your hosts file to point to localhost as well.
171
185
 
186
+ ## httpsDevServer
187
+
188
+ type `boolean`
189
+
190
+ Default: `false`
191
+
192
+ Whether or not to use `https` for the local development server with a self-signed certificate. This is useful when testing authentication flows that require access to `window.crypto`.
193
+
172
194
  ## initialPath
173
195
 
174
196
  type `string`
@@ -179,7 +201,7 @@ The browser URL to open when running `sku start` or `sku start-ssr`. It will def
179
201
 
180
202
  ## languages
181
203
 
182
- type `Array<string>`
204
+ type `Array<string | { name: string }>`
183
205
 
184
206
  The languages your application supports.
185
207
 
@@ -261,6 +283,18 @@ Default: `./src/render.js`
261
283
 
262
284
  The render entry file to the app. This file should export the required functions for static rendering. See [static-rendering](./docs/static-rendering.md) for more info.
263
285
 
286
+ ## rootResolution
287
+
288
+ type `boolean`
289
+
290
+ Default: `true`
291
+
292
+ Enable root resolution. By default, sku allows importing from the root of the project e.g. `import something from 'src/modules/something'`.
293
+
294
+ Unfortunately, these kinds of imports only work for apps. In packages, the imports will work locally, but fail when consumed from `node_modules`.
295
+
296
+ You can set this option in `sku.config.js`, or adding `"skuCompilePackage": true` to your `package.json` will disable this behaviour by default.
297
+
264
298
  ## routes
265
299
 
266
300
  type `Array<string | {route: string, name: string, entry: string, languages: Array<string>}>`
@@ -321,6 +355,24 @@ Can be an array of site names, or objects with a site name and corresponding hos
321
355
 
322
356
  Can be used to limit the languages rendered for a specific site. Any listed language must exist in the [top level languages attribute](./docs/configuration?id=languages).
323
357
 
358
+ ## skipPackageCompatibilityCompilation
359
+
360
+ type `Array<string>`
361
+
362
+ Default: `[]`
363
+
364
+ When running `sku build`, sku will compile all your external packages (`node_modules`) through `@babel/preset-env`. This is to ensure external packages satisfy the browser support policy. However, this can cause very slow builds when large packages are processed. The `skipPackageCompatibilityCompilation` option allows you to pass a list of trusted packages to skip this behaviour.
365
+
366
+ > Note: `react` & `react-dom` are skipped by default.
367
+
368
+ Example:
369
+
370
+ ```js
371
+ const config = {
372
+ skipPackageCompatibilityCompilation: ['@bloat/very-large-package', 'lodash'],
373
+ };
374
+ ```
375
+
324
376
  ## sourceMapsProd
325
377
 
326
378
  type `boolean`
@@ -344,6 +396,14 @@ Default: `['./src']`
344
396
 
345
397
  An array of directories holding your apps source code. By default, sku expects your source code to be in a directory named `src` in the root of your project. Use this option if your source code needs to be arranged differently.
346
398
 
399
+ ## storybookAddons
400
+
401
+ type `Array<string>`
402
+
403
+ Default: `[]`
404
+
405
+ An array of storybook addons to use.
406
+
347
407
  ## storybookPort
348
408
 
349
409
  type `number`
@@ -360,14 +420,6 @@ Default: `dist-storybook`
360
420
 
361
421
  The directory `sku build-storybook` will output files to.
362
422
 
363
- ## storybookAddons
364
-
365
- type `Array<string>`
366
-
367
- Default: `[]`
368
-
369
- An array of storybook addons to use.
370
-
371
423
  ## supportedBrowsers
372
424
 
373
425
  type `browserslist-query`
@@ -393,29 +445,3 @@ type `function`
393
445
  Default: `({ environment = '', site = '', route = '' }) => path.join(environment, site, route)`
394
446
 
395
447
  This function returns the output path within [`target`](#target) for each rendered page. Generally, this value should be sufficient. If you think you need to modify this setting, please reach out to the `sku-support` group first to discuss.
396
-
397
- ## httpsDevServer
398
-
399
- type `boolean`
400
-
401
- Default: `false`
402
-
403
- Whether or not to use `https` for the local development server with a self-signed certificate. This is useful when testing authentication flows that require access to `window.crypto`.
404
-
405
- ## devServerMiddleware
406
-
407
- type `string`
408
-
409
- Path to a file in your project that exports a function that can receive the Express server.
410
-
411
- This can be used to extend to the dev server middleware.
412
-
413
- Example:
414
-
415
- ```js
416
- module.exports = app => {
417
- app.get('/mock-api', (req, res) => {
418
- ...
419
- })
420
- }
421
- ```
package/docs/index.html CHANGED
@@ -106,5 +106,7 @@
106
106
  <script src="https://unpkg.com/docsify-themeable"></script>
107
107
  <script src="//unpkg.com/docsify/lib/plugins/search.min.js"></script>
108
108
  <script src="//unpkg.com/prismjs/components/prism-diff.min.js"></script>
109
+ <script src="//cdn.jsdelivr.net/npm/prismjs@1.25.0/components/prism-typescript.min.js"></script>
110
+ <script src="//cdn.jsdelivr.net/npm/prismjs@1.25.0/components/prism-bash.min.js"></script>
109
111
  </body>
110
112
  </html>
package/lib/configure.js CHANGED
@@ -5,7 +5,6 @@ const path = require('path');
5
5
  const ensureGitignore = require('ensure-gitignore');
6
6
  const { cwd, getPathFromCwd } = require('./cwd');
7
7
 
8
- const isTypeScript = require('./isTypeScript');
9
8
  const { paths, httpsDevServer, languages } = require('../context');
10
9
  const {
11
10
  bundleReportFolder,
@@ -87,16 +86,10 @@ module.exports = async () => {
87
86
  patterns: lintIgnorePatterns.map(convertToForwardSlashPaths),
88
87
  });
89
88
 
90
- if (isTypeScript) {
91
- // Generate TypeScript configuration
92
- const tsConfigFileName = 'tsconfig.json';
93
- const tslintPath = getPathFromCwd('tslint.json');
94
- await writeFileToCWD(tsConfigFileName, createTSConfig());
95
- gitIgnorePatterns.push(tsConfigFileName);
96
-
97
- // Delete TSLint
98
- await fs.remove(tslintPath);
99
- }
89
+ // Generate TypeScript configuration
90
+ const tsConfigFileName = 'tsconfig.json';
91
+ await writeFileToCWD(tsConfigFileName, createTSConfig());
92
+ gitIgnorePatterns.push(tsConfigFileName);
100
93
 
101
94
  // Generate self-signed certificate and ignore
102
95
  const selfSignedCertificateDirName = '.ssl';
package/lib/parseArgs.js CHANGED
@@ -26,7 +26,6 @@ const optionDefinitions = [
26
26
  name: 'config',
27
27
  alias: 'c',
28
28
  type: String,
29
- defaultValue: 'sku.config.js',
30
29
  },
31
30
  {
32
31
  name: 'debug',
@@ -0,0 +1,7 @@
1
+ /**
2
+ * This is a placeholder file that provides for at least one TypeScript file in the project.
3
+ *
4
+ * Since all projects get a tsconfig.json now, having zero TS files would cause an error.
5
+ *
6
+ * Support for purely JS projects will be removed in a future major version, and this file can be removed.
7
+ * */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sku",
3
- "version": "11.0.3",
3
+ "version": "11.2.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": {
@@ -105,6 +105,8 @@
105
105
  "empty-dir": "^2.0.0",
106
106
  "ensure-gitignore": "^1.1.2",
107
107
  "env-ci": "^5.0.0",
108
+ "esbuild": "^0.13.13",
109
+ "esbuild-register": "^3.2.0",
108
110
  "escape-string-regexp": "^4.0.0",
109
111
  "eslint": "^7.18.0",
110
112
  "eslint-config-seek": "^7.0.8",
@@ -9,8 +9,10 @@ const gracefulSpawn = require('../lib/gracefulSpawn');
9
9
  const { storybookTarget } = require('../context');
10
10
  const buildStorybookPath = require.resolve('@storybook/react/bin/build.js');
11
11
  const configDir = path.resolve(__dirname, '../config/storybook/build');
12
+ const { runVocabCompile } = require('../lib/runVocab');
12
13
 
13
14
  (async () => {
15
+ await runVocabCompile();
14
16
  await rimraf(storybookTarget);
15
17
 
16
18
  argv.push('--config-dir', configDir);
package/scripts/init.js CHANGED
@@ -13,8 +13,6 @@ const prettierWrite = require('../lib/runPrettier').write;
13
13
  const esLintFix = require('../lib/runESLint').fix;
14
14
  const configure = require('../lib/configure');
15
15
  const install = require('../lib/install');
16
- const { getMissingHosts } = require('../lib/hosts');
17
- const { getSuggestedScript } = require('../lib/suggestScript');
18
16
  const banner = require('../lib/banner');
19
17
  const trace = require('debug')('sku:init');
20
18
 
@@ -184,16 +182,8 @@ const args = require('../config/args');
184
182
  await esLintFix();
185
183
  await prettierWrite();
186
184
 
187
- // read configured sites from templated sku config
188
- const sites = require(path.join(root, 'sku.config.js')).sites;
189
- const missingHosts = await getMissingHosts(sites);
190
- const setupHostScript = await getSuggestedScript('setup-hosts', {
191
- sudo: true,
192
- });
193
-
194
185
  const nextSteps = [
195
186
  `${chalk.cyan('cd')} ${projectName}`,
196
- missingHosts.length > 0 ? chalk.cyan(setupHostScript) : null,
197
187
  `${chalk.cyan('yarn start')}`,
198
188
  ]
199
189
  .filter(Boolean)
package/scripts/lint.js CHANGED
@@ -1,5 +1,4 @@
1
1
  const chalk = require('chalk');
2
- const isTypeScript = require('../lib/isTypeScript');
3
2
  const esLintCheck = require('../lib/runESLint').check;
4
3
  const prettierCheck = require('../lib/runPrettier').check;
5
4
  const runTsc = require('../lib/runTsc');
@@ -14,17 +13,15 @@ const { runVocabCompile } = require('../lib/runVocab');
14
13
  await runVocabCompile();
15
14
 
16
15
  try {
17
- if (isTypeScript) {
18
- const hasPaths = typeof pathsToCheck !== 'undefined';
19
- const pathsIncludeTS =
20
- hasPaths &&
21
- pathsToCheck.filter(
22
- (filePath) => filePath.endsWith('.ts') || filePath.endsWith('.tsx'),
23
- ).length > 0;
24
-
25
- if (!hasPaths || pathsIncludeTS) {
26
- await runTsc();
27
- }
16
+ const hasPaths = typeof pathsToCheck !== 'undefined';
17
+ const pathsIncludeTS =
18
+ hasPaths &&
19
+ pathsToCheck.filter(
20
+ (filePath) => filePath.endsWith('.ts') || filePath.endsWith('.tsx'),
21
+ ).length > 0;
22
+
23
+ if (!hasPaths || pathsIncludeTS) {
24
+ await runTsc();
28
25
  }
29
26
 
30
27
  await prettierCheck(pathsToCheck);
@@ -4,16 +4,21 @@ const gracefulSpawn = require('../lib/gracefulSpawn');
4
4
  const { storybookPort } = require('../context');
5
5
  const startStorybookPath = require.resolve('@storybook/react/bin/index.js');
6
6
  const configDir = path.resolve(__dirname, '../config/storybook/start');
7
+ const { watchVocabCompile } = require('../lib/runVocab');
7
8
 
8
9
  argv.push('--port', storybookPort);
9
10
  argv.push('--config-dir', configDir);
10
11
  argv.push('--quiet');
11
12
 
12
- const storybookProcess = gracefulSpawn(startStorybookPath, argv, {
13
- stdio: 'inherit',
14
- env: process.env,
15
- });
13
+ (async () => {
14
+ await watchVocabCompile();
16
15
 
17
- storybookProcess.on('exit', (exitCode) => {
18
- process.exit(exitCode);
19
- });
16
+ const storybookProcess = gracefulSpawn(startStorybookPath, argv, {
17
+ stdio: 'inherit',
18
+ env: process.env,
19
+ });
20
+
21
+ storybookProcess.on('exit', (exitCode) => {
22
+ process.exit(exitCode);
23
+ });
24
+ })();
package/sku-types.d.ts CHANGED
@@ -33,3 +33,385 @@ export interface Render<App = string> {
33
33
 
34
34
  renderDocument(p: RenderDocumentProps<App>): Promise<string> | string;
35
35
  }
36
+
37
+ interface SkuRouteObject {
38
+ route: string;
39
+ name?: string;
40
+ entry?: string;
41
+ languages?: string[];
42
+ }
43
+
44
+ type SkuRoute = string | SkuRouteObject;
45
+
46
+ interface SkuSiteObject {
47
+ name: string;
48
+ host?: string;
49
+ routes?: Array<SkuRoute>;
50
+ languages?: string[];
51
+ }
52
+
53
+ type SkuSite = string | SkuSiteObject;
54
+
55
+ interface TranformOutputPathFunctionParams {
56
+ environment: string;
57
+ site: string;
58
+ path: string;
59
+ }
60
+ type TranformOutputPathFunction = (
61
+ input: TranformOutputPathFunctionParams,
62
+ ) => string;
63
+
64
+ export interface SkuConfig {
65
+ /**
66
+ * The client entry point to the app. The client entry is the file that executes your browser code.
67
+ *
68
+ * @default "./src/client.js"
69
+ * @link https://seek-oss.github.io/sku/#/./docs/configuration?id=cliententry
70
+ */
71
+ clientEntry?: string;
72
+
73
+ /**
74
+ * An array of `node_modules` to be compiled as if they were part of your source code.
75
+ *
76
+ * Ideally, this setting should only be used for internally controlled packages.
77
+ *
78
+ * @default "[]"
79
+ * @link https://seek-oss.github.io/sku/#/./docs/configuration?id=compilepackages
80
+ */
81
+ compilePackages?: string[];
82
+
83
+ /**
84
+ * **Unavailable for libraries**
85
+ *
86
+ * Enable content security policy feature. More info at https://seek-oss.github.io/sku/#/./docs/csp
87
+ *
88
+ * @default false
89
+ * @link https://seek-oss.github.io/sku/#/./docs/configuration?id=cspenabled
90
+ */
91
+ cspEnabled?: boolean;
92
+
93
+ /**
94
+ * Extra external hosts to allow in your `script-src` content security policy. Only relevant if {@link cspEnabled} is set to `true`.
95
+ *
96
+ * @default []
97
+ * @link https://seek-oss.github.io/sku/#/./docs/configuration?id=cspextrascriptsrchosts
98
+ */
99
+ cspExtraScriptSrcHosts?: string[];
100
+
101
+ /**
102
+ * Similar to {@link dangerouslySetWebpackConfig} but for eslint config.
103
+ *
104
+ * @link https://seek-oss.github.io/sku/#/./docs/configuration?id=dangerouslyseteslintconfig
105
+ */
106
+ dangerouslySetESLintConfig?: (existingESLintConfig: any) => any;
107
+
108
+ /**
109
+ * Similar to {@link dangerouslySetWebpackConfig} but for jest config. Make sure {@link setupTests} definitely doesn’t cover your needs before using.
110
+ * Please speak with the `sku-support` group before using.
111
+ *
112
+ * @link https://seek-oss.github.io/sku/#/./docs/configuration?id=dangerouslysetjestconfig
113
+ */
114
+ dangerouslySetJestConfig?: (existingJestConfig: any) => any;
115
+
116
+ /**
117
+ * This function provides a way to override the webpack config after sku has created it.
118
+ * Ideally, this setting is not needed and only used for experimenting/debugging. If you require webpack features not currently supported by sku please speak to the `sku-support` group.
119
+ *
120
+ * Reliance on this setting will cause issues when upgrading sku as any custom settings may break at anytime. You’ve been warned!
121
+ *
122
+ * @link https://seek-oss.github.io/sku/#/./docs/configuration?id=dangerouslysetwebpackconfig
123
+ */
124
+ dangerouslySetWebpackConfig?: (existingWebpackConfig: any) => any;
125
+
126
+ /**
127
+ * Path to a file in your project that exports a function that can receive the Express server.
128
+ * This can be used to extend to the dev server middleware.
129
+ *
130
+ * @link https://seek-oss.github.io/sku/#/./docs/configuration?id=devservermiddleware
131
+ */
132
+ devServerMiddleware?: string;
133
+
134
+ /**
135
+ * Adds static `displayName` properties to React components in production.
136
+ * This setting is designed for usage on sites that generate React code snippets, e.g. Braid.
137
+ *
138
+ * @default false
139
+ * @link https://seek-oss.github.io/sku/#/./docs/configuration?id=displaynamesprod
140
+ */
141
+ displayNamesProd?: boolean;
142
+
143
+ /**
144
+ * **Only for static apps**
145
+ *
146
+ * An array of environments the app supports.
147
+ * Apps should have one environment for local development plus one for each environment they’re deployed to.
148
+ *
149
+ * @default []
150
+ * @link https://seek-oss.github.io/sku/#/./docs/configuration?id=environments
151
+ */
152
+ environments?: string[];
153
+
154
+ /**
155
+ * By default, sku compiles all node_modules in builds that target node.
156
+ * Setting this option to `true` will instead externalize all node_modules, excluding `compilePackages`.
157
+ *
158
+ * @default false
159
+ * @link https://seek-oss.github.io/sku/#/./docs/configuration?id=externalizenodemodules
160
+ */
161
+ externalizeNodeModules?: boolean;
162
+
163
+ /**
164
+ * An array of custom hosts the app can be served off when running `sku start`.
165
+ * You must have configured your hosts file to point to localhost as well.
166
+ *
167
+ * @default ['localhost']
168
+ * @link https://seek-oss.github.io/sku/#/./docs/configuration?id=hosts
169
+ */
170
+ hosts?: string[];
171
+
172
+ /**
173
+ * Whether or not to use https for the local development server with a self-signed certificate.
174
+ * This is useful when testing authentication flows that require access to `window.crypto`.
175
+ *
176
+ * @default false
177
+ * @link https://seek-oss.github.io/sku/#/./docs/configuration?id=httpsdevserver
178
+ */
179
+ httpsDevServer?: boolean;
180
+
181
+ /**
182
+ * The browser URL to open when running `sku start` or `sku start-ssr`.
183
+ * It will default to the first `route` in the {@link routes} array.
184
+ *
185
+ * @default routes[0].route
186
+ * @link https://seek-oss.github.io/sku/#/./docs/configuration?id=initialpath
187
+ */
188
+ initialPath?: string;
189
+
190
+ /**
191
+ * The languages your application supports.
192
+ *
193
+ * @link https://seek-oss.github.io/sku/#/./docs/configuration?id=languages
194
+ */
195
+ languages?: Array<string | { name: string }>;
196
+
197
+ /**
198
+ * **Only for libraries**
199
+ *
200
+ * The entry file for the library. If set, sku will assume the project is a library. Must export its API from this file.
201
+ *
202
+ * @link https://seek-oss.github.io/sku/#/./docs/configuration?id=libraryentry
203
+ */
204
+ libraryEntry?: string;
205
+
206
+ /**
207
+ * **Only for libraries**
208
+ *
209
+ * The global name of the library. Will be added to the `window` object under `window[libraryName]`.
210
+ *
211
+ * @link https://seek-oss.github.io/sku/#/./docs/configuration?id=libraryname
212
+ */
213
+ libraryName?: string;
214
+
215
+ /**
216
+ * Enables linting of import order. This rule supports auto-fix.
217
+ *
218
+ * @link https://seek-oss.github.io/sku/#/./docs/linting?id=import-ordering
219
+ */
220
+ orderImports?: boolean;
221
+
222
+ /**
223
+ * Disables the use of webpack filesystem caching for `sku start` and `sku start-ssr`.
224
+ *
225
+ * @default true
226
+ * @link https://seek-oss.github.io/sku/#/./docs/configuration?id=persistentcache
227
+ */
228
+ persistentCache?: boolean;
229
+
230
+ /**
231
+ * An array of polyfills to be included into all client entry points.
232
+ *
233
+ * @default []
234
+ * @link https://seek-oss.github.io/sku/#/./docs/configuration?id=polyfills
235
+ */
236
+ polyfills?: string[];
237
+
238
+ /**
239
+ * The port the app is hosted on when running `sku start`.
240
+ *
241
+ * @default 8080
242
+ * @link https://seek-oss.github.io/sku/#/./docs/configuration?id=port
243
+ */
244
+ port?: number;
245
+
246
+ /**
247
+ * A folder of public assets to be copied into the `target` directory after `sku build` or `sku build-ssr`.
248
+ *
249
+ * *Caution*: All assets should ideally be imported through the source code to ensure they are named correctly for long term caching.
250
+ * You may run into caching issues using this option. It may be removed in future.
251
+ *
252
+ * @default 'public'
253
+ * @link https://seek-oss.github.io/sku/#/./docs/configuration?id=public
254
+ */
255
+ public?: string;
256
+
257
+ /**
258
+ * The URL all the static assets of the app are accessible under.
259
+ *
260
+ * @default '/'
261
+ * @link https://seek-oss.github.io/sku/#/./docs/configuration?id=publicpath
262
+ */
263
+ publicPath?: string;
264
+
265
+ /**
266
+ * **Only for static apps and libraries**
267
+ *
268
+ * The render entry file to the app. This file should export the required functions for static rendering.
269
+ *
270
+ * @default "./src/render.js"
271
+ * @link https://seek-oss.github.io/sku/#/./docs/configuration?id=renderentry
272
+ */
273
+ renderEntry?: string;
274
+
275
+ /**
276
+ * Enables root resolution.
277
+ *
278
+ * By default, sku allows importing from the root of the project e.g. `import something from 'src/modules/something'`.
279
+ *
280
+ * Unfortunately, these kinds of imports only work for apps.
281
+ * In packages, the imports will work locally, but fail when consumed from `node_modules`.
282
+ *
283
+ * @default true
284
+ * @link https://seek-oss.github.io/sku/#/./docs/configuration?id=rootresolution
285
+ */
286
+ rootResolution?: boolean;
287
+
288
+ /**
289
+ * **Only for static apps**
290
+ *
291
+ * An array of routes for the app. Each route must specify a name and a route corresponding to the path it is hosted under. Each route may also have a custom client entry, which can help with bundle splitting. See static-rendering for more info.
292
+ *
293
+ * Can be used to limit the languages rendered for a specific route. Any listed language must exist in the top level languages attribute.
294
+ *
295
+ * @default ['/']
296
+ * @link https://seek-oss.github.io/sku/#/./docs/configuration?id=routes
297
+ */
298
+ routes?: Array<SkuRoute>;
299
+
300
+ /**
301
+ * *Only for SSR apps**
302
+ *
303
+ * The entry file for the server.
304
+ *
305
+ * @default "./src/server.js"
306
+ * @link https://seek-oss.github.io/sku/#/./docs/configuration?id=serverentry
307
+ */
308
+ serverEntry?: string;
309
+
310
+ /**
311
+ * **Only for SSR apps**
312
+ *
313
+ * The port the server is hosted on when running `sku start-ssr`.
314
+ *
315
+ * @default 8181
316
+ * @link https://seek-oss.github.io/sku/#/./docs/configuration?id=serverport
317
+ */
318
+ serverPort?: number;
319
+
320
+ /**
321
+ * Point to a JS file that will run before your tests to setup the testing environment.
322
+ *
323
+ * @link https://seek-oss.github.io/sku/#/./docs/configuration?id=setuptests
324
+ */
325
+ setupTests?: string | string[];
326
+
327
+ /**
328
+ * **Only for static apps**
329
+ *
330
+ * An array of sites the app supports. These usually correspond to each domain the app is hosted under.
331
+ *
332
+ * @default []
333
+ * @link https://seek-oss.github.io/sku/#/./docs/configuration?id=sites
334
+ */
335
+ sites?: Array<SkuSite>;
336
+
337
+ /**
338
+ * When running `sku build`, sku will compile all your external packages (`node_modules`) through `@babel/preset-env`.
339
+ * This is to ensure external packages satisfy the browser support policy.
340
+ * However, this can cause very slow builds when large packages are processed.
341
+ *
342
+ * The `skipPackageCompatibilityCompilation` option allows you to pass a list of trusted packages to skip this behaviour.
343
+ *
344
+ * @default []
345
+ * @link https://seek-oss.github.io/sku/#/./docs/configuration?id=skippackagecompatibilitycompilation
346
+ */
347
+ skipPackageCompatibilityCompilation?: string[];
348
+
349
+ /**
350
+ * By default source maps will be generated only for development builds. Set to `true` to enable source maps in production.
351
+ *
352
+ * @link https://seek-oss.github.io/sku/#/./docs/configuration?id=sourcemapsprod
353
+ */
354
+ sourceMapsProd?: boolean;
355
+
356
+ /**
357
+ * An array of directories holding your apps source code.
358
+ * By default, sku expects your source code to be in a directory named `src` in the root of your project.
359
+ *
360
+ * Use this option if your source code needs to be arranged differently.
361
+ *
362
+ * @default ['./src']
363
+ * @link https://seek-oss.github.io/sku/#/./docs/configuration?id=srcpaths
364
+ */
365
+ srcPaths?: string[];
366
+
367
+ /**
368
+ * An array of storybook addons to use.
369
+ *
370
+ * @default []
371
+ * @link https://seek-oss.github.io/sku/#/./docs/configuration?id=storybookaddons
372
+ */
373
+ storybookAddons?: string[];
374
+
375
+ /**
376
+ * The port to host storybook on when running `sku storybook`.
377
+ *
378
+ * @default 8081
379
+ * @link https://seek-oss.github.io/sku/#/./docs/configuration?id=storybookport
380
+ */
381
+ storybookPort?: number;
382
+
383
+ /**
384
+ * The directory `sku build-storybook` will output files to.
385
+ *
386
+ * @default 'dist-storybook'
387
+ * @link https://seek-oss.github.io/sku/#/./docs/configuration?id=storybooktarget
388
+ */
389
+ storybookTarget?: string;
390
+
391
+ /**
392
+ * The `browserslist` query describing the apps browser support policy.
393
+ *
394
+ * @default browserslist-config-seek
395
+ * @link https://seek-oss.github.io/sku/#/./docs/configuration?id=supportedbrowsers
396
+ */
397
+ supportedBrowsers?: string[];
398
+
399
+ /**
400
+ * The directory to build your assets into when running `sku build` or `sku build-ssr`.
401
+ *
402
+ * @default 'dist'
403
+ * @link https://seek-oss.github.io/sku/#/./docs/configuration?id=target
404
+ */
405
+ target?: string;
406
+
407
+ /**
408
+ * **Only for static apps**
409
+ *
410
+ * This function returns the output path within {@link target} for each rendered page. Generally, this value should be sufficient.
411
+ *
412
+ * If you think you need to modify this setting, please reach out to the `sku-support` group first to discuss.
413
+ *
414
+ * @link https://seek-oss.github.io/sku/#/./docs/configuration?id=transformoutputpath
415
+ */
416
+ transformOutputPath?: TranformOutputPathFunction;
417
+ }
@@ -1,7 +1,11 @@
1
- module.exports = {
1
+ import type { SkuConfig } from 'sku';
2
+
3
+ const skuConfig: SkuConfig = {
2
4
  clientEntry: 'src/client.tsx',
3
5
  renderEntry: 'src/render.tsx',
4
6
  environments: ['development', 'production'],
5
7
  publicPath: '/path/to/public/assets/', // <-- Required for sku build output
6
8
  orderImports: true
7
9
  };
10
+
11
+ export default skuConfig;
@@ -22,7 +22,7 @@ const skuRender: Render<RenderContext> = {
22
22
  };
23
23
  },
24
24
 
25
- provideClientContext: ({ environment }): ClientContext => ({
25
+ provideClientContext: ({ environment }) => ({
26
26
  environment
27
27
  }),
28
28
 
@@ -1,16 +0,0 @@
1
- const glob = require('fast-glob');
2
- const { cwd } = require('./cwd');
3
- const debug = require('debug')('sku:isTypeScript');
4
-
5
- const tsFiles = glob.sync(['**/*.{ts,tsx}', '!**/node_modules/**'], {
6
- cwd: cwd(),
7
- });
8
- const isTypeScript = tsFiles.length > 0;
9
-
10
- if (isTypeScript) {
11
- debug(
12
- `Found TypeScript in project. Found ${tsFiles.length} with the first at "${tsFiles[0]}".`,
13
- );
14
- }
15
-
16
- module.exports = isTypeScript;