@salesforce/pwa-kit-dev 3.0.0-preview.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. package/LICENSE +14 -0
  2. package/README.md +35 -0
  3. package/bin/pwa-kit-dev.js +461 -0
  4. package/configs/babel/babel-config.js +34 -0
  5. package/configs/eslint/README.md +21 -0
  6. package/configs/eslint/eslint-config.js +11 -0
  7. package/configs/eslint/index.js +11 -0
  8. package/configs/eslint/no-react.js +18 -0
  9. package/configs/eslint/partials/base.js +38 -0
  10. package/configs/eslint/partials/jest.js +24 -0
  11. package/configs/eslint/partials/react.js +29 -0
  12. package/configs/eslint/partials/typescript-permit-any.js +31 -0
  13. package/configs/eslint/partials/typescript.js +17 -0
  14. package/configs/eslint/recommended.js +20 -0
  15. package/configs/eslint/safe-types.js +20 -0
  16. package/configs/jest/jest-babel-transform.js +19 -0
  17. package/configs/jest/jest.config.js +33 -0
  18. package/configs/jest/mocks/fileMock.js +9 -0
  19. package/configs/jest/mocks/styleMock.js +9 -0
  20. package/configs/jest/mocks/svgMock.js +11 -0
  21. package/configs/webpack/config-names.js +24 -0
  22. package/configs/webpack/config.js +425 -0
  23. package/configs/webpack/overrides-plugin.js +120 -0
  24. package/configs/webpack/plugins.js +92 -0
  25. package/package.json +150 -0
  26. package/scripts/version.js +22 -0
  27. package/ssr/server/build-dev-server.js +443 -0
  28. package/ssr/server/build-dev-server.test.js +635 -0
  29. package/ssr/server/loading-screen/css/main.css +272 -0
  30. package/ssr/server/loading-screen/css/normalize.css +349 -0
  31. package/ssr/server/loading-screen/img/cloud-1.svg +1 -0
  32. package/ssr/server/loading-screen/img/cloud-2.svg +1 -0
  33. package/ssr/server/loading-screen/img/cloud-3.svg +1 -0
  34. package/ssr/server/loading-screen/img/cloud.svg +1 -0
  35. package/ssr/server/loading-screen/img/codey-arm.svg +1 -0
  36. package/ssr/server/loading-screen/img/codey-bear.svg +1 -0
  37. package/ssr/server/loading-screen/img/codey-bg.svg +1 -0
  38. package/ssr/server/loading-screen/img/codey-cloud.svg +1 -0
  39. package/ssr/server/loading-screen/img/codey-search.svg +1 -0
  40. package/ssr/server/loading-screen/img/codey.svg +1 -0
  41. package/ssr/server/loading-screen/img/codeyCarry.svg +1 -0
  42. package/ssr/server/loading-screen/img/devDocumentation.svg +1 -0
  43. package/ssr/server/loading-screen/img/devGithub.svg +1 -0
  44. package/ssr/server/loading-screen/img/devTrailhead.svg +1 -0
  45. package/ssr/server/loading-screen/img/logo.svg +1 -0
  46. package/ssr/server/loading-screen/img/slds_spinner_brand_9EA9F1.gif +0 -0
  47. package/ssr/server/loading-screen/index.html +130 -0
  48. package/ssr/server/test_fixtures/app/main.js +6 -0
  49. package/ssr/server/test_fixtures/app/static/favicon.ico +0 -0
  50. package/ssr/server/test_fixtures/localhost.pem +45 -0
  51. package/utils/script-utils.js +312 -0
  52. package/utils/script-utils.test.js +282 -0
  53. package/utils/test-fixtures/minimal-built-app/ssr.js +9 -0
  54. package/utils/test-fixtures/minimal-built-app/static/favicon.ico +0 -0
