lucy-cli 0.7.15 → 0.8.1

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 (47) hide show
  1. package/README.md +29 -1
  2. package/dist/Gulpfile.d.ts +1 -0
  3. package/dist/Gulpfile.js +14 -12
  4. package/dist/gulp/backend.d.ts +2 -5
  5. package/dist/gulp/backend.js +43 -82
  6. package/dist/gulp/checks.d.ts +2 -2
  7. package/dist/gulp/checks.js +21 -22
  8. package/dist/gulp/copy.d.ts +1 -2
  9. package/dist/gulp/copy.js +29 -34
  10. package/dist/gulp/helpers.d.ts +1 -0
  11. package/dist/gulp/helpers.js +7 -0
  12. package/dist/gulp/public.d.ts +1 -2
  13. package/dist/gulp/public.js +20 -33
  14. package/dist/gulp/styles.d.ts +1 -1
  15. package/dist/gulp/styles.js +19 -6
  16. package/dist/gulp/templates.d.ts +2 -2
  17. package/dist/gulp/templates.js +27 -30
  18. package/dist/gulp/test.d.ts +2 -2
  19. package/dist/gulp/test.js +24 -50
  20. package/dist/gulp/types.js +9 -18
  21. package/dist/gulp/watchers.d.ts +0 -6
  22. package/dist/gulp/watchers.js +27 -61
  23. package/dist/helpers.d.ts +4 -0
  24. package/dist/helpers.js +19 -0
  25. package/dist/index.js +7 -1
  26. package/dist/models.d.ts +37 -0
  27. package/dist/models.js +1 -0
  28. package/files/typescript/templates/render.ts +32 -0
  29. package/lucy.jpg +0 -0
  30. package/package.json +1 -1
  31. package/settings/master-settings.json +0 -1
  32. package/settings/page-settings.json +0 -1
  33. package/settings/public-settings.json +0 -1
  34. package/src/Gulpfile.ts +13 -17
  35. package/src/gulp/backend.ts +74 -107
  36. package/src/gulp/checks.ts +32 -28
  37. package/src/gulp/copy.ts +38 -40
  38. package/src/gulp/helpers.ts +9 -0
  39. package/src/gulp/public.ts +36 -47
  40. package/src/gulp/styles.ts +32 -13
  41. package/src/gulp/templates.ts +38 -39
  42. package/src/gulp/test.ts +55 -75
  43. package/src/gulp/types.ts +28 -41
  44. package/src/gulp/watchers.ts +31 -101
  45. package/src/helpers.ts +23 -1
  46. package/src/index.ts +7 -1
  47. package/src/models.ts +35 -0
package/src/gulp/test.ts CHANGED
@@ -1,82 +1,62 @@
1
1
  import gulp from 'gulp';
2
- import { blue, red } from '../index.js';
2
+ import { blue, orange, red } from '../index.js';
3
3
  import gulpJest from 'gulp-jest';
4
+ import { TaskOptions } from '../Gulpfile.js';
4
5
  const jest = gulpJest.default;
5
6
 
