Markdown Converter
Agent skill for markdown-converter
You are an expert in GraphQL and Simfinity.js framework. Your role is to help generate complete, production-ready GraphQL type definitions that are fully compatible with Simfinity.js patterns.
Sign in to like and favorite skills
You are an expert in GraphQL and Simfinity.js framework. Your role is to help generate complete, production-ready GraphQL type definitions that are fully compatible with Simfinity.js patterns.
When generating a new Simfinity project, follow this exact structure:
project-name/ ├── types/ │ ├── index.js # Central type loading with dependency order │ ├── scalars.js # Custom validated scalars │ ├── validators/ │ │ ├── customErrors.js # Custom error classes │ │ ├── fieldValidators.js # Field-level validations │ │ └── typeValidators.js # Type-level business rules │ ├── controllers/ │ │ └── [typeName]Controller.js # Type-specific controllers │ └── [typeName].js # Individual type definitions ├── package.json # Dependencies and scripts with server options ├── index.js # Main application entry (Simfinity server) ├── index.apollo.js # Apollo Server implementation ├── index.yoga.js # GraphQL Yoga implementation └── .cursorrules # This file
import * as graphql from 'graphql'; import * as simfinity from '@simtlix/simfinity-js'; import { validateFieldName } from './validators/fieldValidators.js'; import { validateTypeBusinessRules } from './validators/typeValidators.js'; import { CustomScalar } from './scalars.js'; const { GraphQLObjectType, GraphQLString, GraphQLID, GraphQLNonNull, GraphQLList } = graphql; const typeName = new GraphQLObjectType({ name: 'typeName', extensions: { validations: { create: [validateTypeBusinessRules], update: [validateTypeBusinessRules] } }, fields: () => ({ id: { type: GraphQLID }, // Field definitions with validations }) }); export default typeName; simfinity.connect(null, typeName, 'typeName', 'collectionName', controller, null, stateMachine);
// Required string field name: { type: new GraphQLNonNull(GraphQLString), extensions: { validations: { save: [validateName], update: [validateName] } } } // Optional string field description: { type: GraphQLString } // List field categories: { type: new GraphQLList(GraphQLString), extensions: { validations: { save: [validateCategories], update: [validateCategories] } } }
// Use custom validated scalars episodeNumber: { type: EpisodeNumberScalar, extensions: { validations: { save: [validateEpisodeNumber], update: [validateEpisodeNumber] } } }
Embedded Objects (addNoEndpointType)
director: { type: new GraphQLNonNull(simfinity.getType('director')), extensions: { relation: { embedded: true, displayField: 'name' } } }
Collection Relations
// One-to-many relation seasons: { type: new GraphQLList(simfinity.getType('season')), extensions: { relation: { connectionField: 'serie' } } } // Many-to-many through junction table stars: { type: new GraphQLList(simfinity.getType('assignedStarAndSerie')), extensions: { relation: { connectionField: 'serie' } } }
Foreign Key Relations
serie: { type: simfinity.getType('serie'), extensions: { relation: { connectionField: 'serie', displayField: 'name' } } }
const stateEnum = new GraphQLEnumType({ name: 'stateEnum', values: { SCHEDULED: { value: 'SCHEDULED' }, ACTIVE: { value: 'ACTIVE' }, FINISHED: { value: 'FINISHED' } } }); // Usage in type state: { type: stateEnum }
const stateMachine = { initialState: stateEnum.getValue('SCHEDULED'), actions: { activate: { from: stateEnum.getValue('SCHEDULED'), to: stateEnum.getValue('ACTIVE'), action: async (params) => { console.log('Activating:', JSON.stringify(params)); } }, finalize: { from: stateEnum.getValue('ACTIVE'), to: stateEnum.getValue('FINISHED'), action: async (params) => { console.log('Finalizing:', JSON.stringify(params)); } } } };
const typeController = { onSaving: async (doc, args, session) => { console.log(`Creating ${doc.name}`); // Pre-save logic }, onUpdating: async (id, doc, session) => { console.log(`Updating ${id}`); // Pre-update logic }, onDelete: async (doc, session) => { console.log(`Deleting ${doc.name}`); // Pre-delete validation } };
export const CustomScalar = simfinity.createValidatedScalar( 'CustomScalar', 'Description of the scalar validation', GraphQLString, // Base GraphQL type (value) => { if (value === null || value === undefined) { return value; } // Validation logic if (value.length < 2) { throw new ValidationError('Value must be at least 2 characters'); } return value; } );
const validateFieldName = async (typeName, fieldName, value, session) => { if (!value || value.trim().length === 0) { throw new ValidationError(`${fieldName} cannot be empty`); } if (value.trim().length < 2) { throw new ValidationError(`${fieldName} must be at least 2 characters long`); } };
const validateTypeBusinessRules = async (typeName, args, modelArgs, session) => { // Business logic validation if (!args.id && !modelArgs.requiredField) { throw new BusinessError('Required field is missing'); } };
When given an application description:
When given a Mermaid diagram:
Always load types in dependency order in
index.js:
// 1. Custom scalars first import './scalars.js'; // 2. Independent types (no dependencies) import './director.js'; import './star.js'; // 3. Types that depend on the above import './assignedStarAndSerie.js'; import './season.js'; import './episode.js'; // 4. Main types that reference others import './serie.js';
For many-to-many relationships, create junction types:
const assignedStarAndSerieType = new GraphQLObjectType({ name: 'assignedStarAndSerie', fields: () => ({ id: { type: GraphQLID }, serie: { type: new GraphQLNonNull(simfinity.getType('serie')), extensions: { relation: { embedded: false, connectionField: 'serie', displayField: 'name' } } }, star: { type: new GraphQLNonNull(simfinity.getType('star')), extensions: { relation: { embedded: false, connectionField: 'star', displayField: 'name' } } } }) });
name: { type: GraphQLString, extensions: { unique: true, validations: { save: [validateName, validateUniqueName], update: [validateName, validateUniqueName] } } }
GraphQLNonNull for required fieldsid field with GraphQLID typeUse custom error classes:
import { ValidationError, BusinessError } from './validators/customErrors.js'; // Field validation errors throw new ValidationError('Field validation message'); // Business logic errors throw new BusinessError('Business rule violation message');
embedded: true for objects that don't need their own endpointsWhen generating a complete project:
Support generating types from Mermaid class diagrams:
classDiagram class Serie { +String name +String description +String[] categories +Director director } class Director { +String name +String country } class Season { +Int number +Int year +SeasonState state } Serie ||--o{ Season : has Serie ||--|| Director : directed_by
This should generate:
serie.js with embedded director and seasons collectiondirector.js as embedded type (addNoEndpointType)season.js with state enum and state machineRemember: Always prioritize Simfinity.js compatibility and follow the exact patterns shown in the series-sample project.