package/LICENSE ADDED
@@ -0,0 +1,14 @@
1
+ BSD 3-Clause License
2
+
3
+ Copyright (c) 2021, Salesforce.com, Inc.
4
+ All rights reserved.
5
+
6
+ Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
7
+
8
+ 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
9
+
10
+ 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
11
+
12
+ 3. Neither the name of Salesforce.com nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
13
+
14
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
package/README.md ADDED
@@ -0,0 +1,35 @@
1
+ # PWA Kit Developer Tools
2
+
3
+ A command-line tool to develop, build, and deploy PWA Kit projects.
4
+
5
+ ## Requirements
6
+
7
+ - Node 16.11 or later
8
+ - npm 8 or later
9
+
10
+ To see all the available commands, run:
11
+
12
+ ```bash
13
+ npx @salesforce/pwa-kit-dev --help
14
+ ```
15
+
16
+ ## Documentation
17
+
18
+ The full documentation for PWA Kit and Managed Runtime is hosted on the [Salesforce Developers](https://developer.salesforce.com/docs/commerce/pwa-kit-managed-runtime/overview) portal.
19
+
20
+ ### Useful links:
21
+
22
+ - [Get Started](https://developer.salesforce.com/docs/commerce/pwa-kit-managed-runtime/guide/getting-started.html)
23
+ - [Skills for Success](https://developer.salesforce.com/docs/commerce/pwa-kit-managed-runtime/guide/skills-for-success.html)
24
+ - [Set Up API Access](https://developer.salesforce.com/docs/commerce/pwa-kit-managed-runtime/guide/setting-up-api-access.html)
25
+ - [Configuration Options](https://developer.salesforce.com/docs/commerce/pwa-kit-managed-runtime/guide/configuration-options.html)
26
+ - [Proxy Requests](https://developer.salesforce.com/docs/commerce/pwa-kit-managed-runtime/guide/proxying-requests.html)
27
+ - [Push and Deploy Bundles](https://developer.salesforce.com/docs/commerce/pwa-kit-managed-runtime/guide/pushing-and-deploying-bundles.html)
28
+ - [The Retail React App](https://developer.salesforce.com/docs/commerce/pwa-kit-managed-runtime/guide/retail-react-app.html)
29
+ - [Rendering](https://developer.salesforce.com/docs/commerce/pwa-kit-managed-runtime/guide/rendering.html)
30
+ - [Routing](https://developer.salesforce.com/docs/commerce/pwa-kit-managed-runtime/guide/routing.html)
31
+ - [Phased Headless Rollouts](https://developer.salesforce.com/docs/commerce/pwa-kit-managed-runtime/guide/phased-headless-rollouts.html)
32
+ - [Launch Your Storefront](https://developer.salesforce.com/docs/commerce/pwa-kit-managed-runtime/guide/launching-your-storefront.html)
33
+
34
+ ## Support Policy
35
+ Security patches are provided for 24 months after the general availability of each major version of the SDK (1.0, 2.0, and so on).
@@ -0,0 +1,461 @@
1
+ #!/usr/bin/env node
2
+ /*
3
+ * Copyright (c) 2023, Salesforce, Inc.
4
+ * All rights reserved.
5
+ * SPDX-License-Identifier: BSD-3-Clause
6
+ * For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/BSD-3-Clause
7
+ */
8
+ /* eslint-disable @typescript-eslint/no-var-requires */
9
+ const chalk = require('chalk')
10
+ const p = require('path')
11
+ const fse = require('fs-extra')
12
+ const WebSocket = require('ws')
13
+ const program = require('commander')
14
+ const validator = require('validator')
15
+ const {execSync: _execSync} = require('child_process')
16
+ const projectPkg = require(process.cwd() + '/package.json')
17
+ const {getConfig} = require('@salesforce/pwa-kit-runtime/utils/ssr-config')
18
+
19
+ // Scripts in ./bin have never gone through babel, so we
20
+ // don't have a good pattern for mixing compiled/un-compiled
21
+ // code.
22
+ //
23
+ // This conditional import lets us gradually migrate portions
24
+ // of this script to Typescript, until internal-lib-build
25
+ // has a decent pattern for ./bin scripts!
26
+ const scriptUtils = (() => {
27
+ try {
28
+ return require('../dist/utils/script-utils')
29
+ } catch {
30
+ return require('../utils/script-utils')
31
+ }
32
+ })()
33
+
34
+ const colors = {
35
+ warn: 'yellow',
36
+ error: 'red',
37
+ success: 'cyan'
38
+ }
39
+
40
+ const fancyLog = (level, msg) => {
41
+ const color = colors[level] || 'green'
42
+ const colorFn = chalk[color]
43
+ console.log(`${colorFn(level)}: ${msg}`)
44
+ }
45
+ const info = (msg) => fancyLog('info', msg)
46
+ const success = (msg) => fancyLog('success', msg)
47
+ const warn = (msg) => fancyLog('warn', msg)
48
+ const error = (msg) => fancyLog('error', msg)
49
+
50
+ const execSync = (cmd, opts) => {
51
+ const defaults = {stdio: 'inherit'}
52
+ return _execSync(cmd, {...defaults, ...opts})
53
+ }
54
+
55
+ const getProjectName = async () => {
56
+ const projectPkg = await scriptUtils.getProjectPkg()
57
+ if (!projectPkg.name) {
58
+ throw new Error(`Missing "name" field in "package.json"`)
59
+ }
60
+ return projectPkg.name
61
+ }
62
+
63
+ const main = async () => {
64
+ const pkgRoot = p.join(__dirname, '..')
65
+ process.env.CONTEXT = process.cwd()
66
+
67
+ program.description(
68
+ [
69
+ `PWA Kit Dev`,
70
+ ``,
71
+ `For more information run a command with the --help flag, eg.`,
72
+ ``,
73
+ ` $ pwa-kit-dev push --help`
74
+ ].join('\n')
75
+ )
76
+
77
+ program.addHelpText(
78
+ 'after',
79
+ [
80
+ ``,
81
+ `Usage inside NPM scripts:`,
82
+ ``,
83
+ ` The PWA Kit Developer Tools are used in NPM scripts so you can conveniently`,
84
+ ` run eg. 'npm run push' to push a bundle from a project.`,
85
+ ``,
86
+ ` To pass args to pwa-kit-dev when wrapped in an NPM script, separate them`,
87
+ ` with '--' so they aren't parsed by NPM itself, eg:`,
88
+ ``,
89
+ ` $ pwa-kit-dev push --target production`,
90
+ ``,
91
+ ` Would become this, when used in an NPM script:`,
92
+ ``,
93
+ ` $ npm run push -- --target production`,
94
+ ``,
95
+ ` See https://docs.npmjs.com/cli/v8/commands/npm-run-script`,
96
+ ``
97
+ ].join('\n')
98
+ )
99
+
100
+ /**
101
+ * Return a platform-specific representation of the default credentials
102
+ * location *for documentation purposes only*.
103
+ *
104
+ * It's easier to recognize the intention behind `(default "~/.mobify")` in
105
+ * docs than it is `(default "/Users/xyz/.mobify")`. In the second case,
106
+ * you have to actually remember that this is your home dir!
107
+ */
108
+ const credentialsLocationDisplay = () => {
109
+ const dir = process.platform === 'win32' ? '%USERPROFILE%' : '~'
110
+ return p.join(dir, '.mobify')
111
+ }
112
+
113
+ /**
114
+ * All Managed Runtime commands take common opts like --cloud-origin
115
+ * and --credentialsFile. These are set to be split out from the SDK
116
+ * commands here in the near future.
117
+ */
118
+ const managedRuntimeCommand = (name) => {
119
+ return program
120
+ .command(name)
121
+ .addOption(
122
+ new program.Option('--cloud-origin <origin>', 'the API origin to connect to')
123
+ .default(scriptUtils.DEFAULT_CLOUD_ORIGIN)
124
+ .env('CLOUD_API_BASE')
125
+ )
126
+ .addOption(
127
+ new program.Option(
128
+ '-c, --credentialsFile <credentialsFile>',
129
+ `override the standard credentials file location "${credentialsLocationDisplay()}"`
130
+ )
131
+ // Must default to undefined in order to trigger automatic-lookup
132
+ // of a credentials file, based on --cloud-origin.
133
+ .default(undefined)
134
+ .env('PWA_KIT_CREDENTIALS_FILE')
135
+ )
136
+ .hook('preAction', (thisCommand, actionCommand) => {
137
+ // The final credentialsFile path depends on both cloudOrigin and credentialsFile opts.
138
+ // Pre-process before passing to the command.
139
+ const {cloudOrigin, credentialsFile} = actionCommand.opts()
140
+ actionCommand.setOptionValue(
141
+ 'credentialsFile',
142
+ scriptUtils.getCredentialsFile(cloudOrigin, credentialsFile)
143
+ )
144
+ })
145
+ }
146
+
147
+ managedRuntimeCommand('save-credentials')
148
+ .description(`save API credentials for Managed Runtime`)
149
+ .requiredOption(
150
+ '-u, --user <email>',
151
+ 'the e-mail address you used to register with Managed Runtime',
152
+ (val) => {
153
+ if (!validator.isEmail(val)) {
154
+ throw new program.InvalidArgumentError(`"${val}" is not a valid email`)
155
+ } else {
156
+ return val
157
+ }
158
+ }
159
+ )
160
+ .requiredOption(
161
+ '-k, --key <api-key>',
162
+ `find your API key at https://runtime.commercecloud.com/account/settings`,
163
+ (val) => {
164
+ if (typeof val !== 'string' || val === '') {
165
+ throw new program.InvalidArgumentError(`"api-key" cannot be empty`)
166
+ } else {
167
+ return val
168
+ }
169
+ }
170
+ )
171
+ .action(async ({user, key, credentialsFile}) => {
172
+ try {
173
+ fse.writeJson(credentialsFile, {username: user, api_key: key}, {spaces: 4})
174
+ success(`Saved Managed Runtime credentials to "${chalk.cyan(credentialsFile)}".`)
175
+ } catch (e) {
176
+ error('Failed to save credentials.')
177
+ throw e
178
+ }
179
+ })
180
+
181
+ const appSSRpath = p.join(process.cwd(), 'app', 'ssr.js')
182
+ const appSSRjs = fse.pathExistsSync(appSSRpath)
183
+ const overrideSSRpath = p.join(
184
+ process.cwd(),
185
+ typeof projectPkg?.ccExtensibility?.overridesDir === 'string' &&
186
+ !projectPkg?.ccExtensibility?.overridesDir?.startsWith(p.sep)
187
+ ? p.sep + projectPkg?.ccExtensibility?.overridesDir
188
+ : projectPkg?.ccExtensibility?.overridesDir ?? '',
189
+ 'app',
190
+ 'ssr.js'
191
+ )
192
+ const overrideSSRjs = fse.pathExistsSync(overrideSSRpath)
193
+ const resolvedSSRPath = appSSRjs ? appSSRpath : overrideSSRjs ? overrideSSRpath : null
194
+
195
+ program
196
+ .command('start')
197
+ .description(`develop your app locally`)
198
+ .addOption(
199
+ new program.Option('--inspect', 'enable debugging with --inspect on the node process')
200
+ )
201
+ .addOption(new program.Option('--noHMR', 'disable the client-side hot module replacement'))
202
+ .action(async ({inspect, noHMR}) => {
203
+ execSync(`node${inspect ? ' --inspect' : ''} ${resolvedSSRPath}`, {
204
+ env: {
205
+ ...process.env,
206
+ ...(noHMR ? {HMR: 'false'} : {})
207
+ }
208
+ })
209
+ })
210
+
211
+ program
212
+ .command('build')
213
+ .addOption(
214
+ new program.Option(
215
+ '-b, --buildDirectory <buildDirectory>',
216
+ 'the directory where your project should be built'
217
+ )
218
+ .default(p.join(process.cwd(), 'build'), './build')
219
+ .env('PWA_KIT_BUILD_DIR')
220
+ )
221
+ .description(`build your app for production`)
222
+ .action(async ({buildDirectory}) => {
223
+ const webpack = p.join(require.resolve('webpack'), '..', '..', '..', '.bin', 'webpack')
224
+ const projectWebpack = p.join(process.cwd(), 'webpack.config.js')
225
+ const webpackConf = fse.pathExistsSync(projectWebpack)
226
+ ? projectWebpack
227
+ : p.join(__dirname, '..', 'configs', 'webpack', 'config.js')
228
+ fse.emptyDirSync(buildDirectory)
229
+ execSync(`${webpack} --config ${webpackConf}`, {
230
+ env: {
231
+ NODE_ENV: 'production',
232
+ ...process.env,
233
+ // Command option overrides the env var, so we must continue that pattern
234
+ PWA_KIT_BUILD_DIR: buildDirectory
235
+ }
236
+ })
237
+
238
+ // Copy the project `package.json` into the build folder.
239
+ fse.copyFileSync('package.json', p.join(buildDirectory, 'package.json'))
240
+
241
+ // Copy config files.
242
+ const config = p.resolve('config')
243
+ if (fse.pathExistsSync(config)) {
244
+ fse.copySync(
245
+ config,
246
+ p.join(buildDirectory, 'config'),
247
+ (file) => !p.basename(file).startsWith('local.')
248
+ )
249
+ }
250
+
251
+ const loader = p.join(buildDirectory, 'loader.js')
252
+ if (!fse.pathExistsSync(loader)) {
253
+ fse.outputFileSync(
254
+ loader,
255
+ '// This file is required by Managed Runtime for historical reasons.\n'
256
+ )
257
+ }
258
+ })
259
+
260
+ managedRuntimeCommand('push')
261
+ .description(`push a bundle to Managed Runtime`)
262
+ .addOption(
263
+ new program.Option(
264
+ '-b, --buildDirectory <buildDirectory>',
265
+ 'a custom project build directory that you want to push'
266
+ ).default(p.join(process.cwd(), 'build'), './build')
267
+ )
268
+ .addOption(
269
+ new program.Option(
270
+ '-m, --message <message>',
271
+ 'a message to include along with the uploaded bundle in Managed Runtime'
272
+ )
273
+ // The default message is loaded dynamically as part of `uploadBundle(...)`
274
+ .default(null, '<git branch>:<git commit hash>')
275
+ )
276
+ .addOption(
277
+ new program.Option(
278
+ '-s, --projectSlug <projectSlug>',
279
+ "a project slug that differs from the name property in your project's package.json"
280
+ )
281
+ // We load the slug from the package.json by default, but we don't want to do that
282
+ // unless we need to, so it is loaded conditionally in the action implementation
283
+ .default(null, "the 'name' key from the package.json")
284
+ )
285
+ .addOption(
286
+ new program.Option(
287
+ '-t, --target <target>',
288
+ 'immediately deploy the bundle to this target once it is pushed'
289
+ )
290
+ )
291
+ .action(
292
+ async ({
293
+ buildDirectory,
294
+ message,
295
+ projectSlug,
296
+ target,
297
+ cloudOrigin,
298
+ credentialsFile
299
+ }) => {
300
+ // Set the deployment target env var, this is required to ensure we
301
+ // get the correct configuration object. Do not assign the variable it if
302
+ // the target value is `undefined` as it will serialied as a "undefined"
303
+ // string value.
304
+ if (target) {
305
+ process.env.DEPLOY_TARGET = target
306
+ }
307
+
308
+ const credentials = await scriptUtils.readCredentials(credentialsFile)
309
+
310
+ if (!fse.pathExistsSync(buildDirectory)) {
311
+ throw new Error(`Supplied "buildDirectory" does not exist!`)
312
+ }
313
+
314
+ const mobify = getConfig({buildDirectory}) || {}
315
+
316
+ if (!projectSlug) {
317
+ projectSlug = await getProjectName()
318
+ }
319
+
320
+ const bundle = await scriptUtils.createBundle({
321
+ message,
322
+ ssr_parameters: mobify.ssrParameters,
323
+ ssr_only: mobify.ssrOnly,
324
+ ssr_shared: mobify.ssrShared,
325
+ buildDirectory,
326
+ projectSlug
327
+ })
328
+ const client = new scriptUtils.CloudAPIClient({
329
+ credentials,
330
+ origin: cloudOrigin
331
+ })
332
+
333
+ info(`Beginning upload to ${cloudOrigin}`)
334
+ const data = await client.push(bundle, projectSlug, target)
335
+ const warnings = data.warnings || []
336
+ warnings.forEach(warn)
337
+ success('Bundle Uploaded')
338
+ }
339
+ )
340
+
341
+ program
342
+ .command('lint')
343
+ .description('lint all source files')
344
+ .argument('<path>', 'path or glob to lint')
345
+ .option('--fix', 'Try and fix errors (default: false)')
346
+ .action(async (path, {fix}) => {
347
+ const eslint = p.join(require.resolve('eslint'), '..', '..', '..', '.bin', 'eslint')
348
+ execSync(
349
+ `${eslint} --resolve-plugins-relative-to ${pkgRoot}${fix ? ' --fix' : ''} "${path}"`
350
+ )
351
+ })
352
+
353
+ program
354
+ .command('format')
355
+ .description('automatically re-format all source files')
356
+ .argument('<path>', 'path or glob to format')
357
+ .action(async (path) => {
358
+ const prettier = p.join(require.resolve('prettier'), '..', '..', '.bin', 'prettier')
359
+ execSync(`${prettier} --write "${path}"`)
360
+ })
361
+
362
+ program
363
+ .command('test')
364
+ .description('test the project')
365
+ .action(async (_, {args}) => {
366
+ const jest = p.join(require.resolve('jest'), '..', '..', '..', '.bin', 'jest')
367
+ execSync(
368
+ `${jest} --passWithNoTests --maxWorkers=2${args.length ? ' ' + args.join(' ') : ''}`
369
+ )
370
+ })
371
+
372
+ managedRuntimeCommand('tail-logs')
373
+ .description(`continuously stream environment logs`)
374
+ .addOption(
375
+ new program.Option('-p, --project <projectSlug>', 'the project slug').default(
376
+ null,
377
+ "the 'name' key from package.json"
378
+ )
379
+ )
380
+ .requiredOption('-e, --environment <environmentSlug>', 'the environment slug')
381
+ .action(async ({project, environment, cloudOrigin, credentialsFile}) => {
382
+ if (!project) {
383
+ project = await getProjectName()
384
+ }
385
+
386
+ const credentials = await scriptUtils.readCredentials(credentialsFile)
387
+
388
+ const client = new scriptUtils.CloudAPIClient({
389
+ credentials,
390
+ origin: cloudOrigin
391
+ })
392
+
393
+ const token = await client.createLoggingToken(project, environment)
394
+
395
+ const url = new URL(cloudOrigin.replace('cloud', 'logs'))
396
+ url.protocol = 'wss'
397
+ url.search = new URLSearchParams({
398
+ project,
399
+ environment,
400
+ user: credentials.username,
401
+ access_token: token
402
+ })
403
+
404
+ const ws = new WebSocket(url)
405
+ let heartbeat
406
+
407
+ ws.on('open', () => {
408
+ // Send a heartbeat periodically to bypass idle timeout.
409
+ const idleTimeout = 10 * 60 * 1000
410
+ heartbeat = setInterval(() => ws.ping(), idleTimeout / 2)
411
+ })
412
+
413
+ ws.on('close', (code) => {
414
+ clearInterval(heartbeat)
415
+ console.log('Connection closed with code', code)
416
+ })
417
+
418
+ ws.on('error', (err) => {
419
+ clearInterval(heartbeat)
420
+ error(`Error tailing logs: ${err.message}`)
421
+ throw err
422
+ })
423
+
424
+ ws.on('message', (data) => {
425
+ JSON.parse(data).forEach((log) => {
426
+ const {message, shortRequestId, level} = scriptUtils.parseLog(log.message)
427
+ const color = chalk[colors[level.toLowerCase()] || 'green']
428
+ const paddedLevel = level.padEnd(6)
429
+ console.log(
430
+ chalk.green(new Date(log.timestamp).toISOString()),
431
+ chalk.cyan(shortRequestId),
432
+ ['WARN', 'ERROR'].includes(level)
433
+ ? color.bold(paddedLevel)
434
+ : color(paddedLevel),
435
+ message
436
+ )
437
+ })
438
+ })
439
+ })
440
+
441
+ // Global options
442
+ program.option('-v, --version', 'show version number').action(async ({version}) => {
443
+ if (version) {
444
+ const pkg = await scriptUtils.getPkgJSON()
445
+ console.log(pkg.version)
446
+ } else {
447
+ program.help({error: true})
448
+ }
449
+ })
450
+
451
+ await program.parseAsync(process.argv)
452
+ }
453
+
454
+ Promise.resolve().then(async () => {
455
+ try {
456
+ await main()
457
+ } catch (err) {
458
+ error(err.message || err.toString())
459
+ process.exit(1)
460
+ }
461
+ })
@@ -0,0 +1,34 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = void 0;
7
+ /*
8
+ * Copyright (c) 2021, salesforce.com, inc.
9
+ * All rights reserved.
10
+ * SPDX-License-Identifier: BSD-3-Clause
11
+ * For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/BSD-3-Clause
12
+ */
13
+ const config = {
14
+ sourceType: 'unambiguous',
15
+ presets: [[require('@babel/preset-env'), {
16
+ targets: {
17
+ node: 18
18
+ }
19
+ }], require('@babel/preset-typescript'), require('@babel/preset-react')],
20
+ plugins: [require('@babel/plugin-transform-async-to-generator'), require('@babel/plugin-proposal-object-rest-spread'), require('@babel/plugin-transform-object-assign'), [require('@babel/plugin-transform-runtime'), {
21
+ regenerator: true
22
+ }], require('@babel/plugin-syntax-dynamic-import'), require('@loadable/babel-plugin'), require('@babel/plugin-proposal-optional-chaining'), [require('babel-plugin-formatjs'), {
23
+ idInterpolationPattern: '[sha512:contenthash:base64:6]',
24
+ ast: true
25
+ }]],
26
+ env: {
27
+ test: {
28
+ presets: [require('@babel/preset-env'), require('@babel/preset-react')],
29
+ plugins: [require('babel-plugin-dynamic-import-node-babel-7')]
30
+ }
31
+ }
32
+ };
33
+ var _default = config;
34
+ exports.default = _default;
@@ -0,0 +1,21 @@
1
+ # `pwa-kit-dev` ESLint configuations
2
+
3
+ ## Configs
4
+
5
+ There are three configurations available:
6
+
7
+ * `recommended`: The default expectation for PWA Kit projects. Provides rules for JavaScript, TypeScript, React, and Jest.
8
+ * `no-react`: The `recommended` configuration with React rules removed to avoid logging unnecessary warnings.
9
+ * `safe-types`: The `recommended` configuration with stricter rules in TypeScript files regarding usage of the `any` type.
10
+
11
+ ## Usage
12
+
13
+ Extending a `pwa-kit-dev` ESLint configuration is a little bit from the standard way to extend a file. Because the config is not from a package with a name starting with `eslint-config-`, you must provide the full path to the configuration file using `require.resolve()`. For example, a configuration file that simply extends the `recommended` configuration would look like this:
14
+
15
+ ```js
16
+ module.exports = {
17
+ extends: [require.resolve('@salesforce/pwa-kit-dev/configs/eslint/recommended')]
18
+ }
19
+ ```
20
+
21
+ > **Note:** For convenience, `@salesforce/pwa-kit-dev/configs/eslint` is provided as an alias for the `recommended` configuration.
@@ -0,0 +1,11 @@
1
+ "use strict";
2
+
3
+ /*
4
+ * Copyright (c) 2023, Salesforce, Inc.
5
+ * All rights reserved.
6
+ * SPDX-License-Identifier: BSD-3-Clause
7
+ * For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/BSD-3-Clause
8
+ */
9
+
10
+ /** This is an alias of the default/recommended config, provided for backwards compatibility with v2. */
11
+ module.exports = require('./index');
@@ -0,0 +1,11 @@
1
+ "use strict";
2
+
3
+ /*
4
+ * Copyright (c) 2023, Salesforce, Inc.
5
+ * All rights reserved.
6
+ * SPDX-License-Identifier: BSD-3-Clause
7
+ * For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/BSD-3-Clause
8
+ */
9
+
10
+ // Default config is an alias for 'recommended'
11
+ module.exports = require('./recommended');
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+
3
+ /*
4
+ * Copyright (c) 2023, Salesforce, Inc.
5
+ * All rights reserved.
6
+ * SPDX-License-Identifier: BSD-3-Clause
7
+ * For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/BSD-3-Clause
8
+ */
9
+
10
+ /**
11
+ * Recommended configuration for PWA Kit projects that don't use React.
12
+ * Contains rules for JavaScript, TypeScript, and Jest.
13
+ */
14
+ module.exports = {
15
+ extends: [require.resolve('./partials/base')],
16
+ // TypeScript and Jest rules only apply to specific file paths, so they are overrides.
17
+ overrides: [require('./partials/typescript-permit-any'), require('./partials/jest')]
18
+ };
@@ -0,0 +1,38 @@
1
+ "use strict";
2
+
3
+ /*
4
+ * Copyright (c) 2023, Salesforce, Inc.
5
+ * All rights reserved.
6
+ * SPDX-License-Identifier: BSD-3-Clause
7
+ * For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/BSD-3-Clause
8
+ */
9
+
10
+ /** Base configuration used by all PWA Kit packages. */
11
+ module.exports = {
12
+ parser: '@typescript-eslint/parser',
13
+ parserOptions: {
14
+ ecmaVersion: 2017,
15
+ sourceType: 'module',
16
+ ecmaFeatures: {
17
+ jsx: true
18
+ }
19
+ },
20
+ env: {
21
+ es6: true,
22
+ node: true,
23
+ browser: true
24
+ },
25
+ extends: ['eslint:recommended', 'plugin:@typescript-eslint/recommended', 'plugin:prettier/recommended'],
26
+ plugins: ['@typescript-eslint', 'prettier'],
27
+ reportUnusedDisableDirectives: true,
28
+ rules: {
29
+ // The goal of the no-empty-function rule is to minimize the contextual knowledge required
30
+ // by the reader. The suggested fix for empty functions is to add comments indicating that
31
+ // the empty function is intentional. However, in my opinion, it is clear from context that
32
+ // most of our empty arrow functions are intentional no-ops, so we don't want the rule to be
33
+ // enforced for those.
34
+ '@typescript-eslint/no-empty-function': ['error', {
35
+ allow: ['arrowFunctions']
36
+ }]
37
+ }
38
+ };
@@ -0,0 +1,24 @@
1
+ "use strict";
2
+
3
+ /*
4
+ * Copyright (c) 2023, Salesforce, Inc.
5
+ * All rights reserved.
6
+ * SPDX-License-Identifier: BSD-3-Clause
7
+ * For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/BSD-3-Clause
8
+ */
9
+
10
+ /** Override configuration for Jest files. */
11
+ module.exports = {
12
+ // Jest (v29) default test match pattern
13
+ files: ['**/__tests__/**/*.[jt]s?(x)', '**/?(*.)+(spec|test).[jt]s?(x)'],
14
+ plugins: ['jest'],
15
+ extends: ['plugin:jest/recommended', 'plugin:jest/style'],
16
+ rules: {
17
+ 'jest/expect-expect': ['warn', {
18
+ // Anything starting with `expect` counts as an assertion
19
+ assertFunctionNames: ['expect*', '**.expect*']
20
+ }],
21
+ // This doesn't reliably report errors :(
22
+ 'jest/no-standalone-expect': ['off']
23
+ }
24
+ };