UNPKG

cs-element

Version:

Advanced reactive data management library with state machines, blueprints, persistence, compression, networking, and multithreading support

1,135 lines (985 loc) 37.9 kB
# 🏗️ Blueprint система шаблонов CSElement включает мощную систему Blueprint для создания шаблонов структур данных с параметрами, валидацией и генерацией элементов. ## 📋 Содержание - [Основы Blueprint](#основы-blueprint) - [Создание шаблонов](#создание-шаблонов) - [Параметры и валидация](#параметры-и-валидация) - [Генерация структур](#генерация-структур) - [Полный пример](#полный-пример-система-управления-проектами) ## Основы Blueprint ### Создание простого шаблона ```typescript import { Blueprint, BlueprintType, BlueprintCategory, BlueprintParameter, BlueprintParameterGroup, BlueprintGenerationContext, BlueprintGenerationResult } from 'cs-element'; // Создание простого шаблона const userProfileBlueprint = new Blueprint({ id: 'user-profile', name: 'Профиль пользователя', description: 'Шаблон для создания профиля пользователя', type: BlueprintType.CUSTOM, category: BlueprintCategory.BUSINESS, version: '1.0.0', parameterGroups: [ { id: 'basic', name: 'Основная информация', description: 'Базовые данные пользователя', parameters: [ { id: 'name', name: 'Имя', type: 'string', required: true, defaultValue: 'Новый пользователь' }, { id: 'email', name: 'Email', type: 'string', required: true, validation: { pattern: /^[^\s@]+@[^\s@]+\.[^\s@]+$/, message: 'Некорректный email адрес' } }, { id: 'age', name: 'Возраст', type: 'number', required: false, validation: { min: 18, max: 120 } } ] } ], generator: async (context: BlueprintGenerationContext) => { const { parameters } = context; // Создаем корневой элемент const userElement = new CSElement(`user-${Date.now()}`); await userElement.setData('name', parameters.name); await userElement.setData('email', parameters.email); if (parameters.age) { await userElement.setData('age', parameters.age); } await userElement.setData('createdAt', new Date().toISOString()); await userElement.setData('type', 'user-profile'); return { elements: [userElement], rootElement: userElement, warnings: [] }; } }); // Использование шаблона const result = await userProfileBlueprint.generate({ parameters: { name: 'John Doe', email: 'john@example.com', age: 30 } }); console.log('✅ Профиль создан:', result.rootElement?.id); ``` ### Валидация параметров ```typescript // Проверка параметров перед генерацией const parameters = { name: 'John Doe', email: 'invalid-email', age: 150 }; const validation = userProfileBlueprint.validateParameters(parameters); if (!validation.valid) { console.log('❌ Ошибки валидации:'); validation.errors.forEach(error => { console.log(` - ${error.parameter}: ${error.message}`); }); } if (validation.warnings.length > 0) { console.log('⚠️ Предупреждения:'); validation.warnings.forEach(warning => { console.log(` - ${warning.parameter}: ${warning.message}`); }); } ``` ## Создание шаблонов ### Шаблон с вложенными структурами ```typescript const projectBlueprint = new Blueprint({ id: 'project-structure', name: 'Структура проекта', description: 'Шаблон для создания структуры проекта', type: BlueprintType.CUSTOM, category: BlueprintCategory.TECHNICAL, parameterGroups: [ { id: 'project-info', name: 'Информация о проекте', parameters: [ { id: 'projectName', name: 'Название проекта', type: 'string', required: true }, { id: 'projectType', name: 'Тип проекта', type: 'select', required: true, options: [ { value: 'web', label: 'Веб-приложение' }, { value: 'mobile', label: 'Мобильное приложение' }, { value: 'desktop', label: 'Десктоп приложение' } ] }, { id: 'teamSize', name: 'Размер команды', type: 'number', required: true, validation: { min: 1, max: 50 } } ] }, { id: 'features', name: 'Функциональность', parameters: [ { id: 'modules', name: 'Модули', type: 'multiselect', required: false, options: [ { value: 'auth', label: 'Авторизация' }, { value: 'dashboard', label: 'Панель управления' }, { value: 'reports', label: 'Отчеты' }, { value: 'notifications', label: 'Уведомления' } ] }, { id: 'database', name: 'База данных', type: 'select', required: false, options: [ { value: 'mysql', label: 'MySQL' }, { value: 'postgresql', label: 'PostgreSQL' }, { value: 'mongodb', label: 'MongoDB' } ] } ] } ], generator: async (context: BlueprintGenerationContext) => { const { parameters } = context; const elements: CSElement[] = []; // Создаем корневой элемент проекта const projectElement = new CSElement(`project-${Date.now()}`); await projectElement.setData('name', parameters.projectName); await projectElement.setData('type', parameters.projectType); await projectElement.setData('teamSize', parameters.teamSize); await projectElement.setData('createdAt', new Date().toISOString()); elements.push(projectElement); // Создаем команду const teamElement = new CSElement(`team-${Date.now()}`); await teamElement.setData('name', `${parameters.projectName} Team`); await teamElement.setData('size', parameters.teamSize); // Создаем участников команды for (let i = 1; i <= parameters.teamSize; i++) { const memberElement = new CSElement(`member-${i}`); await memberElement.setData('name', `Team Member ${i}`); await memberElement.setData('role', i === 1 ? 'lead' : 'developer'); teamElement.withChild(memberElement); } projectElement.withChild(teamElement); elements.push(teamElement); // Создаем модули если указаны if (parameters.modules && parameters.modules.length > 0) { const modulesElement = new CSElement(`modules-${Date.now()}`); await modulesElement.setData('name', 'Modules'); for (const moduleId of parameters.modules) { const moduleElement = new CSElement(`module-${moduleId}`); await moduleElement.setData('name', moduleId); await moduleElement.setData('type', 'module'); await moduleElement.setData('status', 'planned'); modulesElement.withChild(moduleElement); elements.push(moduleElement); } projectElement.withChild(modulesElement); elements.push(modulesElement); } // Создаем конфигурацию базы данных if (parameters.database) { const dbElement = new CSElement(`database-${Date.now()}`); await dbElement.setData('name', 'Database'); await dbElement.setData('type', parameters.database); await dbElement.setData('status', 'configured'); projectElement.withChild(dbElement); elements.push(dbElement); } return { elements, rootElement: projectElement, warnings: [] }; } }); ``` ### Условные параметры ```typescript const conditionalBlueprint = new Blueprint({ id: 'conditional-form', name: 'Условная форма', description: 'Форма с условными полями', type: BlueprintType.CUSTOM, category: BlueprintCategory.BUSINESS, parameterGroups: [ { id: 'basic', name: 'Основные параметры', parameters: [ { id: 'formType', name: 'Тип формы', type: 'select', required: true, options: [ { value: 'contact', label: 'Контактная форма' }, { value: 'registration', label: 'Регистрация' }, { value: 'survey', label: 'Опрос' } ] }, { id: 'includePhone', name: 'Включить телефон', type: 'boolean', required: false, defaultValue: false, condition: (params) => params.formType === 'contact' || params.formType === 'registration' }, { id: 'phoneNumber', name: 'Номер телефона', type: 'string', required: false, condition: (params) => params.includePhone === true, dependencies: ['includePhone'] }, { id: 'surveyQuestions', name: 'Количество вопросов', type: 'number', required: false, condition: (params) => params.formType === 'survey', validation: { min: 1, max: 20 } } ] } ], generator: async (context: BlueprintGenerationContext) => { const { parameters } = context; const elements: CSElement[] = []; const formElement = new CSElement(`form-${Date.now()}`); await formElement.setData('type', parameters.formType); await formElement.setData('createdAt', new Date().toISOString()); // Базовые поля const nameField = new CSElement('field-name'); await nameField.setData('type', 'text'); await nameField.setData('label', 'Имя'); await nameField.setData('required', true); formElement.withChild(nameField); const emailField = new CSElement('field-email'); await emailField.setData('type', 'email'); await emailField.setData('label', 'Email'); await emailField.setData('required', true); formElement.withChild(emailField); // Условное поле телефона if (parameters.includePhone && parameters.phoneNumber) { const phoneField = new CSElement('field-phone'); await phoneField.setData('type', 'tel'); await phoneField.setData('label', 'Телефон'); await phoneField.setData('defaultValue', parameters.phoneNumber); formElement.withChild(phoneField); } // Поля опроса if (parameters.formType === 'survey' && parameters.surveyQuestions) { for (let i = 1; i <= parameters.surveyQuestions; i++) { const questionField = new CSElement(`field-question-${i}`); await questionField.setData('type', 'textarea'); await questionField.setData('label', `Вопрос ${i}`); await questionField.setData('required', false); formElement.withChild(questionField); } } elements.push(formElement); return { elements, rootElement: formElement, warnings: [] }; } }); ``` ## Параметры и валидация ### Сложная валидация ```typescript class AdvancedValidator { static validateEmail(email: string): string | true { const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; if (!emailRegex.test(email)) { return 'Некорректный формат email'; } const parts = email.split('@'); if (parts[1].length < 3) { return 'Слишком короткий домен'; } return true; } static validatePassword(password: string): string | true { if (password.length < 8) { return 'Пароль должен содержать минимум 8 символов'; } if (!/[A-Z]/.test(password)) { return 'Пароль должен содержать заглавные буквы'; } if (!/[a-z]/.test(password)) { return 'Пароль должен содержать строчные буквы'; } if (!/[0-9]/.test(password)) { return 'Пароль должен содержать цифры'; } return true; } static validateDateRange(startDate: string, endDate: string): string | true { const start = new Date(startDate); const end = new Date(endDate); if (isNaN(start.getTime()) || isNaN(end.getTime())) { return 'Некорректный формат даты'; } if (start >= end) { return 'Дата начала должна быть раньше даты окончания'; } const diffDays = (end.getTime() - start.getTime()) / (1000 * 60 * 60 * 24); if (diffDays > 365) { return 'Период не может превышать 365 дней'; } return true; } } // Шаблон с продвинутой валидацией const advancedUserBlueprint = new Blueprint({ id: 'advanced-user', name: 'Продвинутый пользователь', description: 'Шаблон с расширенной валидацией', type: BlueprintType.CUSTOM, category: BlueprintCategory.BUSINESS, parameterGroups: [ { id: 'credentials', name: 'Учетные данные', parameters: [ { id: 'email', name: 'Email', type: 'string', required: true, validation: { custom: AdvancedValidator.validateEmail } }, { id: 'password', name: 'Пароль', type: 'string', required: true, validation: { custom: AdvancedValidator.validatePassword } } ] }, { id: 'subscription', name: 'Подписка', parameters: [ { id: 'startDate', name: 'Дата начала', type: 'string', required: true }, { id: 'endDate', name: 'Дата окончания', type: 'string', required: true, dependencies: ['startDate'], validation: { custom: (value: string, allParams: any) => { return AdvancedValidator.validateDateRange(allParams.startDate, value); } } } ] } ], generator: async (context: BlueprintGenerationContext) => { // Генерация элементов... const userElement = new CSElement(`user-${Date.now()}`); // ... логика генерации return { elements: [userElement], rootElement: userElement, warnings: [] }; } }); ``` ### Динамические параметры ```typescript class DynamicParameterGenerator { static generateFieldParameters(fieldCount: number): BlueprintParameter[] { const parameters: BlueprintParameter[] = []; for (let i = 1; i <= fieldCount; i++) { parameters.push({ id: `field${i}Name`, name: `Поле ${i} - Название`, type: 'string', required: true, defaultValue: `Поле ${i}` }); parameters.push({ id: `field${i}Type`, name: `Поле ${i} - Тип`, type: 'select', required: true, options: [ { value: 'text', label: 'Текст' }, { value: 'number', label: 'Число' }, { value: 'boolean', label: 'Логическое' }, { value: 'date', label: 'Дата' } ], defaultValue: 'text' }); parameters.push({ id: `field${i}Required`, name: `Поле ${i} - Обязательное`, type: 'boolean', required: false, defaultValue: false }); } return parameters; } } // Создание шаблона с динамическими параметрами function createDynamicFormBlueprint(fieldCount: number): Blueprint { const dynamicParameters = DynamicParameterGenerator.generateFieldParameters(fieldCount); return new Blueprint({ id: `dynamic-form-${fieldCount}`, name: `Динамическая форма (${fieldCount} полей)`, description: `Форма с ${fieldCount} настраиваемыми полями`, type: BlueprintType.CUSTOM, category: BlueprintCategory.BUSINESS, parameterGroups: [ { id: 'form-config', name: 'Конфигурация формы', parameters: [ { id: 'formTitle', name: 'Заголовок формы', type: 'string', required: true, defaultValue: 'Новая форма' }, ...dynamicParameters ] } ], generator: async (context: BlueprintGenerationContext) => { const { parameters } = context; const elements: CSElement[] = []; const formElement = new CSElement(`form-${Date.now()}`); await formElement.setData('title', parameters.formTitle); await formElement.setData('createdAt', new Date().toISOString()); // Создаем поля динамически for (let i = 1; i <= fieldCount; i++) { const fieldName = parameters[`field${i}Name`]; const fieldType = parameters[`field${i}Type`]; const fieldRequired = parameters[`field${i}Required`]; const fieldElement = new CSElement(`field-${i}`); await fieldElement.setData('name', fieldName); await fieldElement.setData('type', fieldType); await fieldElement.setData('required', fieldRequired); formElement.withChild(fieldElement); elements.push(fieldElement); } elements.push(formElement); return { elements, rootElement: formElement, warnings: [] }; } }); } // Использование динамического шаблона const dynamicForm = createDynamicFormBlueprint(5); ``` ## Генерация структур ### Предварительный просмотр ```typescript // Предварительный просмотр структуры const previewResult = await projectBlueprint.preview({ projectName: 'My Project', projectType: 'web', teamSize: 5, modules: ['auth', 'dashboard'], database: 'postgresql' }); console.log('📊 Предварительный просмотр:', { structure: previewResult.structure, elementCount: previewResult.elementCount, estimatedSize: previewResult.estimatedSize }); ``` ### Генерация с обработкой ошибок ```typescript async function generateWithErrorHandling( blueprint: Blueprint, parameters: Record<string, any> ): Promise<BlueprintGenerationResult | null> { try { // Валидация параметров const validation = blueprint.validateParameters(parameters); if (!validation.valid) { console.error('❌ Ошибки валидации параметров:'); validation.errors.forEach(error => { console.error(` - ${error.parameter}: ${error.message}`); }); return null; } // Показываем предупреждения if (validation.warnings.length > 0) { console.warn('⚠️ Предупреждения:'); validation.warnings.forEach(warning => { console.warn(` - ${warning.parameter}: ${warning.message}`); }); } // Генерация const result = await blueprint.generate({ parameters }); // Проверяем результат if (!result.rootElement) { console.error('❌ Не создан корневой элемент'); return null; } if (result.warnings && result.warnings.length > 0) { console.warn('⚠️ Предупреждения генерации:'); result.warnings.forEach(warning => { console.warn(` - ${warning}`); }); } console.log(`✅ Успешно сгенерировано ${result.elements.length} элементов`); return result; } catch (error) { console.error('❌ Ошибка генерации:', error); return null; } } // Использование const result = await generateWithErrorHandling(projectBlueprint, { projectName: 'My Project', projectType: 'web', teamSize: 5, modules: ['auth', 'dashboard'], database: 'postgresql' }); ``` ## Полный пример: Система управления проектами ```typescript class ProjectManagementBlueprintSystem { private blueprints: Map<string, Blueprint> = new Map(); private generatedProjects: Map<string, CSElement> = new Map(); constructor() { this.initializeBlueprints(); } private initializeBlueprints(): void { // Шаблон простого проекта const simpleProjectBlueprint = new Blueprint({ id: 'simple-project', name: 'Простой проект', description: 'Базовый шаблон проекта', type: BlueprintType.TEMPLATE, category: BlueprintCategory.BUSINESS, parameterGroups: [ { id: 'basic', name: 'Основная информация', parameters: [ { id: 'name', name: 'Название проекта', type: 'string', required: true }, { id: 'description', name: 'Описание', type: 'string', required: false }, { id: 'deadline', name: 'Крайний срок', type: 'string', required: false } ] } ], generator: this.generateSimpleProject }); // Шаблон agile проекта const agileProjectBlueprint = new Blueprint({ id: 'agile-project', name: 'Agile проект', description: 'Проект с agile методологией', type: BlueprintType.TEMPLATE, category: BlueprintCategory.BUSINESS, parameterGroups: [ { id: 'project-info', name: 'Информация о проекте', parameters: [ { id: 'name', name: 'Название проекта', type: 'string', required: true }, { id: 'sprintDuration', name: 'Длительность спринта (недели)', type: 'number', required: true, defaultValue: 2, validation: { min: 1, max: 4 } }, { id: 'sprintCount', name: 'Количество спринтов', type: 'number', required: true, defaultValue: 6, validation: { min: 1, max: 20 } } ] }, { id: 'team', name: 'Команда', parameters: [ { id: 'scrumMaster', name: 'Scrum Master', type: 'string', required: true }, { id: 'productOwner', name: 'Product Owner', type: 'string', required: true }, { id: 'developers', name: 'Разработчики', type: 'array', required: true, validation: { min: 1, max: 10 } } ] } ], generator: this.generateAgileProject }); this.blueprints.set('simple-project', simpleProjectBlueprint); this.blueprints.set('agile-project', agileProjectBlueprint); } private generateSimpleProject = async (context: BlueprintGenerationContext): Promise<BlueprintGenerationResult> => { const { parameters } = context; const elements: CSElement[] = []; // Создаем корневой элемент проекта const projectElement = new CSElement(`project-${Date.now()}`); await projectElement.setData('name', parameters.name); await projectElement.setData('description', parameters.description || ''); await projectElement.setData('deadline', parameters.deadline || ''); await projectElement.setData('type', 'simple'); await projectElement.setData('status', 'created'); await projectElement.setData('createdAt', new Date().toISOString()); // Создаем список задач const tasksElement = new CSElement(`tasks-${Date.now()}`); await tasksElement.setData('name', 'Задачи'); await tasksElement.setData('type', 'task-list'); // Создаем несколько начальных задач const initialTasks = ['Планирование', 'Анализ требований', 'Разработка', 'Тестирование', 'Деплой']; for (const taskName of initialTasks) { const taskElement = new CSElement(`task-${taskName.toLowerCase()}`); await taskElement.setData('name', taskName); await taskElement.setData('status', 'todo'); await taskElement.setData('priority', 'medium'); tasksElement.withChild(taskElement); elements.push(taskElement); } projectElement.withChild(tasksElement); elements.push(projectElement, tasksElement); return { elements, rootElement: projectElement, warnings: [] }; }; private generateAgileProject = async (context: BlueprintGenerationContext): Promise<BlueprintGenerationResult> => { const { parameters } = context; const elements: CSElement[] = []; const warnings: string[] = []; // Создаем корневой элемент проекта const projectElement = new CSElement(`agile-project-${Date.now()}`); await projectElement.setData('name', parameters.name); await projectElement.setData('type', 'agile'); await projectElement.setData('sprintDuration', parameters.sprintDuration); await projectElement.setData('sprintCount', parameters.sprintCount); await projectElement.setData('status', 'created'); await projectElement.setData('createdAt', new Date().toISOString()); // Создаем команду const teamElement = new CSElement(`team-${Date.now()}`); await teamElement.setData('name', 'Команда проекта'); await teamElement.setData('scrumMaster', parameters.scrumMaster); await teamElement.setData('productOwner', parameters.productOwner); // Добавляем разработчиков const developersElement = new CSElement(`developers-${Date.now()}`); await developersElement.setData('name', 'Разработчики'); for (let i = 0; i < parameters.developers.length; i++) { const developerElement = new CSElement(`developer-${i}`); await developerElement.setData('name', parameters.developers[i]); await developerElement.setData('role', 'developer'); developersElement.withChild(developerElement); elements.push(developerElement); } teamElement.withChild(developersElement); projectElement.withChild(teamElement); elements.push(teamElement, developersElement); // Создаем спринты const sprintsElement = new CSElement(`sprints-${Date.now()}`); await sprintsElement.setData('name', 'Спринты'); for (let i = 1; i <= parameters.sprintCount; i++) { const sprintElement = new CSElement(`sprint-${i}`); await sprintElement.setData('name', `Спринт ${i}`); await sprintElement.setData('number', i); await sprintElement.setData('duration', parameters.sprintDuration); await sprintElement.setData('status', i === 1 ? 'active' : 'planned'); // Создаем backlog для спринта const backlogElement = new CSElement(`backlog-sprint-${i}`); await backlogElement.setData('name', `Backlog спринта ${i}`); await backlogElement.setData('type', 'backlog'); sprintElement.withChild(backlogElement); sprintsElement.withChild(sprintElement); elements.push(sprintElement, backlogElement); } projectElement.withChild(sprintsElement); elements.push(sprintsElement); // Создаем product backlog const productBacklogElement = new CSElement(`product-backlog-${Date.now()}`); await productBacklogElement.setData('name', 'Product Backlog'); await productBacklogElement.setData('type', 'product-backlog'); // Добавляем начальные пользовательские истории const initialStories = [ 'Как пользователь, я хочу войти в систему', 'Как пользователь, я хочу просматривать данные', 'Как администратор, я хочу управлять пользователями' ]; for (let i = 0; i < initialStories.length; i++) { const storyElement = new CSElement(`story-${i}`); await storyElement.setData('name', initialStories[i]); await storyElement.setData('type', 'user-story'); await storyElement.setData('priority', 'high'); await storyElement.setData('storyPoints', 5); productBacklogElement.withChild(storyElement); elements.push(storyElement); } projectElement.withChild(productBacklogElement); elements.push(productBacklogElement); // Проверяем размер команды if (parameters.developers.length > 7) { warnings.push('Размер команды больше рекомендуемого (7 человек) для agile проекта'); } elements.push(projectElement); return { elements, rootElement: projectElement, warnings }; }; async createProject(blueprintId: string, parameters: Record<string, any>): Promise<string | null> { const blueprint = this.blueprints.get(blueprintId); if (!blueprint) { console.error(`❌ Шаблон ${blueprintId} не найден`); return null; } const result = await generateWithErrorHandling(blueprint, parameters); if (!result) { return null; } const projectId = result.rootElement!.id; this.generatedProjects.set(projectId, result.rootElement!); console.log(`✅ Проект ${projectId} создан по шаблону ${blueprintId}`); return projectId; } getProject(projectId: string): CSElement | null { return this.generatedProjects.get(projectId) || null; } getAllProjects(): Array<{ id: string; name: string; type: string; createdAt: string; }> { return Array.from(this.generatedProjects.entries()).map(([id, element]) => ({ id, name: element.getData('name') as string, type: element.getData('type') as string, createdAt: element.getData('createdAt') as string })); } getAvailableBlueprints(): Array<{ id: string; name: string; description: string; category: string; parameterGroups: any[]; }> { return Array.from(this.blueprints.values()).map(blueprint => ({ id: blueprint.id, name: blueprint.name, description: blueprint.description, category: blueprint.category, parameterGroups: blueprint.parameterGroups })); } async exportProject(projectId: string): Promise<Blob | null> { const project = this.getProject(projectId); if (!project) { console.error(`❌ Проект ${projectId} не найден`); return null; } const exportData = project.serialize({ includeChildren: true, includeData: true, includeMetadata: true }); return new Blob([JSON.stringify(exportData, null, 2)], { type: 'application/json' }); } async cloneProject(projectId: string, newName: string): Promise<string | null> { const project = this.getProject(projectId); if (!project) { console.error(`❌ Проект ${projectId} не найден`); return null; } // Создаем копию проекта const clonedProject = new CSElement(`cloned-${Date.now()}`); const originalData = project.serialize({ includeChildren: true, includeData: true, includeMetadata: true }); // Восстанавливаем структуру const restored = CSElement.deserialize(originalData); await restored.setData('name', newName); await restored.setData('createdAt', new Date().toISOString()); this.generatedProjects.set(restored.id, restored); console.log(`✅ Проект ${projectId} клонирован как ${restored.id}`); return restored.id; } } // Демонстрация использования async function demonstrateProjectManagement() { const system = new ProjectManagementBlueprintSystem(); try { // Просмотр доступных шаблонов const blueprints = system.getAvailableBlueprints(); console.log('📋 Доступные шаблоны:', blueprints.map(b => b.name)); // Создание простого проекта const simpleProjectId = await system.createProject('simple-project', { name: 'Мой первый проект', description: 'Тестовый проект', deadline: '2024-12-31' }); // Создание agile проекта const agileProjectId = await system.createProject('agile-project', { name: 'Agile проект', sprintDuration: 2, sprintCount: 8, scrumMaster: 'Alice Smith', productOwner: 'Bob Johnson', developers: ['Charlie Brown', 'Diana Prince', 'Eve Adams'] }); // Просмотр созданных проектов const projects = system.getAllProjects(); console.log('📊 Созданные проекты:', projects); // Экспорт проекта if (agileProjectId) { const exportBlob = await system.exportProject(agileProjectId); if (exportBlob) { console.log(`📦 Проект экспортирован, размер: ${exportBlob.size} байт`); } } // Клонирование проекта if (simpleProjectId) { const clonedId = await system.cloneProject(simpleProjectId, 'Клон проекта'); console.log(`📋 Проект клонирован: ${clonedId}`); } } catch (error) { console.error('❌ Ошибка в системе управления проектами:', error); } } demonstrateProjectManagement().catch(console.error); ``` ## 🎯 Заключение Система Blueprint в CSElement обеспечивает: - **🏗️ Структурированное создание** - шаблоны для повторяющихся структур - **✅ Валидация параметров** - проверка входных данных перед генерацией - **🔧 Гибкость** - условные параметры и динамическая генерация - **📊 Предварительный просмотр** - оценка результата до генерации - **🎯 Категоризация** - организация шаблонов по типам и категориям --- **Заключение:** Вы изучили все основные возможности библиотеки CSElement! 🎉