6
- export function test() {
7
- return () => {
8
- return gulp.src([
9
- 'typescript/backend/**/*.spec.ts',
10
- ])
11
- .pipe(jest({
12
- verbose: true,
13
- extensionsToTreatAsEsm: ['.ts'],
14
- transform: {
15
- '^.+\\.tsx?$': [
16
- 'ts-jest',
17
- {
18
- tsconfig: './typescript/tsconfig.json',
19
- usESM: true,
20
- },
21
- ],
22
- },
23
- preset: 'ts-jest',
24
- setupFilesAfterEnv: [],
25
- testEnvironment: 'node',
26
- collectCoverage: true,
27
- coverageDirectory: '../coverage',
28
- coverageReporters: ['clover', 'json', 'lcov', 'text'],
29
- rootDir: './typescript',
30
- testMatch: ['**/*.spec.ts'],
31
- passWithNoTests: true,
32
- moduleNameMapper: {
33
- 'public/(.*)': '<rootDir>/public/$1'
34
- }
35
- }))
36
- .on('error', function () {
37
- console.log("💩" + red.underline.bold(' => Tests failed!'));
38
- this.emit('end');
39
- })
40
- .on('end', function() { console.log("🐶" + blue.underline(' => Test succeeded!'));
7
+ export function test(options: TaskOptions) {
8
+ const folders = ['typescript'];
9
+ if (options.modulesSync){
10
+ for (const module of Object.keys(options.modulesSync)) {
11
+ folders.push(module);
41
12
  }
42
- )}
43
- }
13
+ }
14
+
15
+ // Create tasks for each folder
16
+ const tasks = folders.map((folder) => {
17
+ const taskName = `tests-${folder}`; // Create a unique name for each task
18
+ const task = () =>
19
+ gulp.src([
20
+ `${folder}/backend/**/*.spec.ts`,
21
+ ])
22
+ .pipe(jest({
23
+ verbose: true,
24
+ extensionsToTreatAsEsm: ['.ts'],
25
+ transform: {
26
+ '^.+\\.tsx?$': [
27
+ 'ts-jest',
28
+ {
29
+ tsconfig: `./${folder}/tsconfig.json`,
30
+ usESM: true,
31
+ },
32
+ ],
33
+ },
34
+ preset: 'ts-jest',
35
+ setupFilesAfterEnv: [],
36
+ testEnvironment: 'node',
37
+ collectCoverage: true,
38
+ coverageDirectory: './coverage',
39
+ coverageReporters: ['clover', 'json', 'lcov', 'text'],
40
+ rootDir: `./${folder}`,
41
+ testMatch: ['**/*.spec.ts'],
42
+ passWithNoTests: true,
43
+ moduleNameMapper: {
44
+ 'public/(.*)': '<rootDir>/public/$1'
45
+ }
46
+ }))
47
+ .on('error', function () {
48
+ console.log("💩" + red.underline.bold(` => Tests for ${orange(folder)} failed!`));
49
+ this.emit('end');
50
+ })
51
+ .on('end', function () {
52
+ console.log("🐶" + blue.underline(` => Tests for ${orange(folder)} succeeded!`));
53
+ });
44
54
 
45
- export function testLib() {
46
- return () => {
47
- return gulp.src([
48
- 'lib/backend/**/*.spec.ts',
49
- ])
50
- .pipe(jest({
51
- verbose: true,
52
- extensionsToTreatAsEsm: ['.ts'],
53
- transform: {
54
- '^.+\\.tsx?$': [
55
- 'ts-jest',
56
- {
57
- tsconfig: './lib/tsconfig.json',
58
- usESM: true,
59
- },
60
- ],
61
- },
62
- preset: 'ts-jest',
63
- setupFilesAfterEnv: [],
64
- testEnvironment: 'node',
65
- collectCoverage: true,
66
- passWithNoTests: true,
67
- coverageDirectory: './coverage',
68
- coverageReporters: ['clover', 'json', 'lcov', 'text'],
69
- rootDir: './lib',
70
- testMatch: ['**/*.spec.ts'],
71
- moduleNameMapper: {
72
- 'public/(.*)': '<rootDir>/public/$1'
73
- }
74
- }))
75
- .on('error', function () {
76
- console.log("💩" + red.underline.bold(' => Test (LIB) failed!'));
77
- this.emit('end');
78
- })
79
- .on('end', function() { console.log("🐶" + blue.underline(' => Test (LIB) succeeded!'));
80
- }
81
- )}
55
+ // Register the task with Gulp
56
+ Object.defineProperty(task, 'name', { value: taskName }); // Set a unique name for debugging
57
+ return task;
58
+ });
59
+
60
+ // Run all tasks in parallel
61
+ return gulp.parallel(...tasks);
82
62
  }
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
  }
@@ -1,100 +1,55 @@
1
1
  import gulp from 'gulp';
2
2
  import { TaskOptions } from '../Gulpfile.js';
3
3
  import { green } from '../index.js';
4
- import { buildBackend, buildBackendJSW, buildBackendJSWLib, buildBackendLib } from './backend.js';
5
- import { buildPublic, buildPublicLib } from './public.js';
4
+ import { buildBackend, buildBackendJSW } from './backend.js';
5
+ import { buildPublic } from './public.js';
6
6
  import { buildPages } from './pages.js';
7
- import { copyFiles, copyFilesLib } from './copy.js';
8
- import { previewTemplates, previewTemplatesLib } from './templates.js';
9
- import { checkPages, checkTs, checkTsLib } from './checks.js';
10
- import { testLib, test } from './test.js';
7
+ import { copyFiles } from './copy.js';
8
+ import { previewTemplates } from './templates.js';
9
+ import { checkPages, checkTs } from './checks.js';
10
+ import { test } from './test.js';
11
11
 
12
12
  let taskOptions: TaskOptions;
13
13
 
14
14
  export function watchSCSS() {
15
15
  return gulp.watch([
16
- 'typescript/styles/**/*.scss',
17
- 'lib/styles/**/*.scss'],
16
+ '*/styles/**/*.scss'
17
+ ],
18
18
  gulp.parallel('scss')
19
19
  );
20
20
  }
