@squiz/component-cli-lib 1.12.0-alpha.21 → 1.12.0-alpha.23

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 (40) hide show
  1. package/.npm/_logs/{2023-02-10T03_34_35_584Z-debug-0.log → 2023-02-10T05_40_20_510Z-debug-0.log} +11 -11
  2. package/build.js +4 -0
  3. package/lib/component-init.d.ts +12 -0
  4. package/lib/component-init.spec.d.ts +1 -0
  5. package/lib/index.d.ts +1 -0
  6. package/lib/index.js +85 -84
  7. package/lib/index.js.map +4 -4
  8. package/lib/templates/advanced/build.js +43 -0
  9. package/lib/templates/advanced/main.js +3 -0
  10. package/lib/templates/advanced/manifest.json +53 -0
  11. package/lib/templates/advanced/package.json +11 -0
  12. package/lib/templates/advanced/previews/example.data.json +1 -0
  13. package/lib/templates/advanced/previews/preview.html +9 -0
  14. package/lib/templates/advanced/static/default.js +1 -0
  15. package/lib/templates/advanced/static/default.scss +1 -0
  16. package/lib/templates/basic/main.js +3 -0
  17. package/lib/templates/basic/manifest.json +53 -0
  18. package/lib/templates/basic/previews/example.data.json +1 -0
  19. package/lib/templates/basic/previews/preview.html +9 -0
  20. package/lib/templates/basic/static/default.css +1 -0
  21. package/lib/templates/basic/static/default.js +1 -0
  22. package/package.json +9 -9
  23. package/src/component-init.spec.ts +203 -0
  24. package/src/component-init.ts +48 -0
  25. package/src/index.ts +1 -0
  26. package/templates/advanced/build.js +43 -0
  27. package/templates/advanced/main.js +3 -0
  28. package/templates/advanced/manifest.json +53 -0
  29. package/templates/advanced/package.json +11 -0
  30. package/templates/advanced/previews/example.data.json +1 -0
  31. package/templates/advanced/previews/preview.html +9 -0
  32. package/templates/advanced/static/default.js +1 -0
  33. package/templates/advanced/static/default.scss +1 -0
  34. package/templates/basic/main.js +3 -0
  35. package/templates/basic/manifest.json +53 -0
  36. package/templates/basic/previews/example.data.json +1 -0
  37. package/templates/basic/previews/preview.html +9 -0
  38. package/templates/basic/static/default.css +1 -0
  39. package/templates/basic/static/default.js +1 -0
  40. package/tsconfig.tsbuildinfo +1 -1
