diff --git a/api/src/controllers/enrollmentController.ts b/api/src/controllers/enrollmentController.ts index 1e3527b..0052b5d 100644 --- a/api/src/controllers/enrollmentController.ts +++ b/api/src/controllers/enrollmentController.ts @@ -1,24 +1,24 @@ import { Request, Response } from 'express'; +import { MatriculasRepositoryPSQL } from '../database/psql/matriculasRepositoryPSQL'; +import { MatriculasService } from '../services/matriculasServices'; export const EnrollmentController = async (req: Request, res: Response) => { - const { municipio, etapa } = req.query; - console.log(` Matriculas: Município: ${municipio} - Etapa: ${etapa}`); - const response = { - series: [ - { name: 'pretos', data: [7, 1, 21, 28, 3, 420, 12, 56] }, - { name: 'brancos', data: [10, 20, 500, 40, 50, 60, 70, 100] }, - ], - categories: [ - '2020 Pública', - '2020 Privada', - '2021 Pública', - '2021 Privada', - '2022 Pública', - '2022 Privada', - '2023 Pública', - '2023 Privada', - ], - }; + try { + const { municipio, etapa } = req.query; - res.json(response); + if (typeof municipio !== 'string' || typeof etapa !== 'string') { + return res.status(400).json({ message: 'Parâmetros inválidos.' }); + } + if (!municipio || !etapa) { + return res.status(400).json({ error: 'Municipio e etapa são obrigatórios' }); + } + + const service = new MatriculasService(new MatriculasRepositoryPSQL()); + const result = await service.execute({ municipio, etapa }); + + res.json(result); + } catch (error) { + console.error('Erro ao processar a solicitação:', error); + res.status(400).json({ message: (error as any).message }); + } }; diff --git a/api/src/database/memory/data/matriculasMemoryData.ts b/api/src/database/memory/data/matriculasMemoryData.ts index bb8d3f7..7b07651 100644 --- a/api/src/database/memory/data/matriculasMemoryData.ts +++ b/api/src/database/memory/data/matriculasMemoryData.ts @@ -1,282 +1,194 @@ export const genericData = [ { - ano: 2020, - etapa: 'Ensino Fundamental 1', - matricula: 23, - municipio: 'Patos de Minas', - raca: 'Brancos', - rede: 'Pública', - }, - { - ano: 2020, - etapa: 'Ensino Médio', - matricula: 45, - municipio: 'Uberaba', - raca: 'Brancos', + ano: 2023, + raca: 'Amarela', rede: 'Privada', + etapa: 'EM', + matricula: 55, + municipio: 3106200, }, { - ano: 2020, - etapa: 'Ensino Médio', - matricula: 12, - municipio: 'Patos de Minas', - raca: 'Brancos', - rede: 'Pública', + ano: 2023, + raca: 'Branca', + rede: 'Estadual', + etapa: 'EM', + matricula: 45, + municipio: 3106200, }, { - ano: 2020, - etapa: 'Ensino Médio', + ano: 2023, + raca: 'Branca', + rede: 'Federal', + etapa: 'EM', matricula: 15, - municipio: 'Patos de Minas', - raca: 'Brancos', - rede: 'Privada', - }, - { - ano: 2020, - etapa: 'Ensino Médio', - matricula: 30, - municipio: 'Patos de Minas', - raca: 'Pretos', - rede: 'Pública', + municipio: 3106200, }, { - ano: 2020, - etapa: 'Ensino Médio', - matricula: 3, - municipio: 'Patos de Minas', - raca: 'Pretos', - rede: 'Privada', - }, -]; - -export const disorderedData = [ - { - ano: 2022, - etapa: 'Ensino Médio', - matricula: 25, - municipio: 'Belo Horizonte', - raca: 'Pretos', - rede: 'Pública', - }, - - { - ano: 2021, - etapa: 'Ensino Médio', - matricula: 30, - municipio: 'Belo Horizonte', - raca: 'Brancos', - rede: 'Pública', - }, - - { - ano: 2022, - etapa: 'Ensino Médio', - matricula: 45, - municipio: 'Belo Horizonte', - raca: 'Brancos', + ano: 2023, + raca: 'Branca', rede: 'Privada', + etapa: 'EM', + matricula: 80, + municipio: 3106200, }, - { - ano: 2021, - etapa: 'Ensino Médio', - matricula: 22, - municipio: 'Belo Horizonte', - raca: 'Brancos', + ano: 2023, + raca: 'Indígena', rede: 'Privada', + etapa: 'EM', + matricula: 13, + municipio: 3106200, }, { - ano: 2022, - etapa: 'Ensino Médio', - matricula: 35, - municipio: 'Belo Horizonte', - raca: 'Brancos', - rede: 'Pública', - }, - - { - ano: 2021, - etapa: 'Ensino Médio', - matricula: 40, - municipio: 'Belo Horizonte', - raca: 'Pretos', - rede: 'Pública', + ano: 2023, + raca: 'Não declarada', + rede: 'Estadual', + etapa: 'EM', + matricula: 15995, + municipio: 3106200, }, - { ano: 2022, - etapa: 'Ensino Médio', - matricula: 18, - municipio: 'Belo Horizonte', - raca: 'Pretos', + raca: 'Preta', rede: 'Privada', + etapa: 'EM', + matricula: 14, + municipio: 3106200, }, - { - ano: 2021, - etapa: 'Ensino Médio', - matricula: 28, - municipio: 'Belo Horizonte', - raca: 'Pretos', - rede: 'Privada', + ano: 2023, + raca: 'Parda', + rede: 'Estadual', + etapa: 'EM', + matricula: 60, + municipio: 3106200, }, -]; - -export const incompleteData = [ { - ano: 2022, - etapa: 'Ensino Médio', - matricula: 25, - municipio: 'Belo Horizonte', - raca: 'Pretos', - rede: 'Pública', + ano: 2023, + raca: 'Parda', + rede: 'Federal', + etapa: 'EM', + matricula: 10, + municipio: 3106200, }, - { - ano: 2022, - etapa: 'Ensino Médio', - matricula: 45, - municipio: 'Belo Horizonte', - raca: 'Brancos', + ano: 2023, + raca: 'Parda', rede: 'Privada', + etapa: 'EM', + matricula: 21, + municipio: 3106200, }, - - { - ano: 2022, - etapa: 'Ensino Médio', - matricula: 35, - municipio: 'Belo Horizonte', - raca: 'Brancos', - rede: 'Pública', - }, -]; -export const perfectData = [ { - ano: 2020, - etapa: 'Ensino Médio', + ano: 2023, + raca: 'Preta', + rede: 'Estadual', + etapa: 'EM', matricula: 10, - municipio: 'Belo Horizonte', - raca: 'Brancos', - rede: 'Pública', + municipio: 3106200, }, { - ano: 2020, - etapa: 'Ensino Médio', - matricula: 7, - municipio: 'Belo Horizonte', - raca: 'Pretos', - rede: 'Pública', + ano: 2023, + raca: 'Preta', + rede: 'Federal', + etapa: 'EM', + matricula: 20, + municipio: 3106200, }, { - ano: 2020, - etapa: 'Ensino Médio', - matricula: 20, - municipio: 'Belo Horizonte', - raca: 'Brancos', + ano: 2023, + raca: 'Preta', rede: 'Privada', + etapa: 'EM', + matricula: 7, + municipio: 3106200, }, { - ano: 2020, - etapa: 'Ensino Médio', - matricula: 14, - municipio: 'Belo Horizonte', - raca: 'Pretos', + ano: 2022, + raca: 'Amarela', rede: 'Privada', + etapa: 'EM', + matricula: 79, + municipio: 3106200, }, { - ano: 2021, - etapa: 'Ensino Médio', + ano: 2022, + raca: 'Branca', + rede: 'Estadual', + etapa: 'EM', matricula: 30, - municipio: 'Belo Horizonte', - raca: 'Brancos', - rede: 'Pública', + municipio: 3106200, }, { - ano: 2021, - etapa: 'Ensino Médio', - matricula: 21, - municipio: 'Belo Horizonte', - raca: 'Pretos', - rede: 'Pública', + ano: 2022, + raca: 'Branca', + rede: 'Federal', + etapa: 'EM', + matricula: 20, + municipio: 3106200, }, { - ano: 2021, - etapa: 'Ensino Médio', - matricula: 40, - municipio: 'Belo Horizonte', - raca: 'Brancos', + ano: 2022, + raca: 'Branca', rede: 'Privada', + etapa: 'EM', + matricula: 40, + municipio: 3106200, }, { - ano: 2021, - etapa: 'Ensino Médio', - matricula: 28, - municipio: 'Belo Horizonte', - raca: 'Pretos', - rede: 'Privada', + ano: 2022, + raca: 'Indígena', + rede: 'Estadual', + etapa: 'EM', + matricula: 76, + municipio: 3106200, }, { ano: 2022, - etapa: 'Ensino Médio', - matricula: 50, - municipio: 'Belo Horizonte', - raca: 'Brancos', - rede: 'Pública', + raca: 'Não declarada', + rede: 'Estadual', + etapa: 'EM', + matricula: 7817, + municipio: 3106200, }, { ano: 2022, - etapa: 'Ensino Médio', - matricula: 35, - municipio: 'Belo Horizonte', - raca: 'Pretos', - rede: 'Pública', + raca: 'Parda', + rede: 'Estadual', + etapa: 'EM', + matricula: 15, + municipio: 3106200, }, { ano: 2022, - etapa: 'Ensino Médio', - matricula: 60, - municipio: 'Belo Horizonte', - raca: 'Brancos', - rede: 'Privada', + raca: 'Parda', + rede: 'Federal', + etapa: 'EM', + matricula: 20, + municipio: 3106200, }, { ano: 2022, - etapa: 'Ensino Médio', - matricula: 42, - municipio: 'Belo Horizonte', - raca: 'Pretos', + raca: 'Parda', rede: 'Privada', + etapa: 'EM', + matricula: 7, + municipio: 3106200, }, { - ano: 2023, - etapa: 'Ensino Médio', - matricula: 70, - municipio: 'Belo Horizonte', - raca: 'Brancos', - rede: 'Pública', - }, - { - ano: 2023, - etapa: 'Ensino Médio', - matricula: 49, - municipio: 'Belo Horizonte', - raca: 'Pretos', - rede: 'Pública', - }, - { - ano: 2023, - etapa: 'Ensino Médio', - matricula: 80, - municipio: 'Belo Horizonte', - raca: 'Brancos', - rede: 'Privada', + ano: 2022, + raca: 'Preta', + rede: 'Estadual', + etapa: 'EM', + matricula: 40, + municipio: 3106200, }, { - ano: 2023, - etapa: 'Ensino Médio', - matricula: 56, - municipio: 'Belo Horizonte', - raca: 'Pretos', - rede: 'Privada', + ano: 2022, + raca: 'Preta', + rede: 'Municipal', + etapa: 'EM', + matricula: 10, + municipio: 3106200, }, ]; diff --git a/api/src/database/psql/matriculasRepositoryPSQL.ts b/api/src/database/psql/matriculasRepositoryPSQL.ts new file mode 100644 index 0000000..3718631 --- /dev/null +++ b/api/src/database/psql/matriculasRepositoryPSQL.ts @@ -0,0 +1,43 @@ +import { supabase } from '../..'; +import { + MatriculasRepository, + MatriculasRepositoryOutput, +} from '../../repositories/matriculasRepository'; +import { MatriculasInput } from '../../services/matriculasServices'; + +export class MatriculasRepositoryPSQL extends MatriculasRepository { + async fetch(input: MatriculasInput): Promise { + const { data, error } = await supabase + .from('Filtro') + .select( + ` + id, + municipio_id, + etapa_de_ensino, + ano, + Matricula( id, cor_raca, quantidade, dependencia_administrativa) + `, + ) + .eq('municipio_id', Number(input.municipio)) // Filtrando por município + .eq('etapa_de_ensino', input.etapa) // Filtrando por etapa de ensino + .gt('ano', 2019); + if (error) { + throw new Error(error.message); + } else { + // Processar e retornar os dados no formato esperado + const result: MatriculasRepositoryOutput[] = data + .map((filtro: any) => { + return filtro.Matricula.map((mr: any) => ({ + ano: filtro.ano, + raca: mr.cor_raca, + rede: mr.dependencia_administrativa, + etapa: filtro.etapa_de_ensino, + matricula: mr.quantidade, + municipio: filtro.municipio_id, + })); + }) + .flat(); + return result; + } + } +} diff --git a/api/src/index.ts b/api/src/index.ts index cebed65..0ab9a3e 100644 --- a/api/src/index.ts +++ b/api/src/index.ts @@ -20,7 +20,9 @@ app.use( ); app.get('/', (req: Request, res: Response) => { - res.json('Bem vindo!'); + res.json( + 'Bem vindo à API pública do EducaMinas! Acesse /api/matriculas, /api/indicador ou /api/ranking para obter os dados.', + ); }); app.use('/api-docs', swaggerUi.serve, swaggerUi.setup(swaggerSpec)); diff --git a/api/src/services/matriculasService.spec.ts b/api/src/services/matriculasService.spec.ts index cbffd1e..7a959ca 100644 --- a/api/src/services/matriculasService.spec.ts +++ b/api/src/services/matriculasService.spec.ts @@ -1,10 +1,5 @@ import { describe, expect, test } from 'vitest'; -import { - disorderedData, - genericData, - incompleteData, - perfectData, -} from '../database/memory/data/matriculasMemoryData'; +import { genericData } from '../database/memory/data/matriculasMemoryData'; import { MatriculasRepositoryMemory } from '../database/memory/matriculasRepositoryMemory'; import { MatriculasInput, MatriculasService } from './matriculasServices'; @@ -12,16 +7,19 @@ describe('Matriculas Service', () => { const matriculaRepository = new MatriculasRepositoryMemory(); const matriculasService = new MatriculasService(matriculaRepository); - matriculaRepository.DATA_IN_MEMORY = genericData; + matriculaRepository.DATA_IN_MEMORY = genericData.map((item) => ({ + ...item, + municipio: item.municipio.toString(), + })); const input: MatriculasInput = { - etapa: 'Ensino Médio', - municipio: 'Patos de Minas', + etapa: 'EM', + municipio: '3106200', }; test('should return categories length with success', async () => { const output = await matriculasService.execute(input); - expect(output.categories).toHaveLength(2); + expect(output.categories).toHaveLength(8); }); test('should return first categorie with success', async () => { @@ -39,50 +37,6 @@ describe('Matriculas Service', () => { expect(output.series).toHaveLength(2); }); - test('should return first series with success', async () => { - const output = await matriculasService.execute(input); - expect(output.series[0].name).toEqual('pretos'); - expect(output.series[0].data).toHaveLength(2); - expect(output.series[0].data[0]).toEqual(30); - expect(output.series[0].data[1]).toEqual(3); - }); - - test('should return second series with success', async () => { - const output = await matriculasService.execute(input); - expect(output.series[1].name).toEqual('brancos'); - expect(output.series[1].data).toHaveLength(2); - expect(output.series[1].data[0]).toEqual(12); - expect(output.series[1].data[1]).toEqual(15); - }); - - test('should return output with other city with success', async () => { - const output = await matriculasService.execute({ - ...input, - municipio: 'Uberaba', - }); - expect(output.categories).toHaveLength(1); - expect(output.categories[0]).toEqual('2020 Privada'); - expect(output.series[0].name).toEqual('pretos'); - expect(output.series[0].data).toHaveLength(1); - expect(output.series[1].name).toEqual('brancos'); - expect(output.series[1].data).toHaveLength(1); - expect(output.series[1].data[0]).toEqual(45); - }); - - test('should return output with other etapa with success', async () => { - const output = await matriculasService.execute({ - ...input, - etapa: 'Ensino Fundamental 1', - }); - expect(output.categories).toHaveLength(1); - expect(output.categories[0]).toEqual('2020 Pública'); - expect(output.series[0].name).toEqual('pretos'); - expect(output.series[0].data).toHaveLength(1); - expect(output.series[1].name).toEqual('brancos'); - expect(output.series[1].data).toHaveLength(1); - expect(output.series[1].data[0]).toEqual(23); - }); - test('should return an Error when not exists register with etapa filter', async () => { const incorrectEtapaInput = { ...input, etapa: 'Ensino' }; @@ -99,44 +53,15 @@ describe('Matriculas Service', () => { ); }); test('should return data in order', async () => { - matriculaRepository.DATA_IN_MEMORY = disorderedData; - const response = await matriculasService.execute({ - ...input, - municipio: 'Belo Horizonte', - }); - expect(response.series[0].name).toEqual('pretos'); - expect(response.series[0].data).toEqual([40, 28, 25, 18]); - expect(response.series[1].name).toEqual('brancos'); - expect(response.series[1].data).toEqual([30, 22, 35, 45]); - expect(response.categories).toEqual([ - '2021 Pública', - '2021 Privada', - '2022 Pública', - '2022 Privada', - ]); - }); - test('should return completed data', async () => { - matriculaRepository.DATA_IN_MEMORY = incompleteData; - const response = await matriculasService.execute({ - ...input, - municipio: 'Belo Horizonte', - }); - expect(response.series[0].name).toEqual('pretos'); - expect(response.series[0].data).toEqual([25, 0]); - expect(response.series[1].name).toEqual('brancos'); - expect(response.series[1].data).toEqual([35, 45]); - expect(response.categories).toEqual(['2022 Pública', '2022 Privada']); - }); - test('should return all data correct', async () => { - matriculaRepository.DATA_IN_MEMORY = perfectData; - const response = await matriculasService.execute({ - ...input, - municipio: 'Belo Horizonte', - }); - expect(response.series[0].name).toEqual('pretos'); - expect(response.series[0].data).toEqual([7, 14, 21, 28, 35, 42, 49, 56]); - expect(response.series[1].name).toEqual('brancos'); - expect(response.series[1].data).toEqual([10, 20, 30, 40, 50, 60, 70, 80]); + matriculaRepository.DATA_IN_MEMORY = genericData.map((item) => ({ + ...item, + municipio: item.municipio.toString(), + })); + const response = await matriculasService.execute(input); + expect(response.series[0].name).toEqual('Pretos/Pardos'); + expect(response.series[0].data).toEqual([0, 0, 0, 0, 85, 21, 100, 28]); + expect(response.series[1].name).toEqual('Brancos'); + expect(response.series[1].data).toEqual([0, 0, 0, 0, 50, 40, 60, 80]); expect(response.categories).toEqual([ '2020 Pública', '2020 Privada', diff --git a/api/src/services/matriculasServices.ts b/api/src/services/matriculasServices.ts index 850bc5a..c058815 100644 --- a/api/src/services/matriculasServices.ts +++ b/api/src/services/matriculasServices.ts @@ -24,46 +24,53 @@ export class MatriculasService { } const newData: { [key: string]: number[] } = { - pretos: [], - brancos: [], + 'Pretos/Pardos': [], + Brancos: [], }; const categories: string[] = []; - // Definindo os anos e redes esperados const anos = [2020, 2021, 2022, 2023]; const redes = ['Pública', 'Privada']; - // Criando combinações de ano e rede anos.forEach((ano) => { redes.forEach((rede) => { const category = `${ano} ${rede}`; categories.push(category); - newData.pretos.push(0); - newData.brancos.push(0); + newData['Pretos/Pardos'].push(0); + newData.Brancos.push(0); }); }); - // Atualizando dados de matrículas data.forEach((entry) => { - if (entry.etapa !== input.etapa || entry.municipio !== input.municipio) { - throw new Error('Etapa ou municipio errados.'); + if (entry.etapa !== input.etapa || entry.municipio.toString() !== input.municipio) { + throw new Error('entry.etapa'); + } + + if ( + entry.rede === 'Municipal' || + entry.rede === 'Estadual' || + entry.rede === 'Federal' + ) { + entry.rede = 'Pública'; } const category = `${entry.ano} ${entry.rede}`; const index = categories.indexOf(category); - if (entry.raca === 'Pretos') { - newData.pretos[index] += entry.matricula; - } else if (entry.raca === 'Brancos') { - newData.brancos[index] += entry.matricula; + if (entry.raca === 'Preta' || entry.raca === 'Parda') { + newData['Pretos/Pardos'][index] += entry.matricula; + } else if (entry.raca === 'Branca') { + newData.Brancos[index] += entry.matricula; } }); - for (let i = categories.length - 1; i >= 0; i--) { - if (newData.pretos[i] === 0 && newData.brancos[i] === 0) { - newData.pretos.splice(i, 1); - newData.brancos.splice(i, 1); - categories.splice(i, 1); - } - } + + // REMOVE CATEGORIAS VAZIAS + // for (let i = categories.length - 1; i >= 0; i--) { + // if (newData['Pretos/Pardos'][i] <= 0 && newData.Brancos[i] <= 0) { + // newData['Pretos/Pardos'].splice(i, 1); + // newData.Brancos.splice(i, 1); + // categories.splice(i, 1); + // } + // } const series = Object.entries(newData).map(([name, data]) => ({ name, diff --git a/package-lock.json b/package-lock.json index 377fb62..943c1b7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15,6 +15,7 @@ "cors": "^2.8.5", "dotenv": "^16.4.5", "express": "^4.19.2", + "pre-commit": "^1.2.2", "swagger-jsdoc": "^6.2.8", "swagger-ui-express": "^5.0.1", "ts-node": "^10.9.2", @@ -2128,6 +2129,11 @@ "node": ">=8" } }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" + }, "node_modules/builtins": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/builtins/-/builtins-5.1.0.tgz", @@ -2306,6 +2312,20 @@ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" }, + "node_modules/concat-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", + "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", + "engines": [ + "node >= 0.8" + ], + "dependencies": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" + } + }, "node_modules/content-disposition": { "version": "0.5.4", "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", @@ -2338,6 +2358,11 @@ "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" }, + "node_modules/core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" + }, "node_modules/cors": { "version": "2.8.5", "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", @@ -4548,8 +4573,7 @@ "node_modules/isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "dev": true + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" }, "node_modules/istanbul-lib-coverage": { "version": "3.2.2", @@ -5369,6 +5393,14 @@ "node": ">= 0.8.0" } }, + "node_modules/os-shim": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/os-shim/-/os-shim-0.1.3.tgz", + "integrity": "sha512-jd0cvB8qQ5uVt0lvCIexBaROw1KyKm5sbulg2fWOHjETisuCzWyt+eTZKEMs8v6HwzoGs8xik26jg7eCM6pS+A==", + "engines": { + "node": ">= 0.4.0" + } + }, "node_modules/p-limit": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", @@ -5711,6 +5743,66 @@ "dev": true, "peer": true }, + "node_modules/pre-commit": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/pre-commit/-/pre-commit-1.2.2.tgz", + "integrity": "sha512-qokTiqxD6GjODy5ETAIgzsRgnBWWQHQH2ghy86PU7mIn/wuWeTwF3otyNQZxWBwVn8XNr8Tdzj/QfUXpH+gRZA==", + "hasInstallScript": true, + "dependencies": { + "cross-spawn": "^5.0.1", + "spawn-sync": "^1.0.15", + "which": "1.2.x" + } + }, + "node_modules/pre-commit/node_modules/cross-spawn": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", + "integrity": "sha512-pTgQJ5KC0d2hcY8eyL1IzlBPYjTkyH72XRZPnLyKus2mBfNjQs3klqbJU2VILqZryAZUt9JOb3h/mWMy23/f5A==", + "dependencies": { + "lru-cache": "^4.0.1", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + }, + "node_modules/pre-commit/node_modules/lru-cache": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", + "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", + "dependencies": { + "pseudomap": "^1.0.2", + "yallist": "^2.1.2" + } + }, + "node_modules/pre-commit/node_modules/shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==", + "dependencies": { + "shebang-regex": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/pre-commit/node_modules/shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/pre-commit/node_modules/which": { + "version": "1.2.14", + "resolved": "https://registry.npmjs.org/which/-/which-1.2.14.tgz", + "integrity": "sha512-16uPglFkRPzgiUXYMi1Jf8Z5EzN1iB4V0ZtMXcHZnwsBtQhhHeCqoWw7tsUY42hJGNDWtUsVLTjakIa5BgAxCw==", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "which": "bin/which" + } + }, "node_modules/prelude-ls": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", @@ -5821,6 +5913,11 @@ } } }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, "node_modules/prop-types": { "version": "15.8.1", "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", @@ -5844,6 +5941,11 @@ "node": ">= 0.10" } }, + "node_modules/pseudomap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", + "integrity": "sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ==" + }, "node_modules/pstree.remy": { "version": "1.1.8", "resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.8.tgz", @@ -5931,6 +6033,30 @@ "pify": "^2.3.0" } }, + "node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/readable-stream/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" + }, + "node_modules/readable-stream/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, "node_modules/readdirp": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", @@ -6339,6 +6465,16 @@ "node": ">=0.10.0" } }, + "node_modules/spawn-sync": { + "version": "1.0.15", + "resolved": "https://registry.npmjs.org/spawn-sync/-/spawn-sync-1.0.15.tgz", + "integrity": "sha512-9DWBgrgYZzNghseho0JOuh+5fg9u6QWhAWa51QC7+U5rCheZ/j1DrEZnyE0RBBRqZ9uEXGPgSSM0nky6burpVw==", + "hasInstallScript": true, + "dependencies": { + "concat-stream": "^1.4.7", + "os-shim": "^0.1.2" + } + }, "node_modules/stackback": { "version": "0.0.2", "resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz", @@ -6371,6 +6507,19 @@ "node": ">= 0.4" } }, + "node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/string_decoder/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, "node_modules/string-width": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", @@ -7189,6 +7338,11 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==" + }, "node_modules/typescript": { "version": "5.5.3", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.3.tgz", @@ -7247,9 +7401,7 @@ "node_modules/util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", - "dev": true, - "peer": true + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" }, "node_modules/utils-merge": { "version": "1.0.1", @@ -7719,6 +7871,11 @@ } } }, + "node_modules/yallist": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", + "integrity": "sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A==" + }, "node_modules/yaml": { "version": "2.5.0", "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.5.0.tgz", diff --git a/package.json b/package.json index 7a69f67..e12d676 100644 --- a/package.json +++ b/package.json @@ -4,11 +4,17 @@ "description": "", "main": "index.js", "scripts": { - "start": "node dist/index.js", + "start": "nodemon --exec ts-node api/src/index.ts", "build": "tsc", "lint": "eslint .", - "test": "vitest --coverage" + "test": "vitest --coverage", + "test:ci": "vitest run --silent --passWithNoTests" + }, + "pre-commit": [ + "test:ci", + "lint" + ], "keywords": [], "author": "", "license": "ISC", @@ -19,6 +25,7 @@ "cors": "^2.8.5", "dotenv": "^16.4.5", "express": "^4.19.2", + "pre-commit": "^1.2.2", "swagger-jsdoc": "^6.2.8", "swagger-ui-express": "^5.0.1", "ts-node": "^10.9.2",