slicejs-cli 2.9.1 → 2.9.3

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/client.js CHANGED
@@ -137,9 +137,15 @@ sliceClient
137
137
  const buildCommand = sliceClient.command("build")
138
138
  .description("Build Slice.js project for production")
139
139
  .action(async (options) => {
140
- await runWithVersionCheck(async () => {
141
- await build(options);
142
- });
140
+ const prevEnv = process.env.NODE_ENV;
141
+ process.env.NODE_ENV = 'production';
142
+ try {
143
+ await runWithVersionCheck(async () => {
144
+ await build(options);
145
+ });
146
+ } finally {
147
+ process.env.NODE_ENV = prevEnv;
148
+ }
143
149
  });
144
150
 
145
151
  buildCommand
@@ -172,14 +178,22 @@ sliceClient
172
178
  .option("-p, --port <port>", "Port for development server", 3000)
173
179
  .option("-w, --watch", "Enable watch mode for file changes")
174
180
  .action(async (options) => {
175
- await runWithVersionCheck(async () => {
176
- await startServer({
177
- mode: 'development',
178
- port: parseInt(options.port),
179
- watch: options.watch,
180
- bundled: false
181
+ // Ensure the process.env.NODE_ENV reflects the requested mode for any
182
+ // code (builds, spawned processes, libraries) that reads it.
183
+ const prevEnv = process.env.NODE_ENV;
184
+ process.env.NODE_ENV = 'development';
185
+ try {
186
+ await runWithVersionCheck(async () => {
187
+ await startServer({
188
+ mode: 'development',
189
+ port: parseInt(options.port),
190
+ watch: options.watch,
191
+ bundled: false
192
+ });
181
193
  });
182
- });
194
+ } finally {
195
+ process.env.NODE_ENV = prevEnv;
196
+ }
183
197
  });
184
198
 
185
199
  // START COMMAND - PRODUCTION MODE
@@ -189,14 +203,20 @@ sliceClient
189
203
  .option("-p, --port <port>", "Port for server", 3000)
190
204
  .option("-w, --watch", "Enable watch mode for file changes")
191
205
  .action(async (options) => {
192
- await runWithVersionCheck(async () => {
193
- await startServer({
194
- mode: 'production',
195
- port: parseInt(options.port),
196
- watch: options.watch,
197
- bundled: false
206
+ const prevEnv = process.env.NODE_ENV;
207
+ process.env.NODE_ENV = 'production';
208
+ try {
209
+ await runWithVersionCheck(async () => {
210
+ await startServer({
211
+ mode: 'production',
212
+ port: parseInt(options.port),
213
+ watch: options.watch,
214
+ bundled: false
215
+ });
198
216
  });
199
- });
217
+ } finally {
218
+ process.env.NODE_ENV = prevEnv;
219
+ }
200
220
  });
201
221
 
202
222
  // COMPONENT COMMAND GROUP - For local component management
@@ -94,12 +94,18 @@ function startNodeServer(port, mode) {
94
94
  args.push('--development');
95
95
  }
96
96
 
97
+ // Ensure the spawned server process receives NODE_ENV consistent with the
98
+ // requested mode. This guarantees code that only checks process.env.NODE_ENV
99
+ // (instead of CLI flags) will behave as expected.
100
+ const serverEnv = {
101
+ ...process.env,
102
+ PORT: port,
103
+ NODE_ENV: mode === 'production' ? 'production' : (process.env.NODE_ENV || 'development')
104
+ };
105
+
97
106
  const serverProcess = spawn('node', args, {
98
107
  stdio: ['inherit', 'pipe', 'pipe'],
99
- env: {
100
- ...process.env,
101
- PORT: port
102
- }
108
+ env: serverEnv
103
109
  });
104
110
 
105
111
  let serverStarted = false;
@@ -3,7 +3,7 @@ import fs from 'fs-extra';
3
3
  import path from 'path';
4
4
  import { parse } from '@babel/parser';
5
5
  import traverse from '@babel/traverse';
6
- import { getSrcPath, getComponentsJsPath, getProjectRoot } from '../PathHelper.js';
6
+ import { getSrcPath, getComponentsJsPath, getProjectRoot, getConfigPath } from '../PathHelper.js';
7
7
 
8
8
  export default class DependencyAnalyzer {
9
9
  constructor(moduleUrl) {
@@ -64,11 +64,21 @@ export default class DependencyAnalyzer {
64
64
  */
65
65
  async loadComponentsConfig() {
66
66
  const componentsConfigPath = path.join(this.componentsPath, 'components.js');
67
+ const configPath = getConfigPath(this.moduleUrl);
68
+ let sliceConfig = {};
67
69
 
68
70
  if (!await fs.pathExists(componentsConfigPath)) {
69
71
  throw new Error('components.js not found');
70
72
  }
71
73
 
74
+ if (await fs.pathExists(configPath)) {
75
+ try {
76
+ sliceConfig = await fs.readJson(configPath);
77
+ } catch (error) {
78
+ console.warn('Warning: Could not read sliceConfig.json for component paths:', error.message);
79
+ }
80
+ }
81
+
72
82
  // Read and parse components.js
73
83
  const content = await fs.readFile(componentsConfigPath, 'utf-8');
74
84
 
@@ -87,13 +97,18 @@ export default class DependencyAnalyzer {
87
97
 
88
98
  // Process each category
89
99
  for (const [categoryName, componentList] of categoryMap) {
90
- // Determine category type based on category name
91
- let categoryType = 'Visual'; // default
100
+ const configCategory = sliceConfig?.paths?.components?.[categoryName];
101
+
102
+ // Determine category type based on config or category name
103
+ let categoryType = configCategory?.type || 'Visual';
92
104
  if (categoryName === 'Service') categoryType = 'Service';
93
105
  if (categoryName === 'AppComponents') categoryType = 'Visual'; // AppComponents are visual
94
106
 
95
- // Find category path
96
- const categoryPath = path.join(this.componentsPath, categoryName);
107
+ // Resolve category path from config if available
108
+ let categoryPath = path.join(this.componentsPath, categoryName);
109
+ if (configCategory?.path) {
110
+ categoryPath = getSrcPath(this.moduleUrl, configCategory.path);
111
+ }
97
112
 
98
113
  if (await fs.pathExists(categoryPath)) {
99
114
  const files = await fs.readdir(categoryPath);
@@ -330,6 +345,17 @@ export default class DependencyAnalyzer {
330
345
  return node;
331
346
  }
332
347
 
348
+ if (node.type === 'CallExpression') {
349
+ const calleeName = node.callee?.name || null;
350
+ if (calleeName && node.arguments?.length) {
351
+ const firstArg = node.arguments[0];
352
+ const resolvedObject = resolveObjectExpression(firstArg, scope);
353
+ if (resolvedObject) {
354
+ return resolvedObject;
355
+ }
356
+ }
357
+ }
358
+
333
359
  if (node.type === 'ObjectExpression') {
334
360
  const routesProp = node.properties.find(p => p.key?.name === 'routes');
335
361
  if (routesProp?.value) {
@@ -348,6 +374,10 @@ export default class DependencyAnalyzer {
348
374
  return init;
349
375
  }
350
376
 
377
+ if (init?.type === 'CallExpression') {
378
+ return resolveRoutesArray(init, binding.path.scope);
379
+ }
380
+
351
381
  if (init?.type === 'Identifier') {
352
382
  return resolveRoutesArray(init, binding.path.scope);
353
383
  }
@@ -562,8 +592,46 @@ export default class DependencyAnalyzer {
562
592
  return null;
563
593
  };
564
594
 
595
+ const addRouteConfigDependencies = (routesConfigNode, scope) => {
596
+ if (!routesConfigNode || routesConfigNode.type !== 'ObjectExpression') return;
597
+
598
+ const processObject = (node) => {
599
+ if (!node || node.type !== 'ObjectExpression') return;
600
+
601
+ const componentProp = node.properties.find(p => p.key?.name === 'component');
602
+ if (componentProp?.value) {
603
+ const componentName = resolveStringValue(componentProp.value, scope);
604
+ if (componentName) {
605
+ dependencies.add(componentName);
606
+ }
607
+ }
608
+
609
+ const itemsProp = node.properties.find(p => p.key?.name === 'items');
610
+ if (itemsProp?.value) {
611
+ const itemsNode = resolveRoutesArray(itemsProp.value, scope);
612
+ addMultiRouteDependencies(itemsNode, scope);
613
+ }
614
+
615
+ node.properties.forEach((prop) => {
616
+ const valueNode = prop.value;
617
+ if (valueNode?.type === 'ObjectExpression') {
618
+ processObject(valueNode);
619
+ }
620
+ });
621
+ };
622
+
623
+ processObject(routesConfigNode);
624
+ };
625
+
565
626
  const addMultiRouteDependencies = (routesArrayNode, scope) => {
566
- if (!routesArrayNode || routesArrayNode.type !== 'ArrayExpression') return;
627
+ if (!routesArrayNode) return;
628
+
629
+ if (routesArrayNode.type === 'ObjectExpression') {
630
+ addRouteConfigDependencies(routesArrayNode, scope);
631
+ return;
632
+ }
633
+
634
+ if (routesArrayNode.type !== 'ArrayExpression') return;
567
635
 
568
636
  routesArrayNode.elements.forEach(routeElement => {
569
637
  if (!routeElement) return;
@@ -583,6 +651,12 @@ export default class DependencyAnalyzer {
583
651
  dependencies.add(componentName);
584
652
  }
585
653
  }
654
+
655
+ const itemsProp = routeObject.properties.find(p => p.key?.name === 'items');
656
+ if (itemsProp?.value) {
657
+ const itemsNode = resolveRoutesArray(itemsProp.value, scope);
658
+ addMultiRouteDependencies(itemsNode, scope);
659
+ }
586
660
  }
587
661
  });
588
662
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "slicejs-cli",
3
- "version": "2.9.1",
3
+ "version": "2.9.3",
4
4
  "description": "Command client for developing web applications with Slice.js framework",
5
5
  "main": "client.js",
6
6
  "bin": {
@@ -29,6 +29,8 @@
29
29
  "preferGlobal": false,
30
30
  "license": "ISC",
31
31
  "dependencies": {
32
+ "@babel/parser": "^7.28.5",
33
+ "@babel/traverse": "^7.28.5",
32
34
  "chalk": "^5.6.2",
33
35
  "chokidar": "^3.6.0",
34
36
  "clean-css": "^5.3.3",
@@ -39,8 +41,6 @@
39
41
  "inquirer": "^12.4.2",
40
42
  "ora": "^8.2.0",
41
43
  "slicejs-web-framework": "latest",
42
- "terser": "^5.43.1",
43
- "@babel/parser": "^7.28.5",
44
- "@babel/traverse": "^7.28.5"
44
+ "terser": "^5.43.1"
45
45
  }
46
46
  }