slicejs-cli 3.4.0 → 3.5.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/AGENTS.md +247 -0
- package/client.js +63 -64
- package/commands/Print.js +11 -15
- package/commands/Validations.js +12 -23
- package/commands/buildProduction/buildProduction.js +23 -26
- package/commands/bundle/bundle.js +10 -11
- package/commands/createComponent/createComponent.js +14 -16
- package/commands/deleteComponent/deleteComponent.js +6 -6
- package/commands/doctor/doctor.js +11 -14
- package/commands/getComponent/getComponent.js +99 -162
- package/commands/init/init.js +77 -26
- package/commands/listComponents/listComponents.js +18 -21
- package/commands/startServer/startServer.js +21 -24
- package/commands/startServer/watchServer.js +7 -7
- package/commands/types/types.js +53 -18
- package/commands/utils/PathHelper.js +9 -2
- package/commands/utils/VersionChecker.js +3 -3
- package/commands/utils/bundling/DependencyAnalyzer.js +8 -16
- package/commands/utils/loadConfig.js +31 -0
- package/commands/utils/updateManager.js +3 -4
- package/docs/superpowers/specs/2026-05-10-pwa-generate-design.md +105 -105
- package/package.json +14 -2
- package/post.js +2 -2
- package/tests/bundle-generator.test.js +3 -20
- package/tests/component-registry-parse.test.js +34 -0
- package/tests/fixtures/components.js +8 -0
- package/tests/fixtures/sliceConfig.json +74 -0
- package/tests/getcomponent.test.js +407 -0
- package/tests/helpers/setup.js +97 -0
- package/tests/init-command-contract.test.js +46 -0
- package/tests/local-cli-delegation.test.js +7 -5
- package/tests/path-helper.test.js +206 -0
- package/tests/types-breakage.test.js +491 -0
- package/tests/types-generator-errors.test.js +361 -0
- package/tests/types-generator.test.js +172 -184
|
@@ -1,18 +1,15 @@
|
|
|
1
|
-
// commands/buildProduction/buildProduction.js -
|
|
1
|
+
// commands/buildProduction/buildProduction.js - CLEAN VERSION
|
|
2
2
|
|
|
3
3
|
import fs from 'fs-extra';
|
|
4
4
|
import path from 'path';
|
|
5
|
-
import { fileURLToPath } from 'url';
|
|
6
5
|
import { minify as terserMinify } from 'terser';
|
|
7
6
|
import { minify } from 'html-minifier-terser';
|
|
8
7
|
import CleanCSS from 'clean-css';
|
|
9
8
|
import Print from '../Print.js';
|
|
10
9
|
import { getSrcPath, getDistPath, getConfigPath } from '../utils/PathHelper.js';
|
|
11
10
|
|
|
12
|
-
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
13
|
-
|
|
14
11
|
/**
|
|
15
|
-
*
|
|
12
|
+
* Loads configuration from sliceConfig.json
|
|
16
13
|
*/
|
|
17
14
|
const loadConfig = () => {
|
|
18
15
|
try {
|
|
@@ -26,7 +23,7 @@ const loadConfig = () => {
|
|
|
26
23
|
};
|
|
27
24
|
|
|
28
25
|
/**
|
|
29
|
-
*
|
|
26
|
+
* Checks necessary build dependencies
|
|
30
27
|
*/
|
|
31
28
|
async function checkBuildDependencies() {
|
|
32
29
|
const srcDir = getSrcPath(import.meta.url);
|
|
@@ -50,7 +47,7 @@ async function checkBuildDependencies() {
|
|
|
50
47
|
}
|
|
51
48
|
|
|
52
49
|
/**
|
|
53
|
-
*
|
|
50
|
+
* Verifies that critical Slice.js files exist
|
|
54
51
|
*/
|
|
55
52
|
async function verifySliceFiles(srcDir) {
|
|
56
53
|
Print.info('Verifying Slice.js critical files...');
|
|
@@ -72,7 +69,7 @@ async function verifySliceFiles(srcDir) {
|
|
|
72
69
|
}
|
|
73
70
|
|
|
74
71
|
/**
|
|
75
|
-
*
|
|
72
|
+
* Verifies build integrity for Slice.js
|
|
76
73
|
*/
|
|
77
74
|
async function verifyBuildIntegrity(distDir) {
|
|
78
75
|
Print.info('Verifying build integrity for Slice.js...');
|
|
@@ -101,7 +98,7 @@ async function verifyBuildIntegrity(distDir) {
|
|
|
101
98
|
}
|
|
102
99
|
|
|
103
100
|
/**
|
|
104
|
-
*
|
|
101
|
+
* Copies sliceConfig.json to the dist directory
|
|
105
102
|
*/
|
|
106
103
|
async function copySliceConfig() {
|
|
107
104
|
const srcConfig = getConfigPath(import.meta.url);
|
|
@@ -114,7 +111,7 @@ async function copySliceConfig() {
|
|
|
114
111
|
}
|
|
115
112
|
|
|
116
113
|
/**
|
|
117
|
-
*
|
|
114
|
+
* Processes a complete directory
|
|
118
115
|
*/
|
|
119
116
|
async function processDirectory(srcPath, distPath, baseSrcPath, options) {
|
|
120
117
|
const items = await fs.readdir(srcPath);
|
|
@@ -134,7 +131,7 @@ async function processDirectory(srcPath, distPath, baseSrcPath, options) {
|
|
|
134
131
|
}
|
|
135
132
|
|
|
136
133
|
/**
|
|
137
|
-
*
|
|
134
|
+
* Processes an individual file
|
|
138
135
|
*/
|
|
139
136
|
async function processFile(srcFilePath, distFilePath, options) {
|
|
140
137
|
const ext = path.extname(srcFilePath).toLowerCase();
|
|
@@ -200,7 +197,7 @@ async function processFile(srcFilePath, distFilePath, options) {
|
|
|
200
197
|
}
|
|
201
198
|
|
|
202
199
|
/**
|
|
203
|
-
*
|
|
200
|
+
* Processes the components.js file in a special way
|
|
204
201
|
*/
|
|
205
202
|
async function processComponentsFile(srcPath, distPath) {
|
|
206
203
|
const content = await fs.readFile(srcPath, 'utf8');
|
|
@@ -229,7 +226,7 @@ async function processComponentsFile(srcPath, distPath) {
|
|
|
229
226
|
}
|
|
230
227
|
|
|
231
228
|
/**
|
|
232
|
-
*
|
|
229
|
+
* Minifies JavaScript files preserving Slice.js architecture
|
|
233
230
|
*/
|
|
234
231
|
async function minifyJavaScript(srcPath, distPath) {
|
|
235
232
|
const content = await fs.readFile(srcPath, 'utf8');
|
|
@@ -250,9 +247,9 @@ async function minifyJavaScript(srcPath, distPath) {
|
|
|
250
247
|
reserved: [
|
|
251
248
|
// Core Slice
|
|
252
249
|
'slice', 'Slice', 'SliceJS', 'window', 'document',
|
|
253
|
-
//
|
|
250
|
+
// Main classes
|
|
254
251
|
'Controller', 'StylesManager', 'Router', 'Logger', 'Debugger',
|
|
255
|
-
//
|
|
252
|
+
// Slice methods
|
|
256
253
|
'getClass', 'isProduction', 'getComponent', 'build', 'setTheme', 'attachTemplate',
|
|
257
254
|
// Controller
|
|
258
255
|
'componentCategories', 'templates', 'classes', 'requestedStyles', 'activeComponents',
|
|
@@ -269,7 +266,7 @@ async function minifyJavaScript(srcPath, distPath) {
|
|
|
269
266
|
'onClickCallback', 'props',
|
|
270
267
|
// Custom Elements
|
|
271
268
|
'customElements', 'define', 'HTMLElement',
|
|
272
|
-
// DOM APIs
|
|
269
|
+
// Critical DOM APIs
|
|
273
270
|
'addEventListener', 'removeEventListener', 'querySelector', 'querySelectorAll',
|
|
274
271
|
'appendChild', 'removeChild', 'innerHTML', 'textContent', 'style', 'classList',
|
|
275
272
|
// Lifecycle
|
|
@@ -308,7 +305,7 @@ async function minifyJavaScript(srcPath, distPath) {
|
|
|
308
305
|
}
|
|
309
306
|
|
|
310
307
|
/**
|
|
311
|
-
*
|
|
308
|
+
* Minifies CSS files
|
|
312
309
|
*/
|
|
313
310
|
async function minifyCSS(srcPath, distPath) {
|
|
314
311
|
const content = await fs.readFile(srcPath, 'utf8');
|
|
@@ -334,7 +331,7 @@ async function minifyCSS(srcPath, distPath) {
|
|
|
334
331
|
}
|
|
335
332
|
|
|
336
333
|
/**
|
|
337
|
-
*
|
|
334
|
+
* Minifies HTML files
|
|
338
335
|
*/
|
|
339
336
|
async function minifyHTML(srcPath, distPath) {
|
|
340
337
|
const content = await fs.readFile(srcPath, 'utf8');
|
|
@@ -367,7 +364,7 @@ async function minifyHTML(srcPath, distPath) {
|
|
|
367
364
|
}
|
|
368
365
|
|
|
369
366
|
/**
|
|
370
|
-
*
|
|
367
|
+
* Creates an optimized bundle of the main file
|
|
371
368
|
*/
|
|
372
369
|
async function createOptimizedBundle() {
|
|
373
370
|
Print.buildProgress('Creating optimized bundle...');
|
|
@@ -382,7 +379,7 @@ async function createOptimizedBundle() {
|
|
|
382
379
|
}
|
|
383
380
|
|
|
384
381
|
/**
|
|
385
|
-
*
|
|
382
|
+
* Generates build statistics
|
|
386
383
|
*/
|
|
387
384
|
async function generateBuildStats(srcDir, distDir) {
|
|
388
385
|
Print.buildProgress('Generating build statistics...');
|
|
@@ -422,7 +419,7 @@ async function generateBuildStats(srcDir, distDir) {
|
|
|
422
419
|
}
|
|
423
420
|
|
|
424
421
|
/**
|
|
425
|
-
*
|
|
422
|
+
* Analyzes the build without building
|
|
426
423
|
*/
|
|
427
424
|
async function analyzeBuild() {
|
|
428
425
|
const distDir = getDistPath(import.meta.url);
|
|
@@ -440,7 +437,7 @@ async function analyzeBuild() {
|
|
|
440
437
|
}
|
|
441
438
|
|
|
442
439
|
/**
|
|
443
|
-
*
|
|
440
|
+
* MAIN BUILD FUNCTION
|
|
444
441
|
*/
|
|
445
442
|
export default async function buildProduction(options = {}) {
|
|
446
443
|
const startTime = Date.now();
|
|
@@ -458,7 +455,7 @@ export default async function buildProduction(options = {}) {
|
|
|
458
455
|
|
|
459
456
|
await verifySliceFiles(srcDir);
|
|
460
457
|
|
|
461
|
-
//
|
|
458
|
+
// Clean dist directory
|
|
462
459
|
if (await fs.pathExists(distDir)) {
|
|
463
460
|
if (!options.skipClean) {
|
|
464
461
|
Print.info('Cleaning previous build...');
|
|
@@ -470,7 +467,7 @@ export default async function buildProduction(options = {}) {
|
|
|
470
467
|
await fs.ensureDir(distDir);
|
|
471
468
|
await copySliceConfig();
|
|
472
469
|
|
|
473
|
-
//
|
|
470
|
+
// Process files
|
|
474
471
|
Print.info('Processing and optimizing source files for Slice.js...');
|
|
475
472
|
await processDirectory(srcDir, distDir, srcDir, options);
|
|
476
473
|
Print.success('All source files processed and optimized');
|
|
@@ -498,7 +495,7 @@ export default async function buildProduction(options = {}) {
|
|
|
498
495
|
}
|
|
499
496
|
|
|
500
497
|
/**
|
|
501
|
-
*
|
|
498
|
+
* Preview server for testing the production build
|
|
502
499
|
*/
|
|
503
500
|
export async function serveProductionBuild(port) {
|
|
504
501
|
try {
|
|
@@ -546,7 +543,7 @@ export async function serveProductionBuild(port) {
|
|
|
546
543
|
}
|
|
547
544
|
|
|
548
545
|
/**
|
|
549
|
-
*
|
|
546
|
+
* Build command with options
|
|
550
547
|
*/
|
|
551
548
|
export async function buildCommand(options = {}) {
|
|
552
549
|
const config = loadConfig();
|
|
@@ -4,13 +4,14 @@ import fs from 'fs-extra';
|
|
|
4
4
|
import DependencyAnalyzer from '../utils/bundling/DependencyAnalyzer.js';
|
|
5
5
|
import BundleGenerator from '../utils/bundling/BundleGenerator.js';
|
|
6
6
|
import Print from '..//Print.js';
|
|
7
|
+
import { getProjectRoot, getSrcPath } from '../utils/PathHelper.js';
|
|
7
8
|
|
|
8
9
|
/**
|
|
9
10
|
* Main bundling command
|
|
10
11
|
*/
|
|
11
12
|
export default async function bundle(options = {}) {
|
|
12
13
|
const startTime = Date.now();
|
|
13
|
-
const projectRoot =
|
|
14
|
+
const projectRoot = getProjectRoot(import.meta.url);
|
|
14
15
|
|
|
15
16
|
try {
|
|
16
17
|
Print.title('📦 Slice.js Bundle Generator');
|
|
@@ -82,14 +83,14 @@ export default async function bundle(options = {}) {
|
|
|
82
83
|
*/
|
|
83
84
|
async function validateProject(projectRoot) {
|
|
84
85
|
const requiredPaths = [
|
|
85
|
-
'
|
|
86
|
-
'
|
|
86
|
+
getSrcPath(import.meta.url, 'Components', 'components.js'),
|
|
87
|
+
getSrcPath(import.meta.url, 'routes.js')
|
|
87
88
|
];
|
|
88
89
|
|
|
89
|
-
for (const
|
|
90
|
-
const fullPath = path.join(projectRoot, reqPath);
|
|
90
|
+
for (const fullPath of requiredPaths) {
|
|
91
91
|
if (!await fs.pathExists(fullPath)) {
|
|
92
|
-
|
|
92
|
+
const relativePath = path.relative(projectRoot, fullPath);
|
|
93
|
+
throw new Error(`Required file not found: ${relativePath}`);
|
|
93
94
|
}
|
|
94
95
|
}
|
|
95
96
|
}
|
|
@@ -146,8 +147,7 @@ function printSummary(result, startTime) {
|
|
|
146
147
|
* Subcommand: Clean bundles
|
|
147
148
|
*/
|
|
148
149
|
export async function cleanBundles() {
|
|
149
|
-
const
|
|
150
|
-
const srcPath = path.join(projectRoot, 'src');
|
|
150
|
+
const srcPath = getSrcPath(import.meta.url);
|
|
151
151
|
|
|
152
152
|
try {
|
|
153
153
|
Print.title('🧹 Cleaning bundles...');
|
|
@@ -166,7 +166,7 @@ export async function cleanBundles() {
|
|
|
166
166
|
}
|
|
167
167
|
|
|
168
168
|
// Remove config
|
|
169
|
-
const configPath =
|
|
169
|
+
const configPath = getSrcPath(import.meta.url, 'bundle.config.json');
|
|
170
170
|
if (await fs.pathExists(configPath)) {
|
|
171
171
|
await fs.remove(configPath);
|
|
172
172
|
console.log(` ✓ Deleted: bundle.config.json`);
|
|
@@ -185,8 +185,7 @@ export async function cleanBundles() {
|
|
|
185
185
|
* Subcommand: Bundle information
|
|
186
186
|
*/
|
|
187
187
|
export async function bundleInfo() {
|
|
188
|
-
const
|
|
189
|
-
const configPath = path.join(projectRoot, 'src/bundle.config.json');
|
|
188
|
+
const configPath = getSrcPath(import.meta.url, 'bundle.config.json');
|
|
190
189
|
|
|
191
190
|
try {
|
|
192
191
|
if (!await fs.pathExists(configPath)) {
|
|
@@ -2,21 +2,19 @@
|
|
|
2
2
|
import componentTemplates from './VisualComponentTemplate.js';
|
|
3
3
|
import fs from 'fs-extra';
|
|
4
4
|
import path from 'path';
|
|
5
|
-
import { fileURLToPath } from 'url';
|
|
6
5
|
import Validations from '../Validations.js';
|
|
7
6
|
import Print from '../Print.js';
|
|
8
7
|
import { getSrcPath } from '../utils/PathHelper.js';
|
|
9
|
-
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
10
8
|
|
|
11
9
|
function createComponent(componentName, category) {
|
|
12
|
-
//
|
|
10
|
+
// Validation: Component name is required
|
|
13
11
|
if (!componentName) {
|
|
14
12
|
Print.error('Component name is required');
|
|
15
13
|
Print.commandExample("Create a component", "slice component create");
|
|
16
14
|
return false;
|
|
17
15
|
}
|
|
18
16
|
|
|
19
|
-
//
|
|
17
|
+
// Validation: Valid component name
|
|
20
18
|
if (!Validations.isValidComponentName(componentName)) {
|
|
21
19
|
Print.error(`Invalid component name: '${componentName}'`);
|
|
22
20
|
Print.info('Component name must start with a letter and contain only alphanumeric characters');
|
|
@@ -25,7 +23,7 @@ function createComponent(componentName, category) {
|
|
|
25
23
|
return false;
|
|
26
24
|
}
|
|
27
25
|
|
|
28
|
-
//
|
|
26
|
+
// Validation: Component already exists
|
|
29
27
|
if(Validations.componentExists(componentName)){
|
|
30
28
|
Print.error(`Component '${componentName}' already exists in your project`);
|
|
31
29
|
Print.info('Please use a different name or delete the existing component first');
|
|
@@ -33,7 +31,7 @@ function createComponent(componentName, category) {
|
|
|
33
31
|
return false;
|
|
34
32
|
}
|
|
35
33
|
|
|
36
|
-
//
|
|
34
|
+
// Validation: Valid category
|
|
37
35
|
let flagCategory = Validations.isValidCategory(category);
|
|
38
36
|
|
|
39
37
|
if (!flagCategory.isValid) {
|
|
@@ -44,14 +42,14 @@ function createComponent(componentName, category) {
|
|
|
44
42
|
}
|
|
45
43
|
category = flagCategory.category;
|
|
46
44
|
|
|
47
|
-
//
|
|
45
|
+
// Create class name and file name
|
|
48
46
|
const className = componentName.charAt(0).toUpperCase() + componentName.slice(1);
|
|
49
47
|
const fileName = `${className}.js`;
|
|
50
48
|
let template;
|
|
51
49
|
|
|
52
50
|
const type = Validations.getCategoryType(category);
|
|
53
51
|
|
|
54
|
-
//
|
|
52
|
+
// Generate template based on type
|
|
55
53
|
if(type === 'Visual'){
|
|
56
54
|
template = componentTemplates.visual(className);
|
|
57
55
|
} else if(type === 'Service'){
|
|
@@ -67,7 +65,7 @@ function createComponent(componentName, category) {
|
|
|
67
65
|
const componentDir = getSrcPath(import.meta.url, categoryPathClean, className);
|
|
68
66
|
|
|
69
67
|
try {
|
|
70
|
-
//
|
|
68
|
+
// Create component directory
|
|
71
69
|
fs.ensureDirSync(componentDir);
|
|
72
70
|
} catch (error) {
|
|
73
71
|
Print.error(`Failed to create component directory: '${componentDir}'`);
|
|
@@ -75,10 +73,10 @@ function createComponent(componentName, category) {
|
|
|
75
73
|
return false;
|
|
76
74
|
}
|
|
77
75
|
|
|
78
|
-
//
|
|
76
|
+
// Determine the file path
|
|
79
77
|
let componentPath = path.join(componentDir, fileName);
|
|
80
78
|
|
|
81
|
-
//
|
|
79
|
+
// Verify if the file already exists (double check)
|
|
82
80
|
if (fs.existsSync(componentPath)) {
|
|
83
81
|
Print.error(`Component file already exists at: '${componentPath}'`);
|
|
84
82
|
Print.info('This component may have been created outside the CLI');
|
|
@@ -86,13 +84,13 @@ function createComponent(componentName, category) {
|
|
|
86
84
|
}
|
|
87
85
|
|
|
88
86
|
try {
|
|
89
|
-
//
|
|
87
|
+
// Write component code to file
|
|
90
88
|
fs.writeFileSync(componentPath, template);
|
|
91
89
|
|
|
92
|
-
//
|
|
90
|
+
// If Visual, create additional files (CSS and HTML)
|
|
93
91
|
if(type === 'Visual'){
|
|
94
|
-
const cssPath = `${
|
|
95
|
-
const htmlPath = `${
|
|
92
|
+
const cssPath = path.join(componentDir, `${className}.css`);
|
|
93
|
+
const htmlPath = path.join(componentDir, `${className}.html`);
|
|
96
94
|
|
|
97
95
|
fs.writeFileSync(cssPath, '/* Styles for ' + componentName + ' component */\n');
|
|
98
96
|
fs.writeFileSync(htmlPath, `<div class="${componentName.toLowerCase()}">\n ${componentName}\n</div>`);
|
|
@@ -107,7 +105,7 @@ function createComponent(componentName, category) {
|
|
|
107
105
|
Print.error(`Failed to create component files`);
|
|
108
106
|
Print.info(`Error details: ${error.message}`);
|
|
109
107
|
|
|
110
|
-
//
|
|
108
|
+
// Try to clean up partially created files
|
|
111
109
|
try {
|
|
112
110
|
if (fs.existsSync(componentDir)) {
|
|
113
111
|
fs.removeSync(componentDir);
|
|
@@ -7,21 +7,21 @@ import { getSrcPath } from '../utils/PathHelper.js';
|
|
|
7
7
|
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
8
8
|
|
|
9
9
|
function deleteComponent(componentName, category) {
|
|
10
|
-
//
|
|
10
|
+
// Validation: Component name is required
|
|
11
11
|
if (!componentName) {
|
|
12
12
|
Print.error('Component name is required to delete');
|
|
13
13
|
Print.commandExample("Delete a component", "slice component delete");
|
|
14
14
|
return false;
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
-
//
|
|
17
|
+
// Validation: Valid component name
|
|
18
18
|
if (!Validations.isValidComponentName(componentName)) {
|
|
19
19
|
Print.error(`Invalid component name: '${componentName}'`);
|
|
20
20
|
Print.info('Component name must start with a letter and contain only alphanumeric characters');
|
|
21
21
|
return false;
|
|
22
22
|
}
|
|
23
23
|
|
|
24
|
-
//
|
|
24
|
+
// Validation: Valid category
|
|
25
25
|
let flagCategory = Validations.isValidCategory(category);
|
|
26
26
|
|
|
27
27
|
if (!flagCategory.isValid) {
|
|
@@ -36,7 +36,7 @@ function deleteComponent(componentName, category) {
|
|
|
36
36
|
const categoryPathClean = categoryPath ? categoryPath.replace(/^[/\\]+/, '') : '';
|
|
37
37
|
const componentDir = getSrcPath(import.meta.url, categoryPathClean, componentName);
|
|
38
38
|
|
|
39
|
-
//
|
|
39
|
+
// Check if component directory exists
|
|
40
40
|
if (!fs.existsSync(componentDir)) {
|
|
41
41
|
Print.error(`Component '${componentName}' does not exist in category '${category}'`);
|
|
42
42
|
Print.info('Make sure you selected the correct category');
|
|
@@ -44,7 +44,7 @@ function deleteComponent(componentName, category) {
|
|
|
44
44
|
return false;
|
|
45
45
|
}
|
|
46
46
|
|
|
47
|
-
//
|
|
47
|
+
// Verify it's a directory
|
|
48
48
|
try {
|
|
49
49
|
const stats = fs.statSync(componentDir);
|
|
50
50
|
if (!stats.isDirectory()) {
|
|
@@ -58,7 +58,7 @@ function deleteComponent(componentName, category) {
|
|
|
58
58
|
return false;
|
|
59
59
|
}
|
|
60
60
|
|
|
61
|
-
//
|
|
61
|
+
// Try to delete the component directory and its contents
|
|
62
62
|
try {
|
|
63
63
|
const files = fs.readdirSync(componentDir);
|
|
64
64
|
Print.info(`Deleting ${files.length} file(s) from component directory...`);
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import fs from 'fs-extra';
|
|
2
2
|
import path from 'path';
|
|
3
|
-
import { fileURLToPath } from 'url';
|
|
4
3
|
import { createServer } from 'net';
|
|
5
4
|
import chalk from 'chalk';
|
|
6
5
|
import Table from 'cli-table3';
|
|
@@ -11,10 +10,8 @@ import { promisify } from 'util';
|
|
|
11
10
|
import { getProjectRoot, getSrcPath, getApiPath, getConfigPath, getPath } from '../utils/PathHelper.js';
|
|
12
11
|
import updateManager from '../utils/updateManager.js';
|
|
13
12
|
|
|
14
|
-
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
15
|
-
|
|
16
13
|
/**
|
|
17
|
-
*
|
|
14
|
+
* Checks the Node.js version
|
|
18
15
|
*/
|
|
19
16
|
async function checkNodeVersion() {
|
|
20
17
|
const currentVersion = process.version;
|
|
@@ -36,7 +33,7 @@ async function checkNodeVersion() {
|
|
|
36
33
|
}
|
|
37
34
|
|
|
38
35
|
/**
|
|
39
|
-
*
|
|
36
|
+
* Checks the directory structure
|
|
40
37
|
*/
|
|
41
38
|
async function checkDirectoryStructure() {
|
|
42
39
|
const srcPath = getSrcPath(import.meta.url);
|
|
@@ -64,7 +61,7 @@ async function checkDirectoryStructure() {
|
|
|
64
61
|
}
|
|
65
62
|
|
|
66
63
|
/**
|
|
67
|
-
*
|
|
64
|
+
* Checks sliceConfig.json
|
|
68
65
|
*/
|
|
69
66
|
async function checkConfig() {
|
|
70
67
|
const configPath = getConfigPath(import.meta.url);
|
|
@@ -102,7 +99,7 @@ async function checkConfig() {
|
|
|
102
99
|
}
|
|
103
100
|
|
|
104
101
|
/**
|
|
105
|
-
*
|
|
102
|
+
* Checks port availability
|
|
106
103
|
*/
|
|
107
104
|
async function checkPort() {
|
|
108
105
|
const configPath = getConfigPath(import.meta.url);
|
|
@@ -113,7 +110,7 @@ async function checkPort() {
|
|
|
113
110
|
const config = await fs.readJson(configPath);
|
|
114
111
|
port = config.server?.port || 3000;
|
|
115
112
|
}
|
|
116
|
-
} catch { }
|
|
113
|
+
} catch { /* config missing or unreadable — use default port */ }
|
|
117
114
|
|
|
118
115
|
return new Promise((resolve) => {
|
|
119
116
|
const server = createServer();
|
|
@@ -146,11 +143,11 @@ async function checkPort() {
|
|
|
146
143
|
}
|
|
147
144
|
|
|
148
145
|
/**
|
|
149
|
-
*
|
|
146
|
+
* Checks dependencies in package.json
|
|
150
147
|
*/
|
|
151
148
|
async function checkDependencies() {
|
|
152
149
|
const projectRoot = getProjectRoot(import.meta.url);
|
|
153
|
-
const packagePath =
|
|
150
|
+
const packagePath = getPath(import.meta.url, 'package.json');
|
|
154
151
|
|
|
155
152
|
if (!await fs.pathExists(packagePath)) {
|
|
156
153
|
return {
|
|
@@ -163,7 +160,7 @@ async function checkDependencies() {
|
|
|
163
160
|
try {
|
|
164
161
|
const pkg = await fs.readJson(packagePath);
|
|
165
162
|
const hasFrameworkDep = pkg.dependencies?.['slicejs-web-framework'] || pkg.devDependencies?.['slicejs-web-framework'];
|
|
166
|
-
const frameworkNodePath =
|
|
163
|
+
const frameworkNodePath = getPath(import.meta.url, 'node_modules', 'slicejs-web-framework', 'package.json');
|
|
167
164
|
const hasFrameworkNode = await fs.pathExists(frameworkNodePath);
|
|
168
165
|
const hasFramework = !!(hasFrameworkDep || hasFrameworkNode);
|
|
169
166
|
|
|
@@ -194,7 +191,7 @@ async function checkDependencies() {
|
|
|
194
191
|
}
|
|
195
192
|
|
|
196
193
|
/**
|
|
197
|
-
*
|
|
194
|
+
* Checks component integrity
|
|
198
195
|
*/
|
|
199
196
|
async function checkComponents() {
|
|
200
197
|
const configPath = getConfigPath(import.meta.url);
|
|
@@ -228,7 +225,7 @@ async function checkComponents() {
|
|
|
228
225
|
if (stat.isDirectory()) {
|
|
229
226
|
totalComponents++;
|
|
230
227
|
|
|
231
|
-
//
|
|
228
|
+
// Check JS files
|
|
232
229
|
const jsFile = path.join(itemPath, `${item}.js`);
|
|
233
230
|
if (!await fs.pathExists(jsFile)) {
|
|
234
231
|
componentIssues++;
|
|
@@ -260,7 +257,7 @@ async function checkComponents() {
|
|
|
260
257
|
}
|
|
261
258
|
|
|
262
259
|
/**
|
|
263
|
-
*
|
|
260
|
+
* Main diagnostic command
|
|
264
261
|
*/
|
|
265
262
|
export default async function runDiagnostics() {
|
|
266
263
|
Print.newLine();
|