fix(types): Desktop type safety hardening (TYPE-01)
Some checks failed
CI / Lint & TypeCheck (push) Has been cancelled
CI / Unit Tests (push) Has been cancelled
CI / Build Frontend (push) Has been cancelled
CI / Rust Check (push) Has been cancelled
CI / Security Scan (push) Has been cancelled
CI / E2E Tests (push) Has been cancelled
Some checks failed
CI / Lint & TypeCheck (push) Has been cancelled
CI / Unit Tests (push) Has been cancelled
CI / Build Frontend (push) Has been cancelled
CI / Rust Check (push) Has been cancelled
CI / Security Scan (push) Has been cancelled
CI / E2E Tests (push) Has been cancelled
- Unify ConnectionState: kernel-types.ts now canonical source with 'handshaking', gateway-types.ts re-exports - PromptTemplateInfo source/status → union literals - PromptVariable.type → union literal - CreateRoleRequest id/permissions → optional - PropertyPanel: replace 13 as any with typed accessor pattern - chatStore: window cast via as unknown as Record
This commit is contained in:
@@ -87,8 +87,13 @@ function renderTypeSpecificFields(
|
||||
data: Partial<WorkflowNodeData>,
|
||||
onChange: (field: string, value: unknown) => void
|
||||
) {
|
||||
// Type-safe property accessor for union-typed node data
|
||||
// Type-safe property accessors for union-typed node data
|
||||
const d = data as Record<string, unknown>;
|
||||
const str = (key: string): string => (d[key] as string) || '';
|
||||
const num = (key: string): number | string => (d[key] as number) ?? '';
|
||||
const bool = (key: string): boolean => (d[key] as boolean) || false;
|
||||
const arr = (key: string): string[] => (d[key] as string[]) || [];
|
||||
const obj = (key: string): Record<string, unknown> => (d[key] as Record<string, unknown>) || {};
|
||||
switch (type) {
|
||||
case 'input':
|
||||
return (
|
||||
@@ -99,7 +104,7 @@ function renderTypeSpecificFields(
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
value={d.variableName || ''}
|
||||
value={str('variableName')}
|
||||
onChange={(e) => onChange('variableName', e.target.value)}
|
||||
className="w-full px-3 py-2 border border-gray-300 rounded-lg font-mono"
|
||||
/>
|
||||
@@ -109,7 +114,7 @@ function renderTypeSpecificFields(
|
||||
Default Value
|
||||
</label>
|
||||
<textarea
|
||||
value={d.defaultValue || ''}
|
||||
value={str('defaultValue')}
|
||||
onChange={(e) => {
|
||||
try {
|
||||
const parsed = JSON.parse(e.target.value);
|
||||
@@ -134,7 +139,7 @@ function renderTypeSpecificFields(
|
||||
Template
|
||||
</label>
|
||||
<textarea
|
||||
value={d.template || ''}
|
||||
value={str('template')}
|
||||
onChange={(e) => onChange('template', e.target.value)}
|
||||
className="w-full px-3 py-2 border border-gray-300 rounded-lg font-mono text-sm"
|
||||
rows={6}
|
||||
@@ -146,7 +151,7 @@ function renderTypeSpecificFields(
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
value={d.model || ''}
|
||||
value={str('model')}
|
||||
onChange={(e) => onChange('model', e.target.value)}
|
||||
className="w-full px-3 py-2 border border-gray-300 rounded-lg"
|
||||
placeholder="e.g., gpt-4"
|
||||
@@ -161,7 +166,7 @@ function renderTypeSpecificFields(
|
||||
min="0"
|
||||
max="2"
|
||||
step="0.1"
|
||||
value={d.temperature ?? ''}
|
||||
value={num('temperature')}
|
||||
onChange={(e) => onChange('temperature', parseFloat(e.target.value))}
|
||||
className="w-full px-3 py-2 border border-gray-300 rounded-lg"
|
||||
/>
|
||||
@@ -169,7 +174,7 @@ function renderTypeSpecificFields(
|
||||
<div className="flex items-center gap-2">
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={d.jsonMode || false}
|
||||
checked={bool('jsonMode')}
|
||||
onChange={(e) => onChange('jsonMode', e.target.checked)}
|
||||
className="w-4 h-4 text-blue-600 rounded"
|
||||
/>
|
||||
@@ -187,7 +192,7 @@ function renderTypeSpecificFields(
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
value={d.skillId || ''}
|
||||
value={str('skillId')}
|
||||
onChange={(e) => onChange('skillId', e.target.value)}
|
||||
className="w-full px-3 py-2 border border-gray-300 rounded-lg font-mono"
|
||||
/>
|
||||
@@ -197,7 +202,7 @@ function renderTypeSpecificFields(
|
||||
Input Mappings (JSON)
|
||||
</label>
|
||||
<textarea
|
||||
value={JSON.stringify(d.inputMappings || {}, null, 2)}
|
||||
value={JSON.stringify(obj('inputMappings'), null, 2)}
|
||||
onChange={(e) => {
|
||||
try {
|
||||
const parsed = JSON.parse(e.target.value);
|
||||
@@ -222,7 +227,7 @@ function renderTypeSpecificFields(
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
value={d.handId || ''}
|
||||
value={str('handId')}
|
||||
onChange={(e) => onChange('handId', e.target.value)}
|
||||
className="w-full px-3 py-2 border border-gray-300 rounded-lg font-mono"
|
||||
/>
|
||||
@@ -233,7 +238,7 @@ function renderTypeSpecificFields(
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
value={d.action || ''}
|
||||
value={str('action')}
|
||||
onChange={(e) => onChange('action', e.target.value)}
|
||||
className="w-full px-3 py-2 border border-gray-300 rounded-lg"
|
||||
/>
|
||||
@@ -253,13 +258,13 @@ function renderTypeSpecificFields(
|
||||
<label key={format} className="flex items-center gap-2">
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={(d.formats || []).includes(format)}
|
||||
checked={arr('formats').includes(format)}
|
||||
onChange={(e) => {
|
||||
const formats = d.formats || [];
|
||||
const formats = arr('formats');
|
||||
if (e.target.checked) {
|
||||
onChange('formats', [...formats, format]);
|
||||
} else {
|
||||
onChange('formats', formats.filter((f: string) => f !== format));
|
||||
onChange('formats', formats.filter((f) => f !== format));
|
||||
}
|
||||
}}
|
||||
className="w-4 h-4 text-blue-600 rounded"
|
||||
@@ -275,7 +280,7 @@ function renderTypeSpecificFields(
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
value={d.outputDir || ''}
|
||||
value={str('outputDir')}
|
||||
onChange={(e) => onChange('outputDir', e.target.value)}
|
||||
className="w-full px-3 py-2 border border-gray-300 rounded-lg"
|
||||
placeholder="./output"
|
||||
|
||||
Reference in New Issue
Block a user