lucy-cli 1.1.1 → 1.2.0
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 +36 -26
- package/dist/helpers.d.ts +13 -0
- package/dist/helpers.js +51 -4
- package/dist/index.js +45 -2
- package/dist/init.js +38 -2
- package/dist/settings.json +26 -27
- package/files/.madgerc +8 -0
- package/files/.stylelintrc copy.js +8 -0
- package/package.json +2 -1
- package/src/helpers.ts +68 -5
- package/src/index.ts +47 -2
- package/src/init.ts +44 -4
- package/src/settings.json +26 -27
package/README.md
CHANGED
@@ -42,16 +42,16 @@ Contribution are welcome, issue and pull request and I will merge it if i see it
|
|
42
42
|
|
43
43
|
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:
|
44
44
|
|
45
|
-
1.
|
45
|
+
1. **ESLint Configuration**
|
46
46
|
- Adds ESLint with a default configuration (customizable post-init) to maintain consistent code style and prevent common errors.
|
47
47
|
|
48
|
-
2.
|
48
|
+
2. **Wix Type Definitions**
|
49
49
|
- Exposes Wix type definitions located in `.wix/types/wix-code-types`, allowing direct import and access to the types for comprehensive TypeScript support.
|
50
50
|
|
51
|
-
3.
|
51
|
+
3. **Autocomplete and Type Mapping for Page Elements**
|
52
52
|
- Maps Wix page elements to their respective types, so `$w('element')` calls have full TypeScript support, including autocomplete for properties and methods.
|
53
53
|
|
54
|
-
4.
|
54
|
+
4. **Git Submodule Support**
|
55
55
|
- Includes support for git submodules, providing full type support within submodules and enabling the use of libraries and types across projects.
|
56
56
|
- To add a submodule, include the following in the `lucy.json` file:
|
57
57
|
|
@@ -64,37 +64,43 @@ Lucy-CLI is designed to streamline the setup and management of TypeScript within
|
|
64
64
|
}
|
65
65
|
```
|
66
66
|
|
67
|
-
|
67
|
+
5. **Configurable Setup**
|
68
68
|
- 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.
|
69
69
|
|
70
|
-
|
70
|
+
6. **Execute render functions**
|
71
71
|
- Lucy-CLI can execute render functions located in the backend template folder, allowing you to test render functions locally.
|
72
72
|
|
73
|
-
|
74
|
-
- Lucy-CLI can compile
|
73
|
+
-7. **Compile SCSS files**
|
74
|
+
- Lucy-CLI can compile SCSS files to CSS files.
|
75
75
|
- It compiles styles/global.scss file to global.css.
|
76
76
|
|
77
|
-
|
78
|
-
- Lucy-CLI can install Wix npm packages from the `lucy.json` file
|
77
|
+
8. **Wix NPM Package Installation**
|
78
|
+
- Lucy-CLI can install Wix npm packages from the `lucy.json` file.
|
79
79
|
|
80
|
-
|
80
|
+
-9. **Testing with Vitest**
|
81
81
|
- Lucy-CLI can run tests with Vitest.
|
82
82
|
- It runs tests located backend folder with the file name ending with `.spec.ts`.
|
83
83
|
- it creates a code coverage report in the coverage folder in the lib folders and typescript folders.
|
84
84
|
- Vitest is looking for mokes in typescript folder and lib folder.
|
85
85
|
- You can add additional mock folders in vitest.config.ts file.
|
86
86
|
|
87
|
-
|
87
|
+
10. **Linting with ESLint**
|
88
88
|
- Lucy-CLI can lint the code with ESLint.
|
89
89
|
- It uses the ESLint configuration in the `.eslintrc.cjs` file in the project directory.
|
90
90
|
|
91
|
-
|
91
|
+
11. **Add git version during production build**
|
92
92
|
- Lucy-CLI can add the git version to the production build.
|
93
93
|
- It adds the git version to the `public/constant/env.ts` file in the public folder under the key gitTag.
|
94
|
-
|
94
|
+
12. **Use velo-sync to synchronize local collection with wix**
|
95
95
|
- Lucy-CLI can synchronize the local collection with the wix collection.
|
96
96
|
- More information can be found in the [velo-sync](https://www.npmjs.com/package/velo-sync) documentation.
|
97
97
|
|
98
|
+
13. **Synchronize `package.json` with `lucy.json`**
|
99
|
+
- Lucy-CLI can synchronize dependencies from your project's `package.json` directly into the `lucy.json` configuration. The `dependencies` are mapped to `wixPackages` and `devDependencies` are mapped to `devPackages`.
|
100
|
+
|
101
|
+
14. **Manage CLI Templates**
|
102
|
+
- Lucy-CLI uses a templates folder (`~/.lucy-cli`) to store default configurations and file structures for the `init` command. The `templates` command allows you to easily open and customize these templates.
|
103
|
+
|
98
104
|
## Commands & Options
|
99
105
|
|
100
106
|
Lucy-CLI comes with a range of commands and options to help manage your Wix Velo project. Here’s an overview:
|
@@ -105,11 +111,13 @@ Lucy-CLI comes with a range of commands and options to help manage your Wix Velo
|
|
105
111
|
- **`dev`**: Starts the development environment, including setting up any required services for local development.
|
106
112
|
- **`build-prod`**: Builds the project in production mode, optimizing files for deployment.
|
107
113
|
- **`prepare`**: Re-runs initialization commands, useful for setting up a pre-configured environment.
|
108
|
-
- **`velo-sync`**: Synchronizes
|
109
|
-
- **`install`**: Installs all Wix npm packages listed in the `
|
114
|
+
- **`velo-sync`**: Synchronizes Wix collections.
|
115
|
+
- **`install`**: Installs all Wix and dev npm packages listed in the `lucy.json` file.
|
110
116
|
- **`fix`**: Runs a fix command to resolve common issues in development or production settings.
|
111
|
-
-
|
112
|
-
-
|
117
|
+
- **`docs`**: Generates documentation for the project.
|
118
|
+
- **`cypress`**: Starts the Cypress test runner.
|
119
|
+
- **`templates`**: Opens the Lucy CLI templates folder.
|
120
|
+
- **`sync-pkgs`**: Synchronizes dependencies from `package.json` to `lucy.json`.
|
113
121
|
- **🦮 `e2e`**: Starts the Cypress test runner in CI mode.
|
114
122
|
**Usage:** `e2e <someKey> <someID>`
|
115
123
|
- **`someKey`**: The key for the test.
|
@@ -136,7 +144,7 @@ lucy-cli dev
|
|
136
144
|
# Synchronize database and settings
|
137
145
|
lucy-cli sync
|
138
146
|
|
139
|
-
# Install Wix npm packages from '
|
147
|
+
# Install Wix npm packages from 'lucy.json' with locked versions
|
140
148
|
lucy-cli install -l
|
141
149
|
|
142
150
|
# Force start the dev environment
|
@@ -149,29 +157,31 @@ lucy-cli help
|
|
149
157
|
Usage: lucy-cli <command> [options]
|
150
158
|
|
151
159
|
Commands:
|
152
|
-
🦮 init : Initializes
|
160
|
+
🦮 init : Initializes a WIX project to enable full TS support.
|
153
161
|
🦮 dev : Starts the development environment. This includes setting up any required services for local development.
|
154
162
|
🦮 build-prod : Builds the project in production mode, optimizing files for deployment.
|
155
|
-
🦮 prepare : Prepares the project by
|
156
|
-
🦮 velo-sync : Synchronizes
|
157
|
-
🦮 install : Installs all Wix npm packages listed in the '
|
163
|
+
🦮 prepare : Prepares the project by installing packages & initializing git modules, configured in lucy.json.
|
164
|
+
🦮 velo-sync : Synchronizes Wix collections (run `velo-sync -h` for help).
|
165
|
+
🦮 install : Installs all Wix and dev npm packages listed in the 'lucy.json' file.
|
158
166
|
🦮 fix : Runs a fix command to resolve common issues in development or production settings.
|
159
167
|
🦮 docs : Generates documentation for the project.
|
160
168
|
🦮 cypress : Starts the cypress test runner.
|
161
|
-
🦮
|
169
|
+
🦮 templates : Opens the Lucy CLI templates folder.
|
170
|
+
🦮 sync-pkgs : Syncs dependencies from package.json to lucy.json.
|
171
|
+
🦮 e2e : Starts the cypress test runner in CI mode. Usage: `e2e <key> <buildId>`
|
162
172
|
|
163
173
|
Options:
|
164
174
|
🦮 -h, help : Displays this help message.
|
165
175
|
🦮 -v, version : Displays the current version of Lucy CLI as defined in the project’s package.json.
|
166
176
|
🦮 -f, force : Forces specific commands to execute even if they may lead to potential issues.
|
167
177
|
Used for functions like deleting obsolete pages or initializing missing components.
|
168
|
-
🦮 -l : Locks package versions to those specified in
|
178
|
+
🦮 -l : Locks package versions to those specified in `lucy.json` during installation.
|
169
179
|
|
170
180
|
Examples:
|
171
181
|
🦮 lucy-cli init : Initializes a new Wix project.
|
172
182
|
🦮 lucy-cli dev : Starts the development environment.
|
173
183
|
🦮 lucy-cli sync : Synchronizes database and settings.
|
174
|
-
🦮 lucy-cli install : Installs all Wix npm packages from '
|
184
|
+
🦮 lucy-cli install : Installs all Wix and dev npm packages from 'lucy.json'.
|
175
185
|
🦮 lucy-cli dev -f : Starts the dev environment with forced settings.
|
176
186
|
🦮 lucy-cli install -l : Installs Wix npm packages, respecting locked versions specified in the configuration.
|
177
187
|
```
|
package/dist/helpers.d.ts
CHANGED
@@ -17,3 +17,16 @@ export interface VeloSyncConfig {
|
|
17
17
|
}
|
18
18
|
export declare function saveConfig(config: VeloSyncConfig, file: string): Promise<void>;
|
19
19
|
export declare function readConfig(file: string): Promise<VeloSyncConfig>;
|
20
|
+
export declare function createTemplateFolder(moduleSettings: ModuleSettings): Promise<void>;
|
21
|
+
export type PackageJson = {
|
22
|
+
dependencies?: Record<string, string>;
|
23
|
+
devDependencies?: Record<string, string>;
|
24
|
+
[key: string]: any;
|
25
|
+
};
|
26
|
+
/**
|
27
|
+
* Updates a lucy.json file with dependencies from a package.json file.
|
28
|
+
* It replaces 'wixPackages' with 'dependencies' and 'devPackages' with 'devDependencies'.
|
29
|
+
* @param {string} packageJsonPath - Path to the package.json file.
|
30
|
+
* @param {string} lucyConfigPath - Path to the lucy.json file.
|
31
|
+
*/
|
32
|
+
export declare function updateLucyConfigFromPackageJson(packageJsonPath: string, lucyConfigPath: string): Promise<void>;
|
package/dist/helpers.js
CHANGED
@@ -1,12 +1,13 @@
|
|
1
1
|
import chalk from 'chalk';
|
2
2
|
import { simpleGit } from 'simple-git';
|
3
|
-
import { spawnSync } from 'child_process';
|
3
|
+
import { spawnSync, exec } from 'child_process';
|
4
4
|
// https://www.sergevandenoever.nl/run-gulp4-tasks-programatically-from-node/
|
5
|
-
import path from 'path';
|
5
|
+
import path, { join } from 'path';
|
6
6
|
import { fileURLToPath } from 'url';
|
7
|
-
import { exec } from 'child_process';
|
8
7
|
import os from 'os';
|
9
|
-
import fs from 'fs';
|
8
|
+
import fs, { mkdirSync } from 'fs';
|
9
|
+
import fse from 'fs-extra';
|
10
|
+
import { writeFile } from 'fs/promises';
|
10
11
|
import { blue, green, orange, red, yellow, magenta } from './index.js';
|
11
12
|
export async function installPackages(wixPackages, devPackages, cwd, locked) {
|
12
13
|
if (locked)
|
@@ -168,3 +169,49 @@ export async function readConfig(file) {
|
|
168
169
|
let content = await fs.promises.readFile(file, 'utf-8');
|
169
170
|
return JSON.parse(content);
|
170
171
|
}
|
172
|
+
export async function createTemplateFolder(moduleSettings) {
|
173
|
+
const templatesPath = join(os.homedir(), '.lucy-cli');
|
174
|
+
try {
|
175
|
+
mkdirSync(templatesPath);
|
176
|
+
const defaultTemplatePath = join(templatesPath, 'default');
|
177
|
+
mkdirSync(defaultTemplatePath);
|
178
|
+
const sourceFilesPath = join(moduleSettings.packageRoot, 'files');
|
179
|
+
const defaultTemplateFilesPath = join(defaultTemplatePath, 'files');
|
180
|
+
await fse.copy(sourceFilesPath, defaultTemplateFilesPath);
|
181
|
+
const defaultTemplateSettingsPath = join(defaultTemplatePath, 'settings.json');
|
182
|
+
await writeFile(defaultTemplateSettingsPath, JSON.stringify(moduleSettings.settings, null, 2));
|
183
|
+
console.log(green('✅ Default template created successfully!'));
|
184
|
+
}
|
185
|
+
catch (e) {
|
186
|
+
console.log((`💩 ${red.underline.bold("=> Error creating default template =>")} ${orange(e)}`));
|
187
|
+
return;
|
188
|
+
}
|
189
|
+
}
|
190
|
+
/**
|
191
|
+
* Updates a lucy.json file with dependencies from a package.json file.
|
192
|
+
* It replaces 'wixPackages' with 'dependencies' and 'devPackages' with 'devDependencies'.
|
193
|
+
* @param {string} packageJsonPath - Path to the package.json file.
|
194
|
+
* @param {string} lucyConfigPath - Path to the lucy.json file.
|
195
|
+
*/
|
196
|
+
export async function updateLucyConfigFromPackageJson(packageJsonPath, lucyConfigPath) {
|
197
|
+
try {
|
198
|
+
console.log(`🐕 Reading package definitions from ${orange(packageJsonPath)}...`);
|
199
|
+
const pkgJsonContent = await fs.promises.readFile(packageJsonPath, 'utf-8');
|
200
|
+
const packageJson = JSON.parse(pkgJsonContent);
|
201
|
+
console.log(`🐕 Reading Lucy configuration from ${orange(lucyConfigPath)}...`);
|
202
|
+
const lucyConfigContent = await fs.promises.readFile(lucyConfigPath, 'utf-8');
|
203
|
+
const lucyConfig = JSON.parse(lucyConfigContent);
|
204
|
+
const { dependencies = {}, devDependencies = {} } = packageJson;
|
205
|
+
// Note: `wixPackages` are installed using `wix install`. If your `dependencies`
|
206
|
+
// contain packages that are not Wix packages, `lucy-cli install` might fail.
|
207
|
+
lucyConfig.wixPackages = dependencies;
|
208
|
+
lucyConfig.devPackages = devDependencies;
|
209
|
+
console.log(`🐕 Writing updated configuration to ${orange(lucyConfigPath)}...`);
|
210
|
+
await fs.promises.writeFile(lucyConfigPath, JSON.stringify(lucyConfig, null, 2));
|
211
|
+
console.log(green.underline('✅ Lucy configuration updated successfully!'));
|
212
|
+
}
|
213
|
+
catch (error) {
|
214
|
+
console.error(`💩 ${red.underline.bold('=> Error updating lucy.json from package.json:')} ${orange(error.message)}`);
|
215
|
+
throw error; // re-throw to allow caller to handle
|
216
|
+
}
|
217
|
+
}
|
package/dist/index.js
CHANGED
@@ -11,9 +11,10 @@ import { join } from 'path';
|
|
11
11
|
import fs from 'fs/promises';
|
12
12
|
import { init } from './init.js';
|
13
13
|
import { sync } from './sync.js';
|
14
|
-
import { runGulp, installPackages, killAllProcesses, cleanupWatchers } from './helpers.js';
|
14
|
+
import { runGulp, installPackages, killAllProcesses, cleanupWatchers, createTemplateFolder, updateLucyConfigFromPackageJson } from './helpers.js';
|
15
15
|
import { prepare } from './prepare.js';
|
16
|
-
import { spawnSync } from 'child_process';
|
16
|
+
import { spawn, spawnSync } from 'child_process';
|
17
|
+
import os from 'os';
|
17
18
|
export const orange = chalk.hex('#FFA500');
|
18
19
|
export const blue = chalk.blueBright;
|
19
20
|
export const green = chalk.greenBright;
|
@@ -87,6 +88,33 @@ async function main() {
|
|
87
88
|
console.log("🐾" + blue.bold(` => ${projectPackageJSON.version}`));
|
88
89
|
return;
|
89
90
|
}
|
91
|
+
if (moduleSettings.args.includes('templates')) {
|
92
|
+
const templatesPath = join(os.homedir(), '.lucy-cli');
|
93
|
+
if (!existsSync(templatesPath)) {
|
94
|
+
console.log((`💩 ${red.underline.bold("=> Lucy templates folder not found at =>")} ${orange(templatesPath)}`));
|
95
|
+
console.log(chalk.yellow('🐕 Creating templates folder with default template...'));
|
96
|
+
await createTemplateFolder(moduleSettings);
|
97
|
+
}
|
98
|
+
console.log(`🐕 ${blue.underline('Opening templates folder at:')} ${orange(templatesPath)}`);
|
99
|
+
let command;
|
100
|
+
switch (process.platform) {
|
101
|
+
case 'darwin':
|
102
|
+
command = 'open';
|
103
|
+
break;
|
104
|
+
case 'win32':
|
105
|
+
command = 'start';
|
106
|
+
break;
|
107
|
+
default:
|
108
|
+
command = 'xdg-open';
|
109
|
+
break;
|
110
|
+
}
|
111
|
+
const child = spawn(command, [templatesPath], { detached: true, stdio: 'ignore' });
|
112
|
+
child.on('error', (err) => {
|
113
|
+
console.error(`💩 ${red.underline.bold('Failed to open folder:')} ${orange(err.message)}`);
|
114
|
+
});
|
115
|
+
child.unref();
|
116
|
+
return;
|
117
|
+
}
|
90
118
|
// Run velo sync
|
91
119
|
if (moduleSettings.args.includes('velo-sync')) {
|
92
120
|
await sync(moduleSettings, projectSettings);
|
@@ -105,6 +133,8 @@ async function main() {
|
|
105
133
|
console.log("🦮 " + magenta.bold('fix') + " : Runs a fix command to resolve common issues in development or production settings.");
|
106
134
|
console.log("🦮 " + magenta.bold('docs') + " : Generates documentation for the project.");
|
107
135
|
console.log("🦮 " + magenta.bold('cypress') + " : Starts the cypress test runner.");
|
136
|
+
console.log("🦮 " + magenta.bold('templates') + " : Opens the Lucy CLI templates folder.");
|
137
|
+
console.log("🦮 " + magenta.bold('sync-pkgs') + " : Syncs dependencies from package.json to lucy.json.");
|
108
138
|
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>");
|
109
139
|
console.log("\nOptions:");
|
110
140
|
console.log("🦮 " + magenta.bold('-h, help') + " : Displays this help message.");
|
@@ -235,6 +265,19 @@ async function main() {
|
|
235
265
|
runGulp(moduleSettings, projectSettings, 'fix-wix');
|
236
266
|
return;
|
237
267
|
}
|
268
|
+
if (moduleSettings.args.includes('sync-pkgs')) {
|
269
|
+
console.log("🐕" + magenta.underline(' => Syncing package.json with lucy.json'));
|
270
|
+
if (!existsSync(moduleSettings.packageJsonPath)) {
|
271
|
+
console.log((`💩 ${red.underline.bold("=> package.json not found at =>")} ${orange(moduleSettings.packageJsonPath)}`));
|
272
|
+
return;
|
273
|
+
}
|
274
|
+
if (!existsSync(moduleSettings.lucyConfigPath)) {
|
275
|
+
console.log((`💩 ${red.underline.bold("=> lucy.json not found at =>")} ${orange(moduleSettings.lucyConfigPath)}`));
|
276
|
+
return;
|
277
|
+
}
|
278
|
+
await updateLucyConfigFromPackageJson(moduleSettings.packageJsonPath, moduleSettings.lucyConfigPath);
|
279
|
+
return;
|
280
|
+
}
|
238
281
|
console.log("🐕" + blue.underline.bold(' => Running dev'));
|
239
282
|
runGulp(moduleSettings, projectSettings, 'dev');
|
240
283
|
}
|
package/dist/init.js
CHANGED
@@ -4,8 +4,11 @@ import fse from 'fs-extra';
|
|
4
4
|
import { join } from 'path';
|
5
5
|
import fs from 'fs/promises';
|
6
6
|
import path from 'path';
|
7
|
+
import os from 'os';
|
8
|
+
import enquirer from 'enquirer';
|
7
9
|
import { blue, orange, red } from './index.js';
|
8
|
-
import { gitInit, installPackages } from './helpers.js';
|
10
|
+
import { createTemplateFolder, gitInit, installPackages } from './helpers.js';
|
11
|
+
const { Select } = enquirer;
|
9
12
|
/**
|
10
13
|
* Init Lucy project
|
11
14
|
* @param {string} cwd Current working directory
|
@@ -17,7 +20,40 @@ export async function init(moduleSettings, projectSettings) {
|
|
17
20
|
console.log((`💩 ${red.underline.bold("=> This project is already initialized =>")} ${orange(moduleSettings.targetFolder)}`));
|
18
21
|
return;
|
19
22
|
}
|
20
|
-
|
23
|
+
const templatesPath = join(os.homedir(), '.lucy-cli');
|
24
|
+
if (!existsSync(templatesPath)) {
|
25
|
+
console.log(chalk.yellow(`Templates folder not found at ${orange(templatesPath)}. Creating it with a default template...`));
|
26
|
+
await createTemplateFolder(moduleSettings);
|
27
|
+
}
|
28
|
+
const templateChoices = (await fs.readdir(templatesPath, { withFileTypes: true }))
|
29
|
+
.filter(dirent => dirent.isDirectory())
|
30
|
+
.map(dirent => dirent.name);
|
31
|
+
if (templateChoices.length === 0) {
|
32
|
+
console.log((`💩 ${red.underline.bold("=> No templates found in =>")} ${orange(templatesPath)}`));
|
33
|
+
return;
|
34
|
+
}
|
35
|
+
const prompt = new Select({
|
36
|
+
name: 'template',
|
37
|
+
message: 'Select a project template',
|
38
|
+
choices: templateChoices
|
39
|
+
});
|
40
|
+
const selectedTemplate = await prompt.run();
|
41
|
+
const templateDir = join(templatesPath, selectedTemplate);
|
42
|
+
const templateFilesDir = join(templateDir, 'files');
|
43
|
+
const templateSettingsPath = join(templateDir, 'settings.json');
|
44
|
+
if (!existsSync(templateSettingsPath)) {
|
45
|
+
console.log((`💩 ${red.underline.bold("=> Template is missing settings.json at =>")} ${orange(templateSettingsPath)}`));
|
46
|
+
return;
|
47
|
+
}
|
48
|
+
try {
|
49
|
+
const templateSettingsRaw = await fs.readFile(templateSettingsPath, 'utf8');
|
50
|
+
moduleSettings.settings = JSON.parse(templateSettingsRaw);
|
51
|
+
}
|
52
|
+
catch (e) {
|
53
|
+
console.log((`💩 ${red.underline.bold("=> Error reading or parsing template settings =>")} ${orange(e)}`));
|
54
|
+
return;
|
55
|
+
}
|
56
|
+
await copyFolder(templateFilesDir, moduleSettings.targetFolder);
|
21
57
|
await editJson(moduleSettings.packageJsonPath, ['type', 'scripts'], ['module', moduleSettings.settings.scripts]);
|
22
58
|
await stringReplace(join(moduleSettings.targetFolder, 'currents.config.js'), ['__ProjectName__'], [path.basename(moduleSettings.targetFolder)]);
|
23
59
|
await installPackages(moduleSettings.settings.wixPackages, moduleSettings.settings.devPackages, moduleSettings.targetFolder, moduleSettings.lockVersion);
|
package/dist/settings.json
CHANGED
@@ -12,48 +12,47 @@
|
|
12
12
|
"initialized": false,
|
13
13
|
"wixPackages": {},
|
14
14
|
"devPackages": {
|
15
|
-
"@eslint/js": "^9.
|
15
|
+
"@eslint/js": "^9.30.1",
|
16
16
|
"@styled/typescript-styled-plugin": "^1.0.1",
|
17
17
|
"@total-typescript/ts-reset": "^0.6.1",
|
18
|
-
"@types/node": "^
|
18
|
+
"@types/node": "^24.0.10",
|
19
19
|
"@types/nodemailer": "^6.4.17",
|
20
|
-
"
|
21
|
-
"@
|
22
|
-
"@
|
23
|
-
"eslint
|
24
|
-
"@vitest/coverage-v8": "^2.
|
25
|
-
"@
|
26
|
-
"@
|
27
|
-
"@typescript-eslint/utils": "^8.15.0",
|
28
|
-
"@wix/cli": "^1.1.52",
|
20
|
+
"@types/react": "^19.1.8",
|
21
|
+
"@typescript-eslint/eslint-plugin": "^8.35.1",
|
22
|
+
"@typescript-eslint/parser": "^8.35.1",
|
23
|
+
"@typescript-eslint/utils": "^8.35.1",
|
24
|
+
"@vitest/coverage-v8": "^3.2.4",
|
25
|
+
"@vitest/ui": "^3.2.4",
|
26
|
+
"@wix/cli": "^1.1.101",
|
29
27
|
"@wix/eslint-plugin-cli": "^1.0.2",
|
30
|
-
"cypress": "^
|
31
|
-
"cypress-cloud": "^1.
|
32
|
-
"esbuild": "^0.
|
33
|
-
"eslint": "^9.
|
28
|
+
"cypress": "^14.5.1",
|
29
|
+
"cypress-cloud": "^1.13.1",
|
30
|
+
"esbuild": "^0.25.5",
|
31
|
+
"eslint": "^9.30.1",
|
34
32
|
"eslint-plugin-exception-handling": "^1.5.4",
|
35
|
-
"eslint-plugin-import": "^2.
|
36
|
-
"eslint-plugin-jsdoc": "^
|
33
|
+
"eslint-plugin-import": "^2.32.0",
|
34
|
+
"eslint-plugin-jsdoc": "^51.3.3",
|
37
35
|
"eslint-plugin-named-import-spacing": "^1.0.3",
|
38
36
|
"eslint-plugin-promise": "^7.2.1",
|
39
37
|
"eslint-plugin-simple-import-sort": "^12.1.1",
|
40
|
-
"prettier": "^3.
|
41
|
-
"sass": "^1.
|
38
|
+
"prettier": "^3.6.2",
|
39
|
+
"sass": "^1.89.2",
|
42
40
|
"ts-node": "^10.9.2",
|
43
|
-
"tsx": "^4.
|
44
|
-
"typedoc": "0.
|
45
|
-
"
|
46
|
-
"typescript
|
41
|
+
"tsx": "^4.20.3",
|
42
|
+
"typedoc": "^0.28.7",
|
43
|
+
"typedoc-github-theme": "^0.3.0",
|
44
|
+
"typescript": "^5.8.3",
|
45
|
+
"typescript-eslint": "^8.35.1",
|
47
46
|
"typescript-eslint-language-service": "^5.0.5",
|
48
|
-
"
|
49
|
-
"vitest
|
50
|
-
"
|
47
|
+
"vite-tsconfig-paths": "^5.1.4",
|
48
|
+
"vitest": "^3.2.4",
|
49
|
+
"vitest-tsconfig-paths": "^3.4.1"
|
51
50
|
},
|
52
51
|
"scripts": {
|
53
52
|
"postinstall": "wix sync-types",
|
54
53
|
"wix:dev": "wix dev",
|
55
54
|
"dev": "lucy-cli dev",
|
56
|
-
"lint": "eslint .",
|
55
|
+
"lint": "NODE_OPTIONS=\"--max-old-space-size=32768\" eslint .",
|
57
56
|
"docs": "typedoc --tsconfig typescript/tsconfig.json --skipErrorChecking",
|
58
57
|
"build": "lucy-cli build-prod",
|
59
58
|
"fix-wix": "lucy-cli fix-wix",
|
package/files/.madgerc
ADDED
package/package.json
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
{
|
2
2
|
"type": "module",
|
3
3
|
"name": "lucy-cli",
|
4
|
-
"version": "1.
|
4
|
+
"version": "1.2.0",
|
5
5
|
"description": "Lucy Framework for WIX Studio Editor",
|
6
6
|
"main": ".dist/index.js",
|
7
7
|
"scripts": {
|
@@ -38,6 +38,7 @@
|
|
38
38
|
"chalk": "^5.3.0",
|
39
39
|
"cypress": "13.15.2",
|
40
40
|
"cypress-cloud": "^1.9.3",
|
41
|
+
"enquirer": "^2.4.1",
|
41
42
|
"glob": "^7.2.3",
|
42
43
|
"gulp": "4.0.2",
|
43
44
|
"gulp-clean": "^0.4.0",
|
package/src/helpers.ts
CHANGED
@@ -1,16 +1,16 @@
|
|
1
1
|
import chalk from 'chalk';
|
2
2
|
import { simpleGit } from 'simple-git';
|
3
|
-
import { spawnSync } from 'child_process';
|
3
|
+
import { spawnSync, exec } from 'child_process';
|
4
4
|
// https://www.sergevandenoever.nl/run-gulp4-tasks-programatically-from-node/
|
5
|
-
import path from 'path';
|
5
|
+
import path, { join } from 'path';
|
6
6
|
import { fileURLToPath } from 'url';
|
7
7
|
import { LucySettings, ModuleSettings, ProjectSettings } from '.';
|
8
|
-
import { exec } from 'child_process';
|
9
8
|
import os from 'os';
|
10
|
-
import fs from 'fs';
|
9
|
+
import fs, { mkdirSync } from 'fs';
|
10
|
+
import fse from 'fs-extra';
|
11
|
+
import { writeFile } from 'fs/promises';
|
11
12
|
|
12
13
|
import { blue, green, orange, red, yellow, magenta } from './index.js';
|
13
|
-
import { fsync } from 'fs';
|
14
14
|
|
15
15
|
export async function installPackages(wixPackages: Record<string, string>, devPackages: Record<string, string>, cwd: string, locked: boolean ) {
|
16
16
|
if (locked) console.log("🐕" + blue.underline(` => Installing & version locked packages!`));
|
@@ -187,4 +187,67 @@ export async function saveConfig(config:VeloSyncConfig, file: string) {
|
|
187
187
|
export async function readConfig(file: string): Promise<VeloSyncConfig> {
|
188
188
|
let content = await fs.promises.readFile(file, 'utf-8');
|
189
189
|
return JSON.parse(content);
|
190
|
+
}
|
191
|
+
|
192
|
+
export async function createTemplateFolder(moduleSettings: ModuleSettings) {
|
193
|
+
const templatesPath = join(os.homedir(), '.lucy-cli');
|
194
|
+
|
195
|
+
try {
|
196
|
+
mkdirSync(templatesPath);
|
197
|
+
|
198
|
+
const defaultTemplatePath = join(templatesPath, 'default');
|
199
|
+
mkdirSync(defaultTemplatePath);
|
200
|
+
|
201
|
+
const sourceFilesPath = join(moduleSettings.packageRoot, 'files');
|
202
|
+
const defaultTemplateFilesPath = join(defaultTemplatePath, 'files');
|
203
|
+
await fse.copy(sourceFilesPath, defaultTemplateFilesPath);
|
204
|
+
|
205
|
+
const defaultTemplateSettingsPath = join(defaultTemplatePath, 'settings.json');
|
206
|
+
await writeFile(defaultTemplateSettingsPath, JSON.stringify(moduleSettings.settings, null, 2));
|
207
|
+
|
208
|
+
console.log(green('✅ Default template created successfully!'));
|
209
|
+
} catch (e) {
|
210
|
+
console.log((`💩 ${red.underline.bold("=> Error creating default template =>")} ${orange(e)}`));
|
211
|
+
return;
|
212
|
+
}
|
213
|
+
}
|
214
|
+
|
215
|
+
export type PackageJson = {
|
216
|
+
dependencies?: Record<string, string>;
|
217
|
+
devDependencies?: Record<string, string>;
|
218
|
+
[key: string]: any;
|
219
|
+
}
|
220
|
+
|
221
|
+
/**
|
222
|
+
* Updates a lucy.json file with dependencies from a package.json file.
|
223
|
+
* It replaces 'wixPackages' with 'dependencies' and 'devPackages' with 'devDependencies'.
|
224
|
+
* @param {string} packageJsonPath - Path to the package.json file.
|
225
|
+
* @param {string} lucyConfigPath - Path to the lucy.json file.
|
226
|
+
*/
|
227
|
+
export async function updateLucyConfigFromPackageJson(packageJsonPath: string, lucyConfigPath: string): Promise<void> {
|
228
|
+
try {
|
229
|
+
console.log(`🐕 Reading package definitions from ${orange(packageJsonPath)}...`);
|
230
|
+
const pkgJsonContent = await fs.promises.readFile(packageJsonPath, 'utf-8');
|
231
|
+
const packageJson: PackageJson = JSON.parse(pkgJsonContent);
|
232
|
+
|
233
|
+
console.log(`🐕 Reading Lucy configuration from ${orange(lucyConfigPath)}...`);
|
234
|
+
const lucyConfigContent = await fs.promises.readFile(lucyConfigPath, 'utf-8');
|
235
|
+
const lucyConfig: LucySettings = JSON.parse(lucyConfigContent);
|
236
|
+
|
237
|
+
const { dependencies = {}, devDependencies = {} } = packageJson;
|
238
|
+
|
239
|
+
// Note: `wixPackages` are installed using `wix install`. If your `dependencies`
|
240
|
+
// contain packages that are not Wix packages, `lucy-cli install` might fail.
|
241
|
+
lucyConfig.wixPackages = dependencies;
|
242
|
+
lucyConfig.devPackages = devDependencies;
|
243
|
+
|
244
|
+
console.log(`🐕 Writing updated configuration to ${orange(lucyConfigPath)}...`);
|
245
|
+
await fs.promises.writeFile(lucyConfigPath, JSON.stringify(lucyConfig, null, 2));
|
246
|
+
|
247
|
+
console.log(green.underline('✅ Lucy configuration updated successfully!'));
|
248
|
+
|
249
|
+
} catch (error: any) {
|
250
|
+
console.error(`💩 ${red.underline.bold('=> Error updating lucy.json from package.json:')} ${orange(error.message)}`);
|
251
|
+
throw error; // re-throw to allow caller to handle
|
252
|
+
}
|
190
253
|
}
|
package/src/index.ts
CHANGED
@@ -11,9 +11,10 @@ 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, killAllProcesses, cleanupWatchers } from './helpers.js';
|
14
|
+
import { runGulp, installPackages, killAllProcesses, cleanupWatchers, createTemplateFolder, updateLucyConfigFromPackageJson } from './helpers.js';
|
15
15
|
import { prepare } from './prepare.js';
|
16
|
-
import { spawnSync } from 'child_process';
|
16
|
+
import { spawn, spawnSync } from 'child_process';
|
17
|
+
import os from 'os';
|
17
18
|
|
18
19
|
export type LucySettings = {
|
19
20
|
modules: {
|
@@ -147,6 +148,33 @@ async function main(): Promise<void> {
|
|
147
148
|
|
148
149
|
return;
|
149
150
|
}
|
151
|
+
|
152
|
+
if (moduleSettings.args.includes('templates')) {
|
153
|
+
const templatesPath = join(os.homedir(), '.lucy-cli');
|
154
|
+
if (!existsSync(templatesPath)) {
|
155
|
+
console.log((`💩 ${red.underline.bold("=> Lucy templates folder not found at =>")} ${orange(templatesPath)}`));
|
156
|
+
console.log(chalk.yellow('🐕 Creating templates folder with default template...'));
|
157
|
+
await createTemplateFolder(moduleSettings);
|
158
|
+
}
|
159
|
+
|
160
|
+
console.log(`🐕 ${blue.underline('Opening templates folder at:')} ${orange(templatesPath)}`);
|
161
|
+
|
162
|
+
let command: string;
|
163
|
+
switch (process.platform) {
|
164
|
+
case 'darwin': command = 'open'; break;
|
165
|
+
case 'win32': command = 'start'; break;
|
166
|
+
default: command = 'xdg-open'; break;
|
167
|
+
}
|
168
|
+
|
169
|
+
const child = spawn(command, [templatesPath], { detached: true, stdio: 'ignore' });
|
170
|
+
child.on('error', (err) => {
|
171
|
+
console.error(`💩 ${red.underline.bold('Failed to open folder:')} ${orange(err.message)}`);
|
172
|
+
});
|
173
|
+
child.unref();
|
174
|
+
return;
|
175
|
+
}
|
176
|
+
|
177
|
+
|
150
178
|
// Run velo sync
|
151
179
|
if(moduleSettings.args.includes('velo-sync')){
|
152
180
|
await sync(moduleSettings, projectSettings);
|
@@ -167,6 +195,8 @@ async function main(): Promise<void> {
|
|
167
195
|
console.log("🦮 " + magenta.bold('fix') + " : Runs a fix command to resolve common issues in development or production settings.");
|
168
196
|
console.log("🦮 " + magenta.bold('docs') + " : Generates documentation for the project.");
|
169
197
|
console.log("🦮 " + magenta.bold('cypress') + " : Starts the cypress test runner.");
|
198
|
+
console.log("🦮 " + magenta.bold('templates') + " : Opens the Lucy CLI templates folder.");
|
199
|
+
console.log("🦮 " + magenta.bold('sync-pkgs') + " : Syncs dependencies from package.json to lucy.json.");
|
170
200
|
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>");
|
171
201
|
console.log("\nOptions:");
|
172
202
|
console.log("🦮 " + magenta.bold('-h, help') + " : Displays this help message.");
|
@@ -316,6 +346,21 @@ async function main(): Promise<void> {
|
|
316
346
|
return;
|
317
347
|
}
|
318
348
|
|
349
|
+
if(moduleSettings.args.includes('sync-pkgs')){
|
350
|
+
console.log("🐕" + magenta.underline(' => Syncing package.json with lucy.json'));
|
351
|
+
if (!existsSync(moduleSettings.packageJsonPath)) {
|
352
|
+
console.log((`💩 ${red.underline.bold("=> package.json not found at =>")} ${orange(moduleSettings.packageJsonPath)}`));
|
353
|
+
return;
|
354
|
+
}
|
355
|
+
if (!existsSync(moduleSettings.lucyConfigPath)) {
|
356
|
+
console.log((`💩 ${red.underline.bold("=> lucy.json not found at =>")} ${orange(moduleSettings.lucyConfigPath)}`));
|
357
|
+
return;
|
358
|
+
}
|
359
|
+
await updateLucyConfigFromPackageJson(moduleSettings.packageJsonPath, moduleSettings.lucyConfigPath);
|
360
|
+
return;
|
361
|
+
}
|
362
|
+
|
363
|
+
|
319
364
|
console.log("🐕" + blue.underline.bold(' => Running dev'));
|
320
365
|
runGulp(moduleSettings, projectSettings, 'dev');
|
321
366
|
}
|
package/src/init.ts
CHANGED
@@ -2,13 +2,14 @@ import chalk from 'chalk';
|
|
2
2
|
import { existsSync, mkdirSync, promises as fsPromises } from 'fs';
|
3
3
|
import fse from 'fs-extra';
|
4
4
|
import { join } from 'path';
|
5
|
-
import { simpleGit } from 'simple-git';
|
6
5
|
import fs from 'fs/promises';
|
7
|
-
import { spawnSync } from 'child_process';
|
8
6
|
import path from 'path';
|
7
|
+
import os from 'os';
|
8
|
+
import enquirer from 'enquirer';
|
9
9
|
import { ModuleSettings, ProjectSettings, blue, green, orange, red } from './index.js';
|
10
|
-
import { gitInit, installPackages } from './helpers.js';
|
10
|
+
import { createTemplateFolder, gitInit, installPackages } from './helpers.js';
|
11
11
|
|
12
|
+
const { Select } = enquirer as any;
|
12
13
|
/**
|
13
14
|
* Init Lucy project
|
14
15
|
* @param {string} cwd Current working directory
|
@@ -22,7 +23,46 @@ export async function init(moduleSettings: ModuleSettings, projectSettings: Proj
|
|
22
23
|
return;
|
23
24
|
}
|
24
25
|
|
25
|
-
|
26
|
+
const templatesPath = join(os.homedir(), '.lucy-cli');
|
27
|
+
if (!existsSync(templatesPath)) {
|
28
|
+
console.log(chalk.yellow(`Templates folder not found at ${orange(templatesPath)}. Creating it with a default template...`));
|
29
|
+
await createTemplateFolder(moduleSettings);
|
30
|
+
}
|
31
|
+
|
32
|
+
const templateChoices = (await fs.readdir(templatesPath, { withFileTypes: true }))
|
33
|
+
.filter(dirent => dirent.isDirectory())
|
34
|
+
.map(dirent => dirent.name);
|
35
|
+
|
36
|
+
if (templateChoices.length === 0) {
|
37
|
+
console.log((`💩 ${red.underline.bold("=> No templates found in =>")} ${orange(templatesPath)}`));
|
38
|
+
return;
|
39
|
+
}
|
40
|
+
|
41
|
+
const prompt = new Select({
|
42
|
+
name: 'template',
|
43
|
+
message: 'Select a project template',
|
44
|
+
choices: templateChoices
|
45
|
+
});
|
46
|
+
|
47
|
+
const selectedTemplate = await prompt.run();
|
48
|
+
const templateDir = join(templatesPath, selectedTemplate);
|
49
|
+
const templateFilesDir = join(templateDir, 'files');
|
50
|
+
const templateSettingsPath = join(templateDir, 'settings.json');
|
51
|
+
|
52
|
+
if (!existsSync(templateSettingsPath)) {
|
53
|
+
console.log((`💩 ${red.underline.bold("=> Template is missing settings.json at =>")} ${orange(templateSettingsPath)}`));
|
54
|
+
return;
|
55
|
+
}
|
56
|
+
|
57
|
+
try {
|
58
|
+
const templateSettingsRaw = await fs.readFile(templateSettingsPath, 'utf8');
|
59
|
+
moduleSettings.settings = JSON.parse(templateSettingsRaw);
|
60
|
+
} catch (e) {
|
61
|
+
console.log((`💩 ${red.underline.bold("=> Error reading or parsing template settings =>")} ${orange(e)}`));
|
62
|
+
return;
|
63
|
+
}
|
64
|
+
|
65
|
+
await copyFolder(templateFilesDir, moduleSettings.targetFolder);
|
26
66
|
|
27
67
|
await editJson(moduleSettings.packageJsonPath, ['type', 'scripts'], ['module', moduleSettings.settings.scripts ]);
|
28
68
|
await stringReplace(join(moduleSettings.targetFolder, 'currents.config.js'), ['__ProjectName__'], [path.basename(moduleSettings.targetFolder)]);
|
package/src/settings.json
CHANGED
@@ -12,48 +12,47 @@
|
|
12
12
|
"initialized": false,
|
13
13
|
"wixPackages": {},
|
14
14
|
"devPackages": {
|
15
|
-
"@eslint/js": "^9.
|
15
|
+
"@eslint/js": "^9.30.1",
|
16
16
|
"@styled/typescript-styled-plugin": "^1.0.1",
|
17
17
|
"@total-typescript/ts-reset": "^0.6.1",
|
18
|
-
"@types/node": "^
|
18
|
+
"@types/node": "^24.0.10",
|
19
19
|
"@types/nodemailer": "^6.4.17",
|
20
|
-
"
|
21
|
-
"@
|
22
|
-
"@
|
23
|
-
"eslint
|
24
|
-
"@vitest/coverage-v8": "^2.
|
25
|
-
"@
|
26
|
-
"@
|
27
|
-
"@typescript-eslint/utils": "^8.15.0",
|
28
|
-
"@wix/cli": "^1.1.52",
|
20
|
+
"@types/react": "^19.1.8",
|
21
|
+
"@typescript-eslint/eslint-plugin": "^8.35.1",
|
22
|
+
"@typescript-eslint/parser": "^8.35.1",
|
23
|
+
"@typescript-eslint/utils": "^8.35.1",
|
24
|
+
"@vitest/coverage-v8": "^3.2.4",
|
25
|
+
"@vitest/ui": "^3.2.4",
|
26
|
+
"@wix/cli": "^1.1.101",
|
29
27
|
"@wix/eslint-plugin-cli": "^1.0.2",
|
30
|
-
"cypress": "^
|
31
|
-
"cypress-cloud": "^1.
|
32
|
-
"esbuild": "^0.
|
33
|
-
"eslint": "^9.
|
28
|
+
"cypress": "^14.5.1",
|
29
|
+
"cypress-cloud": "^1.13.1",
|
30
|
+
"esbuild": "^0.25.5",
|
31
|
+
"eslint": "^9.30.1",
|
34
32
|
"eslint-plugin-exception-handling": "^1.5.4",
|
35
|
-
"eslint-plugin-import": "^2.
|
36
|
-
"eslint-plugin-jsdoc": "^
|
33
|
+
"eslint-plugin-import": "^2.32.0",
|
34
|
+
"eslint-plugin-jsdoc": "^51.3.3",
|
37
35
|
"eslint-plugin-named-import-spacing": "^1.0.3",
|
38
36
|
"eslint-plugin-promise": "^7.2.1",
|
39
37
|
"eslint-plugin-simple-import-sort": "^12.1.1",
|
40
|
-
"prettier": "^3.
|
41
|
-
"sass": "^1.
|
38
|
+
"prettier": "^3.6.2",
|
39
|
+
"sass": "^1.89.2",
|
42
40
|
"ts-node": "^10.9.2",
|
43
|
-
"tsx": "^4.
|
44
|
-
"typedoc": "0.
|
45
|
-
"
|
46
|
-
"typescript
|
41
|
+
"tsx": "^4.20.3",
|
42
|
+
"typedoc": "^0.28.7",
|
43
|
+
"typedoc-github-theme": "^0.3.0",
|
44
|
+
"typescript": "^5.8.3",
|
45
|
+
"typescript-eslint": "^8.35.1",
|
47
46
|
"typescript-eslint-language-service": "^5.0.5",
|
48
|
-
"
|
49
|
-
"vitest
|
50
|
-
"
|
47
|
+
"vite-tsconfig-paths": "^5.1.4",
|
48
|
+
"vitest": "^3.2.4",
|
49
|
+
"vitest-tsconfig-paths": "^3.4.1"
|
51
50
|
},
|
52
51
|
"scripts": {
|
53
52
|
"postinstall": "wix sync-types",
|
54
53
|
"wix:dev": "wix dev",
|
55
54
|
"dev": "lucy-cli dev",
|
56
|
-
"lint": "eslint .",
|
55
|
+
"lint": "NODE_OPTIONS=\"--max-old-space-size=32768\" eslint .",
|
57
56
|
"docs": "typedoc --tsconfig typescript/tsconfig.json --skipErrorChecking",
|
58
57
|
"build": "lucy-cli build-prod",
|
59
58
|
"fix-wix": "lucy-cli fix-wix",
|