@nlabs/lex 1.48.7 → 1.49.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.
- package/.storybook/main.ts +9 -2
- package/.vscode/settings.json +1 -6
- package/README.md +249 -0
- package/eslint.config.mjs +24 -0
- package/examples/lex.config.js +18 -8
- package/examples/serverless-example/README.md +109 -0
- package/examples/serverless-example/dist/handlers/echo.js +15 -0
- package/examples/serverless-example/dist/handlers/graphql.js +137 -0
- package/examples/serverless-example/dist/handlers/hello.js +15 -0
- package/examples/serverless-example/dist/handlers/test.js +17 -0
- package/examples/serverless-example/dist/handlers/websocket.js +14 -0
- package/examples/serverless-example/lex.config.mjs +74 -0
- package/jest.config.mjs +13 -12
- package/{dist → lib}/LexConfig.d.ts +7 -6
- package/lib/LexConfig.js +268 -0
- package/lib/commands/ai/ai.js +303 -0
- package/{dist → lib}/commands/build/build.d.ts +3 -0
- package/lib/commands/build/build.js +494 -0
- package/{dist → lib}/commands/clean/clean.js +1 -1
- package/lib/commands/compile/compile.js +241 -0
- package/lib/commands/copy/copy.js +38 -0
- package/{dist → lib}/commands/create/create.js +1 -1
- package/{dist → lib}/commands/dev/dev.d.ts +2 -0
- package/lib/commands/dev/dev.js +286 -0
- package/{dist → lib}/commands/init/init.js +1 -1
- package/lib/commands/lint/lint.js +962 -0
- package/{dist → lib}/commands/migrate/migrate.js +1 -1
- package/lib/commands/publish/publish.js +104 -0
- package/lib/commands/serverless/serverless.d.ts +17 -0
- package/lib/commands/serverless/serverless.js +662 -0
- package/lib/commands/storybook/storybook.js +249 -0
- package/lib/commands/test/test.js +428 -0
- package/lib/commands/update/update.js +128 -0
- package/{dist → lib}/create/changelog.js +1 -1
- package/{dist → lib}/index.d.ts +1 -0
- package/{dist → lib}/index.js +2 -1
- package/lib/lex.js +73 -0
- package/lib/utils/aiService.d.ts +9 -0
- package/lib/utils/aiService.js +299 -0
- package/{dist → lib}/utils/app.d.ts +3 -0
- package/lib/utils/app.js +296 -0
- package/{dist → lib}/utils/file.d.ts +7 -3
- package/lib/utils/file.js +229 -0
- package/lib/utils/translations.d.ts +1 -0
- package/lib/utils/translations.js +74 -0
- package/package.json +60 -54
- package/postcss.config.js +5 -3
- package/tsconfig.build.json +2 -2
- package/webpack.config.js +229 -39
- package/dist/LexConfig.js +0 -287
- package/dist/commands/ai/ai.js +0 -303
- package/dist/commands/build/build.js +0 -404
- package/dist/commands/compile/compile.js +0 -234
- package/dist/commands/copy/copy.js +0 -38
- package/dist/commands/dev/dev.js +0 -74
- package/dist/commands/lint/lint.js +0 -993
- package/dist/commands/publish/publish.js +0 -104
- package/dist/commands/storybook/storybook.js +0 -249
- package/dist/commands/test/test.js +0 -429
- package/dist/commands/update/update.js +0 -132
- package/dist/lex.js +0 -70
- package/dist/utils/aiService.d.ts +0 -9
- package/dist/utils/aiService.js +0 -299
- package/dist/utils/app.js +0 -267
- package/dist/utils/file.js +0 -185
- package/emptyModule.js +0 -0
- package/eslint.config.js +0 -3
- /package/{dist → lib}/Button.stories.d.ts +0 -0
- /package/{dist → lib}/commands/ai/ai.d.ts +0 -0
- /package/{dist → lib}/commands/ai/index.d.ts +0 -0
- /package/{dist → lib}/commands/ai/index.js +0 -0
- /package/{dist → lib}/commands/clean/clean.d.ts +0 -0
- /package/{dist → lib}/commands/compile/compile.d.ts +0 -0
- /package/{dist → lib}/commands/config/config.d.ts +0 -0
- /package/{dist → lib}/commands/config/config.js +0 -0
- /package/{dist → lib}/commands/copy/copy.d.ts +0 -0
- /package/{dist → lib}/commands/create/create.d.ts +0 -0
- /package/{dist → lib}/commands/init/init.d.ts +0 -0
- /package/{dist → lib}/commands/link/link.d.ts +0 -0
- /package/{dist → lib}/commands/link/link.js +0 -0
- /package/{dist → lib}/commands/lint/autofix.d.ts +0 -0
- /package/{dist → lib}/commands/lint/lint.d.ts +0 -0
- /package/{dist → lib}/commands/migrate/migrate.d.ts +0 -0
- /package/{dist → lib}/commands/publish/publish.d.ts +0 -0
- /package/{dist → lib}/commands/storybook/storybook.d.ts +0 -0
- /package/{dist → lib}/commands/test/test.d.ts +0 -0
- /package/{dist → lib}/commands/update/update.d.ts +0 -0
- /package/{dist → lib}/commands/upgrade/upgrade.d.ts +0 -0
- /package/{dist → lib}/commands/upgrade/upgrade.js +0 -0
- /package/{dist → lib}/commands/versions/versions.d.ts +0 -0
- /package/{dist → lib}/commands/versions/versions.js +0 -0
- /package/{dist → lib}/create/changelog.d.ts +0 -0
- /package/{dist → lib}/lex.d.ts +0 -0
- /package/{dist → lib}/storybook/index.d.ts +0 -0
- /package/{dist → lib}/storybook/index.js +0 -0
- /package/{dist → lib}/test-react/index.d.ts +0 -0
- /package/{dist → lib}/test-react/index.js +0 -0
- /package/{dist → lib}/types.d.ts +0 -0
- /package/{dist → lib}/types.js +0 -0
- /package/{dist → lib}/utils/deepMerge.d.ts +0 -0
- /package/{dist → lib}/utils/deepMerge.js +0 -0
- /package/{dist → lib}/utils/log.d.ts +0 -0
- /package/{dist → lib}/utils/log.js +0 -0
- /package/{dist → lib}/utils/reactShim.d.ts +0 -0
- /package/{dist → lib}/utils/reactShim.js +0 -0
package/.storybook/main.ts
CHANGED
|
@@ -50,9 +50,9 @@ const config = {
|
|
|
50
50
|
loader: 'babel-loader',
|
|
51
51
|
options: {
|
|
52
52
|
presets: [
|
|
53
|
-
'
|
|
53
|
+
'@babel/preset-typescript',
|
|
54
54
|
[
|
|
55
|
-
'
|
|
55
|
+
'@babel/preset-react',
|
|
56
56
|
{
|
|
57
57
|
runtime: 'automatic'
|
|
58
58
|
}
|
|
@@ -63,6 +63,13 @@ const config = {
|
|
|
63
63
|
]
|
|
64
64
|
}
|
|
65
65
|
]
|
|
66
|
+
},
|
|
67
|
+
resolve: {
|
|
68
|
+
...config.resolve,
|
|
69
|
+
extensions: ['.js', '.ts', '.tsx', '.json', '.mdx'],
|
|
70
|
+
extensionAlias: {
|
|
71
|
+
'.js': ['.ts', '.tsx', '.js']
|
|
72
|
+
}
|
|
66
73
|
}
|
|
67
74
|
};
|
|
68
75
|
}
|
package/.vscode/settings.json
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
"editor.defaultFormatter": "dbaeumer.vscode-eslint"
|
|
7
7
|
},
|
|
8
8
|
"[typescript]": {
|
|
9
|
-
"editor.defaultFormatter": "vscode
|
|
9
|
+
"editor.defaultFormatter": "dbaeumer.vscode-eslint"
|
|
10
10
|
},
|
|
11
11
|
"[typescriptreact]": {
|
|
12
12
|
"editor.defaultFormatter": "dbaeumer.vscode-eslint"
|
|
@@ -43,12 +43,7 @@
|
|
|
43
43
|
"eslint.experimental.useFlatConfig": true,
|
|
44
44
|
"eslint.format.enable": true,
|
|
45
45
|
"eslint.lintTask.enable": true,
|
|
46
|
-
"eslint.nodePath": "./node_modules",
|
|
47
|
-
"eslint.options": {
|
|
48
|
-
"overrideConfigFile": "./eslint.config.js"
|
|
49
|
-
},
|
|
50
46
|
"eslint.run": "onType",
|
|
51
|
-
"eslint.runtime": "./node_modules/eslint/bin/eslint.js",
|
|
52
47
|
"eslint.validate": [
|
|
53
48
|
"javascript",
|
|
54
49
|
"javascriptreact",
|
package/README.md
CHANGED
|
@@ -142,8 +142,17 @@ lex dev --bundleAnalyzer
|
|
|
142
142
|
|
|
143
143
|
# Custom webpack config
|
|
144
144
|
lex dev --config ./custom.webpack.js
|
|
145
|
+
|
|
146
|
+
# Force refresh cached public IP
|
|
147
|
+
lex dev --usePublicIp
|
|
145
148
|
```
|
|
146
149
|
|
|
150
|
+
**🌐 Public IP Caching**: Lex automatically caches your public IP address for 1 week to reduce API calls. Use `--usePublicIp` to force refresh the cache when needed.
|
|
151
|
+
|
|
152
|
+
**📁 Static Assets**: If your HTML template references static assets (like favicon.ico, manifest.json, or images) with absolute paths, ensure these files exist in your source directory or use relative paths to avoid webpack compilation errors.
|
|
153
|
+
|
|
154
|
+
**🎨 Public Assets**: Use the `webpack.publicPath` configuration to specify a directory for public assets (images, videos, audio, PDFs, etc.). Files in this directory will be automatically copied to the output and optimized for web delivery.
|
|
155
|
+
|
|
147
156
|
### 🏗️ **Production Builds**
|
|
148
157
|
|
|
149
158
|
```bash
|
|
@@ -270,6 +279,246 @@ export default {
|
|
|
270
279
|
};
|
|
271
280
|
```
|
|
272
281
|
|
|
282
|
+
## 📋 Configuration Options Reference
|
|
283
|
+
|
|
284
|
+
Lex provides extensive configuration options through the `lex.config.js` file. Here's a comprehensive reference of all available options:
|
|
285
|
+
|
|
286
|
+
### 🎯 **Project Settings**
|
|
287
|
+
|
|
288
|
+
| Option | Type | Default | Description | Example |
|
|
289
|
+
|--------|------|---------|-------------|---------|
|
|
290
|
+
| `entryHTML` | `string` | `'index.html'` | HTML template file | `entryHTML: 'app.html'` |
|
|
291
|
+
| `entryJs` | `string` | `'index.js'` | Main JavaScript entry file | `entryJs: 'main.tsx'` |
|
|
292
|
+
| `outputFile` | `string` | `undefined` | Specific output filename | `outputFile: 'bundle.js'` |
|
|
293
|
+
| `outputFullPath` | `string` | `path.resolve('./dist')` | Absolute output path for build artifacts. Used by webpack dev server for static file serving. | `outputFullPath: '/absolute/build'` |
|
|
294
|
+
| `outputHash` | `boolean` | `false` | Add hash to output filenames | `outputHash: true` |
|
|
295
|
+
| `outputPath` | `string` | `'./dist'` | Output directory path | `outputPath: './build'` |
|
|
296
|
+
| `packageManager` | `'npm' \| 'yarn'` | `'npm'` | Package manager to use | `packageManager: 'yarn'` |
|
|
297
|
+
| `preset` | `'web' \| 'node' \| 'lambda' \| 'mobile'` | `'web'` | Project preset type | `preset: 'node'` |
|
|
298
|
+
| `sourceFullPath` | `string` | `path.resolve('./src')` | Absolute source code path | `sourceFullPath: '/absolute/path'` |
|
|
299
|
+
| `sourcePath` | `string` | `'./src'` | Source code directory path | `sourcePath: './app'` |
|
|
300
|
+
| `targetEnvironment` | `'web' \| 'node'` | `'web'` | Target runtime environment | `targetEnvironment: 'node'` |
|
|
301
|
+
| `useGraphQl` | `boolean` | `false` | Enable GraphQL support | `useGraphQl: true` |
|
|
302
|
+
| `useTypescript` | `boolean` | `false` | Enable TypeScript support | `useTypescript: true` |
|
|
303
|
+
|
|
304
|
+
### 🤖 **AI Configuration**
|
|
305
|
+
|
|
306
|
+
| Option | Type | Default | Description | Example |
|
|
307
|
+
|--------|------|---------|-------------|---------|
|
|
308
|
+
| `ai.apiKey` | `string` | `undefined` | API key for AI provider | `ai: { apiKey: 'sk-...' }` |
|
|
309
|
+
| `ai.maxTokens` | `number` | `4000` | Maximum tokens for AI responses | `ai: { maxTokens: 8000 }` |
|
|
310
|
+
| `ai.model` | `string` | `'gpt-4o'` | AI model to use | `ai: { model: 'gpt-4' }` |
|
|
311
|
+
| `ai.provider` | `'cursor' \| 'copilot' \| 'openai' \| 'anthropic' \| 'none'` | `'none'` | AI service provider | `ai: { provider: 'openai' }` |
|
|
312
|
+
| `ai.temperature` | `number` | `0.1` | AI response creativity (0-1) | `ai: { temperature: 0.7 }` |
|
|
313
|
+
|
|
314
|
+
### ⚡ **ESBuild Configuration**
|
|
315
|
+
|
|
316
|
+
| Option | Type | Default | Description | Example |
|
|
317
|
+
|--------|------|---------|-------------|---------|
|
|
318
|
+
| `esbuild.banner` | `Record<string, string>` | `undefined` | Banner text for output files | `esbuild: { banner: { js: '// My Banner' } }` |
|
|
319
|
+
| `esbuild.define` | `Record<string, string>` | `undefined` | Global variable definitions | `esbuild: { define: { 'process.env.NODE_ENV': '"production"' } }` |
|
|
320
|
+
| `esbuild.drop` | `string[]` | `['console', 'debugger']` | Code to drop in production | `esbuild: { drop: ['console'] }` |
|
|
321
|
+
| `esbuild.entryPoints` | `string[]` | `undefined` | Entry points for ESBuild | `esbuild: { entryPoints: ['src/index.ts'] }` |
|
|
322
|
+
| `esbuild.external` | `string[]` | `undefined` | External dependencies | `esbuild: { external: ['react'] }` |
|
|
323
|
+
| `esbuild.footer` | `Record<string, string>` | `undefined` | Footer text for output files | `esbuild: { footer: { js: '// My Footer' } }` |
|
|
324
|
+
| `esbuild.format` | `'cjs' \| 'esm'` | `undefined` | Output format | `esbuild: { format: 'esm' }` |
|
|
325
|
+
| `esbuild.legalComments` | `'none' \| 'inline' \| 'eof' \| 'linked' \| 'separate'` | `'none'` | Legal comments handling | `esbuild: { legalComments: 'inline' }` |
|
|
326
|
+
| `esbuild.metafile` | `boolean` | `false` | Generate metafile | `esbuild: { metafile: true }` |
|
|
327
|
+
| `esbuild.minify` | `boolean` | `true` | Enable minification | `esbuild: { minify: false }` |
|
|
328
|
+
| `esbuild.outdir` | `string` | `undefined` | Output directory for ESBuild | `esbuild: { outdir: './build' }` |
|
|
329
|
+
| `esbuild.platform` | `'node' \| 'browser'` | `undefined` | Target platform | `esbuild: { platform: 'browser' }` |
|
|
330
|
+
| `esbuild.pure` | `string[]` | `['console.log', 'console.warn', 'console.error']` | Pure function calls | `esbuild: { pure: ['console.log'] }` |
|
|
331
|
+
| `esbuild.sourcemap` | `boolean \| 'inline' \| 'external'` | `false` | Source map generation | `esbuild: { sourcemap: true }` |
|
|
332
|
+
| `esbuild.splitting` | `boolean` | `true` | Enable code splitting | `esbuild: { splitting: false }` |
|
|
333
|
+
| `esbuild.target` | `string` | `undefined` | Target environment | `esbuild: { target: 'es2020' }` |
|
|
334
|
+
| `esbuild.treeShaking` | `boolean` | `true` | Enable tree shaking | `esbuild: { treeShaking: false }` |
|
|
335
|
+
|
|
336
|
+
### 🧪 **Jest Configuration**
|
|
337
|
+
|
|
338
|
+
| Option | Type | Default | Description | Example |
|
|
339
|
+
|--------|------|---------|-------------|---------|
|
|
340
|
+
| `jest.extensionsToTreatAsEsm` | `string[]` | `undefined` | Extensions to treat as ES modules | `jest: { extensionsToTreatAsEsm: ['.ts', '.tsx'] }` |
|
|
341
|
+
| `jest.moduleNameMapper` | `Record<string, string>` | `undefined` | Module name mappings | `jest: { moduleNameMapper: { '\\.(css)$': 'identity-obj-proxy' } }` |
|
|
342
|
+
| `jest.preset` | `string` | `undefined` | Jest preset | `jest: { preset: 'ts-jest' }` |
|
|
343
|
+
| `jest.roots` | `string[]` | `undefined` | Test root directories | `jest: { roots: ['<rootDir>/src'] }` |
|
|
344
|
+
| `jest.testEnvironment` | `string` | `undefined` | Test environment | `jest: { testEnvironment: 'jsdom' }` |
|
|
345
|
+
| `jest.transform` | `Record<string, [string, object]>` | `undefined` | Transform configurations | `jest: { transform: { '^.+\\.tsx?$': ['ts-jest'] } }` |
|
|
346
|
+
| `jest.transformIgnorePatterns` | `string[]` | `undefined` | Patterns to ignore in transforms | `jest: { transformIgnorePatterns: ['node_modules'] }` |
|
|
347
|
+
|
|
348
|
+
### 🔧 **ESLint Configuration**
|
|
349
|
+
|
|
350
|
+
| Option | Type | Default | Description | Example |
|
|
351
|
+
|--------|------|---------|-------------|---------|
|
|
352
|
+
| `eslint.extends` | `string[]` | `undefined` | ESLint extends configurations | `eslint: { extends: ['@typescript-eslint/recommended'] }` |
|
|
353
|
+
| `eslint.rules` | `Linter.RulesRecord` | `undefined` | ESLint rules | `eslint: { rules: { 'no-console': 'warn' } }` |
|
|
354
|
+
|
|
355
|
+
### 📦 **Webpack Configuration**
|
|
356
|
+
|
|
357
|
+
| Option | Type | Default | Description | Example |
|
|
358
|
+
|--------|------|---------|-------------|---------|
|
|
359
|
+
| `webpack.entry` | `string \| string[]` | `undefined` | Webpack entry points | `webpack: { entry: './src/index.js' }` |
|
|
360
|
+
| `webpack.module` | `object` | `undefined` | Webpack module configuration | `webpack: { module: { rules: [...] } }` |
|
|
361
|
+
| `webpack.output` | `object` | `undefined` | Webpack output configuration | `webpack: { output: { filename: 'bundle.js' } }` |
|
|
362
|
+
| `webpack.plugins` | `unknown[]` | `undefined` | Webpack plugins | `webpack: { plugins: [new MyPlugin()] }` |
|
|
363
|
+
| `webpack.publicPath` | `string` | `'./src/static'` | Path to public assets directory. Files in this directory will be copied to the output and optimized (images/videos compressed, audio optimized) | `webpack: { publicPath: './assets' }` |
|
|
364
|
+
|
|
365
|
+
### 🔗 **Library Configuration**
|
|
366
|
+
|
|
367
|
+
| Option | Type | Default | Description | Example |
|
|
368
|
+
|--------|------|---------|-------------|---------|
|
|
369
|
+
| `libraryName` | `string` | `undefined` | Library name for UMD builds | `libraryName: 'MyLibrary'` |
|
|
370
|
+
| `libraryTarget` | `string` | `undefined` | Library target format | `libraryTarget: 'umd'` |
|
|
371
|
+
|
|
372
|
+
### 📁 **File Management**
|
|
373
|
+
|
|
374
|
+
| Option | Type | Default | Description | Example |
|
|
375
|
+
|--------|------|---------|-------------|---------|
|
|
376
|
+
| `configFiles` | `string[]` | `[]` | Additional config files to include | `configFiles: ['./config/custom.js']` |
|
|
377
|
+
| `copyFiles` | `string[]` | `[]` | Files to copy during build | `copyFiles: ['public/assets']` |
|
|
378
|
+
| `env` | `object` | `null` | Environment variables | `env: { NODE_ENV: 'development' }` |
|
|
379
|
+
| `gitUrl` | `string` | `undefined` | Git repository URL | `gitUrl: 'https://github.com/user/repo'` |
|
|
380
|
+
|
|
381
|
+
### 📝 **Usage Examples**
|
|
382
|
+
|
|
383
|
+
#### Basic TypeScript Project
|
|
384
|
+
|
|
385
|
+
```javascript
|
|
386
|
+
export default {
|
|
387
|
+
useTypescript: true,
|
|
388
|
+
sourcePath: './src',
|
|
389
|
+
outputPath: './dist',
|
|
390
|
+
preset: 'web',
|
|
391
|
+
targetEnvironment: 'web'
|
|
392
|
+
};
|
|
393
|
+
```
|
|
394
|
+
|
|
395
|
+
#### Node.js Library
|
|
396
|
+
|
|
397
|
+
```javascript
|
|
398
|
+
export default {
|
|
399
|
+
useTypescript: true,
|
|
400
|
+
preset: 'node',
|
|
401
|
+
targetEnvironment: 'node',
|
|
402
|
+
libraryName: 'MyLibrary',
|
|
403
|
+
libraryTarget: 'umd',
|
|
404
|
+
esbuild: {
|
|
405
|
+
format: 'cjs',
|
|
406
|
+
platform: 'node',
|
|
407
|
+
external: ['lodash']
|
|
408
|
+
}
|
|
409
|
+
};
|
|
410
|
+
```
|
|
411
|
+
|
|
412
|
+
#### AI-Powered Development
|
|
413
|
+
|
|
414
|
+
```javascript
|
|
415
|
+
export default {
|
|
416
|
+
useTypescript: true,
|
|
417
|
+
ai: {
|
|
418
|
+
provider: 'openai',
|
|
419
|
+
apiKey: process.env.OPENAI_API_KEY,
|
|
420
|
+
model: 'gpt-4',
|
|
421
|
+
maxTokens: 8000,
|
|
422
|
+
temperature: 0.3
|
|
423
|
+
},
|
|
424
|
+
jest: {
|
|
425
|
+
testEnvironment: 'jsdom',
|
|
426
|
+
setupFilesAfterEnv: ['./src/setupTests.ts']
|
|
427
|
+
}
|
|
428
|
+
};
|
|
429
|
+
```
|
|
430
|
+
|
|
431
|
+
#### Advanced ESBuild Configuration
|
|
432
|
+
|
|
433
|
+
```javascript
|
|
434
|
+
export default {
|
|
435
|
+
useTypescript: true,
|
|
436
|
+
esbuild: {
|
|
437
|
+
minify: true,
|
|
438
|
+
sourcemap: 'inline',
|
|
439
|
+
target: 'es2020',
|
|
440
|
+
format: 'esm',
|
|
441
|
+
splitting: true,
|
|
442
|
+
metafile: true,
|
|
443
|
+
define: {
|
|
444
|
+
'process.env.NODE_ENV': '"production"',
|
|
445
|
+
'global': 'globalThis'
|
|
446
|
+
},
|
|
447
|
+
banner: {
|
|
448
|
+
js: '// My Awesome Library v1.0.0'
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
};
|
|
452
|
+
```
|
|
453
|
+
|
|
454
|
+
## 🚨 Troubleshooting
|
|
455
|
+
|
|
456
|
+
### Common Issues
|
|
457
|
+
|
|
458
|
+
#### 404 Error with "Static Paths" Message
|
|
459
|
+
|
|
460
|
+
If you see a 404 error with a message like "Static Paths /path/to/dist", this is likely because the webpack dev server is trying to serve static files from a directory that doesn't exist yet.
|
|
461
|
+
|
|
462
|
+
**Solution**: The `outputFullPath` directory should exist before starting the dev server. You can:
|
|
463
|
+
|
|
464
|
+
- Run `lex build` first to create the output directory
|
|
465
|
+
- Or ensure your `outputPath` configuration points to an existing directory
|
|
466
|
+
|
|
467
|
+
#### Port Already in Use
|
|
468
|
+
|
|
469
|
+
If you get an "address already in use" error, another process is using the default port (7001).
|
|
470
|
+
|
|
471
|
+
**Solution**: Kill the existing process or use a different port:
|
|
472
|
+
|
|
473
|
+
```bash
|
|
474
|
+
# Kill processes on port 7001
|
|
475
|
+
lsof -ti:7001 | xargs kill -9
|
|
476
|
+
|
|
477
|
+
# Or use a different port
|
|
478
|
+
lex dev --port 3000
|
|
479
|
+
```
|
|
480
|
+
|
|
481
|
+
#### TypeScript Configuration Issues
|
|
482
|
+
|
|
483
|
+
If TypeScript compilation fails, ensure your `tsconfig.json` is properly configured.
|
|
484
|
+
|
|
485
|
+
**Solution**: Check that your `tsconfig.json` includes the correct paths:
|
|
486
|
+
|
|
487
|
+
```json
|
|
488
|
+
{
|
|
489
|
+
"compilerOptions": {
|
|
490
|
+
"outDir": "./dist",
|
|
491
|
+
"rootDir": "./src"
|
|
492
|
+
},
|
|
493
|
+
"include": ["src/**/*"],
|
|
494
|
+
"exclude": ["node_modules", "dist"]
|
|
495
|
+
}
|
|
496
|
+
```
|
|
497
|
+
|
|
498
|
+
#### Missing Static Assets Error
|
|
499
|
+
|
|
500
|
+
If you see webpack compilation errors about missing static assets (like favicon.ico, manifest.json, or images), this is because your HTML template references files that don't exist.
|
|
501
|
+
|
|
502
|
+
**Solution**: Either create the missing files or update your HTML template to use relative paths:
|
|
503
|
+
|
|
504
|
+
```html
|
|
505
|
+
<!-- Instead of absolute paths -->
|
|
506
|
+
<link rel="icon" href="/favicon.ico" />
|
|
507
|
+
<link rel="manifest" href="/manifest.json" />
|
|
508
|
+
|
|
509
|
+
<!-- Use relative paths -->
|
|
510
|
+
<link rel="icon" href="favicon.ico" />
|
|
511
|
+
<link rel="manifest" href="manifest.json" />
|
|
512
|
+
```
|
|
513
|
+
|
|
514
|
+
Or create the missing files in your source directory:
|
|
515
|
+
|
|
516
|
+
```bash
|
|
517
|
+
touch src/favicon.ico
|
|
518
|
+
touch src/manifest.json
|
|
519
|
+
mkdir -p src/images && touch src/images/logo-icon-64.png
|
|
520
|
+
```
|
|
521
|
+
|
|
273
522
|
## 📚 Documentation
|
|
274
523
|
|
|
275
524
|
- 📖 **[Full Documentation](http://lex.nitrogenlabs.com)** - Complete API reference
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import {typescriptConfig} from 'eslint-config-styleguidejs';
|
|
2
|
+
|
|
3
|
+
export default [
|
|
4
|
+
...typescriptConfig,
|
|
5
|
+
{
|
|
6
|
+
rules: {
|
|
7
|
+
'keyword-spacing': ['error', {
|
|
8
|
+
after: true,
|
|
9
|
+
before: true,
|
|
10
|
+
overrides: {
|
|
11
|
+
for: {after: false},
|
|
12
|
+
if: {after: false},
|
|
13
|
+
switch: {after: false},
|
|
14
|
+
while: {after: false}
|
|
15
|
+
}
|
|
16
|
+
}],
|
|
17
|
+
'space-before-blocks': ['error', {
|
|
18
|
+
classes: 'always',
|
|
19
|
+
functions: 'always',
|
|
20
|
+
keywords: 'always'
|
|
21
|
+
}]
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
];
|
package/examples/lex.config.js
CHANGED
|
@@ -7,32 +7,42 @@ export default {
|
|
|
7
7
|
// Source and output paths
|
|
8
8
|
sourcePath: './src',
|
|
9
9
|
outputPath: './dist',
|
|
10
|
-
|
|
10
|
+
|
|
11
11
|
// Project settings
|
|
12
12
|
useTypescript: true,
|
|
13
13
|
targetEnvironment: 'web',
|
|
14
14
|
preset: 'web',
|
|
15
|
-
|
|
15
|
+
|
|
16
16
|
// AI configuration
|
|
17
17
|
// Use this section to configure AI features for lint --fix and ai commands
|
|
18
18
|
ai: {
|
|
19
19
|
// Available providers: 'cursor', 'copilot', 'openai', 'anthropic', 'none'
|
|
20
20
|
provider: 'cursor',
|
|
21
|
-
|
|
21
|
+
|
|
22
22
|
// API key for external providers (recommended to use environment variables)
|
|
23
23
|
// apiKey: process.env.OPENAI_API_KEY,
|
|
24
|
-
|
|
24
|
+
|
|
25
25
|
// Model configuration (specific to each provider)
|
|
26
26
|
model: 'cursor-code', // For Cursor IDE
|
|
27
27
|
// model: 'copilot-codex', // For GitHub Copilot
|
|
28
28
|
// model: 'gpt-4o', // For OpenAI
|
|
29
29
|
// model: 'claude-3-sonnet', // For Anthropic
|
|
30
|
-
|
|
30
|
+
|
|
31
31
|
// Optional parameters
|
|
32
32
|
maxTokens: 4000,
|
|
33
33
|
temperature: 0.1
|
|
34
34
|
},
|
|
35
|
-
|
|
35
|
+
|
|
36
|
+
// Webpack configuration
|
|
37
|
+
webpack: {
|
|
38
|
+
// Path to public assets directory (defaults to './src/static')
|
|
39
|
+
publicPath: './src/static',
|
|
40
|
+
|
|
41
|
+
// Other webpack configuration options
|
|
42
|
+
devtool: 'source-map',
|
|
43
|
+
plugins: []
|
|
44
|
+
},
|
|
45
|
+
|
|
36
46
|
// Build configuration
|
|
37
47
|
esbuild: {
|
|
38
48
|
entryPoints: ['src/index.ts'],
|
|
@@ -41,10 +51,10 @@ export default {
|
|
|
41
51
|
target: 'es2020',
|
|
42
52
|
format: 'esm'
|
|
43
53
|
},
|
|
44
|
-
|
|
54
|
+
|
|
45
55
|
// Test configuration
|
|
46
56
|
jest: {
|
|
47
57
|
roots: ['<rootDir>/src'],
|
|
48
58
|
testEnvironment: 'node'
|
|
49
59
|
}
|
|
50
|
-
};
|
|
60
|
+
};
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
# Serverless Example
|
|
2
|
+
|
|
3
|
+
This example demonstrates how to use the `lex serverless` command to run AWS Lambda functions locally with HTTP and WebSocket support.
|
|
4
|
+
|
|
5
|
+
## Setup
|
|
6
|
+
|
|
7
|
+
1. Navigate to this directory:
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
cd examples/serverless-example
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
2. Start the serverless development server:
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
lex serverless
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## Available Endpoints
|
|
20
|
+
|
|
21
|
+
### HTTP Endpoints
|
|
22
|
+
|
|
23
|
+
- **GET /hello** - Returns a hello message with request details
|
|
24
|
+
- **POST /echo** - Echoes back the request body
|
|
25
|
+
|
|
26
|
+
### WebSocket Endpoint
|
|
27
|
+
|
|
28
|
+
- **ws://localhost:3002** - WebSocket server for real-time communication
|
|
29
|
+
|
|
30
|
+
## Testing the Endpoints
|
|
31
|
+
|
|
32
|
+
### HTTP Testing
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
# Test GET endpoint
|
|
36
|
+
curl http://localhost:3000/hello
|
|
37
|
+
|
|
38
|
+
# Test POST endpoint
|
|
39
|
+
curl -X POST http://localhost:3000/echo \
|
|
40
|
+
-H "Content-Type: application/json" \
|
|
41
|
+
-d '{"message": "Hello from curl!"}'
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
### WebSocket Testing
|
|
45
|
+
|
|
46
|
+
You can use a WebSocket client or browser console:
|
|
47
|
+
|
|
48
|
+
```javascript
|
|
49
|
+
// In browser console
|
|
50
|
+
const ws = new WebSocket('ws://localhost:3002');
|
|
51
|
+
ws.onopen = () => {
|
|
52
|
+
console.log('Connected to WebSocket');
|
|
53
|
+
ws.send(JSON.stringify({
|
|
54
|
+
action: '$default',
|
|
55
|
+
body: 'Hello from WebSocket!'
|
|
56
|
+
}));
|
|
57
|
+
};
|
|
58
|
+
ws.onmessage = (event) => {
|
|
59
|
+
console.log('Received:', JSON.parse(event.data));
|
|
60
|
+
};
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
## Configuration
|
|
64
|
+
|
|
65
|
+
The serverless configuration is defined in `lex.config.mjs`:
|
|
66
|
+
|
|
67
|
+
```javascript
|
|
68
|
+
export default {
|
|
69
|
+
outputFullPath: './dist',
|
|
70
|
+
serverless: {
|
|
71
|
+
functions: {
|
|
72
|
+
hello: {
|
|
73
|
+
handler: 'handlers/hello.js',
|
|
74
|
+
events: [
|
|
75
|
+
{
|
|
76
|
+
http: {
|
|
77
|
+
path: '/hello',
|
|
78
|
+
method: 'GET',
|
|
79
|
+
cors: true
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
]
|
|
83
|
+
}
|
|
84
|
+
},
|
|
85
|
+
custom: {
|
|
86
|
+
'serverless-offline': {
|
|
87
|
+
httpPort: 3000,
|
|
88
|
+
wsPort: 3002,
|
|
89
|
+
host: 'localhost'
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
};
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
## Handler Functions
|
|
97
|
+
|
|
98
|
+
Handler functions receive AWS Lambda-style event and context objects:
|
|
99
|
+
|
|
100
|
+
- **event**: Contains request data (HTTP method, path, headers, body, etc.)
|
|
101
|
+
- **context**: Contains Lambda context information (function name, request ID, etc.)
|
|
102
|
+
|
|
103
|
+
## Features
|
|
104
|
+
|
|
105
|
+
- **HTTP Server**: Routes HTTP requests to appropriate Lambda functions
|
|
106
|
+
- **WebSocket Server**: Handles WebSocket connections and messages
|
|
107
|
+
- **CORS Support**: Automatic CORS headers for cross-origin requests
|
|
108
|
+
- **Dynamic Loading**: Loads handlers from the output directory
|
|
109
|
+
- **AWS Lambda Simulation**: Provides event and context objects similar to AWS Lambda
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export const handler = async (event, context) => {
|
|
2
|
+
return {
|
|
3
|
+
statusCode: 200,
|
|
4
|
+
headers: {
|
|
5
|
+
'Content-Type': 'application/json'
|
|
6
|
+
},
|
|
7
|
+
body: JSON.stringify({
|
|
8
|
+
message: 'Echo response',
|
|
9
|
+
receivedData: event.body,
|
|
10
|
+
path: event.path,
|
|
11
|
+
method: event.httpMethod,
|
|
12
|
+
timestamp: new Date().toISOString()
|
|
13
|
+
})
|
|
14
|
+
};
|
|
15
|
+
};
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
export const handler = async (event, context) => {
|
|
2
|
+
console.log('GraphQL handler started');
|
|
3
|
+
console.log('Event:', JSON.stringify(event, null, 2));
|
|
4
|
+
|
|
5
|
+
// Simulate GraphQL resolver logic
|
|
6
|
+
const resolvers = {
|
|
7
|
+
Query: {
|
|
8
|
+
hello: () => {
|
|
9
|
+
console.log('Resolver: hello called');
|
|
10
|
+
return 'Hello from GraphQL!';
|
|
11
|
+
},
|
|
12
|
+
users: () => {
|
|
13
|
+
console.log('Resolver: users called');
|
|
14
|
+
return [
|
|
15
|
+
{ id: 1, name: 'John Doe', email: 'john@example.com' },
|
|
16
|
+
{ id: 2, name: 'Jane Smith', email: 'jane@example.com' }
|
|
17
|
+
];
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
Mutation: {
|
|
21
|
+
signUp: (_, args) => {
|
|
22
|
+
const user = args.user;
|
|
23
|
+
console.log('Resolver: signUp called with user:', user);
|
|
24
|
+
console.log('Processing signup for:', user.email);
|
|
25
|
+
|
|
26
|
+
// Simulate some processing
|
|
27
|
+
const userId = Math.floor(Math.random() * 1000);
|
|
28
|
+
console.log('Generated user ID:', userId);
|
|
29
|
+
|
|
30
|
+
return {
|
|
31
|
+
userId,
|
|
32
|
+
username: user.username,
|
|
33
|
+
email: user.email
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
try {
|
|
40
|
+
// Parse the GraphQL request
|
|
41
|
+
const body = JSON.parse(event.body);
|
|
42
|
+
console.log('GraphQL Query:', body.query);
|
|
43
|
+
console.log('GraphQL Variables:', body.variables);
|
|
44
|
+
|
|
45
|
+
// Simulate GraphQL execution
|
|
46
|
+
if (body.query.includes('signUp')) {
|
|
47
|
+
console.log('Executing signUp mutation');
|
|
48
|
+
// Extract user data from the query since we're not using a real GraphQL parser
|
|
49
|
+
const userMatch = body.query.match(/signUp\(user:\s*{([^}]+)}\)/);
|
|
50
|
+
if (userMatch) {
|
|
51
|
+
const userData = userMatch[1];
|
|
52
|
+
const emailMatch = userData.match(/email:\s*"([^"]+)"/);
|
|
53
|
+
const passwordMatch = userData.match(/password:\s*"([^"]+)"/);
|
|
54
|
+
const usernameMatch = userData.match(/username:\s*"([^"]+)"/);
|
|
55
|
+
const confirmMatch = userData.match(/confirm:\s*"([^"]+)"/);
|
|
56
|
+
|
|
57
|
+
const user = {
|
|
58
|
+
email: emailMatch ? emailMatch[1] : '',
|
|
59
|
+
password: passwordMatch ? passwordMatch[1] : '',
|
|
60
|
+
username: usernameMatch ? usernameMatch[1] : '',
|
|
61
|
+
confirm: confirmMatch ? confirmMatch[1] : ''
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
const result = resolvers.Mutation.signUp(null, { user });
|
|
65
|
+
console.log('SignUp result:', result);
|
|
66
|
+
|
|
67
|
+
return {
|
|
68
|
+
statusCode: 200,
|
|
69
|
+
headers: {
|
|
70
|
+
'Content-Type': 'application/json'
|
|
71
|
+
},
|
|
72
|
+
body: JSON.stringify({
|
|
73
|
+
data: {
|
|
74
|
+
users: {
|
|
75
|
+
signUp: result
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
})
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
} else if (body.query.includes('hello')) {
|
|
82
|
+
console.log('Executing hello query');
|
|
83
|
+
const result = resolvers.Query.hello();
|
|
84
|
+
console.log('Hello result:', result);
|
|
85
|
+
|
|
86
|
+
return {
|
|
87
|
+
statusCode: 200,
|
|
88
|
+
headers: {
|
|
89
|
+
'Content-Type': 'application/json'
|
|
90
|
+
},
|
|
91
|
+
body: JSON.stringify({
|
|
92
|
+
data: {
|
|
93
|
+
hello: result
|
|
94
|
+
}
|
|
95
|
+
})
|
|
96
|
+
};
|
|
97
|
+
} else if (body.query.includes('users')) {
|
|
98
|
+
console.log('Executing users query');
|
|
99
|
+
const result = resolvers.Query.users();
|
|
100
|
+
console.log('Users result:', result);
|
|
101
|
+
|
|
102
|
+
return {
|
|
103
|
+
statusCode: 200,
|
|
104
|
+
headers: {
|
|
105
|
+
'Content-Type': 'application/json'
|
|
106
|
+
},
|
|
107
|
+
body: JSON.stringify({
|
|
108
|
+
data: {
|
|
109
|
+
users: result
|
|
110
|
+
}
|
|
111
|
+
})
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
console.log('No matching query found');
|
|
116
|
+
return {
|
|
117
|
+
statusCode: 400,
|
|
118
|
+
headers: {
|
|
119
|
+
'Content-Type': 'application/json'
|
|
120
|
+
},
|
|
121
|
+
body: JSON.stringify({
|
|
122
|
+
errors: [{ message: 'Query not supported' }]
|
|
123
|
+
})
|
|
124
|
+
};
|
|
125
|
+
} catch (error) {
|
|
126
|
+
console.error('GraphQL handler error:', error);
|
|
127
|
+
return {
|
|
128
|
+
statusCode: 500,
|
|
129
|
+
headers: {
|
|
130
|
+
'Content-Type': 'application/json'
|
|
131
|
+
},
|
|
132
|
+
body: JSON.stringify({
|
|
133
|
+
errors: [{ message: error.message }]
|
|
134
|
+
})
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export const handler = async (event, context) => {
|
|
2
|
+
return {
|
|
3
|
+
statusCode: 200,
|
|
4
|
+
headers: {
|
|
5
|
+
'Content-Type': 'application/json'
|
|
6
|
+
},
|
|
7
|
+
body: JSON.stringify({
|
|
8
|
+
message: 'Hello from serverless!',
|
|
9
|
+
path: event.path,
|
|
10
|
+
method: event.httpMethod,
|
|
11
|
+
queryParams: event.queryStringParameters,
|
|
12
|
+
timestamp: new Date().toISOString()
|
|
13
|
+
})
|
|
14
|
+
};
|
|
15
|
+
};
|