@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
@@ -0,0 +1,282 @@
1
+ "use strict";
2
+
3
+ var _fsExtra = require("fs-extra");
4
+ var _path = _interopRequireDefault(require("path"));
5
+ var _os = _interopRequireDefault(require("os"));
6
+ var scriptUtils = _interopRequireWildcard(require("./script-utils"));
7
+ function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
8
+ function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
9
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
10
+ function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
11
+ function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }
12
+ function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
13
+ function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return typeof key === "symbol" ? key : String(key); }
14
+ function _toPrimitive(input, hint) { if (typeof input !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (typeof res !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); }
15
+ function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { Promise.resolve(value).then(_next, _throw); } }
16
+ function _asyncToGenerator(fn) { return function () { var self = this, args = arguments; return new Promise(function (resolve, reject) { var gen = fn.apply(self, args); function _next(value) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value); } function _throw(err) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err); } _next(undefined); }); }; } /*
17
+ * Copyright (c) 2021, salesforce.com, inc.
18
+ * All rights reserved.
19
+ * SPDX-License-Identifier: BSD-3-Clause
20
+ * For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/BSD-3-Clause
21
+ */
22
+ const pkg = (0, _fsExtra.readJsonSync)(_path.default.join(__dirname, '../package.json'));
23
+ describe('scriptUtils', () => {
24
+ const originalEnv = process.env;
25
+ let tmpDir;
26
+ beforeEach( /*#__PURE__*/_asyncToGenerator(function* () {
27
+ process.env = _objectSpread({}, originalEnv);
28
+ tmpDir = yield (0, _fsExtra.mkdtemp)(_path.default.join(_os.default.tmpdir(), 'scriptUtils-tests'));
29
+ }));
30
+ afterEach( /*#__PURE__*/_asyncToGenerator(function* () {
31
+ process.env = originalEnv;
32
+ tmpDir && (yield (0, _fsExtra.rm)(tmpDir, {
33
+ recursive: true
34
+ }));
35
+ }));
36
+ test('glob() with no patterns matches nothing', () => {
37
+ const matcher = scriptUtils.glob();
38
+ expect(matcher('')).toBe(false);
39
+ expect(matcher('a.js')).toBe(false);
40
+ expect(matcher()).toBe(false);
41
+ });
42
+ describe('glob() filters correctly', () => {
43
+ const patterns = ['ssr.js', '**/*.jpg', '!**/no.jpg', 'abc.{js,jsx}'];
44
+ const matcher = scriptUtils.glob(patterns);
45
+
46
+ // Paths we expect to match
47
+ const expectToMatch = ['ssr.js', 'test1.jpg', 'static/test2.jpg', 'static/assets/test3.jpg', 'abc.js', 'abc.jsx'];
48
+ expectToMatch.forEach(path => test(`Expect path "${path}" to match`, () => {
49
+ expect(matcher(path)).toBe(true);
50
+ }));
51
+
52
+ // Paths we expect not to match
53
+ const expectNotToMatch = ['ssrxjs', 'subdirectory/ssr.js', 'no.jpg', 'static/no.jpg', 'abc.jsz'];
54
+ expectNotToMatch.forEach(path => test(`Expect path "${path}" to NOT match`, () => {
55
+ expect(matcher(path)).toBe(false);
56
+ }));
57
+ const allPaths = expectToMatch.concat(expectNotToMatch);
58
+ test('glob works with Array.filter', () => {
59
+ const matched = allPaths.filter(matcher);
60
+ expect(matched).toHaveLength(expectToMatch.length);
61
+ });
62
+ });
63
+ describe('CloudAPIClient', () => {
64
+ const username = 'user123';
65
+ const api_key = '123';
66
+ const encoded = Buffer.from(`${username}:${api_key}`, 'binary').toString('base64');
67
+ const expectedAuthHeader = {
68
+ Authorization: `Basic ${encoded}`
69
+ };
70
+ test('getAuthHeader', /*#__PURE__*/_asyncToGenerator(function* () {
71
+ const client = new scriptUtils.CloudAPIClient({
72
+ credentials: {
73
+ username,
74
+ api_key
75
+ }
76
+ });
77
+ expect(client.getAuthHeader()).toEqual(expectedAuthHeader);
78
+ }));
79
+ test('getHeaders', /*#__PURE__*/_asyncToGenerator(function* () {
80
+ const client = new scriptUtils.CloudAPIClient({
81
+ credentials: {
82
+ username,
83
+ api_key
84
+ }
85
+ });
86
+ expect(yield client.getHeaders()).toEqual(_objectSpread({
87
+ 'User-Agent': `${pkg.name}@${pkg.version}`
88
+ }, expectedAuthHeader));
89
+ }));
90
+ });
91
+ test('getPkgJSON', /*#__PURE__*/_asyncToGenerator(function* () {
92
+ const pkg = yield scriptUtils.getPkgJSON();
93
+ expect(pkg.name).toBe('@salesforce/pwa-kit-dev');
94
+ }));
95
+ describe('defaultMessage', () => {
96
+ test('works', /*#__PURE__*/_asyncToGenerator(function* () {
97
+ const mockGit = {
98
+ branch: () => 'branch',
99
+ short: () => 'short'
100
+ };
101
+ expect(scriptUtils.defaultMessage(mockGit)).toBe('branch: short');
102
+ }));
103
+ test('works outside of a git repo', /*#__PURE__*/_asyncToGenerator(function* () {
104
+ const mockGit = {
105
+ branch: () => {
106
+ throw {
107
+ code: 'ENOENT'
108
+ };
109
+ },
110
+ short: () => 'short'
111
+ };
112
+ expect(scriptUtils.defaultMessage(mockGit)).toBe('PWA Kit Bundle');
113
+ }));
114
+ test('works with any other error', /*#__PURE__*/_asyncToGenerator(function* () {
115
+ const mockGit = {
116
+ branch: () => {
117
+ throw new Error();
118
+ },
119
+ short: () => 'short'
120
+ };
121
+ expect(scriptUtils.defaultMessage(mockGit)).toBe('PWA Kit Bundle');
122
+ }));
123
+ });
124
+ test('getCredentialsFile', /*#__PURE__*/_asyncToGenerator(function* () {
125
+ expect(scriptUtils.getCredentialsFile('https://example.com', '/path/to/.mobify')).toBe('/path/to/.mobify');
126
+ expect(scriptUtils.getCredentialsFile('https://example.com', undefined)).toBe(_path.default.join(_os.default.homedir(), '.mobify--example.com'));
127
+ expect(scriptUtils.getCredentialsFile('https://cloud.mobify.com', undefined)).toBe(_path.default.join(_os.default.homedir(), '.mobify'));
128
+ }));
129
+ describe('readCredentials', () => {
130
+ test('should work', /*#__PURE__*/_asyncToGenerator(function* () {
131
+ const creds = {
132
+ username: 'alice',
133
+ api_key: 'xyz'
134
+ };
135
+ const thePath = _path.default.join(tmpDir, '.mobify.test');
136
+ yield (0, _fsExtra.writeFile)(thePath, JSON.stringify(creds), 'utf8');
137
+ expect(yield scriptUtils.readCredentials(thePath)).toEqual(creds);
138
+ }));
139
+ test('should throw', /*#__PURE__*/_asyncToGenerator(function* () {
140
+ const thePath = _path.default.join(tmpDir, '.mobify.test');
141
+ yield expect( /*#__PURE__*/_asyncToGenerator(function* () {
142
+ return yield scriptUtils.readCredentials(thePath);
143
+ })).rejects.toThrow(Error);
144
+ }));
145
+ });
146
+ describe('createBundle', () => {
147
+ test('should throw if ssr_only and ssr_shared is empty', /*#__PURE__*/_asyncToGenerator(function* () {
148
+ yield expect( /*#__PURE__*/_asyncToGenerator(function* () {
149
+ return yield scriptUtils.createBundle({
150
+ message: null,
151
+ ssr_parameters: {},
152
+ ssr_only: [],
153
+ ssr_shared: [],
154
+ buildDirectory: tmpDir,
155
+ projectSlug: 'slug'
156
+ });
157
+ })).rejects.toThrow('no ssrOnly or ssrShared files are defined');
158
+ }));
159
+ test('should throw buildDir does not exist', /*#__PURE__*/_asyncToGenerator(function* () {
160
+ yield expect( /*#__PURE__*/_asyncToGenerator(function* () {
161
+ return yield scriptUtils.createBundle({
162
+ message: null,
163
+ ssr_parameters: {},
164
+ ssr_only: ['*.js'],
165
+ ssr_shared: ['*.js'],
166
+ buildDirectory: _path.default.join(tmpDir, 'does-not-exist'),
167
+ projectSlug: 'slug'
168
+ });
169
+ })).rejects.toThrow('Build directory at path');
170
+ }));
171
+ test('should archive a bundle', /*#__PURE__*/_asyncToGenerator(function* () {
172
+ const message = 'message';
173
+ const bundle = yield scriptUtils.createBundle({
174
+ message,
175
+ ssr_parameters: {},
176
+ ssr_only: ['*.js'],
177
+ ssr_shared: ['**/*.*'],
178
+ buildDirectory: _path.default.join(__dirname, 'test-fixtures', 'minimal-built-app'),
179
+ projectSlug: 'slug'
180
+ });
181
+ expect(bundle.message).toEqual(message);
182
+ expect(bundle.encoding).toBe('base64');
183
+ expect(bundle.ssr_parameters).toEqual({});
184
+ expect(bundle.ssr_only).toEqual(['ssr.js']);
185
+ expect(bundle.ssr_shared).toEqual(['ssr.js', 'static/favicon.ico']);
186
+
187
+ // De-code and re-encode gives the same result, to show that it *is* b64 encoded
188
+ expect(Buffer.from(bundle.data, 'base64').toString('base64')).toEqual(bundle.data);
189
+ }));
190
+ });
191
+ describe('pushBundle', () => {
192
+ test.each([[{
193
+ projectSlug: 'project-slug',
194
+ targetSlug: undefined,
195
+ expectedURL: 'https://cloud.mobify.com/api/projects/project-slug/builds/',
196
+ status: 200
197
+ }], [{
198
+ projectSlug: 'project-slug',
199
+ targetSlug: 'target-slug',
200
+ expectedURL: 'https://cloud.mobify.com/api/projects/project-slug/builds/target-slug/',
201
+ status: 200
202
+ }], [{
203
+ projectSlug: 'project-slug',
204
+ targetSlug: undefined,
205
+ expectedURL: 'https://cloud.mobify.com/api/projects/project-slug/builds/',
206
+ status: 401
207
+ }]])('should push a built bundle and handle status codes (%p)', /*#__PURE__*/function () {
208
+ var _ref18 = _asyncToGenerator(function* ({
209
+ projectSlug,
210
+ targetSlug,
211
+ expectedURL,
212
+ status
213
+ }) {
214
+ const message = 'message';
215
+ const bundle = yield scriptUtils.createBundle({
216
+ message,
217
+ ssr_parameters: {},
218
+ ssr_only: ['*.js'],
219
+ ssr_shared: ['**/*.*'],
220
+ buildDirectory: _path.default.join(__dirname, 'test-fixtures', 'minimal-built-app'),
221
+ projectSlug
222
+ });
223
+ const username = 'user123';
224
+ const api_key = '123';
225
+ const credentials = {
226
+ username,
227
+ api_key
228
+ };
229
+ const goodResponseBody = {
230
+ anything: 'anything'
231
+ };
232
+
233
+ // Older APIs on Cloud return JSON for good responses and text for errors,
234
+ // hence the strange looking mock response setup.
235
+ const text = () => status === 200 ? Promise.resolve(JSON.stringify(goodResponseBody)) : Promise.resolve('An error occurred');
236
+ const json = () => status === 200 ? Promise.resolve(goodResponseBody) : Promise.reject();
237
+ const responseMock = {
238
+ status,
239
+ text,
240
+ json
241
+ };
242
+ const fetchMock = jest.fn( /*#__PURE__*/_asyncToGenerator(function* () {
243
+ return responseMock;
244
+ }));
245
+ const client = new scriptUtils.CloudAPIClient({
246
+ credentials,
247
+ fetch: fetchMock
248
+ });
249
+ const fn = /*#__PURE__*/function () {
250
+ var _ref20 = _asyncToGenerator(function* () {
251
+ return yield client.push(bundle, projectSlug, targetSlug);
252
+ });
253
+ return function fn() {
254
+ return _ref20.apply(this, arguments);
255
+ };
256
+ }();
257
+
258
+ // TODO: Split up this batch of tests to avoid conditional assertions
259
+ if (status === 200) {
260
+ // eslint-disable-next-line jest/no-conditional-expect
261
+ expect(yield fn()).toBe(goodResponseBody);
262
+ } else {
263
+ // eslint-disable-next-line jest/no-conditional-expect
264
+ yield expect(fn).rejects.toThrow('For more information visit');
265
+ }
266
+ expect(fetchMock).toHaveBeenCalledTimes(1);
267
+ expect(fetchMock).toHaveBeenCalledWith(expectedURL, expect.objectContaining({
268
+ body: expect.anything(Buffer),
269
+ method: 'POST',
270
+ headers: {
271
+ Authorization: expect.stringMatching(/^Basic /),
272
+ 'Content-Length': expect.stringMatching(/^\d+$/),
273
+ 'User-Agent': `${pkg.name}@${pkg.version}`
274
+ }
275
+ }));
276
+ });
277
+ return function (_x) {
278
+ return _ref18.apply(this, arguments);
279
+ };
280
+ }());
281
+ });
282
+ });
@@ -0,0 +1,9 @@
1
+ /*
2
+ * Copyright (c) 2021, Salesforce, Inc.
3
+ * All rights reserved.
4
+ * SPDX-License-Identifier: BSD-3-Clause
5
+ * For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/BSD-3-Clause
6
+ */
7
+
8
+ // This file needs to exist as a text fixture, but doesn't need content!
9
+ "use strict";