@nlabs/lex 1.49.5 → 1.50.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.
Files changed (52) hide show
  1. package/.swcrc +35 -0
  2. package/README.md +43 -59
  3. package/config.json +32 -8
  4. package/examples/lex.config.js +110 -10
  5. package/lex.config.js +34 -7
  6. package/lib/Button.stories.js +99 -0
  7. package/lib/LexConfig.d.ts +60 -22
  8. package/lib/LexConfig.js +285 -244
  9. package/lib/commands/ai/ai.js +287 -288
  10. package/lib/commands/ai/index.js +8 -7
  11. package/lib/commands/build/build.d.ts +2 -2
  12. package/lib/commands/build/build.js +349 -458
  13. package/lib/commands/clean/clean.js +45 -33
  14. package/lib/commands/compile/compile.js +214 -228
  15. package/lib/commands/config/config.js +46 -42
  16. package/lib/commands/copy/copy.js +36 -35
  17. package/lib/commands/create/create.js +200 -121
  18. package/lib/commands/dev/dev.d.ts +1 -0
  19. package/lib/commands/dev/dev.js +261 -259
  20. package/lib/commands/init/init.js +108 -88
  21. package/lib/commands/link/link.js +18 -14
  22. package/lib/commands/lint/lint.js +735 -742
  23. package/lib/commands/migrate/migrate.js +49 -36
  24. package/lib/commands/publish/publish.js +116 -96
  25. package/lib/commands/serverless/serverless.js +611 -585
  26. package/lib/commands/storybook/storybook.js +242 -238
  27. package/lib/commands/test/test.js +381 -409
  28. package/lib/commands/update/update.js +141 -120
  29. package/lib/commands/upgrade/upgrade.js +51 -44
  30. package/lib/commands/versions/versions.d.ts +1 -1
  31. package/lib/commands/versions/versions.js +36 -38
  32. package/lib/create/changelog.js +136 -125
  33. package/lib/index.js +40 -38
  34. package/lib/lex.js +95 -68
  35. package/lib/storybook/index.js +6 -1
  36. package/lib/test-react/index.js +7 -84
  37. package/lib/types.d.ts +1 -1
  38. package/lib/types.js +7 -1
  39. package/lib/utils/aiService.js +240 -227
  40. package/lib/utils/app.js +274 -273
  41. package/lib/utils/deepMerge.js +37 -23
  42. package/lib/utils/file.js +218 -215
  43. package/lib/utils/log.js +29 -27
  44. package/lib/utils/reactShim.js +7 -85
  45. package/lib/utils/translations.js +92 -82
  46. package/package.json +59 -60
  47. package/templates/typescript/DataLayer.js.txt +218 -0
  48. package/templates/typescript/DataLayer.test.js.txt +268 -0
  49. package/templates/typescript/DataLayer.test.ts.txt +269 -0
  50. package/templates/typescript/DataLayer.ts.txt +227 -0
  51. package/webpack.config.js +38 -28
  52. package/lib/commands/lint/autofix.d.ts +0 -2
