UNPKG

leds-spark-lib

Version:

Biblioteca de geração de código

297 lines (291 loc) 13.9 kB
import { generateAdmin } from './admin-generator.js'; import { generateModels } from './model-generator.js'; import { generateURLAPI } from './url-generator.js'; import { generateAPIView } from './view-generator.js'; import { generateSerializer } from './serialize-generator.js'; import { isLocalEntity, isModule, base_ident, capitalizeString, createPath } from '../../../../models/model.js'; import path from 'path'; import fs from 'fs'; import { expandToString } from '../../../../../util/template-string.js'; const ident = base_ident; export function generateModules(app, target_folder) { // Processa quais Entidades representam algum ator const entity_to_actor = new Map(); // app.abstractElements.filter(isActor).forEach(a => { // if(a.entity && getRef(a.entity)) { // entity_to_actor.set(getRef(a.entity), a) // } // }) const APPS_PATH = createPath(target_folder, "backend", "apps/"); // Criando os models, service e applications for (const m of app.abstractElements.filter(isModule)) { const MODULE_PATH = createPath(APPS_PATH, m.name.toLowerCase()); fs.writeFileSync(path.join(createPath(MODULE_PATH, "migrations/"), "__init__.py"), ""); fs.writeFileSync(path.join(MODULE_PATH, "/__init__.py"), create_init(m)); fs.writeFileSync(path.join(MODULE_PATH, "/models.py"), generateModels(m)); fs.writeFileSync(path.join(MODULE_PATH, "/admin.py"), generateAdmin(m)); fs.writeFileSync(path.join(MODULE_PATH, "/utils.py"), generateUtil()); // fs.writeFileSync(APPS_PATH + m.name.toLowerCase + "/factory.py", m.createFactory) fs.writeFileSync(path.join(MODULE_PATH, "/apps.py"), createApps(m)); fs.writeFileSync(path.join(MODULE_PATH, "/api_urls.py"), generateURLAPI(m)); fs.writeFileSync(path.join(MODULE_PATH, "/api_views.py"), generateAPIView(m, new Set(entity_to_actor.keys()))); fs.writeFileSync(path.join(MODULE_PATH, "/pagination.py"), pagination()); fs.writeFileSync(path.join(MODULE_PATH, "/signals.py"), generateSignals(m, entity_to_actor)); fs.writeFileSync(path.join(MODULE_PATH, "/serializers.py"), generateSerializer(m)); const TEST_PATH = createPath(MODULE_PATH, "/test/unit/"); for (const e of m.elements.filter(isLocalEntity)) { fs.writeFileSync(path.join(TEST_PATH, e.name.toLowerCase() + "_tests.py"), createclasstest(e, m)); } } } function generateUtil() { const lines = [ `from hashids import Hashids`, `from django.conf import settings`, ``, `hashids = Hashids(settings.HASHIDS_SALT, min_length=8)`, ``, `def h_encode(id):`, `${ident}return hashids.encode(id)`, ``, `def h_decode(h):`, `${ident}if z := hashids.decode(h):`, `${ident}${ident}return z[0]`, ``, ``, `class HashIdConverter:`, `${ident}regex = '[a-zA-Z0-9]{8,}'`, ``, `${ident}def to_python(self, value):`, `${ident}${ident}return h_decode(value)`, ``, `${ident}def to_url(self, value):`, `${ident}${ident}return h_encode(value)`, `` ]; return lines.join('\n'); } function pagination() { const lines = [ `from rest_framework import pagination`, `from rest_framework.response import Response`, ``, `class CustomPagination(pagination.PageNumberPagination):`, `${ident}page_size = 10`, `${ident}page_size_query_param = 'page_size'`, `${ident}max_page_size = 1000`, ``, `${ident}def get_paginated_response(self, data):`, `${ident}${ident}return Response({`, `${ident}${ident}${ident}'meta': {`, `${ident}${ident}${ident}${ident}'current_page': self.page.number,`, `${ident}${ident}${ident}${ident}'per_page': self.page.paginator.per_page,`, `${ident}${ident}${ident}${ident}'max_per_page': self.max_page_size,`, `${ident}${ident}${ident}${ident}'total': self.page.paginator.count`, `${ident}${ident}${ident}},`, `${ident}${ident}${ident}'data': data`, `${ident}${ident}})`, `` ]; return lines.join('\n'); } function create_init(m) { return `default_app_config = 'apps.${m.name.toLowerCase()}.apps.${capitalizeString(m.name)}Config'\n`; } function createApps(m) { const lines = [ `from django.apps import AppConfig`, // `from django.utils.translation import gettext_lazy as _`, ``, `class ${capitalizeString(m.name)}Config(AppConfig):`, `${ident}name = 'apps.${m.name.toLowerCase()}'`, `${ident}label = 'apps_${m.name.toLowerCase()}'`, ``, `${ident}def ready(self):`, `${ident}${ident}import apps.${m.name.toLowerCase()}.signals`, ``, ]; return lines.join('\n'); } function createattributeJsontest(e) { return e.attributes.map(a => `'${a.name}' : ${createAtrributeValuesTest(a)}`); } function createattributetest(e) { return e.attributes.map(a => `${a.name} = ${createAtrributeValuesTest(a)}`).join(', '); } function createAtrributeValuesTest(a) { switch (a.type.toLowerCase()) { case 'cpf': return "self.faker.cpf()"; case 'cnpj': return "self.faker.cnpj()"; case 'string': return "self.faker.first_name()"; case 'integer': return "random.uniform(0, 100)"; case 'decimal': return "random.uniform(0.00, 100.5)"; case 'email': return "self.faker.ascii_company_email()"; case 'url': return `'http://'+ self.fake.domain_name()`; case 'telefone': case 'celular': return "self.faker.phone_number()"; case 'datetime': case 'date': return "self.faker.date()"; default: return "TODO"; } } function createclasstest(e, m) { const lines = [ `import json`, `from rest_framework import status`, `from django.test import TestCase, Client`, `from django.urls import reverse`, `from ${m.name.toLowerCase()}.models import ${e.name}`, `from ${m.name.toLowerCase()}.serializers import ${e.name}Serializer`, `from faker import Faker`, `import random`, ``, `class ${e.name}Tests(TestCase):`, `${ident}def setUp(self):`, `${ident}${ident}self.faker = Faker('pt_BR')`, `${ident}${ident}self.client = Client()`, ``, `${ident}${ident}self.${e.name.toLowerCase()}_1 = ${e.name}.objects.create(${createattributetest(e)})`, `${ident}${ident}self.${e.name.toLowerCase()}_2 = ${e.name}.objects.create(${createattributetest(e)})`, `${ident}${ident}self.${e.name.toLowerCase()}_3 = ${e.name}.objects.create(${createattributetest(e)})`, ``, `${ident}${ident}self.valid_payload = {`, `${ident}${ident}${ident}${createattributeJsontest(e)}`, `${ident}${ident}}`, `${ident}${ident}self.invalid_payload = {`, // TODO Como gerar um payload invalido `${ident}${ident}${ident}${createattributeJsontest(e)}`, `${ident}${ident}}`, ``, `${ident}def test_valid_create(self):`, `${ident}${ident}response = self.client.post(`, `${ident}${ident}${ident}reverse('${e.name.toLowerCase()}-api-list'),`, `${ident}${ident}${ident}data=json.dumps(self.valid_payload),`, `${ident}${ident}${ident}content_type='application/json'`, `${ident}${ident})`, `${ident}${ident}self.assertEqual(response.status_code, status.HTTP_201_CREATED)`, ``, `${ident}def test_invalid_create(self):`, `${ident}${ident}response = self.client.post(`, `${ident}${ident}${ident}reverse('${e.name.toLowerCase()}-api-list'),`, `${ident}${ident}${ident}data=json.dumps(self.invalid_payload),`, `${ident}${ident}${ident}content_type='application/json'`, `${ident}${ident})`, `${ident}${ident}self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)`, ``, `${ident}def test_valid_upload(self):`, `${ident}${ident}response = self.client.put(`, `${ident}${ident}${ident}reverse('${e.name.toLowerCase()}-detail',`, `${ident}${ident}${ident}kwargs={'pk': self.${e.name.toLowerCase()}_1.id}),`, `${ident}${ident}${ident}data=json.dumps(self.valid_payload),`, `${ident}${ident}${ident}content_type='application/json'`, `${ident}${ident})`, `${ident}${ident}self.assertEqual(response.status_code, status.HTTP_200_OK)`, ``, `${ident}def test_invalid_upload(self):`, `${ident}${ident}response = self.client.put(`, `${ident}${ident}${ident}reverse('${e.name.toLowerCase()}-detail',`, `${ident}${ident}${ident}kwargs={'pk': self.${e.name.toLowerCase()}_1.id}),`, `${ident}${ident}${ident}data=json.dumps(self.invalid_payload),`, `${ident}${ident}${ident}content_type='application/json'`, `${ident}${ident})`, `${ident}${ident}self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)`, ``, `${ident}# retornando todos os elementos `, `${ident}def test_retrieve_all(self):`, `${ident}${ident}response = self.client.get(reverse('${e.name.toLowerCase()}-api-list'))`, `${ident}${ident}data = ${e.name}.objects.all()`, `${ident}${ident}serializer = ${e.name}Serializer(data, context={'request': None}, many=True)`, `${ident}${ident}# Aqui deve comparar todos os compos do objeto com serialização`, `${ident}${ident}self.assertEqual(response.data, serializer.data)`, ``, `${ident}${ident}self.assertIsNotNone(response.data)`, `${ident}${ident}self.assertEqual(response.status_code, status.HTTP_200_OK)`, ``, `${ident}# retornando um elemento`, `${ident}def test_valid_get_element(self):`, `${ident}${ident}response = self.client.get(reverse('${e.name.toLowerCase()}-detail',kwargs={'pk': self.${e.name.toLowerCase()}_1.id}))`, `${ident}${ident}data = ${e.name}.objects.get(pk=self.condicao_1.id)`, `${ident}${ident}# Aqui deve comparar todos os campos do objeto com serialização`, `${ident}${ident}self.assertEqual(str(data.uuid),response.data['uuid'])`, `${ident}${ident}self.assertIsNotNone(response.data)`, `${ident}${ident}self.assertEqual(response.status_code, status.HTTP_200_OK)`, ``, `${ident}# erro ao retornar um elemento invalido`, `${ident}def test_invalid_get_element(self):`, `${ident}${ident}response = self.client.get(reverse('${e.name.toLowerCase()}-detail',kwargs={'pk': 666}))`, `${ident}${ident}self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)`, ``, `${ident}# Delete um elemento valido`, `${ident}def test_valid_delete(self):`, `${ident}${ident}response = self.client.delete(reverse('${e.name.toLowerCase()}-detail',kwargs={'pk': self.${e.name.toLowerCase()}_1.id}))`, `${ident}${ident}self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT)`, ``, `${ident}# Delete um elemento valido`, `${ident}def test_invalid_delete(self):`, `${ident}${ident}response = self.client.delete(reverse('${e.name.toLowerCase()}-detail',kwargs={'pk': 666}))`, `${ident}${ident}self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)`, `` ]; return lines.join('\n'); } function generateSignals(m, map) { const non_abstract_entities = m.elements.filter(isLocalEntity).filter(e => !e.is_abstract); const lines = [ `from .models import ${non_abstract_entities.map(e => e.name).join(', ')}`, `from django.db.models.signals import (`, `${ident}pre_init, post_init,`, `${ident}pre_save, post_save,`, `${ident}pre_delete, post_delete,`, `${ident}m2m_changed`, `)`, `from django.dispatch import receiver`, `from django.contrib.auth.models import Group`, // `from .services import *`, ``, ...non_abstract_entities.flatMap(e => { return [ `## Signals from ${e.name}`, entitySignals(e, map), ``, ]; }), ]; return lines.join('\n'); } function entitySignals(e, map) { const post_save = map.has(e) ? expandToString ` if created: group = Group.objects.get(name="${map.get(e)?.id}") instance.user_application.groups.add(group) ` : 'pass'; return expandToString ` @receiver(pre_init, sender=${e.name}) def pre_init_${e.name.toLowerCase()}(sender, *args, **kwargs): ${ident}pass @receiver(post_init, sender=${e.name}) def post_init_${e.name.toLowerCase()}(sender, instance, **kwargs): ${ident}pass @receiver(pre_save, sender=${e.name}) def pre_save_${e.name.toLowerCase()}(sender, instance, raw, using, update_fields, **kwargs): ${ident}pass @receiver(post_save, sender=${e.name}) def post_save_${e.name.toLowerCase()}(sender, instance, created, raw, using, update_fields, **kwargs): ${ident}${post_save} @receiver(pre_delete, sender=${e.name}) def pre_delete_${e.name.toLowerCase()}(sender, instance, using, **kwargs): ${ident}pass @receiver(post_delete, sender=${e.name}) def post_delete_${e.name.toLowerCase()}(sender, instance, using, **kwargs): ${ident}pass @receiver(m2m_changed, sender=${e.name}) def m2m_changed_${e.name.toLowerCase()}(sender, instance, action, reverse, model, pk_set, using, **kwargs): ${ident}pass `; } //# sourceMappingURL=module-generator.js.map