lucy-cli 0.8.3 โ 0.9.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.
- package/README.md +11 -0
- package/dist/Gulpfile.js +6 -1
- package/dist/gulp/backend.js +34 -19
- package/dist/gulp/checks.js +3 -2
- package/dist/gulp/clean.js +5 -3
- package/dist/gulp/copy.js +2 -1
- package/dist/gulp/pages.d.ts +1 -1
- package/dist/gulp/pages.js +20 -11
- package/dist/gulp/pipeline.js +3 -2
- package/dist/gulp/public.js +19 -13
- package/dist/gulp/styles.js +7 -1
- package/dist/gulp/templates.js +2 -1
- package/dist/gulp/test.js +2 -1
- package/dist/gulp/types.js +3 -3
- package/dist/helpers.d.ts +6 -1
- package/dist/helpers.js +73 -7
- package/dist/index.js +67 -5
- package/dist/settings.json +3 -1
- package/files/cypress/e2e/base/base.cy.ts +14 -0
- package/files/cypress/fixtures/example.json +5 -0
- package/files/cypress/support/commands.ts +37 -0
- package/files/cypress/support/e2e.ts +24 -0
- package/files/cypress/tsconfig.json +9 -0
- package/files/cypress.config.ts +14 -2
- package/package.json +9 -7
- package/src/Gulpfile.ts +5 -1
- package/src/gulp/backend.ts +44 -32
- package/src/gulp/checks.ts +4 -2
- package/src/gulp/clean.ts +5 -3
- package/src/gulp/copy.ts +2 -1
- package/src/gulp/pages.ts +26 -16
- package/src/gulp/pipeline.ts +3 -2
- package/src/gulp/public.ts +21 -15
- package/src/gulp/styles.ts +7 -1
- package/src/gulp/templates.ts +2 -1
- package/src/gulp/test.ts +2 -1
- package/src/gulp/types.ts +3 -3
- package/src/helpers.ts +74 -10
- package/src/index.ts +76 -5
- package/src/settings.json +3 -1
- package/src/types.d.ts +2 -1
package/src/helpers.ts
CHANGED
@@ -1,15 +1,14 @@
|
|
1
1
|
import chalk from 'chalk';
|
2
|
-
import { join } from 'path';
|
3
2
|
import { simpleGit } from 'simple-git';
|
4
|
-
import fs from 'fs/promises';
|
5
3
|
import { spawnSync } from 'child_process';
|
6
4
|
// https://www.sergevandenoever.nl/run-gulp4-tasks-programatically-from-node/
|
7
5
|
import path from 'path';
|
8
6
|
import { fileURLToPath } from 'url';
|
9
7
|
import { ModuleSettings, ProjectSettings } from '.';
|
10
8
|
import { exec } from 'child_process';
|
9
|
+
import os from 'os';
|
11
10
|
|
12
|
-
import { blue, green, orange, red } from './index.js';
|
11
|
+
import { blue, green, orange, red, yellow, magenta } from './index.js';
|
13
12
|
|
14
13
|
export async function installPackages(wixPackages: Record<string, string>, devPackages: Record<string, string>, cwd: string, locked: boolean ) {
|
15
14
|
if (locked) console.log("๐" + blue.underline(` => Installing & version locked packages!`));
|
@@ -83,19 +82,84 @@ export async function runGulp(moduleSettings: ModuleSettings, projectSettings: P
|
|
83
82
|
/**
|
84
83
|
* Clean up and run a command before exiting the process.
|
85
84
|
*/
|
86
|
-
export function
|
85
|
+
export function cleanupWatchers() {
|
86
|
+
console.log(`๐งน ${magenta.underline('Cleaning up Watchman watchers...')}`);
|
87
87
|
const cwd = process.cwd();
|
88
|
-
const command = `watchman watch-del
|
89
|
-
|
90
|
-
console.log("๐" + blue.underline(' => Cleaning up...'));
|
88
|
+
const command = `watchman watch-del "${cwd}"`; // Adjust for Windows paths
|
91
89
|
exec(command, (error, stdout, stderr) => {
|
92
90
|
if (error) {
|
93
|
-
console.error(`๐ฉ Failed to run cleanup: ${error.message}`);
|
91
|
+
console.error(`๐ฉ ${red.underline('Failed to run cleanup:')} ${orange(error.message)}`);
|
94
92
|
return;
|
95
93
|
}
|
96
94
|
if (stderr) {
|
97
|
-
console.error(`โ ๏ธ
|
95
|
+
console.error(`โ ๏ธ ${yellow.underline('Watchman stderr:')} ${stderr}`);
|
98
96
|
}
|
99
|
-
console.log(`โ
Watchman cleanup success: ${stdout}`);
|
97
|
+
console.log(`โ
${green.underline('Watchman cleanup success:')} ${stdout}`);
|
100
98
|
});
|
101
99
|
}
|
100
|
+
|
101
|
+
/**
|
102
|
+
* Kill all processes matching a specific substring in their command, with a fallback for Windows.
|
103
|
+
* @param {string} processPattern - The substring to match (e.g., "wix:dev" or "@wix/cli/bin/wix.cjs").
|
104
|
+
*/
|
105
|
+
export function killAllProcesses(processPattern: string) {
|
106
|
+
const isWindows = os.platform() === 'win32';
|
107
|
+
const command = isWindows
|
108
|
+
? `tasklist /FI "IMAGENAME eq node.exe" /FO CSV | findstr "${processPattern}"` // Adjust for Node.js processes
|
109
|
+
: `ps -eo pid,command | grep "${processPattern}" | grep -v grep`;
|
110
|
+
|
111
|
+
exec(command, (error, stdout, stderr) => {
|
112
|
+
if (error) {
|
113
|
+
console.error(`๐ฉ ${red.underline('Failed to find processes:')} ${orange(error.message)}`);
|
114
|
+
return;
|
115
|
+
}
|
116
|
+
if (stderr) {
|
117
|
+
console.error(`โ ๏ธ ${yellow.underline('Error output:')} ${stderr}`);
|
118
|
+
}
|
119
|
+
if (!stdout.trim()) {
|
120
|
+
console.log(`โน๏ธ ${blue.underline(`No processes found matching pattern:`)} ${orange(processPattern)}`);
|
121
|
+
return;
|
122
|
+
}
|
123
|
+
|
124
|
+
console.log(`๐ ${magenta.underline('Found matching processes:')}\n${stdout}`);
|
125
|
+
const lines = stdout.trim().split('\n');
|
126
|
+
const pids = isWindows
|
127
|
+
? lines.map(line => line.match(/"(\d+)"/)?.[1]) // Extract PID from Windows tasklist output
|
128
|
+
: lines.map(line => line.trim().split(/\s+/)[0]).filter(pid => !isNaN(Number(pid)));
|
129
|
+
|
130
|
+
pids.forEach(pid => {
|
131
|
+
if (!pid) return;
|
132
|
+
try {
|
133
|
+
const killCommand = isWindows
|
134
|
+
? `taskkill /PID ${pid} /T /F` // Forcefully terminate the process on Windows
|
135
|
+
: `kill -SIGTERM ${pid}`;
|
136
|
+
|
137
|
+
exec(killCommand, (killError) => {
|
138
|
+
if (killError) {
|
139
|
+
console.error(`โ ๏ธ ${yellow.underline('Failed to kill process with PID')} ${orange(pid)}: ${red(killError.message)}`);
|
140
|
+
} else {
|
141
|
+
console.log(`โ
${green.underline('Killed process with PID:')} ${orange(pid)}`);
|
142
|
+
}
|
143
|
+
});
|
144
|
+
|
145
|
+
// Schedule SIGKILL fallback for non-Windows platforms
|
146
|
+
if (!isWindows) {
|
147
|
+
setTimeout(() => {
|
148
|
+
try {
|
149
|
+
process.kill(parseInt(pid, 10), 'SIGKILL');
|
150
|
+
console.log(`๐ช ${red.underline('Sent SIGKILL to process with PID:')} ${orange(pid)} (fallback).`);
|
151
|
+
} catch (killError: any) {
|
152
|
+
if (killError.code === 'ESRCH') {
|
153
|
+
console.log(`โ
${green.underline('Process with PID')} ${orange(pid)} ${green.underline('already terminated.')}`);
|
154
|
+
} else {
|
155
|
+
console.error(`โ ๏ธ ${yellow.underline('Failed to send SIGKILL to process with PID')} ${orange(pid)}: ${red(killError.message)}`);
|
156
|
+
}
|
157
|
+
}
|
158
|
+
}, 10000);
|
159
|
+
}
|
160
|
+
} catch (err: any) {
|
161
|
+
console.error(`โ ๏ธ ${yellow.underline('Failed to kill process with PID')} ${orange(pid)}: ${red(err.message)}`);
|
162
|
+
}
|
163
|
+
});
|
164
|
+
});
|
165
|
+
}
|
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,
|
14
|
+
import { runGulp, installPackages, killAllProcesses, cleanupWatchers } from './helpers.js';
|
15
15
|
import { prepare } from './prepare.js';
|
16
16
|
import { spawnSync } from 'child_process';
|
17
17
|
|
@@ -71,10 +71,50 @@ const __filename = fileURLToPath(import.meta.url);
|
|
71
71
|
// eslint-disable-next-line @typescript-eslint/naming-convention
|
72
72
|
const __dirname = dirname(__filename);
|
73
73
|
|
74
|
+
// const cwd = process.cwd();
|
75
|
+
// const command = `watchman watch-del '${cwd}'`;
|
76
|
+
// killAllProcesses('@wix/cli/bin/wix.cjs'); // Matches processes running the Wix CLI
|
77
|
+
// killAllProcesses('wix:dev');
|
78
|
+
|
79
|
+
|
80
|
+
process.on('exit', (code) => {
|
81
|
+
killAllProcesses('@wix/cli/bin/wix.cjs'); // Matches processes running the Wix CLI
|
82
|
+
killAllProcesses('wix:dev');
|
83
|
+
cleanupWatchers();
|
84
|
+
console.log(`๐ช ${magenta.underline('Process exiting with code:')} ${orange(code)}`);
|
85
|
+
});
|
86
|
+
|
74
87
|
process.on('SIGINT', () => {
|
75
|
-
|
76
|
-
|
77
|
-
|
88
|
+
console.log(`๐ ${green.underline('Received Ctrl+C (SIGINT), cleaning up...')}`);
|
89
|
+
killAllProcesses('@wix/cli/bin/wix.cjs'); // Matches processes running the Wix CLI
|
90
|
+
killAllProcesses('wix:dev');
|
91
|
+
cleanupWatchers();
|
92
|
+
process.exit(); // Exit explicitly after handling
|
93
|
+
});
|
94
|
+
|
95
|
+
process.on('SIGTERM', () => {
|
96
|
+
console.log(`๐ ${red.underline('Received termination signal (SIGTERM), cleaning up...')}`);
|
97
|
+
killAllProcesses('@wix/cli/bin/wix.cjs'); // Matches processes running the Wix CLI
|
98
|
+
killAllProcesses('wix:dev');
|
99
|
+
cleanupWatchers();
|
100
|
+
process.exit(); // Exit explicitly after handling
|
101
|
+
});
|
102
|
+
|
103
|
+
process.on('uncaughtException', (error) => {
|
104
|
+
console.error(`๐ฅ ${red.underline('Uncaught Exception:')}`, error);
|
105
|
+
killAllProcesses('@wix/cli/bin/wix.cjs'); // Matches processes running the Wix CLI
|
106
|
+
killAllProcesses('wix:dev');
|
107
|
+
cleanupWatchers();
|
108
|
+
process.exit(1); // Exit with an error code
|
109
|
+
});
|
110
|
+
|
111
|
+
process.on('unhandledRejection', (reason, promise) => {
|
112
|
+
console.error(`๐จ ${yellow.underline('Unhandled Rejection at:')} ${orange(promise)}`);
|
113
|
+
console.error(`๐จ ${red.underline('Reason:')} ${reason}`); cleanupWatchers();
|
114
|
+
killAllProcesses('@wix/cli/bin/wix.cjs'); // Matches processes running the Wix CLI
|
115
|
+
killAllProcesses('wix:dev');
|
116
|
+
cleanupWatchers();
|
117
|
+
process.exit(1); // Exit with an error code
|
78
118
|
});
|
79
119
|
|
80
120
|
/**
|
@@ -115,6 +155,8 @@ async function main(): Promise<void> {
|
|
115
155
|
console.log("๐ฆฎ " + magenta.bold('install') + " : Installs all Wix npm packages listed in the 'lucy.json' file in the project directory.");
|
116
156
|
console.log("๐ฆฎ " + magenta.bold('fix') + " : Runs a fix command to resolve common issues in development or production settings.");
|
117
157
|
console.log("๐ฆฎ " + magenta.bold('docs') + " : Generates documentation for the project.");
|
158
|
+
console.log("๐ฆฎ " + magenta.bold('cypress') + " : Starts the cypress test runner.");
|
159
|
+
console.log("๐ฆฎ " + magenta.bold('e2e') + " : Starts the cypress test runner in CI mode. first argument is the key second is the build id <e2e <somekey <someID>");
|
118
160
|
console.log("\nOptions:");
|
119
161
|
console.log("๐ฆฎ " + magenta.bold('-h, help') + " : Displays this help message.");
|
120
162
|
console.log("๐ฆฎ " + magenta.bold('-v, version') + " : Displays the current version of Lucy CLI as defined in the projectโs package.json.");
|
@@ -194,11 +236,40 @@ async function main(): Promise<void> {
|
|
194
236
|
if(moduleSettings.args.includes('docs')){
|
195
237
|
const res = spawnSync('yarn docs', { shell: true, stdio: 'inherit' });
|
196
238
|
if (res.error) {
|
197
|
-
return console.log((`๐ฉ ${red.underline.bold("=> Failed to
|
239
|
+
return console.log((`๐ฉ ${red.underline.bold("=> Failed to Docs generated => ")} ${orange(res.error.message)}`));
|
198
240
|
}
|
199
241
|
return console.log("๐" + blue.underline(` => Docs generated!`));
|
200
242
|
}
|
201
243
|
|
244
|
+
if(moduleSettings.args.includes('cypress')){
|
245
|
+
const res = spawnSync('yarn cypress', { shell: true, stdio: 'inherit' });
|
246
|
+
if (res.error) {
|
247
|
+
return console.log((`๐ฉ ${red.underline.bold("=> Failed to start cypress => ")} ${orange(res.error.message)}`));
|
248
|
+
}
|
249
|
+
return console.log("๐" + blue.underline(` => Started Cypress`));
|
250
|
+
}
|
251
|
+
|
252
|
+
if (moduleSettings.args.includes('e2e')) {
|
253
|
+
// Extract arguments
|
254
|
+
const e2eIndex = moduleSettings.args.indexOf('e2e');
|
255
|
+
const key = moduleSettings.args[e2eIndex + 1];
|
256
|
+
const buildId = moduleSettings.args[e2eIndex + 2];
|
257
|
+
|
258
|
+
// Validate that both arguments are provided
|
259
|
+
if (!key && !buildId) {
|
260
|
+
console.log(`๐ฉ ${red.underline.bold("=> Missing required arguments:")} ${orange("key")} and ${orange("build ID")}`);
|
261
|
+
process.exit(1);
|
262
|
+
}
|
263
|
+
|
264
|
+
// Run Cypress with the provided arguments
|
265
|
+
const res = spawnSync(`yarn e2e --key ${key} --ci-build-id ${buildId}`, { shell: true, stdio: 'inherit' });
|
266
|
+
if (res.error) {
|
267
|
+
console.log(`๐ฉ ${red.underline.bold("=> Failed to start Cypress =>")} ${orange(res.error.message)}`);
|
268
|
+
process.exit(1);
|
269
|
+
}
|
270
|
+
return console.log("๐ " + blue.underline(`=> Started Cypress successfully`));
|
271
|
+
}
|
272
|
+
|
202
273
|
if(moduleSettings.args.includes('prepare')){
|
203
274
|
await prepare( moduleSettings, projectSettings);
|
204
275
|
|
package/src/settings.json
CHANGED
@@ -57,6 +57,8 @@
|
|
57
57
|
"fix-wix": "lucy-cli fix-wix",
|
58
58
|
"tsc": "tsc -p ./typescript/tsconfig.json --noEmit",
|
59
59
|
"test": "jest --config jest.config.ts --passWithNoTests",
|
60
|
-
"test:watch": "jest --config jest.config.ts --watch"
|
60
|
+
"test:watch": "jest --config jest.config.ts --watch",
|
61
|
+
"cypress": "cypress open",
|
62
|
+
"e2e": "cypress-cloud run --parallel --record"
|
61
63
|
}
|
62
64
|
}
|
package/src/types.d.ts
CHANGED