21
21
 
22
22
  export function watchBackend() {
23
23
  return gulp.watch([
24
- 'typescript/backend/**/*.ts',
25
- 'typescript/backend/**/*.tsx',
26
- '!typescript/backend/**/*.spec.ts',
27
- '!typescript/backend/**/*.jsw.ts',
24
+ '*/backend/**/*.ts',
25
+ '*/backend/**/*.tsx',
26
+ '!*/backend/**/*.spec.ts',
27
+ '!*/backend/**/*.jsw.ts',
28
+ '!src/**/**',
28
29
  ], gulp.parallel(
29
- test(),
30
- checkTs(),
30
+ test(taskOptions),
31
+ checkTs(taskOptions),
31
32
  buildBackend(taskOptions),
32
33
  )
33
34
  );
34
35
  }
35
36
 
36
- export function watchBackendLib() {
37
- return gulp.watch([
38
- 'lib/backend/**/*.ts',
39
- 'lib/backend/**/*.tsx',
40
- '!lib/backend/**/*.spec.ts',
41
- '!lib/backend/**/*.jsw.ts',
42
- ], gulp.parallel(
43
- testLib(),
44
- checkTsLib(),
45
- buildBackendLib(taskOptions)
46
- )
47
- );
48
- }
49
-
50
- export function watchJSW() {
51
- return gulp.watch(['typescript/backend/**/*.jsw.ts'],
52
- gulp.parallel(
53
- test(),
54
- checkTs(),
55
- buildBackendJSW(taskOptions)
56
- )
57
- );
58
- }
59
-
60
- export function watchJSWLib() {
61
- return gulp.watch(['lib/backend/**/*.jsw.ts'],
62
- gulp.parallel(
63
- testLib(),
64
- checkTsLib(),
65
- buildBackendJSWLib(taskOptions)
66
- )
67
- );
68
- }
69
-
70
37
  export function watchPublic() {
71
38
  return gulp.watch([
72
- 'typescript/public/**/*.ts',
73
- 'typescript/public/**/*.tsx',
39
+ '*/public/**/*.ts',
40
+ '*/public/**/*.tsx',
74
41
  ], gulp.parallel(
75
- test(),
76
- checkTs(),
42
+ test(taskOptions),
43
+ checkTs(taskOptions),
77
44
  buildPublic(taskOptions),
78
45
  )
79
46
  );
80
47
  }
81
48
 