@@ -0,0 +1,269 @@
1
+ /**
2
+ * Copyright (c) 2018-Present, Nitrogen Labs, Inc.
3
+ * Copyrights licensed under the MIT License. See the accompanying LICENSE file for terms.
4
+ */
5
+ import {APIGatewayProxyEvent, Context} from 'aws-lambda';
6
+
7
+ import {DataLayer, handler} from './DataLayer.js';
8
+
9
+ describe('DataLayer', () => {
10
+ let dataLayer: DataLayer;
11
+ let mockContext: Context;
12
+
13
+ beforeEach(() => {
14
+ dataLayer = new DataLayer({
15
+ tableName: 'test-table',
16
+ region: 'us-east-1'
17
+ });
18
+
19
+ mockContext = {
20
+ awsRequestId: 'test-request-id',
21
+ functionName: 'test-function',
22
+ functionVersion: '$LATEST',
23
+ getRemainingTimeInMillis: () => 30000,
24
+ invokedFunctionArn: 'arn:aws:lambda:us-east-1:123456789012:function:test-function',
25
+ logGroupName: '/aws/lambda/test-function',
26
+ logStreamName: 'test-log-stream',
27
+ memoryLimitInMB: '128'
28
+ } as Context;
29
+ });
30
+
31
+ describe('getItem', () => {
32
+ it('should get an item by ID', async () => {
33
+ const result = await dataLayer.getItem('test-id');
34
+
35
+ expect(result).toEqual({
36
+ id: 'test-id',
37
+ data: 'sample data',
38
+ timestamp: expect.any(String)
39
+ });
40
+ });
41
+ });
42
+
43
+ describe('createItem', () => {
44
+ it('should create a new item', async () => {
45
+ const itemData = {
46
+ name: 'Test Item',
47
+ description: 'A test item'
48
+ };
49
+
50
+ const result = await dataLayer.createItem(itemData);
51
+
52
+ expect(result).toEqual({
53
+ id: expect.stringMatching(/^item-\d+$/),
54
+ name: 'Test Item',
55
+ description: 'A test item',
56
+ createdAt: expect.any(String),
57
+ updatedAt: expect.any(String)
58
+ });
59
+ });
60
+
61
+ it('should create an item with custom ID', async () => {
62
+ const itemData = {
63
+ id: 'custom-id',
64
+ name: 'Test Item'
65
+ };
66
+
67
+ const result = await dataLayer.createItem(itemData);
68
+
69
+ expect(result.id).toBe('custom-id');
70
+ expect(result.name).toBe('Test Item');
71
+ });
72
+ });
73
+
74
+ describe('updateItem', () => {
75
+ it('should update an existing item', async () => {
76
+ const updateData = {
77
+ name: 'Updated Item',
78
+ description: 'Updated description'
79
+ };
80
+
81
+ const result = await dataLayer.updateItem('test-id', updateData);
82
+
83
+ expect(result).toEqual({
84
+ id: 'test-id',
85
+ name: 'Updated Item',
86
+ description: 'Updated description',
87
+ updatedAt: expect.any(String)
88
+ });
89
+ });
90
+ });
91
+
92
+ describe('deleteItem', () => {
93
+ it('should delete an item by ID', async () => {
94
+ const result = await dataLayer.deleteItem('test-id');
95
+
96
+ expect(result).toBe(true);
97
+ });
98
+ });
99
+
100
+ describe('listItems', () => {
101
+ it('should list items without filters', async () => {
102
+ const result = await dataLayer.listItems();
103
+
104
+ expect(Array.isArray(result)).toBe(true);
105
+ expect(result.length).toBeGreaterThan(0);
106
+ expect(result[0]).toHaveProperty('id');
107
+ expect(result[0]).toHaveProperty('data');
108
+ expect(result[0]).toHaveProperty('timestamp');
109
+ });
110
+
111
+ it('should list items with filters', async () => {
112
+ const filters = {
113
+ status: 'active'
114
+ };
115
+
116
+ const result = await dataLayer.listItems(filters);
117
+
118
+ expect(Array.isArray(result)).toBe(true);
119
+ });
120
+ });
121
+
122
+ describe('handleRequest', () => {
123
+ it('should handle GET request for single item', async () => {
124
+ const event: APIGatewayProxyEvent = {
125
+ httpMethod: 'GET',
126
+ pathParameters: {id: 'test-id'},
127
+ body: null,
128
+ queryStringParameters: null
129
+ } as APIGatewayProxyEvent;
130
+
131
+ const result = await dataLayer.handleRequest(event, mockContext);
132
+
133
+ expect(result.statusCode).toBe(200);
134
+ expect(result.headers['Content-Type']).toBe('application/json');
135
+ expect(result.headers['Access-Control-Allow-Origin']).toBe('*');
136
+
137
+ const body = JSON.parse(result.body);
138
+ expect(body.id).toBe('test-id');
139
+ });
140
+
141
+ it('should handle GET request for list items', async () => {
142
+ const event: APIGatewayProxyEvent = {
143
+ httpMethod: 'GET',
144
+ pathParameters: null,
145
+ body: null,
146
+ queryStringParameters: {status: 'active'}
147
+ } as APIGatewayProxyEvent;
148
+
149
+ const result = await dataLayer.handleRequest(event, mockContext);
150
+
151
+ expect(result.statusCode).toBe(200);
152
+ const body = JSON.parse(result.body);
153
+ expect(Array.isArray(body)).toBe(true);
154
+ });
155
+
156
+ it('should handle POST request', async () => {
157
+ const event: APIGatewayProxyEvent = {
158
+ httpMethod: 'POST',
159
+ pathParameters: null,
160
+ body: JSON.stringify({
161
+ name: 'New Item',
162
+ description: 'A new item'
163
+ }),
164
+ queryStringParameters: null
165
+ } as APIGatewayProxyEvent;
166
+
167
+ const result = await dataLayer.handleRequest(event, mockContext);
168
+
169
+ expect(result.statusCode).toBe(200);
170
+ const body = JSON.parse(result.body);
171
+ expect(body.name).toBe('New Item');
172
+ expect(body.description).toBe('A new item');
173
+ });
174
+
175
+ it('should handle PUT request', async () => {
176
+ const event: APIGatewayProxyEvent = {
177
+ httpMethod: 'PUT',
178
+ pathParameters: {id: 'test-id'},
179
+ body: JSON.stringify({
180
+ name: 'Updated Item'
181
+ }),
182
+ queryStringParameters: null
183
+ } as APIGatewayProxyEvent;
184
+
185
+ const result = await dataLayer.handleRequest(event, mockContext);
186
+
187
+ expect(result.statusCode).toBe(200);
188
+ const body = JSON.parse(result.body);
189
+ expect(body.id).toBe('test-id');
190
+ expect(body.name).toBe('Updated Item');
191
+ });
192
+
193
+ it('should handle DELETE request', async () => {
194
+ const event: APIGatewayProxyEvent = {
195
+ httpMethod: 'DELETE',
196
+ pathParameters: {id: 'test-id'},
197
+ body: null,
198
+ queryStringParameters: null
199
+ } as APIGatewayProxyEvent;
200
+
201
+ const result = await dataLayer.handleRequest(event, mockContext);
202
+
203
+ expect(result.statusCode).toBe(200);
204
+ const body = JSON.parse(result.body);
205
+ expect(body.message).toBe('Item deleted successfully');
206
+ });
207
+
208
+ it('should return 400 for PUT without ID', async () => {
209
+ const event: APIGatewayProxyEvent = {
210
+ httpMethod: 'PUT',
211
+ pathParameters: null,
212
+ body: JSON.stringify({name: 'Updated Item'}),
213
+ queryStringParameters: null
214
+ } as APIGatewayProxyEvent;
215
+
216
+ const result = await dataLayer.handleRequest(event, mockContext);
217
+
218
+ expect(result.statusCode).toBe(400);
219
+ const body = JSON.parse(result.body);
220
+ expect(body.error).toBe('ID is required for update operations');
221
+ });
222
+
223
+ it('should return 400 for DELETE without ID', async () => {
224
+ const event: APIGatewayProxyEvent = {
225
+ httpMethod: 'DELETE',
226
+ pathParameters: null,
227
+ body: null,
228
+ queryStringParameters: null
229
+ } as APIGatewayProxyEvent;
230
+
231
+ const result = await dataLayer.handleRequest(event, mockContext);
232
+
233
+ expect(result.statusCode).toBe(400);
234
+ const body = JSON.parse(result.body);
235
+ expect(body.error).toBe('ID is required for delete operations');
236
+ });
237
+
238
+ it('should return 405 for unsupported method', async () => {
239
+ const event: APIGatewayProxyEvent = {
240
+ httpMethod: 'OPTIONS',
241
+ pathParameters: null,
242
+ body: null,
243
+ queryStringParameters: null
244
+ } as APIGatewayProxyEvent;
245
+
246
+ const result = await dataLayer.handleRequest(event, mockContext);
247
+
248
+ expect(result.statusCode).toBe(405);
249
+ const body = JSON.parse(result.body);
250
+ expect(body.error).toBe('Method not allowed');
251
+ });
252
+ });
253
+
254
+ describe('handler function', () => {
255
+ it('should work as Lambda handler', async () => {
256
+ const event: APIGatewayProxyEvent = {
257
+ httpMethod: 'GET',
258
+ pathParameters: {id: 'test-id'},
259
+ body: null,
260
+ queryStringParameters: null
261
+ } as APIGatewayProxyEvent;
262
+
263
+ const result = await handler(event, mockContext);
264
+
265
+ expect(result.statusCode).toBe(200);
266
+ expect(result.headers['Content-Type']).toBe('application/json');
267
+ });
268
+ });
269
+ });
@@ -0,0 +1,227 @@
1
+ /**
2
+ * Copyright (c) 2018-Present, Nitrogen Labs, Inc.
3
+ * Copyrights licensed under the MIT License. See the accompanying LICENSE file for terms.
4
+ */
5
+ import {APIGatewayProxyEvent, APIGatewayProxyResult, Context} from 'aws-lambda';
6
+
7
+ export interface DataLayerOptions {
8
+ readonly tableName?: string;
9
+ readonly region?: string;
10
+ readonly endpoint?: string;
11
+ }
12
+
13
+ export class DataLayer {
14
+ private readonly options: DataLayerOptions;
15
+
16
+ constructor(options: DataLayerOptions = {}) {
17
+ this.options = {
18
+ tableName: process.env.TABLE_NAME || 'default-table',
19
+ region: process.env.AWS_REGION || 'us-east-1',
20
+ endpoint: process.env.DYNAMODB_ENDPOINT,
21
+ ...options
22
+ };
23
+ }
24
+
25
+ /**
26
+ * Get a single item by ID
27
+ */
28
+ async getItem(id: string): Promise<any> {
29
+ try {
30
+ // TODO: Implement DynamoDB getItem logic
31
+ console.log(`Getting item with ID: ${id}`);
32
+
33
+ // Example response structure
34
+ return {
35
+ id,
36
+ data: 'sample data',
37
+ timestamp: new Date().toISOString()
38
+ };
39
+ } catch (error) {
40
+ console.error('Error getting item:', error);
41
+ throw error;
42
+ }
43
+ }
44
+
45
+ /**
46
+ * Create a new item
47
+ */
48
+ async createItem(data: any): Promise<any> {
49
+ try {
50
+ // TODO: Implement DynamoDB putItem logic
51
+ console.log('Creating new item:', data);
52
+
53
+ const newItem = {
54
+ id: data.id || `item-${Date.now()}`,
55
+ ...data,
56
+ createdAt: new Date().toISOString(),
57
+ updatedAt: new Date().toISOString()
58
+ };
59
+
60
+ return newItem;
61
+ } catch (error) {
62
+ console.error('Error creating item:', error);
63
+ throw error;
64
+ }
65
+ }
66
+
67
+ /**
68
+ * Update an existing item
69
+ */
70
+ async updateItem(id: string, data: any): Promise<any> {
71
+ try {
72
+ // TODO: Implement DynamoDB updateItem logic
73
+ console.log(`Updating item ${id}:`, data);
74
+
75
+ const updatedItem = {
76
+ id,
77
+ ...data,
78
+ updatedAt: new Date().toISOString()
79
+ };
80
+
81
+ return updatedItem;
82
+ } catch (error) {
83
+ console.error('Error updating item:', error);
84
+ throw error;
85
+ }
86
+ }
87
+
88
+ /**
89
+ * Delete an item by ID
90
+ */
91
+ async deleteItem(id: string): Promise<boolean> {
92
+ try {
93
+ // TODO: Implement DynamoDB deleteItem logic
94
+ console.log(`Deleting item with ID: ${id}`);
95
+
96
+ return true;
97
+ } catch (error) {
98
+ console.error('Error deleting item:', error);
99
+ throw error;
100
+ }
101
+ }
102
+
103
+ /**
104
+ * List items with optional filtering
105
+ */
106
+ async listItems(filters?: any): Promise<any[]> {
107
+ try {
108
+ // TODO: Implement DynamoDB scan/query logic
109
+ console.log('Listing items with filters:', filters);
110
+
111
+ // Example response
112
+ return [
113
+ {
114
+ id: 'item-1',
115
+ data: 'sample data 1',
116
+ timestamp: new Date().toISOString()
117
+ },
118
+ {
119
+ id: 'item-2',
120
+ data: 'sample data 2',
121
+ timestamp: new Date().toISOString()
122
+ }
123
+ ];
124
+ } catch (error) {
125
+ console.error('Error listing items:', error);
126
+ throw error;
127
+ }
128
+ }
129
+
130
+ /**
131
+ * Lambda handler for HTTP requests
132
+ */
133
+ async handleRequest(event: APIGatewayProxyEvent, context: Context): Promise<APIGatewayProxyResult> {
134
+ try {
135
+ const {httpMethod, pathParameters, body, queryStringParameters} = event;
136
+ const id = pathParameters?.id;
137
+
138
+ let result: any;
139
+
140
+ switch (httpMethod) {
141
+ case 'GET':
142
+ if (id) {
143
+ result = await this.getItem(id);
144
+ } else {
145
+ result = await this.listItems(queryStringParameters);
146
+ }
147
+ break;
148
+
149
+ case 'POST':
150
+ const createData = body ? JSON.parse(body) : {};
151
+ result = await this.createItem(createData);
152
+ break;
153
+
154
+ case 'PUT':
155
+ case 'PATCH':
156
+ if (!id) {
157
+ return {
158
+ statusCode: 400,
159
+ headers: {
160
+ 'Content-Type': 'application/json',
161
+ 'Access-Control-Allow-Origin': '*'
162
+ },
163
+ body: JSON.stringify({error: 'ID is required for update operations'})
164
+ };
165
+ }
166
+ const updateData = body ? JSON.parse(body) : {};
167
+ result = await this.updateItem(id, updateData);
168
+ break;
169
+
170
+ case 'DELETE':
171
+ if (!id) {
172
+ return {
173
+ statusCode: 400,
174
+ headers: {
175
+ 'Content-Type': 'application/json',
176
+ 'Access-Control-Allow-Origin': '*'
177
+ },
178
+ body: JSON.stringify({error: 'ID is required for delete operations'})
179
+ };
180
+ }
181
+ await this.deleteItem(id);
182
+ result = {message: 'Item deleted successfully'};
183
+ break;
184
+
185
+ default:
186
+ return {
187
+ statusCode: 405,
188
+ headers: {
189
+ 'Content-Type': 'application/json',
190
+ 'Access-Control-Allow-Origin': '*'
191
+ },
192
+ body: JSON.stringify({error: 'Method not allowed'})
193
+ };
194
+ }
195
+
196
+ return {
197
+ statusCode: 200,
198
+ headers: {
199
+ 'Content-Type': 'application/json',
200
+ 'Access-Control-Allow-Origin': '*'
201
+ },
202
+ body: JSON.stringify(result)
203
+ };
204
+
205
+ } catch (error) {
206
+ console.error('Handler error:', error);
207
+
208
+ return {
209
+ statusCode: 500,
210
+ headers: {
211
+ 'Content-Type': 'application/json',
212
+ 'Access-Control-Allow-Origin': '*'
213
+ },
214
+ body: JSON.stringify({
215
+ error: 'Internal server error',
216
+ message: error instanceof Error ? error.message : 'Unknown error'
217
+ })
218
+ };
219
+ }
220
+ }
221
+ }
222
+
223
+ // Export the handler function for Lambda
224
+ export const handler = async (event: APIGatewayProxyEvent, context: Context): Promise<APIGatewayProxyResult> => {
225
+ const dataLayer = new DataLayer();
226
+ return dataLayer.handleRequest(event, context);
227
+ };
package/webpack.config.js CHANGED
@@ -9,7 +9,7 @@ import CompressionWebpackPlugin from 'compression-webpack-plugin';
9
9
  import CopyWebpackPlugin from 'copy-webpack-plugin';
