lucy-cli 0.8.0 → 0.8.2

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/README.md CHANGED
@@ -8,6 +8,13 @@ Lucy-CLI was developed out of a personal need to gain full TypeScript support fo
8
8
 
9
9
  Lucy, my loyal dog, accompanied me during long nights working on a major project where I developed this CLI. Her companionship and resilience inspired the name "Lucy-CLI."
10
10
 
11
+ ## CAUTION: Thing to keep in mind before using Lucy-CLI
12
+
13
+ This CLI is still in development and may have bugs. Please use it with caution.
14
+ Libraries are expected to have the same folder structure as the main typescript folder except for the pages folder.
15
+ (backend, public, styles)
16
+ The lucy CLI is opinionated and may not work with all projects.
17
+
11
18
  ## What It Does
12
19
 
13
20
  Lucy-CLI is designed to streamline the setup and management of TypeScript within Wix Velo projects, providing tools to enhance code quality and reduce development time. Here’s what it offers:
@@ -27,7 +34,28 @@ Lucy-CLI is designed to streamline the setup and management of TypeScript within
27
34
  5. **Configurable Setup**
28
35
  - After initialization, Lucy-CLI creates a `lucy-config.json` configuration file where you can modify settings, add dev packages, specify Wix packages, and configure git submodules.
29
36
 
30
- ---
37
+ 6. **Execute render functions**
38
+ - Lucy-CLI can execute render functions located in the backend template folder, allowing you to test render functions locally.
39
+
40
+ 7. **compile sccs files**
41
+ - Lucy-CLI can compile scss files to css files.
42
+ - It compiles styles/global.scss file to global.css.
43
+
44
+ 8. **Wix NPM Package Installation**
45
+ - Lucy-CLI can install Wix npm packages from the `lucy.json` file in the project directory.
46
+
47
+ 9. **Teting with Jest**
48
+ - Lucy-CLI can run tests with Jest.
49
+ - It runs tests located backend folder with the file name ending with `.spec.ts`.
50
+ - it creates a code coverage report in the coverage folder in the lib folders and typescript folders.
51
+
52
+ 10. **Linting with ESLint**
53
+ - Lucy-CLI can lint the code with ESLint.
54
+ - It uses the ESLint configuration in the `.eslintrc.cjs` file in the project directory.
55
+
56
+ 11. **Add git version during production build**
57
+ - Lucy-CLI can add the git version to the production build.
58
+ - It adds the git version to the `public/constant/env.ts` file in the public folder under the key gitTag.
31
59
 
32
60
  ## Commands & Options
33
61
 