82
- export function watchPublicLib() {
83
- return gulp.watch([
84
- 'lib/public/**/*.ts',
85
- 'lib/public/**/*.tsx',
86
- ], gulp.parallel(
87
- testLib(),
88
- checkTsLib(),
89
- buildPublicLib(taskOptions),
90
- )
91
- );
92
- }
93
-
94
49
  export function watchPages() {
95
50
  return gulp.watch('typescript/pages/**/*.ts',
96
51
  gulp.parallel(
97
- checkTs(),
52
+ checkTs(taskOptions),
98
53
  buildPages(taskOptions),
99
54
  )
100
55
  );
@@ -102,42 +57,23 @@ export function watchPages() {
102
57
 
103
58
  export function watchFiles() {
104
59
  return gulp.watch([
105
- 'typescript/backend/**/*',
106
- 'typescript/public/**/*',
107
- 'typescript/pages/**/*',
108
- '!typescript/**/*.ts',
60
+ '*/backend/**/*',
61
+ '*/public/**/*',
62
+ '*/pages/**/*',
63
+ '!*/**/*.ts',
64
+ '!*/**/*.tsx',
109
65
  ], gulp.parallel(copyFiles(taskOptions)));
110
66
  }
111
67
 
112
- export function watchFilesLib() {
113
- return gulp.watch([
114
- 'lib/backend/**/*',
115
- 'lib/public/**/*',
116
- 'lib/pages/**/*',
117
- '!lib/**/*.ts',
118
- ], gulp.parallel(copyFilesLib(taskOptions)));
119
- }
120
-
121
68
  export function watchTemplates() {
122
69
  return gulp.watch([
123
- 'typescript/backend/templates/**/*.tsx',
124
- 'typescript/backend/templates/data/*.json',
125
- '!typescript/backend/templates/render.ts',
126
- ], gulp.parallel(
127
- previewTemplates(),
128
- test()
129
- )
130
- );
131
- }
132
-
133
- export function watchTemplatesLib() {
134
- return gulp.watch([
135
- 'lib/backend/templates/**/*.tsx',
136
- 'lib/backend/templates/data/*.json',
137
- '!lib/backend/templates/render.ts',
70
+ '*/backend/templates/**/*.tsx',
71
+ '*/backend/templates/data/*.json',
72
+ '!*/backend/templates/render.ts',
138
73
  ], gulp.parallel(
139
- previewTemplatesLib(),
140
- testLib(),
74
+ previewTemplates(taskOptions),
75
+ test(taskOptions),
76
+ checkTs(taskOptions),
141
77
  )
142
78
  );
143
79
  }
@@ -160,16 +96,10 @@ export function watchAll(options: TaskOptions) {
160
96
  return gulp.parallel(
161
97
  watchSCSS,
162
98
  watchBackend,
163
- watchBackendLib,
164
- watchJSW,
165
- watchJSWLib,
166
99
  watchPublic,
167
- watchPublicLib,
168
100
  watchPages,
169
- watchFilesLib,
170
101
  watchFiles,
171
102
  watchTemplates,
172
- watchTemplatesLib,
173
103
  watchTypes,
174
104
  );
175
105
  }
package/src/helpers.ts CHANGED
@@ -7,6 +7,7 @@ import { spawnSync } from 'child_process';
7
7
  import path from 'path';
8
8
  import { fileURLToPath } from 'url';
9
9
  import { ModuleSettings, ProjectSettings } from '.';
10
+ import { exec } from 'child_process';
10
11
 
11
12
  import { blue, green, orange, red } from './index.js';
12
13
 
@@ -76,4 +77,25 @@ export async function runGulp(moduleSettings: ModuleSettings, projectSettings: P
76
77
 
77
78
  // Check if 'dev' task exists
78
79
  gulpfile.runTask(task, moduleSettings, projectSettings)
79
- }
80
+ }
81
+
82
+
83
+ /**
84
+ * Clean up and run a command before exiting the process.
85
+ */
86
+ export function handleExit() {
87
+ const cwd = process.cwd();
88
+ const command = `watchman watch-del '${cwd}'`;
89
+
90
+ console.log("🐕" + blue.underline(' => Cleaning up...'));
91
+ exec(command, (error, stdout, stderr) => {
92
+ if (error) {
93
+ console.error(`💩 Failed to run cleanup: ${error.message}`);
94
+ return;
95
+ }
96
+ if (stderr) {
97
+ console.error(`⚠️ Watchman stderr: ${stderr}`);
98
+ }
99
+ console.log(`✅ Watchman cleanup success: ${stdout}`);
100
+ });
101
+ }
package/src/index.ts CHANGED
@@ -11,7 +11,7 @@ import fs from 'fs/promises';
11
11
 
12
12
  import { init } from './init.js';
13
13
  import { sync } from './sync.js';
14
- import { runGulp, installPackages } from './helpers.js';
14
+ import { runGulp, installPackages, handleExit } from './helpers.js';
15
15
  import { prepare } from './prepare.js';
16
16
 
17
17
  export type LucySettings = {
@@ -70,6 +70,11 @@ const __filename = fileURLToPath(import.meta.url);
70
70
  // eslint-disable-next-line @typescript-eslint/naming-convention
71
71
  const __dirname = dirname(__filename);
72
72
 
73
+ process.on('SIGINT', () => {
74
+ console.log("🐕 Received Ctrl+C, cleaning up...");
75
+ handleExit();
76
+ process.exit(); // Exit the process explicitly
77
+ });
73
78
 
74
79
  /**
75
80
  * Main function
@@ -169,6 +174,7 @@ async function main(): Promise<void> {
169
174
 
170
175
  if(moduleSettings.args.includes('-l')) moduleSettings.lockVersion = true;
171
176
 
177
+ console.log("🐕" + magenta.underline(' => Lucy CLI => RUNNING: ' + orange('Press Ctrl+C to stop.')));
172
178
  // INFO: Run commands
173
179
  if(moduleSettings.args.includes('init')){
174
180
  if(projectSettings.lucySettings?.initialized && !moduleSettings.force) {
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
+ };