@nlabs/lex 1.59.4 โ†’ 2.0.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.
Files changed (41) hide show
  1. package/.storybook/main.ts +3 -47
  2. package/README.md +13 -19
  3. package/__mocks__/build.js +3 -3
  4. package/config.json +3 -1
  5. package/examples/lex.config.js +3 -7
  6. package/lib/LexConfig.d.ts +2 -6
  7. package/lib/LexConfig.js +2 -2
  8. package/lib/commands/ai/ai.js +3 -3
  9. package/lib/commands/build/build.d.ts +5 -3
  10. package/lib/commands/build/build.js +66 -156
  11. package/lib/commands/config/config.js +9 -7
  12. package/lib/commands/dev/dev.d.ts +0 -2
  13. package/lib/commands/dev/dev.js +24 -115
  14. package/lib/commands/init/init.js +4 -9
  15. package/lib/commands/migrate/migrate.js +2 -2
  16. package/lib/commands/serverless-dev/serverless-dev.js +2 -2
  17. package/lib/commands/versions/versions.d.ts +1 -1
  18. package/lib/commands/versions/versions.js +4 -4
  19. package/lib/lex.js +10 -11
  20. package/lib/types.d.ts +1 -1
  21. package/lib/types.js +1 -1
  22. package/lib/utils/app.d.ts +0 -2
  23. package/lib/utils/app.js +2 -29
  24. package/lib/utils/{webpack/LexSvgSpritemapPlugin.d.ts โ†’ assets/LexSvgSpritemap.d.ts} +6 -8
  25. package/lib/utils/assets/LexSvgSpritemap.js +219 -0
  26. package/lib/utils/file.d.ts +0 -4
  27. package/lib/utils/file.js +4 -100
  28. package/lib/utils/staticSite.d.ts +15 -0
  29. package/lib/utils/staticSite.js +80 -0
  30. package/lib/utils/vite/assets.d.ts +19 -0
  31. package/lib/utils/vite/assets.js +249 -0
  32. package/lib/utils/vite/config.d.ts +12 -0
  33. package/lib/utils/vite/config.js +279 -0
  34. package/package.json +27 -45
  35. package/postcss.config.js +1 -2
  36. package/tsconfig.lint.json +0 -1
  37. package/tsconfig.test.json +0 -1
  38. package/lib/utils/webpack/LexSvgSpritemapPlugin.js +0 -255
  39. package/scripts/test-webpack.js +0 -453
  40. package/webpack.config.d.ts +0 -2
  41. package/webpack.config.js +0 -960
