mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-04-24 00:09:32 +00:00
Compare commits
2 Commits
fix/qwenvl
...
fix-schema
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ae184609c8 | ||
|
|
88c4b086dc |
160
docs/SCHEMA_GENERATION.md
Normal file
160
docs/SCHEMA_GENERATION.md
Normal file
@@ -0,0 +1,160 @@
|
|||||||
|
# ComfyUI Workflow Schema Generation
|
||||||
|
|
||||||
|
This document describes the process for generating and maintaining JSON Schema definitions for ComfyUI workflows.
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
ComfyUI uses **Zod schemas** in TypeScript to define workflow structure, which are converted to **JSON Schema** format for external consumption, documentation, and validation.
|
||||||
|
|
||||||
|
### Schema Versions
|
||||||
|
|
||||||
|
- **Version 0.4** (Legacy): Original workflow format with array-based links
|
||||||
|
- **Version 1.0** (Current): Modern format with object-based links, subgraphs, and reroutes
|
||||||
|
|
||||||
|
## Schema Generation Process
|
||||||
|
|
||||||
|
### Prerequisites
|
||||||
|
|
||||||
|
1. Ensure all dependencies are installed: `npm install`
|
||||||
|
2. Verify TypeScript compilation: `npm run typecheck`
|
||||||
|
|
||||||
|
### Command
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm run json-schema
|
||||||
|
```
|
||||||
|
|
||||||
|
This runs the generation script: `scripts/generate-json-schema.ts`
|
||||||
|
|
||||||
|
### Output
|
||||||
|
|
||||||
|
Generated schemas are written to `./schemas/` directory:
|
||||||
|
|
||||||
|
- `workflow-0_4.json` (~80KB) - Legacy workflow format
|
||||||
|
- `workflow-1_0.json` (~82KB) - Current workflow format
|
||||||
|
- `node-def-v1.json` - Node definition schema v1
|
||||||
|
- `node-def-v2.json` - Node definition schema v2
|
||||||
|
|
||||||
|
**Note**: The `./schemas/` directory is gitignored and not committed to the repository.
|
||||||
|
|
||||||
|
## When to Regenerate Schemas
|
||||||
|
|
||||||
|
### Required Regeneration
|
||||||
|
|
||||||
|
Run schema generation when:
|
||||||
|
|
||||||
|
1. **Schema Changes**: Any modifications to files in `/src/schemas/`
|
||||||
|
2. **Breaking Changes**: Changes that affect data structure or validation
|
||||||
|
3. **New Features**: Adding new workflow capabilities (subgraphs, reroutes, etc.)
|
||||||
|
4. **Documentation Updates**: When schema descriptions change
|
||||||
|
|
||||||
|
### Schema Version Bumping
|
||||||
|
|
||||||
|
Only increment schema version for **breaking changes**:
|
||||||
|
|
||||||
|
- Data structure changes (field renames, type changes)
|
||||||
|
- Required field additions
|
||||||
|
- Format changes that break backward compatibility
|
||||||
|
|
||||||
|
**Non-breaking changes** (documentation, optional fields) should NOT bump the version.
|
||||||
|
|
||||||
|
## Schema Sources
|
||||||
|
|
||||||
|
### Primary Schemas (Zod-based)
|
||||||
|
|
||||||
|
#### Workflow Schemas
|
||||||
|
- **File**: `src/schemas/comfyWorkflowSchema.ts`
|
||||||
|
- **Exports**: `zComfyWorkflow` (v0.4), `zComfyWorkflow1` (v1.0)
|
||||||
|
- **Purpose**: Defines workflow JSON structure for both legacy and modern formats
|
||||||
|
|
||||||
|
#### Node Definition Schemas
|
||||||
|
- **Files**:
|
||||||
|
- `src/schemas/nodeDefSchema.ts` (v1)
|
||||||
|
- `src/schemas/nodeDef/nodeDefSchemaV2.ts` (v2)
|
||||||
|
- **Purpose**: Defines node definition structure for different versions
|
||||||
|
|
||||||
|
### Generation Configuration
|
||||||
|
|
||||||
|
The generation script uses:
|
||||||
|
- **Library**: `zod-to-json-schema`
|
||||||
|
- **Strategy**: `$refStrategy: 'none'` (inlines all references)
|
||||||
|
- **Output**: Formatted JSON with proper naming
|
||||||
|
|
||||||
|
## Standard Operating Procedure (SOP)
|
||||||
|
|
||||||
|
### For Schema Updates
|
||||||
|
|
||||||
|
1. **Make Changes**: Modify Zod schemas in `/src/schemas/`
|
||||||
|
2. **Test Locally**: Ensure changes work with existing workflows
|
||||||
|
3. **Run Generation**: `npm run json-schema`
|
||||||
|
4. **Validate Output**: Check generated schemas for correctness
|
||||||
|
5. **Test Integration**: Verify schemas work with external tools
|
||||||
|
6. **Document Changes**: Update this document if process changes
|
||||||
|
|
||||||
|
### For Version Bumps
|
||||||
|
|
||||||
|
1. **Assess Breaking Changes**: Determine if changes are truly breaking
|
||||||
|
2. **Update Version**: Increment version number in schema definition
|
||||||
|
3. **Update Validation**: Modify `validateComfyWorkflow()` function
|
||||||
|
4. **Update Serialization**: Update LGraph serialization if needed
|
||||||
|
5. **Test Backward Compatibility**: Ensure old workflows still load
|
||||||
|
6. **Document Migration**: Provide migration guide if needed
|
||||||
|
|
||||||
|
### For External Publishing
|
||||||
|
|
||||||
|
**Current Status**: No automated publishing to docs.comfy.org exists yet.
|
||||||
|
|
||||||
|
**Recommended Process**:
|
||||||
|
1. Generate schemas locally
|
||||||
|
2. Copy to appropriate documentation repository
|
||||||
|
3. Update documentation with new schema versions
|
||||||
|
4. Coordinate with docs team for publication
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
### Common Issues
|
||||||
|
|
||||||
|
#### Lodash Import Errors
|
||||||
|
**Error**: `SyntaxError: The requested module 'lodash' does not provide an export named 'clamp'`
|
||||||
|
|
||||||
|
**Solution**: Use the simplified generation script that avoids litegraph imports:
|
||||||
|
```bash
|
||||||
|
npx tsx scripts/generate-json-schema-simple.ts
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Recursive Reference Warnings
|
||||||
|
**Warning**: `Recursive reference detected... Defaulting to any`
|
||||||
|
|
||||||
|
**Explanation**: This is expected for subgraph definitions and doesn't affect functionality.
|
||||||
|
|
||||||
|
### Schema Validation Issues
|
||||||
|
|
||||||
|
1. **Check Source Schema**: Verify Zod schema is valid
|
||||||
|
2. **Test TypeScript**: Run `npm run typecheck`
|
||||||
|
3. **Check Dependencies**: Ensure all imports resolve correctly
|
||||||
|
4. **Validate Output**: Test generated JSON Schema with online validators
|
||||||
|
|
||||||
|
## Integration Points
|
||||||
|
|
||||||
|
### External Documentation
|
||||||
|
- **docs.comfy.org**: Official ComfyUI documentation site
|
||||||
|
- **Workflow Spec**: https://docs.comfy.org/specs/workflow_json
|
||||||
|
|
||||||
|
### Development Tools
|
||||||
|
- **IDE Support**: Generated schemas provide autocomplete and validation
|
||||||
|
- **API Validation**: External tools can validate workflow JSON
|
||||||
|
- **Documentation Generation**: Schemas document workflow structure
|
||||||
|
|
||||||
|
## Future Improvements
|
||||||
|
|
||||||
|
1. **Automated Publishing**: Set up CI/CD to publish schemas to docs.comfy.org
|
||||||
|
2. **Version Management**: Implement semantic versioning for schema changes
|
||||||
|
3. **Migration Tools**: Create utilities to migrate between schema versions
|
||||||
|
4. **Testing**: Add automated tests for schema generation and validation
|
||||||
|
5. **Documentation**: Generate human-readable documentation from schemas
|
||||||
|
|
||||||
|
## References
|
||||||
|
|
||||||
|
- **Zod Documentation**: https://zod.dev/
|
||||||
|
- **JSON Schema Specification**: https://json-schema.org/
|
||||||
|
- **ComfyUI Workflow Specification**: https://docs.comfy.org/specs/workflow_json
|
||||||
@@ -4,49 +4,101 @@ import { fromZodError } from 'zod-validation-error'
|
|||||||
// GroupNode is hacking node id to be a string, so we need to allow that.
|
// GroupNode is hacking node id to be a string, so we need to allow that.
|
||||||
// innerNode.id = `${this.node.id}:${i}`
|
// innerNode.id = `${this.node.id}:${i}`
|
||||||
// Remove it after GroupNode is redesigned.
|
// Remove it after GroupNode is redesigned.
|
||||||
export const zNodeId = z.union([z.number().int(), z.string()])
|
/**
|
||||||
export const zNodeInputName = z.string()
|
* Node identifier that can be either a number or string.
|
||||||
|
* Numeric IDs are standard, string IDs are used for GroupNodes.
|
||||||
|
*/
|
||||||
|
export const zNodeId = z
|
||||||
|
.union([z.number().int(), z.string()])
|
||||||
|
.describe('Unique identifier for a node in the workflow')
|
||||||
|
|
||||||
|
/** Name of a node input slot */
|
||||||
|
export const zNodeInputName = z
|
||||||
|
.string()
|
||||||
|
.describe('The name of a node input parameter')
|
||||||
|
|
||||||
export type NodeId = z.infer<typeof zNodeId>
|
export type NodeId = z.infer<typeof zNodeId>
|
||||||
export const zSlotIndex = z.union([
|
|
||||||
z.number().int(),
|
/**
|
||||||
z
|
* Index of a slot on a node (input or output).
|
||||||
.string()
|
* Can be number or string that parses to a number.
|
||||||
.transform((val) => parseInt(val))
|
*/
|
||||||
.refine((val) => !isNaN(val), {
|
export const zSlotIndex = z
|
||||||
message: 'Invalid number'
|
.union([
|
||||||
})
|
z.number().int(),
|
||||||
])
|
z
|
||||||
|
.string()
|
||||||
|
.transform((val) => parseInt(val))
|
||||||
|
.refine((val) => !isNaN(val), {
|
||||||
|
message: 'Invalid number'
|
||||||
|
})
|
||||||
|
])
|
||||||
|
.describe('Index of an input or output slot on a node')
|
||||||
|
|
||||||
// TODO: Investigate usage of array and number as data type usage in custom nodes.
|
// TODO: Investigate usage of array and number as data type usage in custom nodes.
|
||||||
// Known usage:
|
// Known usage:
|
||||||
// - https://github.com/rgthree/rgthree-comfy Context Big node is using array as type.
|
// - https://github.com/rgthree/rgthree-comfy Context Big node is using array as type.
|
||||||
export const zDataType = z.union([z.string(), z.array(z.string()), z.number()])
|
/**
|
||||||
|
* Data type for node inputs/outputs. Can be string, array of strings, or number.
|
||||||
|
* Most common types are strings like 'IMAGE', 'LATENT', 'MODEL', etc.
|
||||||
|
*/
|
||||||
|
export const zDataType = z
|
||||||
|
.union([z.string(), z.array(z.string()), z.number()])
|
||||||
|
.describe('Data type specification for node connections')
|
||||||
|
|
||||||
const zVector2 = z.union([
|
/**
|
||||||
z
|
* 2D position or size vector [x, y].
|
||||||
.object({ 0: z.number(), 1: z.number() })
|
* Can be array tuple or object with numeric indices.
|
||||||
.passthrough()
|
*/
|
||||||
.transform((v) => [v[0], v[1]] as [number, number]),
|
const zVector2 = z
|
||||||
z.tuple([z.number(), z.number()])
|
.union([
|
||||||
])
|
z
|
||||||
|
.object({ 0: z.number(), 1: z.number() })
|
||||||
|
.passthrough()
|
||||||
|
.transform((v) => [v[0], v[1]] as [number, number]),
|
||||||
|
z.tuple([z.number(), z.number()])
|
||||||
|
])
|
||||||
|
.describe('2D coordinate or size vector')
|
||||||
|
|
||||||
// Definition of an AI model file used in the workflow.
|
/**
|
||||||
const zModelFile = z.object({
|
* AI model file definition used in the workflow.
|
||||||
name: z.string(),
|
* Contains metadata for downloading and verifying model files.
|
||||||
url: z.string().url(),
|
*/
|
||||||
hash: z.string().optional(),
|
const zModelFile = z
|
||||||
hash_type: z.string().optional(),
|
.object({
|
||||||
directory: z.string()
|
/** Model file name */
|
||||||
})
|
name: z.string().describe('Model file name'),
|
||||||
|
/** Download URL for the model */
|
||||||
|
url: z.string().url().describe('Download URL for the model'),
|
||||||
|
/** File hash for integrity verification */
|
||||||
|
hash: z
|
||||||
|
.string()
|
||||||
|
.optional()
|
||||||
|
.describe('File hash for integrity verification'),
|
||||||
|
/** Hash algorithm type (e.g., 'sha256') */
|
||||||
|
hash_type: z.string().optional().describe('Hash algorithm type'),
|
||||||
|
/** Directory where model should be stored */
|
||||||
|
directory: z.string().describe('Directory where model should be stored')
|
||||||
|
})
|
||||||
|
.describe('AI model file metadata')
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Graph state tracking for ID generation in schema version 1.
|
||||||
|
* Maintains counters for generating unique IDs for new elements.
|
||||||
|
*/
|
||||||
const zGraphState = z
|
const zGraphState = z
|
||||||
.object({
|
.object({
|
||||||
lastGroupId: z.number(),
|
/** Last assigned group ID */
|
||||||
lastNodeId: z.number(),
|
lastGroupId: z.number().describe('Last assigned group ID'),
|
||||||
lastLinkId: z.number(),
|
/** Last assigned node ID */
|
||||||
lastRerouteId: z.number()
|
lastNodeId: z.number().describe('Last assigned node ID'),
|
||||||
|
/** Last assigned link ID */
|
||||||
|
lastLinkId: z.number().describe('Last assigned link ID'),
|
||||||
|
/** Last assigned reroute ID */
|
||||||
|
lastRerouteId: z.number().describe('Last assigned reroute ID')
|
||||||
})
|
})
|
||||||
.passthrough()
|
.passthrough()
|
||||||
|
.describe('Graph state tracking for ID generation')
|
||||||
|
|
||||||
const zComfyLink = z.tuple([
|
const zComfyLink = z.tuple([
|
||||||
z.number(), // Link id
|
z.number(), // Link id
|
||||||
@@ -287,24 +339,52 @@ export const zBaseExportableGraph = z.object({
|
|||||||
subgraphs: z.array(zSubgraphInstance).optional()
|
subgraphs: z.array(zSubgraphInstance).optional()
|
||||||
})
|
})
|
||||||
|
|
||||||
/** Schema version 0.4 */
|
/**
|
||||||
|
* ComfyUI Workflow JSON Schema version 0.4 (legacy).
|
||||||
|
* This is the original workflow format used by ComfyUI.
|
||||||
|
*/
|
||||||
export const zComfyWorkflow = zBaseExportableGraph
|
export const zComfyWorkflow = zBaseExportableGraph
|
||||||
.extend({
|
.extend({
|
||||||
id: z.string().uuid().optional(),
|
/** Unique workflow identifier */
|
||||||
revision: z.number().optional(),
|
id: z.string().uuid().optional().describe('Unique workflow identifier'),
|
||||||
last_node_id: zNodeId,
|
/** Workflow revision number */
|
||||||
last_link_id: z.number(),
|
revision: z.number().optional().describe('Workflow revision number'),
|
||||||
nodes: z.array(zComfyNode),
|
/** Highest node ID used in this workflow */
|
||||||
links: z.array(zComfyLink),
|
last_node_id: zNodeId.describe('Highest node ID used in this workflow'),
|
||||||
floatingLinks: z.array(zComfyLinkObject).optional(),
|
/** Highest link ID used in this workflow */
|
||||||
groups: z.array(zGroup).optional(),
|
last_link_id: z.number().describe('Highest link ID used in this workflow'),
|
||||||
config: zConfig.optional().nullable(),
|
/** All nodes in the workflow */
|
||||||
extra: zExtra.optional().nullable(),
|
nodes: z.array(zComfyNode).describe('All nodes in the workflow'),
|
||||||
version: z.number(),
|
/** Node connections (legacy tuple format) */
|
||||||
models: z.array(zModelFile).optional(),
|
links: z
|
||||||
definitions: zGraphDefinitions.optional()
|
.array(zComfyLink)
|
||||||
|
.describe('Node connections in legacy tuple format'),
|
||||||
|
/** Floating links (unconnected endpoints) */
|
||||||
|
floatingLinks: z
|
||||||
|
.array(zComfyLinkObject)
|
||||||
|
.optional()
|
||||||
|
.describe('Floating links with unconnected endpoints'),
|
||||||
|
/** Visual groupings of nodes */
|
||||||
|
groups: z.array(zGroup).optional().describe('Visual groupings of nodes'),
|
||||||
|
/** Workflow configuration settings */
|
||||||
|
config: zConfig
|
||||||
|
.optional()
|
||||||
|
.nullable()
|
||||||
|
.describe('Workflow configuration settings'),
|
||||||
|
/** Extra metadata and extensions */
|
||||||
|
extra: zExtra
|
||||||
|
.optional()
|
||||||
|
.nullable()
|
||||||
|
.describe('Extra metadata and extensions'),
|
||||||
|
/** Schema version number */
|
||||||
|
version: z.number().describe('Schema version number (0.4)'),
|
||||||
|
/** Required model files */
|
||||||
|
models: z.array(zModelFile).optional().describe('Required AI model files'),
|
||||||
|
/** Subgraph definitions */
|
||||||
|
definitions: zGraphDefinitions.optional().describe('Subgraph definitions')
|
||||||
})
|
})
|
||||||
.passthrough()
|
.passthrough()
|
||||||
|
.describe('ComfyUI Workflow JSON Schema v0.4')
|
||||||
|
|
||||||
/** Required for recursive definition of subgraphs. */
|
/** Required for recursive definition of subgraphs. */
|
||||||
interface ComfyWorkflow1BaseType {
|
interface ComfyWorkflow1BaseType {
|
||||||
@@ -339,37 +419,76 @@ interface ComfyWorkflow1BaseOutput extends ComfyWorkflow1BaseType {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Schema version 1 */
|
/**
|
||||||
|
* ComfyUI Workflow JSON Schema version 1 (current).
|
||||||
|
* This is the modern workflow format with improved structure and features.
|
||||||
|
*/
|
||||||
export const zComfyWorkflow1 = zBaseExportableGraph
|
export const zComfyWorkflow1 = zBaseExportableGraph
|
||||||
.extend({
|
.extend({
|
||||||
id: z.string().uuid().optional(),
|
/** Unique workflow identifier */
|
||||||
revision: z.number().optional(),
|
id: z.string().uuid().optional().describe('Unique workflow identifier'),
|
||||||
version: z.literal(1),
|
/** Workflow revision number for tracking changes */
|
||||||
config: zConfig.optional().nullable(),
|
revision: z
|
||||||
state: zGraphState,
|
.number()
|
||||||
groups: z.array(zGroup).optional(),
|
.optional()
|
||||||
nodes: z.array(zComfyNode),
|
.describe('Workflow revision number for tracking changes'),
|
||||||
links: z.array(zComfyLinkObject).optional(),
|
/** Schema version (always 1 for this format) */
|
||||||
floatingLinks: z.array(zComfyLinkObject).optional(),
|
version: z.literal(1).describe('Schema version number (1)'),
|
||||||
reroutes: z.array(zReroute).optional(),
|
/** Workflow configuration settings */
|
||||||
extra: zExtra.optional().nullable(),
|
config: zConfig
|
||||||
models: z.array(zModelFile).optional(),
|
.optional()
|
||||||
|
.nullable()
|
||||||
|
.describe('Workflow configuration settings'),
|
||||||
|
/** Graph state for ID tracking and generation */
|
||||||
|
state: zGraphState.describe('Graph state for ID tracking and generation'),
|
||||||
|
/** Visual groupings of nodes */
|
||||||
|
groups: z.array(zGroup).optional().describe('Visual groupings of nodes'),
|
||||||
|
/** All nodes in the workflow */
|
||||||
|
nodes: z.array(zComfyNode).describe('All nodes in the workflow'),
|
||||||
|
/** Node connections (modern object format) */
|
||||||
|
links: z
|
||||||
|
.array(zComfyLinkObject)
|
||||||
|
.optional()
|
||||||
|
.describe('Node connections in modern object format'),
|
||||||
|
/** Floating links (unconnected endpoints) */
|
||||||
|
floatingLinks: z
|
||||||
|
.array(zComfyLinkObject)
|
||||||
|
.optional()
|
||||||
|
.describe('Floating links with unconnected endpoints'),
|
||||||
|
/** Reroute nodes for organizing connections */
|
||||||
|
reroutes: z
|
||||||
|
.array(zReroute)
|
||||||
|
.optional()
|
||||||
|
.describe('Reroute nodes for organizing connections'),
|
||||||
|
/** Extra metadata and extensions */
|
||||||
|
extra: zExtra
|
||||||
|
.optional()
|
||||||
|
.nullable()
|
||||||
|
.describe('Extra metadata and extensions'),
|
||||||
|
/** Required AI model files */
|
||||||
|
models: z.array(zModelFile).optional().describe('Required AI model files'),
|
||||||
|
/** Subgraph definitions */
|
||||||
definitions: z
|
definitions: z
|
||||||
.object({
|
.object({
|
||||||
subgraphs: z.lazy(
|
/** Nested subgraph definitions */
|
||||||
(): z.ZodArray<
|
subgraphs: z
|
||||||
z.ZodType<
|
.lazy(
|
||||||
SubgraphDefinitionBase<ComfyWorkflow1BaseOutput>,
|
(): z.ZodArray<
|
||||||
z.ZodTypeDef,
|
z.ZodType<
|
||||||
SubgraphDefinitionBase<ComfyWorkflow1BaseInput>
|
SubgraphDefinitionBase<ComfyWorkflow1BaseOutput>,
|
||||||
>,
|
z.ZodTypeDef,
|
||||||
'many'
|
SubgraphDefinitionBase<ComfyWorkflow1BaseInput>
|
||||||
> => z.array(zSubgraphDefinition)
|
>,
|
||||||
)
|
'many'
|
||||||
|
> => z.array(zSubgraphDefinition)
|
||||||
|
)
|
||||||
|
.describe('Nested subgraph definitions')
|
||||||
})
|
})
|
||||||
.optional()
|
.optional()
|
||||||
|
.describe('Subgraph definitions')
|
||||||
})
|
})
|
||||||
.passthrough()
|
.passthrough()
|
||||||
|
.describe('ComfyUI Workflow JSON Schema v1')
|
||||||
|
|
||||||
export const zExportedSubgraphIONode = z.object({
|
export const zExportedSubgraphIONode = z.object({
|
||||||
id: zNodeId,
|
id: zNodeId,
|
||||||
@@ -481,6 +600,14 @@ const zWorkflowVersion = z.object({
|
|||||||
version: z.number()
|
version: z.number()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validates a ComfyUI workflow JSON against the appropriate schema version.
|
||||||
|
* Supports both legacy (v0.4) and modern (v1) workflow formats.
|
||||||
|
*
|
||||||
|
* @param data - The workflow data to validate
|
||||||
|
* @param onError - Error callback function for validation failures
|
||||||
|
* @returns Parsed and validated workflow data or null if invalid
|
||||||
|
*/
|
||||||
export async function validateComfyWorkflow(
|
export async function validateComfyWorkflow(
|
||||||
data: unknown,
|
data: unknown,
|
||||||
onError: (error: string) => void = console.warn
|
onError: (error: string) => void = console.warn
|
||||||
@@ -489,17 +616,18 @@ export async function validateComfyWorkflow(
|
|||||||
|
|
||||||
let result: SafeParseReturnType<unknown, ComfyWorkflowJSON>
|
let result: SafeParseReturnType<unknown, ComfyWorkflowJSON>
|
||||||
if (!versionResult.success) {
|
if (!versionResult.success) {
|
||||||
// Invalid workflow
|
// Invalid workflow - missing or invalid version
|
||||||
const error = fromZodError(versionResult.error)
|
const error = fromZodError(versionResult.error)
|
||||||
onError(`Workflow does not contain a valid version. Zod error:\n${error}`)
|
onError(`Workflow does not contain a valid version. Zod error:\n${error}`)
|
||||||
return null
|
return null
|
||||||
} else if (versionResult.data.version === 1) {
|
} else if (versionResult.data.version === 1) {
|
||||||
// Schema version 1
|
// Modern schema version 1 (current)
|
||||||
result = await zComfyWorkflow1.safeParseAsync(data)
|
result = await zComfyWorkflow1.safeParseAsync(data)
|
||||||
} else {
|
} else {
|
||||||
// Unknown or old version: 0.4
|
// Legacy or unknown version: defaults to 0.4 format
|
||||||
result = await zComfyWorkflow.safeParseAsync(data)
|
result = await zComfyWorkflow.safeParseAsync(data)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (result.success) return result.data
|
if (result.success) return result.data
|
||||||
|
|
||||||
const error = fromZodError(result.error)
|
const error = fromZodError(result.error)
|
||||||
|
|||||||
Reference in New Issue
Block a user