diff --git a/apps/web-tss/package.json b/apps/web-tss/package.json index cfbb61aa7..aa478f275 100644 --- a/apps/web-tss/package.json +++ b/apps/web-tss/package.json @@ -6,8 +6,10 @@ "scripts": { "dev": "vite dev --port 3000", "dev:fast": "pnpm run build && pnpm run start", - "start": "bun .output/server/index.mjs", + "start": "node .output/server/index.mjs", + "start:bun": "bun .output/server/index.mjs", "build": "cross-env NODE_OPTIONS=--max-old-space-size=8192 vite build -- --typecheck", + "build:local": "cross-env NODE_OPTIONS=--max-old-space-size=8192 vite build -- --typecheck --local", "build:no-typecheck": "vite build", "build:fix": "pnpm build:no-typecheck && pnpm run build:fix-react-symlink", "build:fix-react-symlink": "npx tsx scripts/fix-react-symlink.ts", diff --git a/apps/web-tss/src/lib/metrics/files/MyYamlEditor.stories.tsx b/apps/web-tss/src/lib/metrics/files/MyYamlEditor.stories.tsx deleted file mode 100644 index 3da96ceea..000000000 --- a/apps/web-tss/src/lib/metrics/files/MyYamlEditor.stories.tsx +++ /dev/null @@ -1,25 +0,0 @@ -import type { Meta, StoryObj } from '@storybook/react-vite'; -import { MyYamlEditor } from './validateMetricYaml'; - -const meta: Meta = { - title: 'Lib/Files/MyYamlEditorWithValidation', - component: MyYamlEditor, - tags: ['autodocs'], - parameters: { - layout: 'centered', - }, - decorators: [ - (Story) => ( -
- -
- ), - ], -}; - -export default meta; -type Story = StoryObj; - -export const Default: Story = { - args: {}, -}; diff --git a/apps/web-tss/src/lib/metrics/files/validateMetricYaml.tsx b/apps/web-tss/src/lib/metrics/files/validateMetricYaml.tsx index 977632f5c..906aac2f4 100644 --- a/apps/web-tss/src/lib/metrics/files/validateMetricYaml.tsx +++ b/apps/web-tss/src/lib/metrics/files/validateMetricYaml.tsx @@ -1,202 +1,202 @@ -// import MonacoEditor from '@monaco-editor/react'; -// import * as yaml from 'js-yaml'; -// import type { editor } from 'monaco-editor/esm/vs/editor/editor.api'; -// import type React from 'react'; -// import { useRef } from 'react'; +import MonacoEditor from '@monaco-editor/react'; +import * as yaml from 'js-yaml'; +import type { editor } from 'monaco-editor/esm/vs/editor/editor.api'; +import type React from 'react'; +import { useRef } from 'react'; -// type IMarkerData = editor.IMarkerData; +type IMarkerData = editor.IMarkerData; -// // Initial YAML content for testing -// const initialValue = `Person: "John Doe" -// Place: "Wonderland" -// Age: 30 -// Siblings: -// Jane: 25 -// Jim: 28`; +// Initial YAML content for testing +const initialValue = `Person: "John Doe" +Place: "Wonderland" +Age: 30 +Siblings: + Jane: 25 + Jim: 28`; -// // Helper function to find line number for a specific key in YAML content -// const findLineNumberForKey = (content: string, key: string): number => { -// const lines = content.split('\n'); -// for (let i = 0; i < lines.length; i++) { -// if (lines[i].trim().startsWith(`${key}:`)) { -// return i + 1; // Line numbers are 1-based -// } -// } -// return 1; // Default to line 1 if not found -// }; +// Helper function to find line number for a specific key in YAML content +const findLineNumberForKey = (content: string, key: string): number => { + const lines = content.split('\n'); + for (let i = 0; i < lines.length; i++) { + if (lines[i].trim().startsWith(`${key}:`)) { + return i + 1; // Line numbers are 1-based + } + } + return 1; // Default to line 1 if not found +}; -// // Linting function that validates YAML content -// export const validateMetricYaml = ( -// content: string, -// monaco: typeof import('monaco-editor') -// ): IMarkerData[] => { -// const markers: IMarkerData[] = []; -// let parsed: unknown; +// Linting function that validates YAML content +export const validateMetricYaml = ( + content: string, + monaco: typeof import('monaco-editor') +): IMarkerData[] => { + const markers: IMarkerData[] = []; + let parsed: unknown; -// // Parse YAML content -// try { -// parsed = yaml.load(content); -// } catch (error: unknown) { -// // For parse errors, extract line and column information from the error -// let lineNumber = 1; -// let columnNumber = 1; + // Parse YAML content + try { + parsed = yaml.load(content); + } catch (error: unknown) { + // For parse errors, extract line and column information from the error + let lineNumber = 1; + let columnNumber = 1; -// if (error instanceof Error) { -// // Extract line number from error message if available -// if ('mark' in error && typeof error.mark === 'object' && error.mark) { -// const mark = error.mark as { line?: number; column?: number }; -// lineNumber = (mark.line || 0) + 1; // Monaco uses 1-based line numbers -// columnNumber = (mark.column || 0) + 1; // Monaco uses 1-based column numbers -// } else { -// // Fallback to regex for older versions or different error types -// const lineMatch = error.message.match(/line (\d+)/i); -// if (lineMatch?.[1]) { -// lineNumber = Number.parseInt(lineMatch[1], 10); -// } -// } -// } + if (error instanceof Error) { + // Extract line number from error message if available + if ('mark' in error && typeof error.mark === 'object' && error.mark) { + const mark = error.mark as { line?: number; column?: number }; + lineNumber = (mark.line || 0) + 1; // Monaco uses 1-based line numbers + columnNumber = (mark.column || 0) + 1; // Monaco uses 1-based column numbers + } else { + // Fallback to regex for older versions or different error types + const lineMatch = error.message.match(/line (\d+)/i); + if (lineMatch?.[1]) { + lineNumber = Number.parseInt(lineMatch[1], 10); + } + } + } -// markers.push({ -// severity: monaco.MarkerSeverity.Error, -// message: `Invalid YAML: ${(error as Error).message}`, -// startLineNumber: lineNumber, -// startColumn: columnNumber, -// endLineNumber: lineNumber, -// endColumn: columnNumber, -// }); + markers.push({ + severity: monaco.MarkerSeverity.Error, + message: `Invalid YAML: ${(error as Error).message}`, + startLineNumber: lineNumber, + startColumn: columnNumber, + endLineNumber: lineNumber, + endColumn: columnNumber, + }); -// return markers; -// } + return markers; + } -// // Ensure the parsed result is an object -// if (typeof parsed !== 'object' || parsed === null) { -// markers.push({ -// severity: monaco.MarkerSeverity.Error, -// message: 'YAML content should be an object with properties.', -// startLineNumber: 1, -// startColumn: 1, -// endLineNumber: 1, -// endColumn: 1, -// }); -// return markers; -// } + // Ensure the parsed result is an object + if (typeof parsed !== 'object' || parsed === null) { + markers.push({ + severity: monaco.MarkerSeverity.Error, + message: 'YAML content should be an object with properties.', + startLineNumber: 1, + startColumn: 1, + endLineNumber: 1, + endColumn: 1, + }); + return markers; + } -// // Allowed keys -// const allowedKeys = ['Person', 'Place', 'Age', 'Siblings']; -// const keys = Object.keys(parsed); + // Allowed keys + const allowedKeys = ['Person', 'Place', 'Age', 'Siblings']; + const keys = Object.keys(parsed); -// // Check for any unexpected keys -// for (const key of keys) { -// if (!allowedKeys.includes(key)) { -// markers.push({ -// severity: monaco.MarkerSeverity.Warning, -// message: `Unexpected key: "${key}"`, -// startLineNumber: findLineNumberForKey(content, key) || 1, -// startColumn: 1, -// endLineNumber: findLineNumberForKey(content, key) || 1, -// endColumn: 100, -// }); -// } -// } + // Check for any unexpected keys + for (const key of keys) { + if (!allowedKeys.includes(key)) { + markers.push({ + severity: monaco.MarkerSeverity.Warning, + message: `Unexpected key: "${key}"`, + startLineNumber: findLineNumberForKey(content, key) || 1, + startColumn: 1, + endLineNumber: findLineNumberForKey(content, key) || 1, + endColumn: 100, + }); + } + } -// // Check for missing keys -// for (const key of allowedKeys) { -// if (!(key in parsed)) { -// markers.push({ -// severity: monaco.MarkerSeverity.Error, -// message: `Missing required key: "${key}"`, -// startLineNumber: 1, -// startColumn: 1, -// endLineNumber: 1, -// endColumn: 100, -// }); -// } -// } + // Check for missing keys + for (const key of allowedKeys) { + if (!(key in parsed)) { + markers.push({ + severity: monaco.MarkerSeverity.Error, + message: `Missing required key: "${key}"`, + startLineNumber: 1, + startColumn: 1, + endLineNumber: 1, + endColumn: 100, + }); + } + } -// // Validate types for each field -// if ('Person' in parsed && typeof parsed.Person !== 'string') { -// const lineNumber = findLineNumberForKey(content, 'Person'); -// markers.push({ -// severity: monaco.MarkerSeverity.Error, -// message: 'The "Person" field must be a string.', -// startLineNumber: lineNumber, -// startColumn: 1, -// endLineNumber: lineNumber, -// endColumn: content.split('\n')[lineNumber - 1]?.length || 1, -// }); -// } + // Validate types for each field + if ('Person' in parsed && typeof parsed.Person !== 'string') { + const lineNumber = findLineNumberForKey(content, 'Person'); + markers.push({ + severity: monaco.MarkerSeverity.Error, + message: 'The "Person" field must be a string.', + startLineNumber: lineNumber, + startColumn: 1, + endLineNumber: lineNumber, + endColumn: content.split('\n')[lineNumber - 1]?.length || 1, + }); + } -// if ('Place' in parsed && typeof parsed.Place !== 'string') { -// const lineNumber = findLineNumberForKey(content, 'Place'); -// markers.push({ -// severity: monaco.MarkerSeverity.Error, -// message: 'The "Place" field must be a string.', -// startLineNumber: lineNumber, -// startColumn: 1, -// endLineNumber: lineNumber, -// endColumn: content.split('\n')[lineNumber - 1]?.length || 1, -// }); -// } + if ('Place' in parsed && typeof parsed.Place !== 'string') { + const lineNumber = findLineNumberForKey(content, 'Place'); + markers.push({ + severity: monaco.MarkerSeverity.Error, + message: 'The "Place" field must be a string.', + startLineNumber: lineNumber, + startColumn: 1, + endLineNumber: lineNumber, + endColumn: content.split('\n')[lineNumber - 1]?.length || 1, + }); + } -// if ('Age' in parsed && typeof parsed.Age !== 'number') { -// const lineNumber = findLineNumberForKey(content, 'Age'); -// markers.push({ -// severity: monaco.MarkerSeverity.Error, -// message: 'The "Age" field must be a number.', -// startLineNumber: lineNumber, -// startColumn: 1, -// endLineNumber: lineNumber, -// endColumn: content.split('\n')[lineNumber - 1]?.length || 1, -// }); -// } + if ('Age' in parsed && typeof parsed.Age !== 'number') { + const lineNumber = findLineNumberForKey(content, 'Age'); + markers.push({ + severity: monaco.MarkerSeverity.Error, + message: 'The "Age" field must be a number.', + startLineNumber: lineNumber, + startColumn: 1, + endLineNumber: lineNumber, + endColumn: content.split('\n')[lineNumber - 1]?.length || 1, + }); + } -// if ('Siblings' in parsed) { -// const siblingsLineNumber = findLineNumberForKey(content, 'Siblings'); + if ('Siblings' in parsed) { + const siblingsLineNumber = findLineNumberForKey(content, 'Siblings'); -// if ( -// typeof parsed.Siblings !== 'object' || -// Array.isArray(parsed.Siblings) || -// parsed.Siblings === null -// ) { -// markers.push({ -// severity: monaco.MarkerSeverity.Error, -// message: 'The "Siblings" field must be an object with sibling name-age pairs.', -// startLineNumber: siblingsLineNumber, -// startColumn: 1, -// endLineNumber: siblingsLineNumber, -// endColumn: content.split('\n')[siblingsLineNumber - 1]?.length || 1, -// }); -// } else { -// // Validate that each sibling's age is a number -// const lines = content.split('\n'); -// for (const [siblingName, siblingAge] of Object.entries(parsed.Siblings)) { -// if (typeof siblingAge !== 'number') { -// // Look for the sibling in the content -// let siblingLineNumber = siblingsLineNumber + 1; // Start after Siblings: -// for (let i = siblingsLineNumber; i < lines.length; i++) { -// if (lines[i].trim().startsWith(`${siblingName}:`)) { -// siblingLineNumber = i + 1; -// break; -// } -// } + if ( + typeof parsed.Siblings !== 'object' || + Array.isArray(parsed.Siblings) || + parsed.Siblings === null + ) { + markers.push({ + severity: monaco.MarkerSeverity.Error, + message: 'The "Siblings" field must be an object with sibling name-age pairs.', + startLineNumber: siblingsLineNumber, + startColumn: 1, + endLineNumber: siblingsLineNumber, + endColumn: content.split('\n')[siblingsLineNumber - 1]?.length || 1, + }); + } else { + // Validate that each sibling's age is a number + const lines = content.split('\n'); + for (const [siblingName, siblingAge] of Object.entries(parsed.Siblings)) { + if (typeof siblingAge !== 'number') { + // Look for the sibling in the content + let siblingLineNumber = siblingsLineNumber + 1; // Start after Siblings: + for (let i = siblingsLineNumber; i < lines.length; i++) { + if (lines[i].trim().startsWith(`${siblingName}:`)) { + siblingLineNumber = i + 1; + break; + } + } -// markers.push({ -// severity: monaco.MarkerSeverity.Error, -// message: `The age for sibling "${siblingName}" must be a number.`, -// startLineNumber: siblingLineNumber, -// startColumn: 1, -// endLineNumber: siblingLineNumber, -// endColumn: lines[siblingLineNumber - 1]?.length || 1, -// }); -// } -// } -// } -// } + markers.push({ + severity: monaco.MarkerSeverity.Error, + message: `The age for sibling "${siblingName}" must be a number.`, + startLineNumber: siblingLineNumber, + startColumn: 1, + endLineNumber: siblingLineNumber, + endColumn: lines[siblingLineNumber - 1]?.length || 1, + }); + } + } + } + } -// return markers; -// }; + return markers; +}; -// // Helper to configure Monaco YAML schema +// Helper to configure Monaco YAML schema // const configureYamlSchema = ( // monaco: typeof import('monaco-editor'), // editor: editor.IStandaloneCodeEditor diff --git a/apps/web-tss/vite.config.ts b/apps/web-tss/vite.config.ts index 4da07280b..2afca8b72 100644 --- a/apps/web-tss/vite.config.ts +++ b/apps/web-tss/vite.config.ts @@ -10,8 +10,7 @@ const config = defineConfig(({ command, mode }) => { const isProduction = mode === 'production'; const isTypecheck = process.argv.includes('--typecheck') || process.env.TYPECHECK === 'true'; const useChecker = !process.env.VITEST && isBuild; - const isLocalBuild = process.env.VITE_PUBLIC_API2_URL?.includes('127.0.0.1'); - console.log('isLocalBuild', isLocalBuild, process.env.VITE_PUBLIC_API2_URL); + const isLocalBuild = process.argv.includes('--local'); return { server: { port: 3000 }, @@ -19,7 +18,10 @@ const config = defineConfig(({ command, mode }) => { // this is the plugin that enables path aliases viteTsConfigPaths({ projects: ['./tsconfig.json'] }), tailwindcss(), - tanstackStart({ customViteReactPlugin: true, target: 'cloudflare-module' }), + tanstackStart({ + customViteReactPlugin: true, + target: isLocalBuild ? 'bun' : 'cloudflare-module', + }), viteReact(), useChecker ? checker({