10
10
  import cssnano from 'cssnano';
11
11
  import DotenvPlugin from 'dotenv-webpack';
12
- import {EsbuildPlugin} from 'esbuild-loader';
12
+ import CssMinimizerPlugin from 'css-minimizer-webpack-plugin';
13
13
  import FaviconsWebpackPlugin from 'favicons-webpack-plugin';
14
14
  import {existsSync} from 'fs';
15
15
  import {sync as globSync} from 'glob';
@@ -34,6 +34,7 @@ import {merge} from 'webpack-merge';
34
34
  import {WebpackPluginServe} from 'webpack-plugin-serve';
35
35
 
36
36
  import {relativeFilePath, relativeNodePath} from './lib/utils/file.js';
37
+ import {LexConfig} from './lib/LexConfig.js';
37
38
 
38
39
  const {ProgressPlugin, ProvidePlugin} = webpack;
39
40
  const isProduction = process.env.NODE_ENV === 'production';
@@ -53,7 +54,7 @@ const {
53
54
  webpack: webpackCustom
54
55
  } = lexConfig;
55
56
 
56
- const webpackPublicPath = webpackCustom?.publicPath || './src/static';
57
+ const webpackStaticPath = webpackCustom?.staticPath || './src/static';
57
58
 
58
59
  const { publicPath: _, ...webpackConfigFiltered } = webpackCustom || {};
