diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index 5c19b0d234..4328b33204 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -32,6 +32,7 @@ jobs: path: | charts/*/dist/* chat/*/dist/* + mcp-ui/*/dist/* packages/*/dist/* tools/*/dist/* key: ${{ runner.os }}-build-cache-${{ hashFiles('package.json', 'pnpm-lock.yaml', '**/src/') }} @@ -64,7 +65,7 @@ jobs: - name: Build if: ${{ steps.build-cache.outputs.cache-hit != 'true' }} - run: pnpm build + run: pnpm build:packages - uses: actions/cache/save@v4 name: Save build cache @@ -73,6 +74,7 @@ jobs: path: | charts/*/dist/* chat/*/dist/* + mcp-ui/*/dist/* packages/*/dist/* tools/*/dist/* key: ${{ steps.build-cache.outputs.cache-primary-key }} @@ -111,6 +113,7 @@ jobs: path: | charts/*/dist/* chat/*/dist/* + mcp-ui/*/dist/* packages/*/dist/* tools/*/dist/* key: ${{needs.build.outputs.cache-primary-key}} @@ -150,6 +153,7 @@ jobs: path: | charts/*/dist/* chat/*/dist/* + mcp-ui/*/dist/* packages/*/dist/* tools/*/dist/* key: ${{needs.build.outputs.cache-primary-key}} @@ -201,6 +205,7 @@ jobs: path: | charts/*/dist/* chat/*/dist/* + mcp-ui/*/dist/* packages/*/dist/* tools/*/dist/* key: ${{needs.build.outputs.cache-primary-key}} @@ -246,6 +251,7 @@ jobs: path: | charts/*/dist/* chat/*/dist/* + mcp-ui/*/dist/* packages/*/dist/* tools/*/dist/* key: ${{needs.build.outputs.cache-primary-key}} diff --git a/.github/workflows/react17.yml b/.github/workflows/react17.yml index 945f961179..2797b3e063 100644 --- a/.github/workflows/react17.yml +++ b/.github/workflows/react17.yml @@ -32,6 +32,7 @@ jobs: path: | charts/*/dist/* chat/*/dist/* + mcp-ui/*/dist/* packages/*/dist/* tools/*/dist/* key: ${{ runner.os }}-REACT17-build-cache-${{ hashFiles('package.json', 'pnpm-lock.yaml', '**/src/') }} @@ -51,7 +52,7 @@ jobs: run: pnpm install --prefer-offline # Intentionally not using --frozen-lockfile to allow for pnpm-lock.yaml updates - name: Build packages - run: pnpm build + run: pnpm build --filter=!'@lg-apps/*' - uses: actions/cache/save@v4 name: Save build cache @@ -60,6 +61,7 @@ jobs: path: | charts/*/dist/* chat/*/dist/* + mcp-ui/*/dist/* packages/*/dist/* tools/*/dist/* key: ${{ steps.build-cache.outputs.cache-primary-key }} @@ -85,6 +87,7 @@ jobs: path: | charts/*/dist/* chat/*/dist/* + mcp-ui/*/dist/* packages/*/dist/* tools/*/dist/* key: ${{needs.build.outputs.cache-primary-key}} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 2b3ec4ef95..a14e5a42f6 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -35,6 +35,7 @@ jobs: chat/*/dist/* chat/*/tsdoc.json chat/*/stories.js + mcp-ui/*/dist/* packages/*/dist/* packages/*/tsdoc.json packages/*/stories.js @@ -58,7 +59,7 @@ jobs: - name: Build if: ${{ steps.build-cache.outputs.cache-hit != 'true' }} - run: pnpm build + run: pnpm build:packages - name: Generate docs if: ${{ steps.build-cache.outputs.cache-hit != 'true' }} @@ -75,6 +76,7 @@ jobs: chat/*/dist/* chat/*/tsdoc.json chat/*/stories.js + mcp-ui/*/dist/* packages/*/dist/* packages/*/tsdoc.json packages/*/stories.js @@ -118,6 +120,7 @@ jobs: chat/*/dist/* chat/*/tsdoc.json chat/*/stories.js + mcp-ui/*/dist/* packages/*/dist/* packages/*/tsdoc.json packages/*/stories.js @@ -171,6 +174,7 @@ jobs: chat/*/dist/* chat/*/tsdoc.json chat/*/stories.js + mcp-ui/*/dist/* packages/*/dist/* packages/*/tsdoc.json packages/*/stories.js @@ -232,6 +236,7 @@ jobs: chat/*/dist/* chat/*/tsdoc.json chat/*/stories.js + mcp-ui/*/dist/* packages/*/dist/* packages/*/tsdoc.json packages/*/stories.js @@ -284,6 +289,7 @@ jobs: chat/*/dist/* chat/*/tsdoc.json chat/*/stories.js + mcp-ui/*/dist/* packages/*/dist/* packages/*/tsdoc.json packages/*/stories.js diff --git a/apps/mcp-ui-app/.gitignore b/apps/mcp-ui-app/.gitignore new file mode 100644 index 0000000000..c1cf3d2709 --- /dev/null +++ b/apps/mcp-ui-app/.gitignore @@ -0,0 +1,37 @@ +# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. + +# dependencies +/node_modules +/.pnp +.pnp.js + +# testing +/coverage + +# next.js +/.next/ +/out/ + +# production +/build + +# misc +.DS_Store +*.pem + +# debug +npm-debug.log* +yarn-debug.log* +yarn-error.log* + +# local env files +.env*.local +.env.local + +# vercel +.vercel + +# typescript +*.tsbuildinfo +next-env.d.ts + diff --git a/apps/mcp-ui-app/README.md b/apps/mcp-ui-app/README.md new file mode 100644 index 0000000000..dc6a87250a --- /dev/null +++ b/apps/mcp-ui-app/README.md @@ -0,0 +1,73 @@ +# MCP UI App + +A Next.js application for the MCP UI, configured for iframe embedding with CORS and CSP headers. + +## Getting Started + +### 1. Environment Setup + +Create a `.env.local` file in the app root with the following variables: + +```bash +# Base URL for the application +NEXT_PUBLIC_BASE_URL=http://localhost:3000 + +# Allowed parent origins for iframe embedding (comma-separated) +ALLOWED_IFRAME_ORIGINS=http://localhost:3000,http://localhost:3001,https://your-app.com +``` + +Configuration options: + +- `NEXT_PUBLIC_BASE_URL`: The base URL of your application +- `ALLOWED_IFRAME_ORIGINS`: Comma-separated list of allowed parent origins for iframe embedding + +### 2. Install dependencies + +```bash +pnpm install +``` + +### 3. Run the development server + +```bash +pnpm dev +``` + +Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. + +## Configuration + +### Base URL + +The base URL is configured via the `NEXT_PUBLIC_BASE_URL` environment variable and can be accessed in your code: + +```typescript +import config from '@/config'; + +console.log(config.baseUrl); // http://localhost:3000 +``` + +### CORS and Iframe Embedding + +The app is configured with: + +- **CORS headers**: Allow cross-origin requests from specified origins +- **CSP headers**: Content Security Policy appropriate for iframe embedding +- **Frame ancestors**: Controls which domains can embed this app in an iframe + +To allow your app to be embedded in an iframe from specific domains, add them to the `ALLOWED_IFRAME_ORIGINS` environment variable. + +## Build + +This app is excluded from the default `pnpm build` command in the workspace. To build this app specifically, run: + +```bash +cd apps/mcp-ui-app +pnpm build +``` + +Or from the workspace root: + +```bash +pnpm build:apps +``` diff --git a/apps/mcp-ui-app/next.config.js b/apps/mcp-ui-app/next.config.js new file mode 100644 index 0000000000..6c1d08e0c8 --- /dev/null +++ b/apps/mcp-ui-app/next.config.js @@ -0,0 +1,60 @@ +/** @type {import('next').NextConfig} */ +const nextConfig = { + reactStrictMode: true, + transpilePackages: [ + '@lg-mcp-ui/list-databases', + '@leafygreen-ui/card', + '@leafygreen-ui/typography', + '@leafygreen-ui/emotion', + '@leafygreen-ui/tokens', + '@leafygreen-ui/lib', + ], + + async headers() { + // Get allowed origins from environment variable + const allowedOrigins = process.env.ALLOWED_IFRAME_ORIGINS?.split(',') || [ + '*', + ]; + + return [ + { + // Apply to all routes + source: '/:path*', + headers: [ + // CORS headers for iframe embedding + { + key: 'Access-Control-Allow-Origin', + value: allowedOrigins[0] || '*', // Use first origin or wildcard + }, + { + key: 'Access-Control-Allow-Methods', + value: 'GET, POST, PUT, DELETE, OPTIONS', + }, + { + key: 'Access-Control-Allow-Headers', + value: 'Content-Type, Authorization', + }, + { + key: 'Access-Control-Allow-Credentials', + value: 'true', + }, + // Content Security Policy for iframe embedding + { + key: 'Content-Security-Policy', + value: [ + "default-src 'self'", + "script-src 'self' 'unsafe-eval' 'unsafe-inline'", + "style-src 'self' 'unsafe-inline'", + "img-src 'self' data: https:", + "font-src 'self' data:", + "connect-src 'self'", + `frame-ancestors ${allowedOrigins.join(' ')}`, // Allows embedding in iframes from these origins + ].join('; '), + }, + ], + }, + ]; + }, +}; + +module.exports = nextConfig; diff --git a/apps/mcp-ui-app/package.json b/apps/mcp-ui-app/package.json new file mode 100644 index 0000000000..7f52989096 --- /dev/null +++ b/apps/mcp-ui-app/package.json @@ -0,0 +1,24 @@ +{ + "name": "@lg-apps/mcp-ui-app", + "version": "0.1.0", + "private": true, + "scripts": { + "dev": "next dev", + "build": "next build", + "start": "next start", + "lint": "next lint" + }, + "dependencies": { + "@lg-mcp-ui/list-databases": "workspace:*", + "next": "^14.2.0", + "react": "^18.2.0", + "react-dom": "^18.2.0" + }, + "devDependencies": { + "@types/node": "^20.12.5", + "@types/react": "18.2.23", + "@types/react-dom": "18.2.8", + "typescript": "~5.8.0" + } +} + diff --git a/apps/mcp-ui-app/src/app/layout.tsx b/apps/mcp-ui-app/src/app/layout.tsx new file mode 100644 index 0000000000..9ae2c7da9c --- /dev/null +++ b/apps/mcp-ui-app/src/app/layout.tsx @@ -0,0 +1,19 @@ +import React from 'react'; +import type { Metadata } from 'next'; + +export const metadata: Metadata = { + title: 'MCP UI App', + description: 'MCP UI Application', +}; + +export default function RootLayout({ + children, +}: { + children: React.ReactNode; +}) { + return ( + + {children} + + ); +} diff --git a/apps/mcp-ui-app/src/app/list-databases/page.tsx b/apps/mcp-ui-app/src/app/list-databases/page.tsx new file mode 100644 index 0000000000..43e4e0dfb5 --- /dev/null +++ b/apps/mcp-ui-app/src/app/list-databases/page.tsx @@ -0,0 +1,8 @@ +'use client'; + +import React from 'react'; +import { ListDatabases } from '@lg-mcp-ui/list-databases'; + +export default function ListDatabasesPage() { + return ; +} diff --git a/apps/mcp-ui-app/src/app/page.tsx b/apps/mcp-ui-app/src/app/page.tsx new file mode 100644 index 0000000000..aca119d09b --- /dev/null +++ b/apps/mcp-ui-app/src/app/page.tsx @@ -0,0 +1,31 @@ +import React from 'react'; + +import config from '@/config'; + +export default function Home() { + return ( +
+

MCP UI App

+

Welcome to the MCP UI Application!

+
+

+ Configuration +

+

+ Base URL: {config.baseUrl} +

+

+ Allowed Origins:{' '} + {config.allowedIframeOrigins.join(', ') || 'Not configured'} +

+
+
+ ); +} diff --git a/apps/mcp-ui-app/src/config/index.ts b/apps/mcp-ui-app/src/config/index.ts new file mode 100644 index 0000000000..85009db6c0 --- /dev/null +++ b/apps/mcp-ui-app/src/config/index.ts @@ -0,0 +1,18 @@ +/** + * Application configuration + */ + +export const config = { + /** + * Base URL of the application + * Defaults to localhost:3000 in development + */ + baseUrl: process.env.NEXT_PUBLIC_BASE_URL || 'http://localhost:3000', + + /** + * Allowed origins for iframe embedding + */ + allowedIframeOrigins: process.env.ALLOWED_IFRAME_ORIGINS?.split(',') || [], +} as const; + +export default config; diff --git a/apps/mcp-ui-app/tsconfig.json b/apps/mcp-ui-app/tsconfig.json new file mode 100644 index 0000000000..7f64e8882a --- /dev/null +++ b/apps/mcp-ui-app/tsconfig.json @@ -0,0 +1,28 @@ +{ + "compilerOptions": { + "target": "ES2017", + "lib": ["dom", "dom.iterable", "esnext"], + "allowJs": true, + "skipLibCheck": true, + "strict": true, + "noEmit": true, + "esModuleInterop": true, + "module": "esnext", + "moduleResolution": "bundler", + "resolveJsonModule": true, + "isolatedModules": true, + "jsx": "preserve", + "incremental": true, + "plugins": [ + { + "name": "next" + } + ], + "paths": { + "@/*": ["./src/*"] + } + }, + "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"], + "exclude": ["node_modules"] +} + diff --git a/mcp-ui/list-databases/package.json b/mcp-ui/list-databases/package.json new file mode 100644 index 0000000000..8140ece94c --- /dev/null +++ b/mcp-ui/list-databases/package.json @@ -0,0 +1,34 @@ +{ + "name": "@lg-mcp-ui/list-databases", + "version": "0.1.0", + "private": true, + "main": "./dist/umd/index.js", + "module": "./dist/esm/index.js", + "types": "./dist/types/index.d.ts", + "license": "Apache-2.0", + "scripts": { + "build": "lg-build bundle", + "tsc": "lg-build tsc", + "docs": "lg-build docs", + "dev": "lg-build bundle --watch" + }, + "peerDependencies": { + "react": "^18.2.0" + }, + "dependencies": { + "@leafygreen-ui/tokens": "workspace:^", + "@leafygreen-ui/lib": "workspace:^", + "@leafygreen-ui/palette": "workspace:^" + }, + "devDependencies": { + "@lg-tools/build": "workspace:^" + }, + "exports": { + ".": { + "development": "./src/index.ts", + "types": "./dist/types/index.d.ts", + "import": "./dist/esm/index.js", + "require": "./dist/umd/index.js" + } + } +} diff --git a/mcp-ui/list-databases/src/ListDatabases.tsx b/mcp-ui/list-databases/src/ListDatabases.tsx new file mode 100644 index 0000000000..7161bb3e44 --- /dev/null +++ b/mcp-ui/list-databases/src/ListDatabases.tsx @@ -0,0 +1,88 @@ +// 'use client'; + +import React from 'react'; + +import { palette } from '@leafygreen-ui/palette'; +import { + borderRadius, + fontFamilies, + fontWeights, + spacing, + typeScales, +} from '@leafygreen-ui/tokens'; + +import { ListDatabasesProps } from './ListDatabases.types'; + +const H3 = ({ children }: { children: React.ReactNode }) => { + return ( +