@@ -0,0 +1,43 @@
1
+ // Build process
2
+ const esbuild = require('esbuild');
3
+ const { sassPlugin } = require('esbuild-sass-plugin');
4
+ const postcss = require('postcss');
5
+ const autoprefixer = require('autoprefixer');
6
+
7
+ const esbuildOptions = {
8
+ outdir: 'dist',
9
+ bundle: true,
10
+ minify: false,
11
+ treeShaking: true,
12
+ };
13
+
14
+ // Server build
15
+ esbuild
16
+ .build({
17
+ ...esbuildOptions,
18
+ platform: 'node',
19
+ entryPoints: ['./main.js'],
20
+ format: 'cjs',
21
+ target: 'node16',
22
+ })
23
+ .catch(() => process.exit(1));
24
+
25
+ // Client Build
26
+ esbuild
27
+ .build({
28
+ ...esbuildOptions,
29
+ platform: 'browser',
30
+ entryPoints: ['./static/default.js', './static/default.scss'],
31
+ format: 'esm',
32
+ target: 'es2020',
33
+ plugins: [
34
+ sassPlugin({
35
+ async transform(source) {
36
+ const { css } = await postcss([autoprefixer]).process(source);
37
+ return css;
38
+ },
39
+ }),
40
+ ],
41
+ })
42
+ .then(() => console.log('⚡ Styles & Scripts Compiled! ⚡ '))
43
+ .catch(() => process.exit(1));
@@ -0,0 +1,3 @@
1
+ export default async function (input, info) {
2
+ return `<div>hello world</div>`;
3
+ }
@@ -0,0 +1,53 @@
1
+ {
2
+ "$schema": "http://localhost:3000/schemas/v1.json",
3
+ "name": "default",
4
+ "namespace": "default-namespace",
5
+ "displayName": "Default Component",
6
+ "description": "Default example component",
7
+ "version": "0.0.1",
8
+ "mainFunction": "main",
9
+ "functions": [
10
+ {
11
+ "name": "main",
12
+ "entry": "main.js",
13
+ "input": {},
14
+ "output": {
15
+ "responseType": "html",
16
+ "staticFiles": [
17
+ {
18
+ "location": "header",
19
+ "file": {
20
+ "type": "css",
21
+ "filepath": "default.css"
22
+ }
23
+ },
24
+ {
25
+ "location": "footer",
26
+ "file": {
27
+ "type": "js",
28
+ "filepath": "default.js"
29
+ }
30
+ }
31
+ ]
32
+ }
33
+ }
34
+ ],
35
+ "previews": {
36
+ "default": {
37
+ "functionData": {
38
+ "main": {
39
+ "inputData": {
40
+ "type": "file",
41
+ "path": "previews/example.data.json"
42
+ },
43
+ "wrapper": {
44
+ "path": "previews/preview.html"
45
+ }
46
+ }
47
+ }
48
+ }
49
+ },
50
+ "staticFiles": {
51
+ "locationRoot": "static"
52
+ }
53
+ }
@@ -0,0 +1,11 @@
1
+ {
2
+ "scripts": {
3
+ "build": "node build.js"
4
+ },
5
+ "devDependencies": {
6
+ "autoprefixer": "^10.4.13",
7
+ "esbuild": "^0.17.6",
8
+ "esbuild-sass-plugin": "^2.4.5",
9
+ "postcss": "^8.4.21"
10
+ }
11
+ }
@@ -0,0 +1,9 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en" dir="ltr">
3
+ <head>
4
+ [component://static-header]
5
+ </head>
6
+ <body>
7
+ [component://output] [component://static-footer]
8
+ </body>
9
+ </html>
@@ -0,0 +1 @@
1
+ // Client Side JS goes here
@@ -0,0 +1 @@
1
+ // Client Side CSS goes here
@@ -0,0 +1,3 @@
1
+ module.exports = async function (input, info) {
2
+ return `<div>hello world</div>`;
3
+ };
@@ -0,0 +1,53 @@
1
+ {
2
+ "$schema": "http://localhost:3000/schemas/v1.json",
3
+ "name": "default",
4
+ "namespace": "default-namespace",
5
+ "displayName": "Default Component",
6
+ "description": "Default example component",
7
+ "version": "0.0.1",
8
+ "mainFunction": "main",
9
+ "functions": [
10
+ {
11
+ "name": "main",
12
+ "entry": "main.js",
13
+ "input": {},
14
+ "output": {
15
+ "responseType": "html",
16
+ "staticFiles": [
17
+ {
18
+ "location": "header",
19
+ "file": {
20
+ "type": "css",
21
+ "filepath": "default.css"
22
+ }
23
+ },
24
+ {
25
+ "location": "footer",
26
+ "file": {
27
+ "type": "js",
28
+ "filepath": "default.js"
29
+ }
30
+ }
31
+ ]
32
+ }
33
+ }
34
+ ],
35
+ "previews": {
36
+ "default": {
37
+ "functionData": {
38
+ "main": {
39
+ "inputData": {
40
+ "type": "file",
41
+ "path": "previews/example.data.json"
42
+ },
43
+ "wrapper": {
44
+ "path": "previews/preview.html"
45
+ }
46
+ }
47
+ }
48
+ }
49
+ },
50
+ "staticFiles": {
51
+ "locationRoot": "static"
52
+ }
53
+ }
@@ -0,0 +1,9 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en" dir="ltr">
3
+ <head>
4
+ [component://static-header]
5
+ </head>
6
+ <body>
7
+ [component://output] [component://static-footer]
8
+ </body>
9
+ </html>
@@ -0,0 +1 @@
1
+ /* Client Side CSS goes here */
@@ -0,0 +1 @@
1
+ // Client Side JS goes here
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@squiz/component-cli-lib",
3
- "version": "1.12.0-alpha.21",
3
+ "version": "1.12.0-alpha.23",
4
4
  "description": "",
5
5
  "main": "lib/index.js",
6
6
  "scripts": {
@@ -12,12 +12,12 @@
12
12
  "author": "",
13
13
  "license": "ISC",
14
14
  "devDependencies": {
15
- "@squiz/component-lib": "1.12.0-alpha.21",
16
- "@squiz/component-web-api-lib": "1.12.0-alpha.21",
17
- "@squiz/dx-common-lib": "1.12.0-alpha.21",
18
- "@squiz/dx-json-schema-lib": "1.12.0-alpha.21",
19
- "@squiz/dx-logger-lib": "1.12.0-alpha.21",
20
- "@squiz/virus-scanner-lib": "1.12.0-alpha.21",
15
+ "@squiz/component-lib": "1.12.0-alpha.23",
16
+ "@squiz/component-web-api-lib": "1.12.0-alpha.23",
17
+ "@squiz/dx-common-lib": "1.12.0-alpha.23",
18
+ "@squiz/dx-json-schema-lib": "1.12.0-alpha.23",
19
+ "@squiz/dx-logger-lib": "1.12.0-alpha.23",
20
+ "@squiz/virus-scanner-lib": "1.12.0-alpha.23",
21
21
  "@types/cli-color": "2.0.2",
22
22
  "@types/express": "4.17.17",
23
23
  "@types/jest": "28.1.8",
@@ -31,12 +31,12 @@
31
31
  "typescript": "4.9.4"
32
32
  },
33
33
  "dependencies": {
34
- "@squiz/render-runtime-lib": "1.12.0-alpha.21",
34
+ "@squiz/render-runtime-lib": "1.12.0-alpha.23",
35
35
  "archiver": "5.3.1",
36
36
  "axios": "1.3.2",
37
37
  "cli-color": "^2.0.2",
38
38
  "open": "^8.4.0",
39
39
  "supertest": "^6.2.3"
40
40
  },
41
- "gitHead": "52e0baca629d181674d9dcd5a83087c1f1f0b324"
41
+ "gitHead": "f309b3e8035b08e5c312212c2bf5305e98e480bc"
42
42
  }
@@ -0,0 +1,203 @@
1
+ import componentInit from './component-init';
2
+ import fs from 'fs-extra';
3
+ import * as logger from '@squiz/dx-logger-lib';
4
+ import path from 'path';
5
+
6
+ jest.mock('fs-extra');
7
+ jest.mock('path', () => {
8
+ return {
9
+ ...jest.requireActual('path'),
10
+ };
11
+ });
12
+
13
+ beforeEach(() => {
14
+ jest.resetAllMocks();
15
+
16
+ // Reset our process.env.NODE_ENV variable
17
+ process.env.NODE_ENV = 'test';
18
+ });
19
+
20
+ describe('componentInit', () => {
21
+ it('should setup a new logger instance with the correct options', async () => {
22
+ const loggerSpy = jest.spyOn(logger, 'getLogger');
23
+
24
+ // Mock the process.env.NODE_ENV variable to be "development"
25
+ process.env.NODE_ENV = 'development';
26
+
27
+ await componentInit({
28
+ componentType: 'basic',
29
+ destination: '',
30
+ });
31
+
32
+ expect(loggerSpy).toHaveBeenCalledWith({
33
+ name: 'component-dev',
34
+ format: 'human',
35
+ silent: false,
36
+ });
37
+ });
38
+
39
+ it('path.resolve should be called with __dirname to get the current script directory', async () => {
40
+ const pathResolveSpy = jest.spyOn(path, 'resolve');
41
+
42
+ await componentInit({
43
+ componentType: 'basic',
44
+ destination: '',
45
+ });
46
+
47
+ expect(pathResolveSpy).toHaveBeenCalledWith(__dirname);
48
+ });
49
+
50
+ it('path.join should be called with the current script directory and the component type to get the source folder', async () => {
51
+ const pathJoinSpy = jest.spyOn(path, 'join');
52
+
53
+ jest
54
+ .spyOn(path, 'resolve')
55
+ .mockReturnValue('/Users/username/Projects/squiz/component-cli-lib/packages/component-cli-lib/src');
56
+
57
+ await componentInit({
58
+ componentType: 'basic',
59
+ destination: '',
60
+ });
61
+
62
+ expect(pathJoinSpy).toHaveBeenCalledWith(
63
+ '/Users/username/Projects/squiz/component-cli-lib/packages/component-cli-lib/src',
64
+ 'templates',
65
+ 'basic',
66
+ );
67
+ });
68
+
69
+ it('path.resolve should be called with the destination folder to get the destination folder', async () => {
70
+ const pathResolveSpy = jest.spyOn(path, 'resolve');
71
+
72
+ jest.spyOn(path, 'resolve').mockReturnValue('/Users/username/Projects/squiz/new-component');
73
+
74
+ await componentInit({
75
+ componentType: 'basic',
76
+ destination: '/Users/username/Projects/squiz/new-component',
77
+ });
78
+
79
+ expect(pathResolveSpy).toHaveBeenCalledWith('/Users/username/Projects/squiz/new-component');
80
+ });
81
+
82
+ it('should fail if the destination folder already exists and there are files in it', async () => {
83
+ // Mock the current script directory
84
+ jest.spyOn(path, 'resolve').mockImplementationOnce(() => {
85
+ return '/Users/username/Projects/squiz/component-cli-lib/packages/component-cli-lib/src';
86
+ });
87
+
88
+ // Mock the destination folder
89
+ jest.spyOn(path, 'resolve').mockImplementationOnce(() => {
90
+ return '/Users/username/Projects/squiz/new-component';
91
+ });
92
+
93
+ // Mock the fs.pathExists function to return true
94
+ jest.spyOn(fs, 'pathExists').mockImplementationOnce(() => {
95
+ return Promise.resolve(true);
96
+ });
97
+
98
+ // Mock the fs.readdirSync function to return an array of files
99
+ jest.spyOn(fs, 'readdir').mockImplementationOnce(() => {
100
+ return Promise.resolve(['file1.txt', 'file2.txt']);
101
+ });
102
+
103
+ await expect(
104
+ componentInit({
105
+ componentType: 'basic',
106
+ destination: '/Users/username/Projects/squiz/new-component',
107
+ }),
108
+ ).rejects.toThrowError('The destination folder already exists and is not empty.');
109
+ });
110
+
111
+ it('should create the destination folder if it does not exist', async () => {
112
+ // Mock the current script directory
113
+ jest.spyOn(path, 'resolve').mockImplementationOnce(() => {
114
+ return '/Users/username/Projects/squiz/component-cli-lib/packages/component-cli-lib/src';
115
+ });
116
+
117
+ // Mock the destination folder
118
+ jest.spyOn(path, 'resolve').mockImplementationOnce(() => {
119
+ return '/Users/username/Projects/squiz/new-component';
120
+ });
121
+
122
+ // Mock the fs.pathExists function to return false
123
+ jest.spyOn(fs, 'pathExists').mockImplementationOnce(() => {
124
+ return Promise.resolve(false);
125
+ });
126
+
127
+ await componentInit({
128
+ componentType: 'basic',
129
+ destination: '/Users/username/Projects/squiz/new-component',
130
+ });
131
+
132
+ expect(fs.mkdirp).toHaveBeenCalledWith('/Users/username/Projects/squiz/new-component');
133
+ });
134
+
135
+ it('should not fail if the destination folder already exists and there are no files in it', async () => {
136
+ // Mock the current script directory
137
+ jest.spyOn(path, 'resolve').mockImplementationOnce(() => {
138
+ return '/Users/username/Projects/squiz/component-cli-lib/packages/component-cli-lib/src';
139
+ });
140
+
141
+ // Mock the destination folder
142
+ jest.spyOn(path, 'resolve').mockImplementationOnce(() => {
143
+ return '/Users/username/Projects/squiz/new-component';
144
+ });
145
+
146
+ // Mock the fs.pathExists function to return true
147
+ jest.spyOn(fs, 'pathExists').mockImplementationOnce(() => {
148
+ return Promise.resolve(true);
149
+ });
150
+
151
+ // Mock the fs.readdir function to return an empty array
152
+ jest.spyOn(fs, 'readdir').mockImplementationOnce(() => {
153
+ return Promise.resolve([]);
154
+ });
155
+
156
+ await expect(
157
+ componentInit({
158
+ componentType: 'basic',
159
+ destination: '/Users/username/Projects/squiz/new-component',
160
+ }),
161
+ ).resolves.toBeUndefined();
162
+ });
163
+
164
+ it('fs.copy should be called with the source folder and the destination folder', async () => {
165
+ // Mock the fs.copy function
166
+ const fsCopySpy = jest.spyOn(fs, 'copy');
167
+
168
+ // Mock the current script directory
169
+ jest.spyOn(path, 'resolve').mockImplementationOnce(() => {
170
+ return '/Users/username/Projects/squiz/component-cli-lib/packages/component-cli-lib/src';
171
+ });
172
+
173
+ // Mock the source folder
174
+ jest.spyOn(path, 'join').mockImplementationOnce(() => {
175
+ return '/Users/username/Projects/squiz/component-cli-lib/packages/component-cli-lib/templates/basic';
176
+ });
177
+
178
+ // Mock the destination folder
179
+ jest.spyOn(path, 'resolve').mockImplementationOnce(() => {
180
+ return '/Users/username/Projects/squiz/new-component';
181
+ });
182
+
183
+ // Mock the fs.pathExists function to return true
184
+ jest.spyOn(fs, 'pathExists').mockImplementationOnce(() => {
185
+ return Promise.resolve(true);
186
+ });
187
+
188
+ // Mock the fs.readdir function to return an empty array
189
+ jest.spyOn(fs, 'readdir').mockImplementationOnce(() => {
190
+ return Promise.resolve([]);
191
+ });
192
+
193
+ await componentInit({
194
+ componentType: 'basic',
195
+ destination: '/Users/username/Projects/squiz/new-component',
196
+ });
197
+
198
+ expect(fsCopySpy).toHaveBeenCalledWith(
199
+ '/Users/username/Projects/squiz/component-cli-lib/packages/component-cli-lib/templates/basic',
200
+ '/Users/username/Projects/squiz/new-component',
201
+ );
202
+ });
203
+ });
@@ -0,0 +1,48 @@
1
+ import fs from 'fs-extra';
2
+ import path from 'path';
3
+ import { getLogger, LoggerOptions } from '@squiz/dx-logger-lib';
4
+
5
+ /**
6
+ * componentInit initializes a new component
7
+ * @param {object} options - The options object
8
+ * @param {string} options.componentType - The type of component to initialize
9
+ * @returns {void}
10
+ */
11
+ export default async function componentInit(options: {
12
+ componentType: 'basic' | 'advanced';
13
+ destination: string;
14
+ loggingFormat?: LoggerOptions['format'];
15
+ }) {
16
+ const logger = getLogger({
17
+ name: 'component-dev',
18
+ format: options.loggingFormat || 'human',
19
+ silent: process.env.NODE_ENV === 'test',
20
+ });
21
+
22
+ logger.info('Initializing component...');
23
+
24
+ // Get our current script directory
25
+ const currentScriptDir = path.resolve(__dirname);
26
+
27
+ // Define the file source to move from
28
+ const sourceFolder = path.join(currentScriptDir, 'templates', options.componentType);
29
+
30
+ // Define the file destination to move to
31
+ const destination = path.resolve(options.destination);
32
+
33
+ // If the destination folder already exists, and it's not empty, throw an error
34
+ if (await fs.pathExists(destination)) {
35
+ const files = await fs.readdir(destination);
36
+ if (files.length > 0) {
37
+ throw new Error('The destination folder already exists and is not empty.');
38
+ }
39
+ } else {
40
+ // If the destination folder doesn't exist, create it
41
+ await fs.mkdirp(destination);
42
+ }
43
+
44
+ // Copy the contents of the source folder to the destination folder
45
+ await fs.copy(sourceFolder, destination);
46
+
47
+ logger.info('Component initialized!');
48
+ }
package/src/index.ts CHANGED
@@ -1,2 +1,3 @@
1
1
  export { uploadComponentFolder } from './upload-component-folder';
2
2
  export { startDevelopmentRender } from './component-dev';
3
+ export { default as componentInit } from './component-init';
@@ -0,0 +1,43 @@
1
+ // Build process
2
+ const esbuild = require('esbuild');
3
+ const { sassPlugin } = require('esbuild-sass-plugin');
4
+ const postcss = require('postcss');
5
+ const autoprefixer = require('autoprefixer');
6
+
7
+ const esbuildOptions = {
8
+ outdir: 'dist',
9
+ bundle: true,
10
+ minify: false,
11
+ treeShaking: true,
12
+ };
13
+
14
+ // Server build
15
+ esbuild
16
+ .build({
17
+ ...esbuildOptions,
18
+ platform: 'node',
19
+ entryPoints: ['./main.js'],
20
+ format: 'cjs',
21
+ target: 'node16',
22
+ })
23
+ .catch(() => process.exit(1));
24
+
25
+ // Client Build
26
+ esbuild
27
+ .build({
28
+ ...esbuildOptions,
29
+ platform: 'browser',
30
+ entryPoints: ['./static/default.js', './static/default.scss'],
31
+ format: 'esm',
32
+ target: 'es2020',
33
+ plugins: [
34
+ sassPlugin({
35
+ async transform(source) {
36
+ const { css } = await postcss([autoprefixer]).process(source);
37
+ return css;
38
+ },
39
+ }),
40
+ ],
41
+ })
42
+ .then(() => console.log('⚡ Styles & Scripts Compiled! ⚡ '))
43
+ .catch(() => process.exit(1));
@@ -0,0 +1,3 @@
1
+ export default async function (input, info) {
2
+ return `<div>hello world</div>`;
3
+ }
@@ -0,0 +1,53 @@
1
+ {
2
+ "$schema": "http://localhost:3000/schemas/v1.json",
3
+ "name": "default",
4
+ "namespace": "default-namespace",
5
+ "displayName": "Default Component",
6
+ "description": "Default example component",
7
+ "version": "0.0.1",
8
+ "mainFunction": "main",
9
+ "functions": [
10
+ {
11
+ "name": "main",
12
+ "entry": "main.js",
13
+ "input": {},
14
+ "output": {
15
+ "responseType": "html",
16
+ "staticFiles": [
17
+ {
18
+ "location": "header",
19
+ "file": {
20
+ "type": "css",
21
+ "filepath": "default.css"
22
+ }
23
+ },
24
+ {
25
+ "location": "footer",
26
+ "file": {
27
+ "type": "js",
28
+ "filepath": "default.js"
29
+ }
30
+ }
31
+ ]
32
+ }
33
+ }
34
+ ],
35
+ "previews": {
36
+ "default": {
37
+ "functionData": {
38
+ "main": {
39
+ "inputData": {
40
+ "type": "file",
41
+ "path": "previews/example.data.json"
42
+ },
43
+ "wrapper": {
44
+ "path": "previews/preview.html"
45
+ }
46
+ }
47
+ }
48
+ }
49
+ },
50
+ "staticFiles": {
51
+ "locationRoot": "static"
52
+ }
53
+ }
@@ -0,0 +1,11 @@
1
+ {
2
+ "scripts": {
3
+ "build": "node build.js"
4
+ },
5
+ "devDependencies": {
6
+ "autoprefixer": "^10.4.13",
7
+ "esbuild": "^0.17.6",
8
+ "esbuild-sass-plugin": "^2.4.5",
9
+ "postcss": "^8.4.21"
10
+ }
11
+ }
@@ -0,0 +1,9 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en" dir="ltr">
3
+ <head>
4
+ [component://static-header]
5
+ </head>
6
+ <body>
7
+ [component://output] [component://static-footer]
8
+ </body>
9
+ </html>
@@ -0,0 +1 @@
1
+ // Client Side JS goes here
@@ -0,0 +1 @@
1
+ // Client Side CSS goes here
@@ -0,0 +1,3 @@
1
+ module.exports = async function (input, info) {
2
+ return `<div>hello world</div>`;
3
+ };