59
60
 
@@ -153,13 +154,13 @@ const imagePath = `${sourceFullPath}/images/`;
153
154
  const fontPath = `${sourceFullPath}/fonts/`;
154
155
  const docPath = `${sourceFullPath}/docs/`;
155
156
 
156
- const publicPathFull = pathResolve(process.cwd(), webpackPublicPath);
157
- if(existsSync(publicPathFull)) {
157
+ const staticPathFull = pathResolve(process.cwd(), webpackStaticPath);
158
+ if(existsSync(staticPathFull)) {
158
159
  staticPaths.push({
159
- from: publicPathFull,
160
+ from: staticPathFull,
160
161
  to: './'
161
162
  });
162
- watchIgnorePaths.push(publicPathFull);
163
+ watchIgnorePaths.push(staticPathFull);
163
164
  }
164
165
 
165
166
  if(existsSync(imagePath)) {
@@ -233,7 +234,7 @@ if(existsSync(`${sourceFullPath}/tsconfig.json`)) {
233
234
  }));
234
235
  }
235
236
 
236
- const esbuildLoaderPath = relativeNodePath('esbuild-loader', dirName);
237
+ const swcLoaderPath = relativeNodePath('swc-loader', dirName);
237
238
  const cssLoaderPath = relativeNodePath('css-loader', dirName);