+ {children} +

+ ); +}; + +const Body = ({ children }: { children: React.ReactNode }) => { + return ( +

+ {children} +

+ ); +}; + +const Card = ({ children }: { children: React.ReactNode }) => { + return ( +
+ {children} +
+ ); +}; + +export default function ListDatabases({ databases }: ListDatabasesProps) { + if (databases.length === 0) { + return ( + +

No databases found

+
+ ); + } + + return ( + +

Databases

+ +
+ ); +} diff --git a/mcp-ui/list-databases/src/ListDatabases.types.ts b/mcp-ui/list-databases/src/ListDatabases.types.ts new file mode 100644 index 0000000000..b492356476 --- /dev/null +++ b/mcp-ui/list-databases/src/ListDatabases.types.ts @@ -0,0 +1,3 @@ +export interface ListDatabasesProps { + databases: Array; +} diff --git a/mcp-ui/list-databases/src/index.ts b/mcp-ui/list-databases/src/index.ts new file mode 100644 index 0000000000..75629fbd30 --- /dev/null +++ b/mcp-ui/list-databases/src/index.ts @@ -0,0 +1,2 @@ +export { default as ListDatabases } from './ListDatabases'; +export type { ListDatabasesProps } from './ListDatabases.types'; diff --git a/mcp-ui/list-databases/tsconfig.json b/mcp-ui/list-databases/tsconfig.json new file mode 100644 index 0000000000..ba0251cda9 --- /dev/null +++ b/mcp-ui/list-databases/tsconfig.json @@ -0,0 +1,31 @@ +{ + "extends": "@lg-tools/build/config/package.tsconfig.json", + "compilerOptions": { + "paths": { + "@leafygreen-ui/*": [ + "../../packages/*/src" + ] + } + }, + "include": [ + "src/**/*" + ], + "exclude": [ + "**/*.stories.*" + ], + "references": [ + { + "path": "../../packages/card" + }, + { + "path": "../../packages/typography" + }, + { + "path": "../../packages/emotion" + }, + { + "path": "../../packages/lib" + } + ] +} + diff --git a/package.json b/package.json index fbcba81d8d..196927163b 100644 --- a/package.json +++ b/package.json @@ -14,7 +14,10 @@ "init:react17": "pnpm clean; npx node ./scripts/react17/init.mjs; pnpm run init", "create-package": "lg create", "build": "turbo run build tsc", + "build:apps": "turbo run build --filter='@lg-apps/*'", "build:cli": "turbo run build tsc --filter=@lg-tools/cli", + "build:packages": "turbo run build tsc --filter=!'@lg-apps/*'", + "dev:mcp-ui": "turbo run dev --filter=@lg-apps/mcp-ui-app", "build:docs": "turbo run docs", "build:tsc": "turbo run tsc", "build:ts-downlevel": "pnpm recursive exec lg-ts-downlevel", @@ -95,7 +98,8 @@ "@leafygreen-ui": "packages", "@lg-charts": "charts", "@lg-chat": "chat", - "@lg-tools": "tools" + "@lg-tools": "tools", + "@lg-mcp-ui": "mcp-ui" } }, "keywords": [ diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 7b285cbc95..a4a086db5a 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -121,6 +121,34 @@ importers: specifier: ~5.8.0 version: 5.8.3 + apps/mcp-ui-app: + dependencies: + '@lg-mcp-ui/list-databases': + specifier: workspace:* + version: link:../../mcp-ui/list-databases + next: + specifier: ^14.2.0 + version: 14.2.33(@babel/core@7.24.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.89.2) + react: + specifier: ^18.2.0 + version: 18.3.1 + react-dom: + specifier: ^18.2.0 + version: 18.3.1(react@18.3.1) + devDependencies: + '@types/node': + specifier: ^20.12.5 + version: 20.19.9 + '@types/react': + specifier: 18.2.23 + version: 18.2.23 + '@types/react-dom': + specifier: 18.2.8 + version: 18.2.8 + typescript: + specifier: ~5.8.0 + version: 5.8.3 + charts/chart-card: dependencies: '@dnd-kit/sortable': @@ -952,6 +980,25 @@ importers: specifier: workspace:^ version: link:../../tools/build + mcp-ui/list-databases: + dependencies: + '@leafygreen-ui/lib': + specifier: workspace:^ + version: link:../../packages/lib + '@leafygreen-ui/palette': + specifier: workspace:^ + version: link:../../packages/palette + '@leafygreen-ui/tokens': + specifier: workspace:^ + version: link:../../packages/tokens + react: + specifier: ^18.2.0 + version: 18.3.1 + devDependencies: + '@lg-tools/build': + specifier: workspace:^ + version: link:../../tools/build + packages/a11y: dependencies: '@leafygreen-ui/emotion': @@ -6005,6 +6052,63 @@ packages: '@types/react': '>=16' react: '>=16' + '@next/env@14.2.33': + resolution: {integrity: sha512-CgVHNZ1fRIlxkLhIX22flAZI/HmpDaZ8vwyJ/B0SDPTBuLZ1PJ+DWMjCHhqnExfmSQzA/PbZi8OAc7PAq2w9IA==} + + '@next/swc-darwin-arm64@14.2.33': + resolution: {integrity: sha512-HqYnb6pxlsshoSTubdXKu15g3iivcbsMXg4bYpjL2iS/V6aQot+iyF4BUc2qA/J/n55YtvE4PHMKWBKGCF/+wA==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [darwin] + + '@next/swc-darwin-x64@14.2.33': + resolution: {integrity: sha512-8HGBeAE5rX3jzKvF593XTTFg3gxeU4f+UWnswa6JPhzaR6+zblO5+fjltJWIZc4aUalqTclvN2QtTC37LxvZAA==} + engines: {node: '>= 10'} + cpu: [x64] + os: [darwin] + + '@next/swc-linux-arm64-gnu@14.2.33': + resolution: {integrity: sha512-JXMBka6lNNmqbkvcTtaX8Gu5by9547bukHQvPoLe9VRBx1gHwzf5tdt4AaezW85HAB3pikcvyqBToRTDA4DeLw==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [linux] + + '@next/swc-linux-arm64-musl@14.2.33': + resolution: {integrity: sha512-Bm+QulsAItD/x6Ih8wGIMfRJy4G73tu1HJsrccPW6AfqdZd0Sfm5Imhgkgq2+kly065rYMnCOxTBvmvFY1BKfg==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [linux] + + '@next/swc-linux-x64-gnu@14.2.33': + resolution: {integrity: sha512-FnFn+ZBgsVMbGDsTqo8zsnRzydvsGV8vfiWwUo1LD8FTmPTdV+otGSWKc4LJec0oSexFnCYVO4hX8P8qQKaSlg==} + engines: {node: '>= 10'} + cpu: [x64] + os: [linux] + + '@next/swc-linux-x64-musl@14.2.33': + resolution: {integrity: sha512-345tsIWMzoXaQndUTDv1qypDRiebFxGYx9pYkhwY4hBRaOLt8UGfiWKr9FSSHs25dFIf8ZqIFaPdy5MljdoawA==} + engines: {node: '>= 10'} + cpu: [x64] + os: [linux] + + '@next/swc-win32-arm64-msvc@14.2.33': + resolution: {integrity: sha512-nscpt0G6UCTkrT2ppnJnFsYbPDQwmum4GNXYTeoTIdsmMydSKFz9Iny2jpaRupTb+Wl298+Rh82WKzt9LCcqSQ==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [win32] + + '@next/swc-win32-ia32-msvc@14.2.33': + resolution: {integrity: sha512-pc9LpGNKhJ0dXQhZ5QMmYxtARwwmWLpeocFmVG5Z0DzWq5Uf0izcI8tLc+qOpqxO1PWqZ5A7J1blrUIKrIFc7Q==} + engines: {node: '>= 10'} + cpu: [ia32] + os: [win32] + + '@next/swc-win32-x64-msvc@14.2.33': + resolution: {integrity: sha512-nOjfZMy8B94MdisuzZo9/57xuFVLHJaDj5e/xrduJp9CV2/HrfxTRH2fbyLe+K9QT41WBLUd4iXX3R7jBp0EUg==} + engines: {node: '>= 10'} + cpu: [x64] + os: [win32] + '@nicolo-ribaudo/eslint-scope-5-internals@5.1.1-v1': resolution: {integrity: sha512-54/JRvkLIzzDWshCWfuhadfrfZVPiElY8Fcgmg1HroEly/EDSszzhBAsarCux+D/kOslTRquNzuyGSmUSTTHGg==} @@ -6672,6 +6776,12 @@ packages: resolution: {integrity: sha512-zSoeKcbCmfMXjA11uDuCJb+1LWNb3vy6Qw/VHj0Nfcl3UuqwuoZWknHsBIhCWvi4wU9vPui3aq054qjVyZqY4A==} engines: {node: '>=14'} + '@swc/counter@0.1.3': + resolution: {integrity: sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==} + + '@swc/helpers@0.5.5': + resolution: {integrity: sha512-KGYxvIOXcceOAbEk4bi/dVLEK9z8sZ0uBB3Il5b1rhfClSpcX0yfRO0KmTkqR2cnQDymwLB+25ZyMzICg/cm/A==} + '@tanstack/react-table@8.21.3': resolution: {integrity: sha512-5nNMTSETP4ykGegmVkhjcS8tTLW6Vl4axfEGQN3v0zdHYbK4UfoqfPChclTrJ4EoK9QynqAu9oUf8VEmrpZ5Ww==} engines: {node: '>=12'} @@ -7518,6 +7628,10 @@ packages: builtin-status-codes@3.0.0: resolution: {integrity: sha512-HpGFw18DgFWlncDfjTa2rcQ4W88O1mC8e8yZ2AvQY5KDaktSTwo+KRf6nHK6FRI5FyRyb/5T6+TSxfP7QyGsmQ==} + busboy@1.6.0: + resolution: {integrity: sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==} + engines: {node: '>=10.16.0'} + call-bind-apply-helpers@1.0.2: resolution: {integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==} engines: {node: '>= 0.4'} @@ -7631,6 +7745,9 @@ packages: resolution: {integrity: sha512-D5J+kHaVb/wKSFcyyV75uCn8fiY4sV38XJoe4CUyGQ+mOU/fMVYUdH1hJC+CJQ5uY3EnW27SbJYS4X8BiLrAFg==} engines: {node: '>= 10.0'} + client-only@0.0.1: + resolution: {integrity: sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==} + clipboard@2.0.11: resolution: {integrity: sha512-C+0bbOqkezLIsmWSvlsXS0Q0bmkugu7jcfMIACB+RDEntIzQIkdr148we28AfSloQLRdZlYL/QYyrq05j/3Faw==} @@ -9881,6 +9998,24 @@ packages: neo-async@2.6.2: resolution: {integrity: sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==} + next@14.2.33: + resolution: {integrity: sha512-GiKHLsD00t4ACm1p00VgrI0rUFAC9cRDGReKyERlM57aeEZkOQGcZTpIbsGn0b562FTPJWmYfKwplfO9EaT6ng==} + engines: {node: '>=18.17.0'} + hasBin: true + peerDependencies: + '@opentelemetry/api': ^1.1.0 + '@playwright/test': ^1.41.2 + react: ^18.2.0 + react-dom: ^18.2.0 + sass: ^1.3.0 + peerDependenciesMeta: + '@opentelemetry/api': + optional: true + '@playwright/test': + optional: true + sass: + optional: true + nice-try@1.0.5: resolution: {integrity: sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==} @@ -10272,6 +10407,10 @@ packages: postcss-value-parser@4.2.0: resolution: {integrity: sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==} + postcss@8.4.31: + resolution: {integrity: sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==} + engines: {node: ^10 || ^12 || >=14} + postcss@8.5.6: resolution: {integrity: sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==} engines: {node: ^10 || ^12 || >=14} @@ -10904,6 +11043,10 @@ packages: stream@0.0.3: resolution: {integrity: sha512-aMsbn7VKrl4A2T7QAQQbzgN7NVc70vgF5INQrBXqn4dCXN1zy3L9HGgLO5s7PExmdrzTJ8uR/27aviW8or8/+A==} + streamsearch@1.1.0: + resolution: {integrity: sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==} + engines: {node: '>=10.0.0'} + string-length@4.0.2: resolution: {integrity: sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==} engines: {node: '>=10'} @@ -11001,6 +11144,19 @@ packages: style-to-object@0.4.4: resolution: {integrity: sha512-HYNoHZa2GorYNyqiCaBgsxvcJIn7OHq6inEga+E6Ke3m5JkoqpQbnFssk4jwe+K7AhGa2fcha4wSOf1Kn01dMg==} + styled-jsx@5.1.1: + resolution: {integrity: sha512-pW7uC1l4mBZ8ugbiZrcIsiIvVx1UmTfw7UkC3Um2tmfUq9Bhk8IiyEIPl6F8agHgjzku6j0xQEZbfA5uSgSaCw==} + engines: {node: '>= 12.0.0'} + peerDependencies: + '@babel/core': '*' + babel-plugin-macros: '*' + react: '>= 16.8.0 || 17.x.x || ^18.0.0-0' + peerDependenciesMeta: + '@babel/core': + optional: true + babel-plugin-macros: + optional: true + stylis@4.2.0: resolution: {integrity: sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw==} @@ -14278,6 +14434,35 @@ snapshots: '@types/react': 18.2.23 react: 18.3.1 + '@next/env@14.2.33': {} + + '@next/swc-darwin-arm64@14.2.33': + optional: true + + '@next/swc-darwin-x64@14.2.33': + optional: true + + '@next/swc-linux-arm64-gnu@14.2.33': + optional: true + + '@next/swc-linux-arm64-musl@14.2.33': + optional: true + + '@next/swc-linux-x64-gnu@14.2.33': + optional: true + + '@next/swc-linux-x64-musl@14.2.33': + optional: true + + '@next/swc-win32-arm64-msvc@14.2.33': + optional: true + + '@next/swc-win32-ia32-msvc@14.2.33': + optional: true + + '@next/swc-win32-x64-msvc@14.2.33': + optional: true + '@nicolo-ribaudo/eslint-scope-5-internals@5.1.1-v1': dependencies: eslint-scope: 5.1.1 @@ -15052,6 +15237,13 @@ snapshots: - supports-color - typescript + '@swc/counter@0.1.3': {} + + '@swc/helpers@0.5.5': + dependencies: + '@swc/counter': 0.1.3 + tslib: 2.8.1 + '@tanstack/react-table@8.21.3(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@tanstack/table-core': 8.21.3 @@ -16121,6 +16313,10 @@ snapshots: builtin-status-codes@3.0.0: {} + busboy@1.6.0: + dependencies: + streamsearch: 1.1.0 + call-bind-apply-helpers@1.0.2: dependencies: es-errors: 1.3.0 @@ -16228,6 +16424,8 @@ snapshots: dependencies: source-map: 0.6.1 + client-only@0.0.1: {} + clipboard@2.0.11: dependencies: good-listener: 1.2.2 @@ -19235,6 +19433,32 @@ snapshots: neo-async@2.6.2: {} + next@14.2.33(@babel/core@7.24.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.89.2): + dependencies: + '@next/env': 14.2.33 + '@swc/helpers': 0.5.5 + busboy: 1.6.0 + caniuse-lite: 1.0.30001727 + graceful-fs: 4.2.11 + postcss: 8.4.31 + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + styled-jsx: 5.1.1(@babel/core@7.24.3)(react@18.3.1) + optionalDependencies: + '@next/swc-darwin-arm64': 14.2.33 + '@next/swc-darwin-x64': 14.2.33 + '@next/swc-linux-arm64-gnu': 14.2.33 + '@next/swc-linux-arm64-musl': 14.2.33 + '@next/swc-linux-x64-gnu': 14.2.33 + '@next/swc-linux-x64-musl': 14.2.33 + '@next/swc-win32-arm64-msvc': 14.2.33 + '@next/swc-win32-ia32-msvc': 14.2.33 + '@next/swc-win32-x64-msvc': 14.2.33 + sass: 1.89.2 + transitivePeerDependencies: + - '@babel/core' + - babel-plugin-macros + nice-try@1.0.5: {} no-case@3.0.4: @@ -19667,6 +19891,12 @@ snapshots: postcss-value-parser@4.2.0: {} + postcss@8.4.31: + dependencies: + nanoid: 3.3.11 + picocolors: 1.1.1 + source-map-js: 1.2.1 + postcss@8.5.6: dependencies: nanoid: 3.3.11 @@ -20429,6 +20659,8 @@ snapshots: dependencies: component-emitter: 2.0.0 + streamsearch@1.1.0: {} + string-length@4.0.2: dependencies: char-regex: 1.0.2 @@ -20546,6 +20778,13 @@ snapshots: dependencies: inline-style-parser: 0.1.1 + styled-jsx@5.1.1(@babel/core@7.24.3)(react@18.3.1): + dependencies: + client-only: 0.0.1 + react: 18.3.1 + optionalDependencies: + '@babel/core': 7.24.3 + stylis@4.2.0: {} superstruct@2.0.2: {} diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index e01ae25f2c..89652f8019 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -1,6 +1,8 @@ packages: - # all packages in direct subdirectories of charts/, chat/, packages/, & tools/ + # all packages in direct subdirectories of apps/, charts/, chat/, packages/, & tools/ + - 'apps/*' - 'charts/*' - 'chat/*' + - 'mcp-ui/*' - 'packages/*' - 'tools/*' diff --git a/scripts/react17/Dockerfile b/scripts/react17/Dockerfile index 89d0bcf4c0..16e58eb675 100644 --- a/scripts/react17/Dockerfile +++ b/scripts/react17/Dockerfile @@ -2,7 +2,7 @@ FROM node:18.20.8 # Set environment variables ENV DEBIAN_FRONTEND=noninteractive -ENV PNPM_VERSION=9.15.0 +ENV PNPM_VERSION=10.18.3 # Install system dependencies RUN apt-get update && apt-get install -y \ diff --git a/scripts/react17/init.mjs b/scripts/react17/init.mjs index 6824cd0a2b..fcab07f8c4 100644 --- a/scripts/react17/init.mjs +++ b/scripts/react17/init.mjs @@ -65,7 +65,13 @@ async function main() { function findTsConfigFiles(dir) { /** @type {Array} */ const results = []; - const packageDirs = ['packages', 'charts', 'chat', 'tools']; + + // Read the root package.json to get package directories dynamically + const rootPackage = JSON.parse( + fs.readFileSync(ROOT_PACKAGE_JSON_PATH, 'utf-8'), + ); + // Get package directories from lg.scopes + const packageDirs = Object.values(rootPackage.lg?.scopes ?? {}); for (const packageDir of packageDirs) { const packagePath = path.join(dir, packageDir); diff --git a/scripts/react17/test-react17.sh b/scripts/react17/test-react17.sh index a4a6e7d607..10c11902ef 100755 --- a/scripts/react17/test-react17.sh +++ b/scripts/react17/test-react17.sh @@ -100,7 +100,8 @@ docker run --name "${CONTAINER_NAME}" \ /bin/bash -c ' set -e npx node ./scripts/react17/init.mjs - pnpm run init + pnpm install + pnpm run build:packages pnpm run test --react17 -- --testTimeout=120000 pnpm build-storybook ' diff --git a/tools/install/src/ALL_PACKAGES.ts b/tools/install/src/ALL_PACKAGES.ts index 238a0402e6..3f608707d0 100644 --- a/tools/install/src/ALL_PACKAGES.ts +++ b/tools/install/src/ALL_PACKAGES.ts @@ -117,4 +117,5 @@ export const ALL_PACKAGES = [ '@lg-tools/test-harnesses', '@lg-tools/update', '@lg-tools/validate', + '@lg-mcp-ui/list-databases', ] as const; diff --git a/tools/test/config/react17/jest.config.js b/tools/test/config/react17/jest.config.js index 37f84bcf85..10407c379b 100644 --- a/tools/test/config/react17/jest.config.js +++ b/tools/test/config/react17/jest.config.js @@ -42,7 +42,12 @@ module.exports = { testEnvironment: 'jsdom', // An array of regexp pattern strings that are matched against all test paths, matched tests are skipped - testPathIgnorePatterns: ['/node_modules/', '/deprecated-packages/'], + testPathIgnorePatterns: [ + '/node_modules/', + '/deprecated-packages/', + '/apps/', + '/mcp-ui/', + ], // The regexp pattern Jest uses to detect test files testRegex: '.spec.[jt]sx?$', diff --git a/turbo.json b/turbo.json index 1494e6f221..1df11b6653 100644 --- a/turbo.json +++ b/turbo.json @@ -7,7 +7,13 @@ "build": { "dependsOn": ["^build", "^prebuild", "prebuild"], "inputs": ["$TURBO_DEFAULT$", "!**/*.stories.{tsx,jsx,mdx}"], - "outputs": ["dist/**/*.js", "dist/**/*.js.map", "stories.js"] + "outputs": [ + "dist/**/*.js", + "dist/**/*.js.map", + "stories.js", + ".next/**", + "out/**" + ] }, "tsc": { "dependsOn": ["^tsc", "^prebuild", "prebuild"], @@ -20,6 +26,10 @@ "docs": { "dependsOn": ["^tsc"], "outputs": ["tsdoc.json"] + }, + "dev": { + "cache": false, + "persistent": true } } }