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 +29 -1
- package/dist/gulp/backend.js +2 -0
- package/dist/gulp/pages.js +1 -0
- package/dist/gulp/public.js +1 -0
- package/dist/gulp/types.js +9 -18
- package/dist/models.d.ts +37 -0
- package/dist/models.js +1 -0
- package/files/.eslintrc.cjs +9 -0
- package/files/typescript/templates/render.ts +32 -0
- package/lucy.jpg +0 -0
- package/package.json +1 -1
- package/src/gulp/backend.ts +2 -0
- package/src/gulp/copy.ts +0 -1
- package/src/gulp/pages.ts +1 -0
- package/src/gulp/public.ts +1 -0
- package/src/gulp/types.ts +28 -41
- package/src/models.ts +35 -0
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
|
|
package/dist/gulp/backend.js
CHANGED
@@ -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) => {
|
package/dist/gulp/pages.js
CHANGED
@@ -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')
|
package/dist/gulp/public.js
CHANGED
@@ -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) => {
|
package/dist/gulp/types.js
CHANGED
@@ -239,26 +239,17 @@ function processJson(obj) {
|
|
239
239
|
}
|
240
240
|
}
|
241
241
|
function cleanTsConfig(json) {
|
242
|
-
//
|
242
|
+
// const paths: Record<string, string[]> = {};
|
243
243
|
if (json.compilerOptions?.paths) {
|
244
|
-
for (const key
|
245
|
-
|
246
|
-
|
247
|
-
|
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
|
-
|
252
|
-
|
253
|
-
|
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
|
}
|
package/dist/models.d.ts
ADDED
@@ -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 {};
|
package/files/.eslintrc.cjs
CHANGED
@@ -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
package/src/gulp/backend.ts
CHANGED
@@ -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
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 () => {
|
package/src/gulp/public.ts
CHANGED
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
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
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
|
-
|
122
|
-
|
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:
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
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
|
-
|
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
|
+
};
|