238
239
  const graphqlLoaderPath = relativeNodePath('graphql-tag/loader', dirName);
239
240
  const htmlLoaderPath = relativeNodePath('html-loader', dirName);
@@ -263,7 +264,7 @@ const alias = aliasKeys.reduce((aliases, key) => {
263
264
  }, {});
264
265
 
265
266
  export default (webpackEnv, webpackOptions) => {
266
- const {bundleAnalyzer, watch, entry: cliEntry, mode: cliMode} = webpackOptions;
267
+ const {bundleAnalyzer, watch, entry: cliEntry, mode: cliMode, port} = webpackOptions;
267
268
  const entryValue = Array.isArray(cliEntry) ? cliEntry[0] : cliEntry;
268
269
 
269
270
  // Debug printout for environment and mode
@@ -322,10 +323,16 @@ export default (webpackEnv, webpackOptions) => {
322
323
  `${sourceFullPath}/**/*.test.ts*`
323
324
  ],
324
325
  include: sourceFullPath,
325
- loader: esbuildLoaderPath,
326
+ loader: swcLoaderPath,
326
327
  options: {
327
- loader: 'ts',
328
- target: targetEnvironment === 'node' ? 'node16' : 'es2016'
328
+ ...LexConfig.config.swc,
329
+ jsc: {
330
+ ...LexConfig.config.swc?.jsc,
331
+ parser: {
332
+ ...LexConfig.config.swc?.jsc?.parser,
333
+ tsx: false
334
+ }
335
+ }
329
336
  },
330
337
  resolve: {
331
338
  symlinks: true
@@ -339,10 +346,23 @@ export default (webpackEnv, webpackOptions) => {
339
346
  `${sourceFullPath}/**/*.test.ts*`
340
347
  ],
341
348
  include: sourceFullPath,
342
- loader: esbuildLoaderPath,
349
+ loader: swcLoaderPath,
343
350
  options: {
344
- loader: 'tsx',
345
- target: targetEnvironment === 'node' ? 'node16' : 'es2016'
351
+ ...LexConfig.config.swc,
352
+ jsc: {
353
+ ...LexConfig.config.swc?.jsc,
354
+ parser: {
355
+ ...LexConfig.config.swc?.jsc?.parser,
356
+ tsx: true
357
+ },
358
+ transform: {
359
+ ...LexConfig.config.swc?.jsc?.transform,
360
+ react: {
361
+ ...LexConfig.config.swc?.jsc?.transform?.react,
362
+ runtime: 'automatic'
363
+ }
364
+ }
365
+ }
346
366
  },
347
367
  resolve: {
348
368
  symlinks: true
@@ -433,13 +453,6 @@ export default (webpackEnv, webpackOptions) => {
433
453
  ]
434
454
  }
435
455
  }
436
- },
437
- {
438
- loader: esbuildLoaderPath,
439
- options: {
440
- loader: 'css',
441
- minify: isProduction
442
- }
443
456
  }