@@ -1,453 +0,0 @@
1
- #!/usr/bin/env node
2
- /**
3
- * Test script to verify webpack, PostCSS plugins, and static file serving
4
- *
5
- * Usage:
6
- * node scripts/test-webpack.js
7
- *
8
- * This script:
9
- * 1. Creates a temporary test project
10
- * 2. Builds it with webpack
11
- * 3. Verifies PostCSS plugins work
12
- * 4. Checks that static files are accessible
13
- */
14
-
15
- import {execSync, spawn} from 'child_process';
16
- import {existsSync, mkdirSync, readFileSync, readdirSync, rmSync, writeFileSync} from 'fs';
17
- import {createConnection} from 'net';
18
- import {tmpdir} from 'os';
19
- import {join} from 'path';
20
-
21
- const testDir = join(tmpdir(), `lex-webpack-test-${Date.now()}`);
22
-
23
- console.log('๐Ÿงช Creating test project...');
24
- mkdirSync(testDir, {recursive: true});
25
- mkdirSync(join(testDir, 'src'), {recursive: true});
26
- mkdirSync(join(testDir, 'src', 'images'), {recursive: true});
27
- mkdirSync(join(testDir, 'src', 'static'), {recursive: true});
28
-
29
- writeFileSync(join(testDir, 'package.json'), JSON.stringify({
30
- name: 'test-webpack-project',
31
- version: '1.0.0',
32
- type: 'module'
33
- }, null, 2));
34
-
35
- writeFileSync(join(testDir, 'src', 'index.html'), `<!DOCTYPE html>
36
- <html>
37
- <head>
38
- <title>Test App</title>
39
- <link rel="stylesheet" href="./styles.css">
40
- </head>
41
- <body>
42
- <div class="container">
43
- <h1>Test App</h1>
44
- <div class="test-for-loop">PostCSS @for loop test</div>
45
- <div class="test-percentage">PostCSS percentage() test</div>
46
- </div>
47
- <script src="./index.js"></script>
48
- </body>
49
- </html>`);
50
-
51
- writeFileSync(join(testDir, 'src', 'index.js'), `
52
- console.log('Hello from test project');
53
- import './styles.css';
54
- `);
55
-
56
- writeFileSync(join(testDir, 'src', 'styles.css'), `
57
- /* Test PostCSS @for loop */
58
- @for $i from 1 to 4 {
59
- .test-for-loop:nth-child($i) {
60
- width: calc($i * 25px);
61
- }
62
- }
63
-
64
- /* Test PostCSS percentage() function */
65
- .test-percentage {
66
- width: percentage(1/3);
67
- padding: percentage(0.05);
68
- }
69
-
70
- .container {
71
- max-width: 1200px;
72
- margin: 0 auto;
73
- }
74
- `);
75
-
76
- writeFileSync(join(testDir, 'src', 'images', 'test.png'), 'fake-png-content');
77
- writeFileSync(join(testDir, 'src', 'images', 'logo-icon-64.png'), 'fake-png-content');
78
- writeFileSync(join(testDir, 'src', 'static', 'test.txt'), 'Static file content');
79
- writeFileSync(join(testDir, 'src', 'favicon.ico'), 'fake-ico-content');
80
- writeFileSync(join(testDir, 'src', 'manifest.json'), JSON.stringify({name: 'Test App'}, null, 2));
81
-
82
- writeFileSync(join(testDir, 'lex.config.js'), `
83
- export default {
84
- entryJs: 'index.js',
85
- entryHTML: 'index.html',
86
- outputPath: './build',
87
- sourcePath: './src',
88
- webpack: {
89
- staticPath: './src/static'
90
- }
91
- };
92
- `);
93
-
94
- console.log('๐Ÿ“ฆ Building with webpack...');
95
- try {
96
- const lexPath = join(process.cwd(), 'lib', 'lex.js');
97
- try {
98
- const result = execSync(`node "${lexPath}" build --bundler webpack --outputPath ./build --sourcePath ./src`, {
99
- cwd: testDir,
100
- stdio: 'pipe',
101
- encoding: 'utf8',
102
- env: {
103
- ...process.env,
104
- NODE_ENV: 'production'
105
- }
106
- });
107
- console.log(result.toString());
108
- } catch(error) {
109
- console.error('Build error output:', error.stdout || error.stderr || error.message);
110
- throw error;
111
- }
112
-
113
- console.log('โœ… Build completed successfully!\n');
114
-
115
- const buildDir = join(testDir, 'build');
116
-
117
- console.log('๐Ÿ” Verifying build output...');
118
-
119
- const indexHtml = join(buildDir, 'index.html');
120
- if(existsSync(indexHtml)) {
121
- const htmlContent = readFileSync(indexHtml, 'utf8');
122
- if(htmlContent.includes('Test App')) {
123
- console.log('โœ… HTML file generated correctly');
124
- } else {
125
- console.log('โŒ HTML content incorrect');
126
- }
127
- } else {
128
- console.log('โŒ HTML file not found');
129
- }
130
-
131
- const cssFiles = ['index.css'];
132
- const jsFiles = ['index.js', 'index.*.js'];
133
- let cssFound = false;
134
- let cssProcessed = false;
135
-
136
- for(const cssFile of cssFiles) {
137
- const cssPath = join(buildDir, cssFile);
138
- if(existsSync(cssPath)) {
139
- cssFound = true;
140
- const cssContent = readFileSync(cssPath, 'utf8');
141
- console.log('โœ… CSS file generated');
142
-
143
- if(cssContent.includes('test-for-loop')) {
144
- const hasForLoop = /width:\s*calc\([^)]*25px\)/.test(cssContent);
145
- if(hasForLoop) {
146
- console.log('โœ… PostCSS @for loop processed correctly');
147
- cssProcessed = true;
148
- }
149
- }
150
-
151
- if(cssContent.includes('test-percentage')) {
152
- const hasPercentage = /width:\s*[\d.]+%/.test(cssContent);
153
- if(hasPercentage) {
154
- console.log('โœ… PostCSS percentage() function processed correctly');
155
- cssProcessed = true;
156
- }
157
- }
158
- break;
159
- }
160
- }
161
-
162
- if(!cssFound) {
163
- const files = readdirSync(buildDir);
164
- const jsFile = files.find((f) => f.startsWith('index.') && f.endsWith('.js') && !f.includes('runtime') && !f.includes('vendors'));
165
- if(jsFile) {
166
- const jsContent = readFileSync(join(buildDir, jsFile), 'utf8');
167
- if(jsContent.includes('calc') && jsContent.includes('25px')) {
168
- console.log('โœ… CSS processed and inlined in JS (PostCSS @for loop detected)');
169
- cssProcessed = true;
170
- }
171
- if(jsContent.includes('%') && /[\d.]+%/.test(jsContent)) {
172
- console.log('โœ… CSS processed and inlined in JS (PostCSS percentage() detected)');
173
- cssProcessed = true;
174
- }
175
- }
176
- if(!cssProcessed) {
177
- console.log('โš ๏ธ CSS file not found (may be inlined or named differently)');
178
- }
179
- }
180
-
181
- const staticFile = join(buildDir, 'test.txt');
182
- if(existsSync(staticFile)) {
183
- const staticContent = readFileSync(staticFile, 'utf8');
184
- if(staticContent === 'Static file content') {
185
- console.log('โœ… Static file copied correctly');
186
- } else {
187
- console.log('โŒ Static file content incorrect');
188
- }
189
- } else {
190
- console.log('โš ๏ธ Static file not found (may not be copied in this configuration)');
191
- }
192
-
193
- console.log('\n๐ŸŒ Testing dev server and static file access...');
194
-
195
- const testPort = 3001;
196
-
197
- if(!existsSync(buildDir)) {
198
- console.log('โš ๏ธ Build directory does not exist, creating it...');
199
- mkdirSync(buildDir, {recursive: true});
200
- }
201
-
202
- let devServerProcess = null;
203
- let serverReady = false;
204
- let serverError = null;
205
-
206
- try {
207
- devServerProcess = spawn('node', [lexPath, 'dev', '--port', testPort.toString(), '--quiet'], {
208
- cwd: testDir,
209
- stdio: 'pipe',
210
- env: {
211
- ...process.env,
212
- LEX_QUIET: 'true',
213
- NODE_ENV: 'development'
214
- }
215
- });
216
-
217
- let serverOutput = '';
218
- let serverStartedOutput = false;
219
- devServerProcess.stdout.on('data', (data) => {
220
- const output = data.toString();
221
- serverOutput += output;
222
- // Check for server ready indicators
223
- if(output.includes('compiled') || output.includes('Local:') || output.includes('http://') || output.includes('webpack compiled')) {
224
- serverStartedOutput = true;
225
- }
226
- });
227
-
228
- devServerProcess.stderr.on('data', (data) => {
229
- const output = data.toString();
230
- serverOutput += output;
231
- if(output.includes('error') || output.includes('Error') || output.includes('ERROR')) {
232
- serverError = output;
233
- }
234
- // Sometimes webpack outputs to stderr but it's not an error
235
- if(output.includes('compiled') || output.includes('webpack')) {
236
- serverStartedOutput = true;
237
- }
238
- });
239
-
240
- devServerProcess.on('error', (error) => {
241
- serverError = error.message;
242
- });
243
-
244
- console.log(`โณ Waiting for dev server to start on port ${testPort}...`);
245
- console.log(' (This may take 30-60 seconds for initial compilation)');
246
-
247
- const checkPort = (port) => new Promise((resolve) => {
248
- const socket = createConnection(port, 'localhost');
249
- socket.on('connect', () => {
250
- socket.destroy();
251
- resolve(true);
252
- });
253
- socket.on('error', () => {
254
- resolve(false);
255
- });
256
- socket.setTimeout(1000, () => {
257
- socket.destroy();
258
- resolve(false);
259
- });
260
- });
261
-
262
- const waitForServer = async () => {
263
- for(let i = 0; i < 90; i++) {
264
- await new Promise((resolve) => setTimeout(resolve, 1000));
265
-
266
- const portOpen = await checkPort(testPort);
267
- if(portOpen || serverStartedOutput) {
268
- // Give it a bit more time to fully initialize
269
- await new Promise((resolve) => setTimeout(resolve, 3000));
270
-
271
- // Try to access the static file directly
272
- try {
273
- const controller = new AbortController();
274
- const timeoutId = setTimeout(() => controller.abort(), 5000);
275
- const response = await fetch(`http://localhost:${testPort}/test.txt`, {
276
- signal: controller.signal
277
- });
278
- clearTimeout(timeoutId);
279
- if(response.ok && response.status === 200) {
280
- const content = await response.text();
281
- if(content.includes('Static file content')) {
282
- return true;
283
- }
284
- }
285
- } catch(error) {
286
- if(error.name !== 'AbortError' && i > 5) {
287
- // Only log after a few attempts
288
- }
289
- }
290
-
291
- // Also try index.html as a fallback check
292
- try {
293
- const controller = new AbortController();
294
- const timeoutId = setTimeout(() => controller.abort(), 5000);
295
- const response = await fetch(`http://localhost:${testPort}/index.html`, {
296
- signal: controller.signal
297
- });
298
- clearTimeout(timeoutId);
299
- if(response.ok || response.status === 200) {
300
- // Server is up, even if static file test didn't work yet
301
- if(i > 10) {
302
- // After 10 seconds, if server is up, try static file again
303
- try {
304
- const staticResponse = await fetch(`http://localhost:${testPort}/test.txt`, {
305
- signal: controller.signal
306
- });
307
- if(staticResponse.ok) {
308
- return true;
309
- }
310
- } catch{
311
- }
312
- }
313
- }
314
- } catch(error) {
315
- if(error.name !== 'AbortError') {
316
- }
317
- }
318
- }
319
-
320
- if(i % 10 === 9 && i > 0) {
321
- console.log(` Still waiting... (${i + 1}/90 seconds)`);
322
- }
323
- }
324
- return false;
325
- };
326
-
327
- serverReady = await waitForServer();
328
-
329
- if(serverError) {
330
- console.log(`โŒ Dev server error: ${serverError}`);
331
- console.log('โŒ HTTP tests cannot run due to server error');
332
- console.log('๐Ÿ’ก Note: Static files are copied to build directory and should be accessible via dev server');
333
- throw new Error(`Dev server failed to start: ${serverError}`);
334
- } else if(!serverReady) {
335
- console.log('โŒ Dev server did not start within 60 seconds');
336
- console.log('โŒ HTTP tests cannot run - this is a required test');
337
- console.log('๐Ÿ’ก To test manually, run: cd <test-dir> && lex dev --port 3001');
338
- if(serverOutput) {
339
- const lastOutput = serverOutput.slice(-2000);
340
- console.log('\nServer output (last 2000 chars):');
341
- console.log(lastOutput);
342
- // Check if there are any obvious errors
343
- if(lastOutput.includes('Error') || lastOutput.includes('error') || lastOutput.includes('Cannot find')) {
344
- console.log('\nโš ๏ธ Potential errors detected in server output above');
345
- }
346
- } else {
347
- console.log(' (No server output captured - server may not have started)');
348
- console.log(' This could indicate the process failed to spawn or exited immediately');
349
- }
350
-
351
- // Check if process is still running
352
- if(devServerProcess && !devServerProcess.killed) {
353
- try {
354
- devServerProcess.kill(0); // Check if process exists
355
- console.log(' (Dev server process is still running but not responding)');
356
- } catch{
357
- console.log(' (Dev server process has exited)');
358
- }
359
- }
360
- throw new Error('Dev server did not start within timeout period - HTTP static file access test cannot run');
361
- } else {
362
- console.log(`โœ… Dev server started on port ${testPort}`);
363
-
364
- const testUrls = [
365
- {url: '/test.txt', expectedContent: 'Static file content', description: 'Static file from staticPath', required: true},
366
- {url: '/index.html', expectedContent: 'Test App', description: 'HTML file', required: false},
367
- {url: '/images/test.png', expectedContent: 'fake-png-content', description: 'Image file', required: false}
368
- ];
369
-
370
- let httpTestFailed = false;
371
- const httpTestErrors = [];
372
-
373
- for(const test of testUrls) {
374
- try {
375
- const response = await fetch(`http://localhost:${testPort}${test.url}`);
376
- if(response.ok) {
377
- const content = await response.text();
378
- if(content.includes(test.expectedContent)) {
379
- console.log(`โœ… ${test.description} accessible via HTTP (${test.url})`);
380
- } else {
381
- const errorMsg = `${test.description} accessible but content doesn't match (${test.url})`;
382
- console.log(`โŒ ${errorMsg}`);
383
- if(test.required) {
384
- httpTestFailed = true;
385
- httpTestErrors.push(errorMsg);
386
- }
387
- }
388
- } else {
389
- const errorMsg = `${test.description} returned status ${response.status} (${test.url})`;
390
- console.log(`โŒ ${errorMsg}`);
391
- if(test.required) {
392
- httpTestFailed = true;
393
- httpTestErrors.push(errorMsg);
394
- }
395
- }
396
- } catch(error) {
397
- const errorMsg = `Failed to fetch ${test.description}: ${error.message}`;
398
- console.log(`โŒ ${errorMsg}`);
399
- if(test.required) {
400
- httpTestFailed = true;
401
- httpTestErrors.push(errorMsg);
402
- }
403
- }
404
- }
405
-
406
- if(httpTestFailed) {
407
- console.log('\nโŒ HTTP static file access test FAILED!');
408
- console.log('Errors:');
409
- httpTestErrors.forEach((err) => console.log(` - ${err}`));
410
- console.log('\n๐Ÿ’ก The dev server must be able to serve static files from the staticPath directory.');
411
- console.log('๐Ÿ’ก Check that the middleware in webpack.config.js is correctly serving files from staticPathFull.');
412
- throw new Error('HTTP static file access test failed');
413
- } else {
414
- console.log('\nโœ… All HTTP static file access tests passed!');
415
- }
416
- }
417
- } catch(error) {
418
- console.error(`\nโŒ Dev server HTTP test failed: ${error.message}`);
419
- console.error('This test is required and must pass.');
420
- throw error;
421
- } finally {
422
- if(devServerProcess) {
423
- console.log('๐Ÿ›‘ Stopping dev server...');
424
- devServerProcess.kill('SIGTERM');
425
- await new Promise((resolve) => setTimeout(resolve, 1000));
426
- if(devServerProcess.killed === false) {
427
- devServerProcess.kill('SIGKILL');
428
- }
429
- console.log('โœ… Dev server stopped');
430
- }
431
- }
432
-
433
- // Only print success if we didn't throw an error
434
- console.log('\n๐ŸŽ‰ All tests passed!');
435
- console.log(`\n๐Ÿ“ Test project location: ${testDir}`);
436
- console.log('๐Ÿ’ก You can inspect the build output in the build/ directory');
437
- } catch(error) {
438
- console.error('\nโŒ Test suite failed:', error.message);
439
- if(error.stack) {
440
- console.error('\nStack trace:');
441
- console.error(error.stack);
442
- }
443
- process.exit(1);
444
- } finally {
445
- console.log('\n๐Ÿงน Cleaning up...');
446
- try {
447
- rmSync(testDir, {recursive: true, force: true});
448
- console.log('โœ… Cleanup complete');
449
- } catch{
450
- console.log('โš ๏ธ Could not clean up test directory:', testDir);
451
- }
452
- }
453
-
@@ -1,2 +0,0 @@
1
- declare function _default(webpackEnv: any, webpackOptions: any): any;
2
- export default _default;