@@ -13,6 +13,7 @@ export function buildBackend(options) {
13
13
  const { outputDir, enableIncrementalBuild } = options;
14
14
  const gulpEsbuild = createGulpEsbuild({
15
15
  incremental: enableIncrementalBuild,
16
+ pipe: true,
16
17
  });
17
18
  // Create tasks for each folder
18
19
  const tasks = folders.map((folder) => {
@@ -51,6 +52,7 @@ export function buildBackendJSW(options) {
51
52
  const { outputDir, enableIncrementalBuild } = options;
52
53
  const gulpEsbuild = createGulpEsbuild({
53
54
  incremental: enableIncrementalBuild,
55
+ pipe: true,
54
56
  });
55
57
  // Create tasks for each folder
56
58
  const tasks = folders.map((folder) => {
@@ -6,6 +6,7 @@ export function buildPages(options) {
6
6
  const { outputDir, enableIncrementalBuild } = options;
7
7
  const gulpEsbuild = createGulpEsbuild({
8
8
  incremental: enableIncrementalBuild, // enables the esbuild's incremental build
9
+ pipe: true, // enables the esbuild's pipe mode
9
10
  });
10
11
  return () => {
11
12
  return gulp.src('typescript/pages/*.ts')
@@ -12,6 +12,7 @@ export function buildPublic(options) {
12
12
  const { outputDir, enableIncrementalBuild } = options;
13
13
  const gulpEsbuild = createGulpEsbuild({
14
14
  incremental: enableIncrementalBuild,
15
+ pipe: true,
15
16
  });
16
17
  // Create tasks for each folder
17
18
  const tasks = folders.map((folder) => {
@@ -239,26 +239,17 @@ function processJson(obj) {
239
239
  }
240
240
  }
241
241
  function cleanTsConfig(json) {
242
- // Process the paths object to remove duplicates
242
+ // const paths: Record<string, string[]> = {};
243
243
  if (json.compilerOptions?.paths) {
244
- for (const key in json.compilerOptions.paths) {
245
- if (Array.isArray(json.compilerOptions.paths[key])) {
246
- const uniquePaths = [...new Set(json.compilerOptions.paths[key])];
247
- json.compilerOptions.paths[key] = uniquePaths.length > 0 ? uniquePaths : undefined;
248
- }
244
+ for (const [key, value] of Object.entries(json.compilerOptions.paths)) {
245
+ const uniquePaths = new Set(value);
246
+ json.compilerOptions.paths[key] = Array.from(uniquePaths);
247
+ // paths[key] = Array.from(uniquePaths);
249
248
  }
249
+ // json.compilerOptions.paths = paths;
250
250
  }
251
- // Process the include array to remove duplicates
252
- if (Array.isArray(json.include)) {
253
- const uniqueIncludes = [...new Set(json.include)];
254
- json.include = uniqueIncludes.length > 0 ? uniqueIncludes : undefined;
255
- }
256
- // Remove empty or undefined fields
257
- if (json.compilerOptions?.paths) {
258
- json.compilerOptions.paths = Object.fromEntries(Object.entries(json.compilerOptions.paths).filter(([_, value]) => value !== undefined));
259
- }
260
- if (json.include?.length === 0) {
261
- delete json.include;
262
- }
251
+ json.include = Array.from(new Set(json.include));
252
+ json.exclude = Array.from(new Set(json.exclude));
253
+ json.files = Array.from(new Set(json.files));
263
254
  return json;
264
255
  }
@@ -0,0 +1,37 @@
1
+ export type TSConfig = {
2
+ compilerOptions?: {
3
+ target?: string;
4
+ module?: string;
5
+ lib?: string[];
6
+ outDir?: string;
7
+ rootDir?: string;
8
+ strict?: boolean;
9
+ esModuleInterop?: boolean;
10
+ allowJs?: boolean;
11
+ checkJs?: boolean;
12
+ declaration?: boolean;
13
+ declarationMap?: boolean;
14
+ sourceMap?: boolean;
15
+ removeComments?: boolean;
16
+ noImplicitAny?: boolean;
17
+ moduleResolution?: "node" | "classic";
18
+ resolveJsonModule?: boolean;
19
+ skipLibCheck?: boolean;
20
+ types?: string[];
21
+ typeRoots?: string[];
22
+ jsx?: "preserve" | "react" | "react-jsx" | "react-jsxdev" | "react-native";
23
+ incremental?: boolean;
24
+ noEmit?: boolean;
25
+ paths?: Record<string, string[]>;
26
+ [key: string]: any;
27
+ };
28
+ include?: string[];
29
+ exclude?: string[];
30
+ files?: string[];
31
+ extends?: string;
32
+ references?: {
33
+ path: string;
34
+ }[];
35
+ compileOnSave?: boolean;
36
+ [key: string]: any;
37
+ };
package/dist/models.js ADDED
@@ -0,0 +1 @@
1
+ export {};
@@ -7,6 +7,7 @@ module.exports = {
7
7
  },
8
8
  ignorePatterns: ['src/**/*', 'typescript/types/backend/**/*', 'typescript/types/pages/**/*', 'typescript/types/public/**/*', 'typescript/types/node/**/*', '.wix/**/*', 'coverage/**/*', 'docs/**/*'],
9
9
  rules: {
10
+ 'no-static-block': 'error',
10
11
  quotes: [2, 'single', { 'avoidEscape': true, 'allowTemplateLiterals': true }],
11
12
  curly: ['error', 'multi-line'],
12
13
  'simple-import-sort/imports': 'error',
@@ -87,6 +88,14 @@ module.exports = {
87
88
  }
88
89
  ],
89
90
  },
91
+ overrides: [
92
+ {
93
+ files: ['**/*.tsx', '**/*.ts'],
94
+ rules: {
95
+ 'no-static-block': 'error'
96
+ }
97
+ }
98
+ ],
90
99
  root: true,
91
100
  env: {
92
101
  es6: true,
@@ -0,0 +1,32 @@
1
+ import * as fs from 'fs';
2
+
3
+
4
+ export interface RenderToFsOPtions {
5
+ renderer: (arg0: any, arg1: any) => Promise<string>;
6
+ dataSource: string;
7
+ destination: string;
8
+ }
9
+ /**
10
+ * Render E-Mail to file system
11
+ * @param {RenderToFsOPtions} options Preview Options
12
+ * @returns {Promise<void>}
13
+ */
14
+ export async function renderToFs(options: RenderToFsOPtions): Promise<void> {
15
+ if (process.env.NODE_ENV === 'production' || process.env.NODE_ENV === 'development') return;
16
+ console.log('rendered', process.env.NODE_ENV, options);
17
+ fs.readFile(`typescript/backend/templates/data/${options.dataSource}`, 'utf8', async (err, data) => {
18
+ if (err){
19
+ console.error('Template Rendere => ', err);
20
+
21
+ return;
22
+ }
23
+ const fakeDate = JSON.parse(data) as any;
24
+ console.log('fakeDate', fakeDate);
25
+ const html = await options.renderer(fakeDate, 'de');
26
+ fs.writeFile(`typescript/backend/templates/preview/${options.destination}.html`, html, err => {
27
+ if (err){
28
+ console.error(err);
29
+ }
30
+ });
31
+ });
32
+ }
package/lucy.jpg CHANGED
Binary file
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "type": "module",
3
3
  "name": "lucy-cli",
4
- "version": "0.8.0",
4
+ "version": "0.8.2",
5
5
  "description": "Lucy Framework for WIX Studio Editor",
6
6
  "main": ".dist/index.js",
7
7
  "scripts": {
@@ -16,6 +16,7 @@ export function buildBackend(options: TaskOptions) {
16
16
  const { outputDir, enableIncrementalBuild } = options;
17
17
  const gulpEsbuild = createGulpEsbuild({
18
18
  incremental: enableIncrementalBuild,
19
+ pipe: true,
19
20
  });
20
21
 
21
22
  // Create tasks for each folder
@@ -64,6 +65,7 @@ export function buildBackendJSW(options: TaskOptions) {
64
65
  const { outputDir, enableIncrementalBuild } = options;
65
66
  const gulpEsbuild = createGulpEsbuild({
66
67
  incremental: enableIncrementalBuild,
68
+ pipe: true,
67
69
  });
68
70
 
69
71
  // Create tasks for each folder
package/src/gulp/copy.ts CHANGED
@@ -15,7 +15,6 @@ export function copyFiles(options: TaskOptions) {
15
15
  const tasks = folders.map((folder) => {
16
16
  const { outputDir} = options;
17
17
 
18
-
19
18
  const taskName = `copy-${folder}`; // Create a unique name for each task
20
19
 
21
20
  const task = () =>
package/src/gulp/pages.ts CHANGED
@@ -8,6 +8,7 @@ export function buildPages(options: TaskOptions) {
8
8
  const { outputDir, enableIncrementalBuild} = options;
9
9
  const gulpEsbuild = createGulpEsbuild({
10
10
  incremental: enableIncrementalBuild, // enables the esbuild's incremental build
11
+ pipe: true, // enables the esbuild's pipe mode
11
12
  });
12
13
 
13
14
  return () => {
@@ -16,6 +16,7 @@ export function buildPublic(options: TaskOptions) {
16
16
  const { outputDir, enableIncrementalBuild } = options;
17
17
  const gulpEsbuild = createGulpEsbuild({
18
18
  incremental: enableIncrementalBuild,
19
+ pipe: true,
19
20
  });
20
21
 
21
22
  // Create tasks for each folder
package/src/gulp/types.ts CHANGED
@@ -9,6 +9,7 @@ import merge from 'merge-stream';
9
9
  import * as insert from 'gulp-insert';
10
10
  import { blue, red, yellow } from '../index.js';
11
11
  import tap from 'gulp-tap';
12
+ import { TSConfig } from '../models';
12
13
 
13
14
  export function updateWixTypes(options: TaskOptions) {
14
15
  return () => {
@@ -111,29 +112,29 @@ export function updateWixTypes(options: TaskOptions) {
111
112
  count ++;
112
113
  if (file.dirname.endsWith('public')) {
113
114
  return stream.pipe(jeditor(publicSettings))
114
- .pipe(jeditor((json: any) => cleanTsConfig(json)))
115
- .pipe(jeditor((json: any) => processJson(json)))
116
- .pipe(replace('"../backend.d.ts",', '', replaceOptions))
117
- .pipe(replace('"../../../src/backend/\\*\\*/\\*.web.js",', '', replaceOptions));
115
+ .pipe(jeditor((json: any) => cleanTsConfig(json)))
116
+ .pipe(jeditor((json: any) => processJson(json)))
117
+ .pipe(replace('"../backend.d.ts",', '', replaceOptions))
118
+ .pipe(replace('"../../../src/backend/\\*\\*/\\*.web.js",', '', replaceOptions));
118
119
  }
119
120
  if (file.dirname.endsWith('backend')) {
120
121
  return stream.pipe(jeditor(backendSettings))
121
- .pipe(jeditor((json: any) => cleanTsConfig(json)))
122
- .pipe(jeditor((json: any) => processJson(json)))
122
+ .pipe(jeditor((json: any) => cleanTsConfig(json)))
123
+ .pipe(jeditor((json: any) => processJson(json)))
123
124
  };
124
125
  if (file.dirname.endsWith('masterPage')) {
125
126
  return stream.pipe(jeditor(masterSettings))
126
- .pipe(jeditor((json: any) => cleanTsConfig(json)))
127
- .pipe(jeditor((json: any) => processJson(json)))
128
- .pipe(replace('"../backend.d.ts",', '', replaceOptions))
129
- .pipe(replace('"../../../src/backend/\\*\\*/\\*.web.js",', '', replaceOptions));
130
- };
131
-
132
- return stream.pipe(jeditor(pageSettings))
133
127
  .pipe(jeditor((json: any) => cleanTsConfig(json)))
134
128
  .pipe(jeditor((json: any) => processJson(json)))
135
129
  .pipe(replace('"../backend.d.ts",', '', replaceOptions))
136
130
  .pipe(replace('"../../../src/backend/\\*\\*/\\*.web.js",', '', replaceOptions));
131
+ };
132
+
133
+ return stream.pipe(jeditor(pageSettings))
134
+ .pipe(jeditor((json: any) => cleanTsConfig(json)))
135
+ .pipe(jeditor((json: any) => processJson(json)))
136
+ .pipe(replace('"../backend.d.ts",', '', replaceOptions))
137
+ .pipe(replace('"../../../src/backend/\\*\\*/\\*.web.js",', '', replaceOptions));
137
138
  }))
138
139
  .pipe(replace('masterPage.masterPage.js', 'masterPage.ts', replaceOptions))
139
140
  .pipe(replace('/src/', '/typescript/', replaceOptions))
@@ -259,33 +260,19 @@ function processJson(obj: any): any {
259
260
  }
260
261
  }
261
262
 
262
- function cleanTsConfig(json: any): any {
263
- // Process the paths object to remove duplicates
264
- if (json.compilerOptions?.paths) {
265
- for (const key in json.compilerOptions.paths) {
266
- if (Array.isArray(json.compilerOptions.paths[key])) {
267
- const uniquePaths = [...new Set(json.compilerOptions.paths[key])];
268
- json.compilerOptions.paths[key] = uniquePaths.length > 0 ? uniquePaths : undefined;
269
- }
270
- }
271
- }
272
-
273
- // Process the include array to remove duplicates
274
- if (Array.isArray(json.include)) {
275
- const uniqueIncludes = [...new Set(json.include)];
276
- json.include = uniqueIncludes.length > 0 ? uniqueIncludes : undefined;
277
- }
278
-
279
- // Remove empty or undefined fields
280
- if (json.compilerOptions?.paths) {
281
- json.compilerOptions.paths = Object.fromEntries(
282
- Object.entries(json.compilerOptions.paths).filter(([_, value]) => value !== undefined)
283
- );
284
- }
285
-
286
- if (json.include?.length === 0) {
287
- delete json.include;
288
- }
263
+ function cleanTsConfig(json: TSConfig): TSConfig {
264
+ // const paths: Record<string, string[]> = {};
265
+ if (json.compilerOptions?.paths) {
266
+ for (const [key, value] of Object.entries(json.compilerOptions.paths)) {
267
+ const uniquePaths = new Set(value);
268
+ json.compilerOptions.paths[key] = Array.from(uniquePaths);
269
+ // paths[key] = Array.from(uniquePaths);
270
+ }
271
+ // json.compilerOptions.paths = paths;
272
+ }
273
+ json.include = Array.from(new Set(json.include));
274
+ json.exclude = Array.from(new Set(json.exclude));
275
+ json.files = Array.from(new Set(json.files));
289
276
 
290
- return json;
277
+ return json;
291
278
  }
package/src/models.ts ADDED
@@ -0,0 +1,35 @@
1
+ export type TSConfig = {
2
+ compilerOptions?: {
3
+ target?: string; // e.g., "ES5", "ES6", "ES2015", "ESNext"
4
+ module?: string; // e.g., "CommonJS", "ES6", "ESNext"
5
+ lib?: string[]; // e.g., ["ES2015", "DOM"]
6
+ outDir?: string;
7
+ rootDir?: string;
8
+ strict?: boolean;
9
+ esModuleInterop?: boolean;
10
+ allowJs?: boolean;
11
+ checkJs?: boolean;
12
+ declaration?: boolean;
13
+ declarationMap?: boolean;
14
+ sourceMap?: boolean;
15
+ removeComments?: boolean;
16
+ noImplicitAny?: boolean;
17
+ moduleResolution?: "node" | "classic";
18
+ resolveJsonModule?: boolean;
19
+ skipLibCheck?: boolean;
20
+ types?: string[]; // e.g., ["node", "jest"]
21
+ typeRoots?: string[]; // e.g., ["./types"]
22
+ jsx?: "preserve" | "react" | "react-jsx" | "react-jsxdev" | "react-native";
23
+ incremental?: boolean;
24
+ noEmit?: boolean;
25
+ paths?: Record<string, string[]>; // Aliases for module paths
26
+ [key: string]: any; // Allow additional compiler options
27
+ };
28
+ include?: string[]; // Glob patterns to include
29
+ exclude?: string[]; // Glob patterns to exclude
30
+ files?: string[]; // Specific files to include
31
+ extends?: string; // Path to a base tsconfig.json
32
+ references?: { path: string }[]; // Project references
33
+ compileOnSave?: boolean;
34
+ [key: string]: any; // Allow additional top-level options
35
+ };