444
457
  ]
445
458
  },
@@ -451,7 +464,7 @@ export default (webpackEnv, webpackOptions) => {
451
464
  },
452
465
  {
453
466
  test: /\.(jpg|jpeg|png|gif|webp|svg|mp4|webm|ogg|mp3|wav|flac|aac)$/,
454
- include: publicPathFull,
467
+ include: staticPathFull,
455
468
  type: 'asset/resource',
456
469
  generator: {
457
470
  filename: '[name].[hash][ext]'
@@ -504,10 +517,7 @@ export default (webpackEnv, webpackOptions) => {
504
517
  isProduction && isWeb
505
518
  ? {
506
519
  minimizer: [
507
- new EsbuildPlugin({
508
- css: true,
509
- target: targetEnvironment
510
- })
520
+ new CssMinimizerPlugin()
511
521
  ],
512
522
  runtimeChunk: 'single',
513
523
  splitChunks: {
@@ -605,7 +615,7 @@ export default (webpackEnv, webpackOptions) => {
605
615
  }
606
616
  },
607
617
  {
608
- from: /\.[css,gif,ico,jpg,json,png,svg]/,
618
+ from: /\\.(css|gif|ico|jpg|json|png|svg)$/,
609
619
  to: ({parsedUrl: {pathname}}) => pathname
610
620
  }
611
621
  ],
@@ -623,7 +633,7 @@ export default (webpackEnv, webpackOptions) => {
623
633
  await next();
624
634
  }),
625
635
  open: process.env.WEBPACK_DEV_OPEN === 'true',
626
- port: 7001,
636
+ port: port || 3000,
627
637
  progress: 'minimal',
628
638
  static: existsSync(outputFullPath) ? [outputFullPath] : [],
629
639
  status: true
@@ -1,2 +0,0 @@
1
- #!/usr/bin/env node
2
- export {};