From 274ba666b40de8f35b19bbf8a8d352e1f15607c7 Mon Sep 17 00:00:00 2001 From: Antonio-Angelo Date: Thu, 30 Apr 2026 19:32:27 +0000 Subject: [PATCH 1/2] =?UTF-8?q?Comita=20todas=20as=20altera=C3=A7=C3=B5es?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 335 +-------------------- README.md | 162 ++++------ config/supabaseClient.js | 17 ++ index.js | 127 ++++++++ package-lock.json | 622 ++++++++++++++++++++++++++++++++++++++- package.json | 28 +- public/style.css | 139 +++++++++ server.js | 136 ++++++++- views/formulario.ejs | 77 +++++ views/index.ejs | 60 ++++ 10 files changed, 1233 insertions(+), 470 deletions(-) create mode 100644 config/supabaseClient.js create mode 100644 index.js create mode 100644 public/style.css create mode 100644 views/formulario.ejs create mode 100644 views/index.ejs diff --git a/.gitignore b/.gitignore index 1aae53ab..2e8157a9 100644 --- a/.gitignore +++ b/.gitignore @@ -1,334 +1,3 @@ -## Ignore Visual Studio temporary files, build results, and -## files generated by popular Visual Studio add-ons. -## -## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore - -# User-specific files -*.suo -*.user -*.userosscache -*.sln.docstates - -# User-specific files (MonoDevelop/Xamarin Studio) -*.userprefs - -# Build results -[Dd]ebug/ -[Dd]ebugPublic/ -[Rr]elease/ -[Rr]eleases/ -x64/ -x86/ -bld/ -[Bb]in/ -[Oo]bj/ -[Ll]og/ - -# Visual Studio 2015/2017 cache/options directory -.vs/ -# Uncomment if you have tasks that create the project's static files in wwwroot -#wwwroot/ - -# Visual Studio 2017 auto generated files -Generated\ Files/ - -# MSTest test Results -[Tt]est[Rr]esult*/ -[Bb]uild[Ll]og.* - -# NUNIT -*.VisualState.xml -TestResult.xml - -# Build Results of an ATL Project -[Dd]ebugPS/ -[Rr]eleasePS/ -dlldata.c - -# Benchmark Results -BenchmarkDotNet.Artifacts/ - -# .NET Core -project.lock.json -project.fragment.lock.json -artifacts/ -**/Properties/launchSettings.json - -# StyleCop -StyleCopReport.xml - -# Files built by Visual Studio -*_i.c -*_p.c -*_i.h -*.ilk -*.meta -*.obj -*.iobj -*.pch -*.pdb -*.ipdb -*.pgc -*.pgd -*.rsp -*.sbr -*.tlb -*.tli -*.tlh -*.tmp -*.tmp_proj -*.log -*.vspscc -*.vssscc -.builds -*.pidb -*.svclog -*.scc - -# Chutzpah Test files -_Chutzpah* - -# Visual C++ cache files -ipch/ -*.aps -*.ncb -*.opendb -*.opensdf -*.sdf -*.cachefile -*.VC.db -*.VC.VC.opendb - -# Visual Studio profiler -*.psess -*.vsp -*.vspx -*.sap - -# Visual Studio Trace Files -*.e2e - -# TFS 2012 Local Workspace -$tf/ - -# Guidance Automation Toolkit -*.gpState - -# ReSharper is a .NET coding add-in -_ReSharper*/ -*.[Rr]e[Ss]harper -*.DotSettings.user - -# JustCode is a .NET coding add-in -.JustCode - -# TeamCity is a build add-in -_TeamCity* - -# DotCover is a Code Coverage Tool -*.dotCover - -# AxoCover is a Code Coverage Tool -.axoCover/* -!.axoCover/settings.json - -# Visual Studio code coverage results -*.coverage -*.coveragexml - -# NCrunch -_NCrunch_* -.*crunch*.local.xml -nCrunchTemp_* - -# MightyMoose -*.mm.* -AutoTest.Net/ - -# Web workbench (sass) -.sass-cache/ - -# Installshield output folder -[Ee]xpress/ - -# DocProject is a documentation generator add-in -DocProject/buildhelp/ -DocProject/Help/*.HxT -DocProject/Help/*.HxC -DocProject/Help/*.hhc -DocProject/Help/*.hhk -DocProject/Help/*.hhp -DocProject/Help/Html2 -DocProject/Help/html - -# Click-Once directory -publish/ - -# Publish Web Output -*.[Pp]ublish.xml -*.azurePubxml -# Note: Comment the next line if you want to checkin your web deploy settings, -# but database connection strings (with potential passwords) will be unencrypted -*.pubxml -*.publishproj - -# Microsoft Azure Web App publish settings. Comment the next line if you want to -# checkin your Azure Web App publish settings, but sensitive information contained -# in these scripts will be unencrypted -PublishScripts/ - -# NuGet Packages -*.nupkg -# The packages folder can be ignored because of Package Restore -**/[Pp]ackages/* -# except build/, which is used as an MSBuild target. -!**/[Pp]ackages/build/ -# Uncomment if necessary however generally it will be regenerated when needed -#!**/[Pp]ackages/repositories.config -# NuGet v3's project.json files produces more ignorable files -*.nuget.props -*.nuget.targets - -# Microsoft Azure Build Output -csx/ -*.build.csdef - -# Microsoft Azure Emulator -ecf/ -rcf/ - -# Windows Store app package directories and files -AppPackages/ -BundleArtifacts/ -Package.StoreAssociation.xml -_pkginfo.txt -*.appx - -# Visual Studio cache files -# files ending in .cache can be ignored -*.[Cc]ache -# but keep track of directories ending in .cache -!*.[Cc]ache/ - -# Others -ClientBin/ -~$* -*~ -*.dbmdl -*.dbproj.schemaview -*.jfm -*.pfx -*.publishsettings -orleans.codegen.cs - -# Including strong name files can present a security risk -# (https://github.com/github/gitignore/pull/2483#issue-259490424) -#*.snk - -# Since there are multiple workflows, uncomment next line to ignore bower_components -# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) -#bower_components/ - -# RIA/Silverlight projects -Generated_Code/ - -# Backup & report files from converting an old project file -# to a newer Visual Studio version. Backup files are not needed, -# because we have git ;-) -_UpgradeReport_Files/ -Backup*/ -UpgradeLog*.XML -UpgradeLog*.htm -ServiceFabricBackup/ -*.rptproj.bak - -# SQL Server files -*.mdf -*.ldf -*.ndf - -# Business Intelligence projects -*.rdl.data -*.bim.layout -*.bim_*.settings -*.rptproj.rsuser - -# Microsoft Fakes -FakesAssemblies/ - -# GhostDoc plugin setting file -*.GhostDoc.xml - -# Node.js Tools for Visual Studio -.ntvs_analysis.dat node_modules/ - -# Visual Studio 6 build log -*.plg - -# Visual Studio 6 workspace options file -*.opt - -# Visual Studio 6 auto-generated workspace file (contains which files were open etc.) -*.vbw - -# Visual Studio LightSwitch build output -**/*.HTMLClient/GeneratedArtifacts -**/*.DesktopClient/GeneratedArtifacts -**/*.DesktopClient/ModelManifest.xml -**/*.Server/GeneratedArtifacts -**/*.Server/ModelManifest.xml -_Pvt_Extensions - -# Paket dependency manager -.paket/paket.exe -paket-files/ - -# FAKE - F# Make -.fake/ - -# JetBrains Rider -.idea/ -*.sln.iml - -# CodeRush -.cr/ - -# Python Tools for Visual Studio (PTVS) -__pycache__/ -*.pyc - -# Cake - Uncomment if you are using it -# tools/** -# !tools/packages.config - -# Tabs Studio -*.tss - -# Telerik's JustMock configuration file -*.jmconfig - -# BizTalk build output -*.btp.cs -*.btm.cs -*.odx.cs -*.xsd.cs - -# OpenCover UI analysis results -OpenCover/ - -# Azure Stream Analytics local run output -ASALocalRun/ - -# MSBuild Binary and Structured Log -*.binlog - -# NVidia Nsight GPU debugger configuration file -*.nvuser - -# MFractors (Xamarin productivity tool) working folder -.mfractor/ - -*.DS_Store - -out \ No newline at end of file +.env +*.log diff --git a/README.md b/README.md index a0b06247..ae8be6cc 100644 --- a/README.md +++ b/README.md @@ -1,101 +1,61 @@ -# Try Out Development Containers: Node.js - -[![Open in Dev Containers](https://img.shields.io/static/v1?label=Dev%20Containers&message=Open&color=blue&logo=visualstudiocode)](https://vscode.dev/redirect?url=vscode://ms-vscode-remote.remote-containers/cloneInVolume?url=https://github.com/microsoft/vscode-remote-try-node) - -A **development container** is a running container with a well-defined tool/runtime stack and its prerequisites. You can try out development containers with **[GitHub Codespaces](https://github.com/features/codespaces)** or **[Visual Studio Code Dev Containers](https://aka.ms/vscode-remote/containers)**. - -This is a sample project that lets you try out either option in a few easy steps. We have a variety of other [vscode-remote-try-*](https://github.com/search?q=org%3Amicrosoft+vscode-remote-try-&type=Repositories) sample projects, too. - -> **Note:** If you already have a Codespace or dev container, you can jump to the [Things to try](#things-to-try) section. - -## Setting up the development container - -### GitHub Codespaces -Follow these steps to open this sample in a Codespace: -1. Click the **Code** drop-down menu. -2. Click on the **Codespaces** tab. -1. Click **Create codespace on main** . - -For more info, check out the [GitHub documentation](https://docs.github.com/en/free-pro-team@latest/github/developing-online-with-codespaces/creating-a-codespace#creating-a-codespace). - -### VS Code Dev Containers - -If you already have VS Code and Docker installed, you can click the badge above or [here](https://vscode.dev/redirect?url=vscode://ms-vscode-remote.remote-containers/cloneInVolume?url=https://github.com/microsoft/vscode-remote-try-node) to get started. Clicking these links will cause VS Code to automatically install the Dev Containers extension if needed, clone the source code into a container volume, and spin up a dev container for use. - -Follow these steps to open this sample in a container using the VS Code Dev Containers extension: - -1. If this is your first time using a development container, please ensure your system meets the pre-reqs (i.e. have Docker installed) in the [getting started steps](https://aka.ms/vscode-remote/containers/getting-started). - -2. To use this repository, you can either open the repository in an isolated Docker volume: - - - Press F1 and select the **Dev Containers: Try a Sample...** command. - - Choose the "Node" sample, wait for the container to start, and try things out! - > **Note:** Under the hood, this will use the **Dev Containers: Clone Repository in Container Volume...** command to clone the source code in a Docker volume instead of the local filesystem. [Volumes](https://docs.docker.com/storage/volumes/) are the preferred mechanism for persisting container data. - - Or open a locally cloned copy of the code: - - - Clone this repository to your local filesystem. - - Press F1 and select the **Dev Containers: Open Folder in Container...** command. - - Select the cloned copy of this folder, wait for the container to start, and try things out! - -## Things to try - -Once you have this sample opened, you'll be able to work with it like you would locally. - -Some things to try: - -1. **Edit:** - - Open `server.js` - - Try adding some code and check out the language features. - - Make a spelling mistake and notice it is detected. The [Code Spell Checker](https://marketplace.visualstudio.com/items?itemName=streetsidesoftware.code-spell-checker) extension was automatically installed because it is referenced in `.devcontainer/devcontainer.json`. - - Also notice that `eslint` and the [ESLint extension](https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint) are installed. Tools are installed in the `mcr.microsoft.com/devcontainers/javascript-node` image and Dev Container settings and metadata are automatically picked up from [image labels](https://containers.dev/implementors/reference/#labels). - -2. **Terminal:** Press Ctrl+Shift+\` and type `uname` and other Linux commands from the terminal window. -3. **Build, Run, and Debug:** - - Open `server.js` - - Add a breakpoint (e.g. on line 20). - - Press F5 to launch the app in the container. - - Once the breakpoint is hit, try hovering over variables, examining locals, and more. - - Continue (F5). You can connect to the server in the container by either: - - Clicking on `Open in Browser` in the notification telling you: `Your service running on port 3000 is available`. - - Clicking the globe icon in the 'Ports' view. The 'Ports' view gives you an organized table of your forwarded ports, and you can access it with the command **Ports: Focus on Ports View**. - - Notice port 3000 in the 'Ports' view is labeled "Hello Remote World." In `devcontainer.json`, you can set `"portsAttributes"`, such as a label for your forwarded ports and the action to be taken when the port is autoforwarded. - - If we didn't know the port was 3000, we could've used a regex instead of "3000" in the `"portsAttributes"`, such as ".+/server.js". - - > **Note:** In Dev Containers, you can access your app at `http://localhost:3000` in a local browser. But in a browser-based Codespace, you must click the link from the notification or the `Ports` view so that the service handles port forwarding in the browser and generates the correct URL. - -4. **Rebuild or update your container** - - You may want to make changes to your container, such as installing a different version of a software or forwarding a new port. You'll rebuild your container for your changes to take effect. - - **Open browser automatically:** As an example change, let's update the `portsAttributes` in the `.devcontainer/devcontainer.json` file to open a browser when our port is automatically forwarded. - - - Open the `.devcontainer/devcontainer.json` file. - - Modify the `"onAutoForward"` attribute in your `portsAttributes` from `"notify"` to `"openBrowser"`. - - Press F1 and select the **Dev Containers: Rebuild Container** or **Codespaces: Rebuild Container** command so the modifications are picked up. - -5. **Install the GitHub CLI using a Dev Container Feature:** - - Press F1 and select the **Dev Containers: Configure Container Features...** or **Codespaces: Configure Container Features...** command. - - Type "github" in the text box at the top. - - Check the check box next to "GitHub CLI" (published by devcontainers) - - Click OK - - Press F1 and select the **Dev Containers: Rebuild Container** or **Codespaces: Rebuild Container** command so the modifications are picked up. - -## Contributing - -This project welcomes contributions and suggestions. Most contributions require you to agree to a -Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us -the rights to use your contribution. For details, visit https://cla.microsoft.com. - -When you submit a pull request, a CLA-bot will automatically determine whether you need to provide -a CLA and decorate the PR appropriately (e.g., label, comment). Simply follow the instructions -provided by the bot. You will only need to do this once across all repos using our CLA. - -This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). -For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or -contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments. - -## License - -Copyright © Microsoft Corporation All rights reserved.
-Licensed under the MIT License. See LICENSE in the project root for license information. +# Projeto 3: CRUD Completo com Supabase + +Este é o projeto final e mais avançado do Guia de Revisão Backend com Node.js. +Ele une tudo o que aprendemos (Express, EJS) e adiciona persistência de dados real usando um banco de dados PostgreSQL hospedado no **Supabase**. + +## 🎯 Objetivos de Aprendizado +- Conectar uma aplicação Node.js a um banco de dados real em nuvem +- Usar variáveis de ambiente (`.env`) para proteger credenciais sensíveis +- Implementar as 4 operações fundamentais de banco de dados (CRUD): + - **C**reate (Inserir dados) + - **R**ead (Ler/Listar dados) + - **U**pdate (Atualizar dados existentes) + - **D**elete (Remover dados) +- Reutilizar views EJS (um único formulário para criar e editar) +- Lidar com operações assíncronas (`async/await`) no Express + +## ⚙️ Pré-requisitos (Configuração do Supabase) + +Para este projeto funcionar, você precisa de uma conta no Supabase: + +1. Crie uma conta em [supabase.com](https://supabase.com) +2. Crie um novo projeto e vá no "SQL Editor" +3. Execute o seguinte código SQL para criar a tabela necessária: + ```sql + CREATE TABLE alunos ( + id SERIAL PRIMARY KEY, + nome TEXT NOT NULL, + email TEXT, + curso TEXT NOT NULL, + created_at TIMESTAMP WITH TIME ZONE DEFAULT TIMEZONE('utc'::text, NOW()) + ); + ``` +4. Vá em "Project Settings" > "API" e copie sua `Project URL` e `anon public key` +5. Crie um arquivo `.env` na raiz desta pasta com as credenciais: + ```env + SUPABASE_URL=sua_url_aqui + SUPABASE_ANON_KEY=sua_chave_aqui + PORT=3000 + ``` + +## 🚀 Como Executar + +1. Abra o terminal na pasta deste projeto +2. Instale as dependências: + ```bash + npm install + ``` +3. Certifique-se de que o arquivo `.env` foi criado com suas credenciais! +4. Inicie o servidor: + ```bash + npm start + ``` +5. Abra no navegador: `http://localhost:3000` + +## 📁 Estrutura do Projeto +- `index.js`: Servidor e rotas CRUD +- `config/supabaseClient.js`: Configuração de conexão com o banco +- `views/`: + - `index.ejs`: Lista de alunos buscando do banco + - `formulario.ejs`: View inteligente que serve tanto para novo cadastro quanto para edição +- `.env`: Arquivo (que você deve criar) com as chaves secretas da API diff --git a/config/supabaseClient.js b/config/supabaseClient.js new file mode 100644 index 00000000..29f7b4c9 --- /dev/null +++ b/config/supabaseClient.js @@ -0,0 +1,17 @@ +const { createClient } = require('@supabase/supabase-js'); +require('dotenv').config(); + +// Verifica se as variáveis de ambiente existem +const supabaseUrl = process.env.SUPABASE_URL; +const supabaseKey = process.env.SUPABASE_ANON_KEY; + +if (!supabaseUrl || !supabaseKey) { + console.error('❌ ERRO: Faltando SUPABASE_URL ou SUPABASE_ANON_KEY no arquivo .env'); + console.log('Crie um arquivo .env na raiz do projeto com as suas credenciais do Supabase.'); + // Em produção, você pode querer lançar um erro ou encerrar a aplicação +} + +// Cria o cliente do Supabase +const supabase = createClient(supabaseUrl || 'https://dummy.supabase.co', supabaseKey || 'dummy-key'); + +module.exports = supabase; diff --git a/index.js b/index.js new file mode 100644 index 00000000..e6896fe9 --- /dev/null +++ b/index.js @@ -0,0 +1,127 @@ +require('dotenv').config(); +const express = require('express'); +const path = require('path'); +const supabase = require('./config/supabaseClient'); + +const app = express(); +const port = process.env.PORT || 3000; + +// Configurar EJS +app.set('view engine', 'ejs'); +app.set('views', path.join(__dirname, 'views')); + +// Middlewares +app.use(express.urlencoded({ extended: true })); +app.use(express.static(path.join(__dirname, 'public'))); + +// Rota principal - Listar alunos (READ) +app.get('/', async (req, res) => { + try { + // Busca dados no Supabase (ordena por id) + const { data: alunos, error } = await supabase + .from('alunos') + .select('*') + .order('id', { ascending: true }); + + if (error) throw error; + + res.render('index', { + titulo: 'Gestão Escolar (Supabase)', + alunos: alunos || [] + }); + } catch (error) { + console.error('Erro ao buscar alunos:', error.message); + res.status(500).send('Erro interno do servidor'); + } +}); + +// Rota para o formulário de cadastro +app.get('/novo', (req, res) => { + res.render('formulario', { + titulo: 'Cadastrar Aluno', + aluno: null // Indica que é um novo cadastro + }); +}); + +// Rota para o formulário de edição +app.get('/editar/:id', async (req, res) => { + try { + const id = req.params.id; + + // Busca o aluno específico + const { data, error } = await supabase + .from('alunos') + .select('*') + .eq('id', id) + .single(); // Retorna apenas um objeto, não um array + + if (error) throw error; + if (!data) return res.status(404).send('Aluno não encontrado'); + + res.render('formulario', { + titulo: 'Editar Aluno', + aluno: data // Passa os dados do aluno para preencher o formulário + }); + } catch (error) { + console.error('Erro ao buscar aluno:', error.message); + res.status(500).send('Erro interno do servidor'); + } +}); + +// Rota para processar cadastro/edição (CREATE / UPDATE) +app.post('/salvar', async (req, res) => { + try { + const { id, nome, email, curso } = req.body; + + // Prepara os dados + const dadosAluno = { nome, email, curso }; + + if (id) { + // Se tem ID, é uma edição (UPDATE) + const { error } = await supabase + .from('alunos') + .update(dadosAluno) + .eq('id', id); + + if (error) throw error; + } else { + // Se não tem ID, é um novo cadastro (CREATE) + const { error } = await supabase + .from('alunos') + .insert([dadosAluno]); + + if (error) throw error; + } + + res.redirect('/'); + } catch (error) { + console.error('Erro ao salvar aluno:', error.message); + res.status(500).send('Erro interno ao salvar os dados'); + } +}); + +// Rota para remover aluno (DELETE) +// Usamos GET aqui para simplificar, pois formulários HTML padrão só suportam GET/POST +// Em uma API real, usaríamos o método DELETE +app.get('/deletar/:id', async (req, res) => { + try { + const id = req.params.id; + + const { error } = await supabase + .from('alunos') + .delete() + .eq('id', id); + + if (error) throw error; + + res.redirect('/'); + } catch (error) { + console.error('Erro ao deletar aluno:', error.message); + res.status(500).send('Erro interno ao deletar'); + } +}); + +// Iniciar servidor +app.listen(port, () => { + console.log(`🚀 Servidor (Supabase CRUD) rodando em http://localhost:${port}`); +}); diff --git a/package-lock.json b/package-lock.json index 335d3a99..03fd19d5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,14 +1,137 @@ { - "name": "docker_web_app", + "name": "projeto3-crud-supabase", "version": "1.0.0", "lockfileVersion": 3, "requires": true, "packages": { "": { - "name": "docker_web_app", + "name": "projeto3-crud-supabase", "version": "1.0.0", + "license": "ISC", "dependencies": { - "express": "^4.20.0" + "@supabase/supabase-js": "^2.39.0", + "dotenv": "^16.3.1", + "ejs": "^3.1.9", + "express": "^4.18.2" + }, + "devDependencies": { + "supabase": "^2.95.6" + } + }, + "node_modules/@isaacs/fs-minipass": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@isaacs/fs-minipass/-/fs-minipass-4.0.1.tgz", + "integrity": "sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w==", + "dev": true, + "license": "ISC", + "dependencies": { + "minipass": "^7.0.4" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@supabase/auth-js": { + "version": "2.78.0", + "resolved": "https://registry.npmjs.org/@supabase/auth-js/-/auth-js-2.78.0.tgz", + "integrity": "sha512-cXDtu1U0LeZj/xfnFoV7yCze37TcbNo8FCxy1FpqhMbB9u9QxxDSW6pA5gm/07Ei7m260Lof4CZx67Cu6DPeig==", + "license": "MIT", + "dependencies": { + "@supabase/node-fetch": "2.6.15", + "tslib": "2.8.1" + } + }, + "node_modules/@supabase/functions-js": { + "version": "2.78.0", + "resolved": "https://registry.npmjs.org/@supabase/functions-js/-/functions-js-2.78.0.tgz", + "integrity": "sha512-t1jOvArBsOINyqaRee1xJ3gryXLvkBzqnKfi6q3YRzzhJbGS6eXz0pXR5fqmJeB01fLC+1njpf3YhMszdPEF7g==", + "license": "MIT", + "dependencies": { + "@supabase/node-fetch": "2.6.15", + "tslib": "2.8.1" + } + }, + "node_modules/@supabase/node-fetch": { + "version": "2.6.15", + "resolved": "https://registry.npmjs.org/@supabase/node-fetch/-/node-fetch-2.6.15.tgz", + "integrity": "sha512-1ibVeYUacxWYi9i0cf5efil6adJ9WRyZBLivgjs+AUpewx1F3xPi7gLgaASI2SmIQxPoCEjAsLAzKPgMJVgOUQ==", + "license": "MIT", + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + } + }, + "node_modules/@supabase/postgrest-js": { + "version": "2.78.0", + "resolved": "https://registry.npmjs.org/@supabase/postgrest-js/-/postgrest-js-2.78.0.tgz", + "integrity": "sha512-AwhpYlSvJ+PSnPmIK8sHj7NGDyDENYfQGKrMtpVIEzQA2ApUjgpUGxzXWN4Z0wEtLQsvv7g4y9HVad9Hzo1TNA==", + "license": "MIT", + "dependencies": { + "@supabase/node-fetch": "2.6.15", + "tslib": "2.8.1" + } + }, + "node_modules/@supabase/realtime-js": { + "version": "2.78.0", + "resolved": "https://registry.npmjs.org/@supabase/realtime-js/-/realtime-js-2.78.0.tgz", + "integrity": "sha512-rCs1zmLe7of7hj4s7G9z8rTqzWuNVtmwDr3FiCRCJFawEoa+RQO1xpZGbdeuVvVmKDyVN6b542Okci+117y/LQ==", + "license": "MIT", + "dependencies": { + "@supabase/node-fetch": "2.6.15", + "@types/phoenix": "^1.6.6", + "@types/ws": "^8.18.1", + "tslib": "2.8.1", + "ws": "^8.18.2" + } + }, + "node_modules/@supabase/storage-js": { + "version": "2.78.0", + "resolved": "https://registry.npmjs.org/@supabase/storage-js/-/storage-js-2.78.0.tgz", + "integrity": "sha512-n17P0JbjHOlxqJpkaGFOn97i3EusEKPEbWOpuk1r4t00Wg06B8Z4GUiq0O0n1vUpjiMgJUkLIMuBVp+bEgunzQ==", + "license": "MIT", + "dependencies": { + "@supabase/node-fetch": "2.6.15", + "tslib": "2.8.1" + } + }, + "node_modules/@supabase/supabase-js": { + "version": "2.78.0", + "resolved": "https://registry.npmjs.org/@supabase/supabase-js/-/supabase-js-2.78.0.tgz", + "integrity": "sha512-xYMRNBFmKp2m1gMuwcp/gr/HlfZKqjye1Ib8kJe29XJNsgwsfO/f8skxnWiscFKTlkOKLuBexNgl5L8dzGt6vA==", + "license": "MIT", + "dependencies": { + "@supabase/auth-js": "2.78.0", + "@supabase/functions-js": "2.78.0", + "@supabase/node-fetch": "2.6.15", + "@supabase/postgrest-js": "2.78.0", + "@supabase/realtime-js": "2.78.0", + "@supabase/storage-js": "2.78.0" + } + }, + "node_modules/@types/node": { + "version": "25.6.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-25.6.0.tgz", + "integrity": "sha512-+qIYRKdNYJwY3vRCZMdJbPLJAtGjQBudzZzdzwQYkEPQd+PJGixUL5QfvCLDaULoLv+RhT3LDkwEfKaAkgSmNQ==", + "license": "MIT", + "dependencies": { + "undici-types": "~7.19.0" + } + }, + "node_modules/@types/phoenix": { + "version": "1.6.7", + "resolved": "https://registry.npmjs.org/@types/phoenix/-/phoenix-1.6.7.tgz", + "integrity": "sha512-oN9ive//QSBkf19rfDv45M7eZPi0eEXylht2OLEXicu5b4KoQ1OzXIw+xDSGWxSxe1JmepRR/ZH283vsu518/Q==", + "license": "MIT" + }, + "node_modules/@types/ws": { + "version": "8.18.1", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.18.1.tgz", + "integrity": "sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg==", + "license": "MIT", + "dependencies": { + "@types/node": "*" } }, "node_modules/accepts": { @@ -24,16 +147,55 @@ "node": ">= 0.6" } }, + "node_modules/agent-base": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-9.0.0.tgz", + "integrity": "sha512-TQf59BsZnytt8GdJKLPfUZ54g/iaUL2OWDSFCCvMOhsHduDQxO8xC4PNeyIkVcA5KwL2phPSv0douC0fgWzmnA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 20" + } + }, "node_modules/array-flatten": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==", "license": "MIT" }, + "node_modules/async": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.6.tgz", + "integrity": "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==", + "license": "MIT" + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "license": "MIT" + }, + "node_modules/bin-links": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/bin-links/-/bin-links-6.0.0.tgz", + "integrity": "sha512-X4CiKlcV2GjnCMwnKAfbVWpHa++65th9TuzAEYtZoATiOE2DQKhSp4CJlyLoTqdhBKlXjpXjCTYPNNFS33Fi6w==", + "dev": true, + "license": "ISC", + "dependencies": { + "cmd-shim": "^8.0.0", + "npm-normalize-package-bin": "^5.0.0", + "proc-log": "^6.0.0", + "read-cmd-shim": "^6.0.0", + "write-file-atomic": "^7.0.0" + }, + "engines": { + "node": "^20.17.0 || >=22.9.0" + } + }, "node_modules/body-parser": { - "version": "1.20.4", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.4.tgz", - "integrity": "sha512-ZTgYYLMOXY9qKU/57FAo8F+HA2dGX7bqGc71txDRC1rS4frdFI5R7NhluHxH6M0YItAP0sHB4uqAOcYKxO6uGA==", + "version": "1.20.5", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.5.tgz", + "integrity": "sha512-3grm+/2tUOvu2cjJkvsIxrv/wVpfXQW4PsQHYm7yk4vfpu7Ekl6nEsYBoJUL6qDwZUx8wUhQ8tR2qz+ad9c9OA==", "license": "MIT", "dependencies": { "bytes": "~3.1.2", @@ -44,7 +206,7 @@ "http-errors": "~2.0.1", "iconv-lite": "~0.4.24", "on-finished": "~2.4.1", - "qs": "~6.14.0", + "qs": "~6.15.1", "raw-body": "~2.5.3", "type-is": "~1.6.18", "unpipe": "~1.0.0" @@ -54,6 +216,30 @@ "npm": "1.2.8000 || >= 1.4.16" } }, + "node_modules/body-parser/node_modules/qs": { + "version": "6.15.1", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.15.1.tgz", + "integrity": "sha512-6YHEFRL9mfgcAvql/XhwTvf5jKcOiiupt2FiJxHkiX1z4j7WL8J/jRHYLluORvc1XxB5rV20KoeK00gVJamspg==", + "license": "BSD-3-Clause", + "dependencies": { + "side-channel": "^1.1.0" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/brace-expansion": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.0.tgz", + "integrity": "sha512-TN1kCZAgdgweJhWWpgKYrQaMNHcDULHkWwQIspdtjV4Y5aurRdZpjAqn6yX3FPqTA9ngHCc4hJxMAMgGfve85w==", + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, "node_modules/bytes": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", @@ -92,6 +278,26 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/chownr": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-3.0.0.tgz", + "integrity": "sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==", + "dev": true, + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=18" + } + }, + "node_modules/cmd-shim": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/cmd-shim/-/cmd-shim-8.0.0.tgz", + "integrity": "sha512-Jk/BK6NCapZ58BKUxlSI+ouKRbjH1NLZCgJkYoab+vEHUY3f6OzpNBN9u7HFSv9J6TRDGs4PLOHezoKGaFRSCA==", + "dev": true, + "license": "ISC", + "engines": { + "node": "^20.17.0 || >=22.9.0" + } + }, "node_modules/content-disposition": { "version": "0.5.4", "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", @@ -128,6 +334,16 @@ "integrity": "sha512-NXdYc3dLr47pBkpUCHtKSwIOQXLVn8dZEuywboCOJY/osA0wFSLlSawr3KN8qXJEyX66FcONTH8EIlVuK0yyFA==", "license": "MIT" }, + "node_modules/data-uri-to-buffer": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz", + "integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 12" + } + }, "node_modules/debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", @@ -156,6 +372,18 @@ "npm": "1.2.8000 || >= 1.4.16" } }, + "node_modules/dotenv": { + "version": "16.6.1", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.6.1.tgz", + "integrity": "sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://dotenvx.com" + } + }, "node_modules/dunder-proto": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", @@ -176,6 +404,21 @@ "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", "license": "MIT" }, + "node_modules/ejs": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.10.tgz", + "integrity": "sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA==", + "license": "Apache-2.0", + "dependencies": { + "jake": "^10.8.5" + }, + "bin": { + "ejs": "bin/cli.js" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/encodeurl": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", @@ -276,6 +519,39 @@ "url": "https://opencollective.com/express" } }, + "node_modules/fetch-blob": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz", + "integrity": "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/jimmywarting" + }, + { + "type": "paypal", + "url": "https://paypal.me/jimmywarting" + } + ], + "license": "MIT", + "dependencies": { + "node-domexception": "^1.0.0", + "web-streams-polyfill": "^3.0.3" + }, + "engines": { + "node": "^12.20 || >= 14.13" + } + }, + "node_modules/filelist": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.6.tgz", + "integrity": "sha512-5giy2PkLYY1cP39p17Ech+2xlpTRL9HLspOfEgm0L6CwBXBTgsK5ou0JtzYuepxkaQ/tvhCFIJ5uXo0OrM2DxA==", + "license": "Apache-2.0", + "dependencies": { + "minimatch": "^5.0.1" + } + }, "node_modules/finalhandler": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.2.tgz", @@ -294,6 +570,19 @@ "node": ">= 0.8" } }, + "node_modules/formdata-polyfill": { + "version": "4.0.10", + "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz", + "integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "fetch-blob": "^3.1.2" + }, + "engines": { + "node": ">=12.20.0" + } + }, "node_modules/forwarded": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", @@ -383,9 +672,9 @@ } }, "node_modules/hasown": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", - "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.3.tgz", + "integrity": "sha512-ej4AhfhfL2Q2zpMmLo7U1Uv9+PyhIZpgQLGT1F9miIGmiCJIoCgSmczFdrc97mWT4kVY72KA+WnnhJ5pghSvSg==", "license": "MIT", "dependencies": { "function-bind": "^1.1.2" @@ -414,6 +703,45 @@ "url": "https://opencollective.com/express" } }, + "node_modules/https-proxy-agent": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-9.0.0.tgz", + "integrity": "sha512-/MVmHp58WkOypgFhCLk4fzpPcFQvTJ/e6LBI7irpIO2HfxUbpmYoHF+KzipzJpxxzJu7aJNWQ0xojJ/dzV2G5g==", + "dev": true, + "license": "MIT", + "dependencies": { + "agent-base": "9.0.0", + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 20" + } + }, + "node_modules/https-proxy-agent/node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/https-proxy-agent/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, + "license": "MIT" + }, "node_modules/iconv-lite": { "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", @@ -441,6 +769,23 @@ "node": ">= 0.10" } }, + "node_modules/jake": { + "version": "10.9.4", + "resolved": "https://registry.npmjs.org/jake/-/jake-10.9.4.tgz", + "integrity": "sha512-wpHYzhxiVQL+IV05BLE2Xn34zW1S223hvjtqk0+gsPrwd/8JNLXJgZZM/iPFsYc1xyphF+6M6EvdE5E9MBGkDA==", + "license": "Apache-2.0", + "dependencies": { + "async": "^3.2.6", + "filelist": "^1.0.4", + "picocolors": "^1.1.1" + }, + "bin": { + "jake": "bin/cli.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/math-intrinsics": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", @@ -510,6 +855,41 @@ "node": ">= 0.6" } }, + "node_modules/minimatch": { + "version": "5.1.9", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.9.tgz", + "integrity": "sha512-7o1wEA2RyMP7Iu7GNba9vc0RWWGACJOCZBJX2GJWip0ikV+wcOsgVuY9uE8CPiyQhkGFSlhuSkZPavN7u1c2Fw==", + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/minipass": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.3.tgz", + "integrity": "sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==", + "dev": true, + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/minizlib": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-3.1.0.tgz", + "integrity": "sha512-KZxYo1BUkWD2TVFLr0MQoM8vUUigWD3LlD83a/75BqC+4qE0Hb1Vo5v1FgcfaNXvfXzr+5EhQ6ing/CaBijTlw==", + "dev": true, + "license": "MIT", + "dependencies": { + "minipass": "^7.1.2" + }, + "engines": { + "node": ">= 18" + } + }, "node_modules/ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", @@ -525,6 +905,56 @@ "node": ">= 0.6" } }, + "node_modules/node-domexception": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz", + "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==", + "deprecated": "Use your platform's native DOMException instead", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/jimmywarting" + }, + { + "type": "github", + "url": "https://paypal.me/jimmywarting" + } + ], + "license": "MIT", + "engines": { + "node": ">=10.5.0" + } + }, + "node_modules/node-fetch": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz", + "integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==", + "dev": true, + "license": "MIT", + "dependencies": { + "data-uri-to-buffer": "^4.0.0", + "fetch-blob": "^3.1.4", + "formdata-polyfill": "^4.0.10" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/node-fetch" + } + }, + "node_modules/npm-normalize-package-bin": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-5.0.0.tgz", + "integrity": "sha512-CJi3OS4JLsNMmr2u07OJlhcrPxCeOeP/4xq67aWNai6TNWWbTrlNDgl8NcFKVlcBKp18GPj+EzbNIgrBfZhsag==", + "dev": true, + "license": "ISC", + "engines": { + "node": "^20.17.0 || >=22.9.0" + } + }, "node_modules/object-inspect": { "version": "1.13.4", "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", @@ -564,6 +994,22 @@ "integrity": "sha512-A/AGNMFN3c8bOlvV9RreMdrv7jsmF9XIfDeCd87+I8RNg6s78BhJxMu69NEMHBSJFxKidViTEdruRwEk/WIKqA==", "license": "MIT" }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "license": "ISC" + }, + "node_modules/proc-log": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/proc-log/-/proc-log-6.1.0.tgz", + "integrity": "sha512-iG+GYldRf2BQ0UDUAd6JQ/RwzaQy6mXmsk/IzlYyal4A4SNFw54MeH4/tLkF4I5WoWG9SQwuqWzS99jaFQHBuQ==", + "dev": true, + "license": "ISC", + "engines": { + "node": "^20.17.0 || >=22.9.0" + } + }, "node_modules/proxy-addr": { "version": "2.0.7", "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", @@ -616,6 +1062,16 @@ "node": ">= 0.8" } }, + "node_modules/read-cmd-shim": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/read-cmd-shim/-/read-cmd-shim-6.0.0.tgz", + "integrity": "sha512-1zM5HuOfagXCBWMN83fuFI/x+T/UhZ7k+KIzhrHXcQoeX5+7gmaDYjELQHmmzIodumBHeByBJT4QYS7ufAgs7A==", + "dev": true, + "license": "ISC", + "engines": { + "node": "^20.17.0 || >=22.9.0" + } + }, "node_modules/safe-buffer": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", @@ -713,13 +1169,13 @@ } }, "node_modules/side-channel-list": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", - "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.1.tgz", + "integrity": "sha512-mjn/0bi/oUURjc5Xl7IaWi/OJJJumuoJFQJfDDyO46+hBWsfaVM65TBHq2eoZBhzl9EchxOijpkbRC8SVBQU0w==", "license": "MIT", "dependencies": { "es-errors": "^1.3.0", - "object-inspect": "^1.13.3" + "object-inspect": "^1.13.4" }, "engines": { "node": ">= 0.4" @@ -765,6 +1221,19 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/statuses": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz", @@ -774,6 +1243,43 @@ "node": ">= 0.8" } }, + "node_modules/supabase": { + "version": "2.95.6", + "resolved": "https://registry.npmjs.org/supabase/-/supabase-2.95.6.tgz", + "integrity": "sha512-gjAT6wYBvmKoS34IjpTp9VDve1sfwcM/s+Q5rJA3OBw8d6nVTdA8edYVz/rfPEMt1V/EY40g63IL6qMBLPvrFw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "bin-links": "^6.0.0", + "https-proxy-agent": "^9.0.0", + "node-fetch": "^3.3.2", + "tar": "7.5.13" + }, + "bin": { + "supabase": "bin/supabase" + }, + "engines": { + "npm": ">=8" + } + }, + "node_modules/tar": { + "version": "7.5.13", + "resolved": "https://registry.npmjs.org/tar/-/tar-7.5.13.tgz", + "integrity": "sha512-tOG/7GyXpFevhXVh8jOPJrmtRpOTsYqUIkVdVooZYJS/z8WhfQUX8RJILmeuJNinGAMSu1veBr4asSHFt5/hng==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "@isaacs/fs-minipass": "^4.0.0", + "chownr": "^3.0.0", + "minipass": "^7.1.2", + "minizlib": "^3.1.0", + "yallist": "^5.0.0" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/toidentifier": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", @@ -783,6 +1289,18 @@ "node": ">=0.6" } }, + "node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", + "license": "MIT" + }, + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD" + }, "node_modules/type-is": { "version": "1.6.18", "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", @@ -796,6 +1314,12 @@ "node": ">= 0.6" } }, + "node_modules/undici-types": { + "version": "7.19.2", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.19.2.tgz", + "integrity": "sha512-qYVnV5OEm2AW8cJMCpdV20CDyaN3g0AjDlOGf1OW4iaDEx8MwdtChUp4zu4H0VP3nDRF/8RKWH+IPp9uW0YGZg==", + "license": "MIT" + }, "node_modules/unpipe": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", @@ -822,6 +1346,76 @@ "engines": { "node": ">= 0.8" } + }, + "node_modules/web-streams-polyfill": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz", + "integrity": "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", + "license": "BSD-2-Clause" + }, + "node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "license": "MIT", + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, + "node_modules/write-file-atomic": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-7.0.1.tgz", + "integrity": "sha512-OTIk8iR8/aCRWBqvxrzxR0hgxWpnYBblY1S5hDWBQfk/VFmJwzmJgQFN3WsoUKHISv2eAwe+PpbUzyL1CKTLXg==", + "dev": true, + "license": "ISC", + "dependencies": { + "signal-exit": "^4.0.1" + }, + "engines": { + "node": "^20.17.0 || >=22.9.0" + } + }, + "node_modules/ws": { + "version": "8.20.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.20.0.tgz", + "integrity": "sha512-sAt8BhgNbzCtgGbt2OxmpuryO63ZoDk/sqaB/znQm94T4fCEsy/yV+7CdC1kJhOU9lboAEU7R3kquuycDoibVA==", + "license": "MIT", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/yallist": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-5.0.0.tgz", + "integrity": "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==", + "dev": true, + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=18" + } } } } diff --git a/package.json b/package.json index c52b0e2c..0c2a54ba 100644 --- a/package.json +++ b/package.json @@ -1,14 +1,28 @@ { - "name": "docker_web_app", + "name": "projeto3-crud-supabase", "version": "1.0.0", - "description": "Node.js on Docker", - "author": "First Last ", - "main": "server.js", - "private": true, + "description": "CRUD completo com Express, EJS e Supabase (PostgreSQL)", + "main": "index.js", "scripts": { - "start": "node server.js" + "start": "node index.js", + "dev": "node --watch index.js" }, + "keywords": [ + "node", + "express", + "ejs", + "supabase", + "crud" + ], + "author": "", + "license": "ISC", "dependencies": { - "express": "^4.20.0" + "@supabase/supabase-js": "^2.39.0", + "dotenv": "^16.3.1", + "ejs": "^3.1.9", + "express": "^4.18.2" + }, + "devDependencies": { + "supabase": "^2.95.6" } } diff --git a/public/style.css b/public/style.css new file mode 100644 index 00000000..5459769d --- /dev/null +++ b/public/style.css @@ -0,0 +1,139 @@ +body { + font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; + margin: 0; + padding: 0; + background-color: #f8f9fa; + color: #212529; +} + +.container { + width: 85%; + margin: auto; + overflow: hidden; + padding-top: 20px; +} + +header { + background: #1e293b; + color: #ffffff; + padding-top: 20px; + min-height: 60px; + border-bottom: #0ea5e9 4px solid; +} + +header h1 { + text-align: center; + margin: 0; + padding-bottom: 15px; +} + +table { + width: 100%; + border-collapse: collapse; + margin: 25px 0; + background: #fff; + box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1); + border-radius: 8px; + overflow: hidden; +} + +table th, table td { + padding: 15px; + text-align: left; + border-bottom: 1px solid #e2e8f0; +} + +table th { + background-color: #f1f5f9; + color: #475569; + font-weight: 600; + text-transform: uppercase; + font-size: 0.85rem; +} + +table tr:hover { + background-color: #f8fafc; +} + +.btn { + display: inline-block; + background: #0ea5e9; + color: #fff; + padding: 8px 16px; + text-decoration: none; + border-radius: 6px; + border: none; + cursor: pointer; + font-size: 14px; + font-weight: 500; + transition: background-color 0.2s; +} + +.btn:hover { + background: #0284c7; +} + +.btn-danger { + background: #ef4444; +} + +.btn-danger:hover { + background: #dc2626; +} + +.btn-warning { + background: #f59e0b; +} + +.btn-warning:hover { + background: #d97706; +} + +.actions { + display: flex; + gap: 8px; +} + +.form-group { + margin-bottom: 20px; +} + +.form-group label { + display: block; + margin-bottom: 8px; + font-weight: 600; + color: #334155; +} + +.form-group input, .form-group select { + width: 100%; + padding: 12px; + border: 1px solid #cbd5e1; + border-radius: 6px; + box-sizing: border-box; + font-size: 1rem; + transition: border-color 0.2s; +} + +.form-group input:focus, .form-group select:focus { + outline: none; + border-color: #0ea5e9; + box-shadow: 0 0 0 3px rgba(14, 165, 233, 0.1); +} + +.card { + background: #fff; + padding: 30px; + margin-top: 20px; + border-radius: 8px; + box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1); +} + +.badge { + background: #e0f2fe; + color: #0369a1; + padding: 4px 8px; + border-radius: 12px; + font-size: 0.8rem; + font-weight: 600; +} diff --git a/server.js b/server.js index f7237623..e6896fe9 100644 --- a/server.js +++ b/server.js @@ -1,21 +1,127 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ +require('dotenv').config(); +const express = require('express'); +const path = require('path'); +const supabase = require('./config/supabaseClient'); -'use strict'; +const app = express(); +const port = process.env.PORT || 3000; -const express = require('express'); +// Configurar EJS +app.set('view engine', 'ejs'); +app.set('views', path.join(__dirname, 'views')); -// Constants -const PORT = 3000; -const HOST = '0.0.0.0'; +// Middlewares +app.use(express.urlencoded({ extended: true })); +app.use(express.static(path.join(__dirname, 'public'))); -// App -const app = express(); -app.get('/', (req, res) => { - res.send('Hello remote world!\n'); +// Rota principal - Listar alunos (READ) +app.get('/', async (req, res) => { + try { + // Busca dados no Supabase (ordena por id) + const { data: alunos, error } = await supabase + .from('alunos') + .select('*') + .order('id', { ascending: true }); + + if (error) throw error; + + res.render('index', { + titulo: 'Gestão Escolar (Supabase)', + alunos: alunos || [] + }); + } catch (error) { + console.error('Erro ao buscar alunos:', error.message); + res.status(500).send('Erro interno do servidor'); + } +}); + +// Rota para o formulário de cadastro +app.get('/novo', (req, res) => { + res.render('formulario', { + titulo: 'Cadastrar Aluno', + aluno: null // Indica que é um novo cadastro + }); }); -app.listen(PORT, HOST); -console.log(`Running on http://${HOST}:${PORT}`); \ No newline at end of file +// Rota para o formulário de edição +app.get('/editar/:id', async (req, res) => { + try { + const id = req.params.id; + + // Busca o aluno específico + const { data, error } = await supabase + .from('alunos') + .select('*') + .eq('id', id) + .single(); // Retorna apenas um objeto, não um array + + if (error) throw error; + if (!data) return res.status(404).send('Aluno não encontrado'); + + res.render('formulario', { + titulo: 'Editar Aluno', + aluno: data // Passa os dados do aluno para preencher o formulário + }); + } catch (error) { + console.error('Erro ao buscar aluno:', error.message); + res.status(500).send('Erro interno do servidor'); + } +}); + +// Rota para processar cadastro/edição (CREATE / UPDATE) +app.post('/salvar', async (req, res) => { + try { + const { id, nome, email, curso } = req.body; + + // Prepara os dados + const dadosAluno = { nome, email, curso }; + + if (id) { + // Se tem ID, é uma edição (UPDATE) + const { error } = await supabase + .from('alunos') + .update(dadosAluno) + .eq('id', id); + + if (error) throw error; + } else { + // Se não tem ID, é um novo cadastro (CREATE) + const { error } = await supabase + .from('alunos') + .insert([dadosAluno]); + + if (error) throw error; + } + + res.redirect('/'); + } catch (error) { + console.error('Erro ao salvar aluno:', error.message); + res.status(500).send('Erro interno ao salvar os dados'); + } +}); + +// Rota para remover aluno (DELETE) +// Usamos GET aqui para simplificar, pois formulários HTML padrão só suportam GET/POST +// Em uma API real, usaríamos o método DELETE +app.get('/deletar/:id', async (req, res) => { + try { + const id = req.params.id; + + const { error } = await supabase + .from('alunos') + .delete() + .eq('id', id); + + if (error) throw error; + + res.redirect('/'); + } catch (error) { + console.error('Erro ao deletar aluno:', error.message); + res.status(500).send('Erro interno ao deletar'); + } +}); + +// Iniciar servidor +app.listen(port, () => { + console.log(`🚀 Servidor (Supabase CRUD) rodando em http://localhost:${port}`); +}); diff --git a/views/formulario.ejs b/views/formulario.ejs new file mode 100644 index 00000000..2e17dde0 --- /dev/null +++ b/views/formulario.ejs @@ -0,0 +1,77 @@ + + + + + + <%= titulo %> + + + +
+
+

Gestão Escolar Supabase DB

+
+
+ +
+
+

<%= titulo %>

+

+ <% if (aluno) { %> + Atualize os dados do aluno abaixo. + <% } else { %> + Preencha os dados para salvar no banco de dados Supabase. + <% } %> +

+ +
+ + <% if (aluno) { %> + + <% } %> + +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + Voltar +
+
+
+
+ + diff --git a/views/index.ejs b/views/index.ejs new file mode 100644 index 00000000..207a9910 --- /dev/null +++ b/views/index.ejs @@ -0,0 +1,60 @@ + + + + + + <%= titulo %> + + + +
+
+

Gestão Escolar Supabase DB

+
+
+ +
+
+
+

Lista de Alunos (Banco de Dados Real)

+ + Novo Aluno +
+ +

Estes dados estão sendo buscados diretamente do banco de dados PostgreSQL no Supabase.

+ + <% if (alunos && alunos.length > 0) { %> + + + + + + + + + + + + <% alunos.forEach(function(aluno) { %> + + + + + + + + <% }); %> + +
IDNomeEmailCursoAções
<%= aluno.id %><%= aluno.nome %><%= aluno.email || 'Não informado' %><%= aluno.curso %> + Editar + Excluir +
+ <% } else { %> +
+

Nenhum aluno encontrado no banco de dados.

+

Cadastre o primeiro aluno para testar o sistema!

+
+ <% } %> +
+
+ + From a3cd89088ef72bef253fd36b147586344026fd85 Mon Sep 17 00:00:00 2001 From: Antonio-Angelo Date: Thu, 30 Apr 2026 20:19:32 +0000 Subject: [PATCH 2/2] aaaa --- .gitignore | 1 + .tables | 0 .vscode/launch.json | 2 +- README.md | 61 +- SELECT | 0 config/dbClient.js | 25 + config/supabaseClient.js | 17 - index.js | 161 +-- package-lock.json | 2108 ++++++++++++++++++++++++------- package.json | 20 +- public/tooplate-forge-script.js | 220 ++++ public/tooplate-forge-style.css | 1933 ++++++++++++++++++++++++++++ scripts/seed.js | 25 + server.js | 127 -- views/cadastro.html | 148 +++ views/formulario.ejs | 77 -- views/index.ejs | 60 - views/index.html | 503 ++++++++ 18 files changed, 4635 insertions(+), 853 deletions(-) create mode 100644 .tables create mode 100644 SELECT create mode 100644 config/dbClient.js delete mode 100644 config/supabaseClient.js create mode 100644 public/tooplate-forge-script.js create mode 100644 public/tooplate-forge-style.css create mode 100644 scripts/seed.js delete mode 100644 server.js create mode 100644 views/cadastro.html delete mode 100644 views/formulario.ejs delete mode 100644 views/index.ejs create mode 100644 views/index.html diff --git a/.gitignore b/.gitignore index 2e8157a9..3fc1f191 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ node_modules/ .env *.log +data/*.sqlite diff --git a/.tables b/.tables new file mode 100644 index 00000000..e69de29b diff --git a/.vscode/launch.json b/.vscode/launch.json index 179ed34f..73b7a5cd 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -8,7 +8,7 @@ "type": "node", "request": "launch", "name": "Launch Program", - "program": "${workspaceFolder}/server.js" + "program": "${workspaceFolder}/index.js" } ] } \ No newline at end of file diff --git a/README.md b/README.md index ae8be6cc..3e05fbf7 100644 --- a/README.md +++ b/README.md @@ -1,42 +1,25 @@ -# Projeto 3: CRUD Completo com Supabase +# Projeto 3: CRUD Completo com SQLite Este é o projeto final e mais avançado do Guia de Revisão Backend com Node.js. -Ele une tudo o que aprendemos (Express, EJS) e adiciona persistência de dados real usando um banco de dados PostgreSQL hospedado no **Supabase**. +Ele une tudo o que aprendemos (Express, HTML estático) e adiciona persistência de dados local usando SQLite. ## 🎯 Objetivos de Aprendizado -- Conectar uma aplicação Node.js a um banco de dados real em nuvem -- Usar variáveis de ambiente (`.env`) para proteger credenciais sensíveis +- Conectar uma aplicação Node.js a um banco de dados local SQLite +- Usar variáveis de ambiente (`.env`) para definir o caminho do banco - Implementar as 4 operações fundamentais de banco de dados (CRUD): - **C**reate (Inserir dados) - **R**ead (Ler/Listar dados) - **U**pdate (Atualizar dados existentes) - **D**elete (Remover dados) -- Reutilizar views EJS (um único formulário para criar e editar) +- Criar uma interface estática responsiva com o template Forge +- Usar fetch para conectar o frontend à API REST do backend - Lidar com operações assíncronas (`async/await`) no Express -## ⚙️ Pré-requisitos (Configuração do Supabase) - -Para este projeto funcionar, você precisa de uma conta no Supabase: - -1. Crie uma conta em [supabase.com](https://supabase.com) -2. Crie um novo projeto e vá no "SQL Editor" -3. Execute o seguinte código SQL para criar a tabela necessária: - ```sql - CREATE TABLE alunos ( - id SERIAL PRIMARY KEY, - nome TEXT NOT NULL, - email TEXT, - curso TEXT NOT NULL, - created_at TIMESTAMP WITH TIME ZONE DEFAULT TIMEZONE('utc'::text, NOW()) - ); - ``` -4. Vá em "Project Settings" > "API" e copie sua `Project URL` e `anon public key` -5. Crie um arquivo `.env` na raiz desta pasta com as credenciais: - ```env - SUPABASE_URL=sua_url_aqui - SUPABASE_ANON_KEY=sua_chave_aqui - PORT=3000 - ``` +## ⚙️ Pré-requisitos (SQLite) + +Para este projeto funcionar, você só precisa ter o Node.js instalado. O arquivo SQLite será criado automaticamente em `data/database.sqlite`. + +Se quiser reiniciar o banco de dados, exclua o arquivo `data/database.sqlite` e rode novamente. ## 🚀 Como Executar @@ -45,17 +28,25 @@ Para este projeto funcionar, você precisa de uma conta no Supabase: ```bash npm install ``` -3. Certifique-se de que o arquivo `.env` foi criado com suas credenciais! +3. Certifique-se de que o arquivo `.env` existe e contenha `SQLITE_FILE` e `PORT`. 4. Inicie o servidor: ```bash npm start ``` 5. Abra no navegador: `http://localhost:3000` +6. Para popular o banco com dados de exemplo: + ```bash + npm run seed + ``` + ## 📁 Estrutura do Projeto -- `index.js`: Servidor e rotas CRUD -- `config/supabaseClient.js`: Configuração de conexão com o banco -- `views/`: - - `index.ejs`: Lista de alunos buscando do banco - - `formulario.ejs`: View inteligente que serve tanto para novo cadastro quanto para edição -- `.env`: Arquivo (que você deve criar) com as chaves secretas da API +- `index.js`: Servidor e rotas REST CRUD +- `config/dbClient.js`: Configuração do banco SQLite local +- `scripts/seed.js`: Script para criar registros de teste na tabela `alunos` +- `views/index.html`: Página inicial do template Forge +- `views/cadastro.html`: Segunda tela de cadastro do template Forge +- `public/tooplate-forge-style.css`: CSS do template Forge +- `public/tooplate-forge-script.js`: JavaScript do template Forge +- `.env`: Configurações de ambiente, incluindo `SQLITE_FILE` e `PORT` + diff --git a/SELECT b/SELECT new file mode 100644 index 00000000..e69de29b diff --git a/config/dbClient.js b/config/dbClient.js new file mode 100644 index 00000000..2d8c4a16 --- /dev/null +++ b/config/dbClient.js @@ -0,0 +1,25 @@ +const sqlite3 = require('sqlite3').verbose(); +const { open } = require('sqlite'); +const path = require('path'); +require('dotenv').config(); + +const dbFile = process.env.SQLITE_FILE || path.join(__dirname, '..', 'data', 'database.sqlite'); + +const dbPromise = open({ + filename: dbFile, + driver: sqlite3.Database, +}); + +(async () => { + const db = await dbPromise; + await db.exec(` + CREATE TABLE IF NOT EXISTS alunos ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + nome TEXT NOT NULL, + email TEXT NOT NULL, + curso TEXT NOT NULL + ); + `); +})(); + +module.exports = dbPromise; diff --git a/config/supabaseClient.js b/config/supabaseClient.js deleted file mode 100644 index 29f7b4c9..00000000 --- a/config/supabaseClient.js +++ /dev/null @@ -1,17 +0,0 @@ -const { createClient } = require('@supabase/supabase-js'); -require('dotenv').config(); - -// Verifica se as variáveis de ambiente existem -const supabaseUrl = process.env.SUPABASE_URL; -const supabaseKey = process.env.SUPABASE_ANON_KEY; - -if (!supabaseUrl || !supabaseKey) { - console.error('❌ ERRO: Faltando SUPABASE_URL ou SUPABASE_ANON_KEY no arquivo .env'); - console.log('Crie um arquivo .env na raiz do projeto com as suas credenciais do Supabase.'); - // Em produção, você pode querer lançar um erro ou encerrar a aplicação -} - -// Cria o cliente do Supabase -const supabase = createClient(supabaseUrl || 'https://dummy.supabase.co', supabaseKey || 'dummy-key'); - -module.exports = supabase; diff --git a/index.js b/index.js index e6896fe9..6a9aa369 100644 --- a/index.js +++ b/index.js @@ -1,127 +1,104 @@ require('dotenv').config(); const express = require('express'); const path = require('path'); -const supabase = require('./config/supabaseClient'); +const dbPromise = require('./config/dbClient'); const app = express(); const port = process.env.PORT || 3000; -// Configurar EJS -app.set('view engine', 'ejs'); -app.set('views', path.join(__dirname, 'views')); - -// Middlewares -app.use(express.urlencoded({ extended: true })); +app.use(express.json()); app.use(express.static(path.join(__dirname, 'public'))); -// Rota principal - Listar alunos (READ) -app.get('/', async (req, res) => { +app.get('/', (req, res) => { + res.sendFile(path.join(__dirname, 'views', 'index.html')); +}); + +app.get('/cadastro', (req, res) => { + res.sendFile(path.join(__dirname, 'views', 'cadastro.html')); +}); + +app.get('/api/alunos', async (req, res) => { try { - // Busca dados no Supabase (ordena por id) - const { data: alunos, error } = await supabase - .from('alunos') - .select('*') - .order('id', { ascending: true }); - - if (error) throw error; - - res.render('index', { - titulo: 'Gestão Escolar (Supabase)', - alunos: alunos || [] - }); + const db = await dbPromise; + const alunos = await db.all('SELECT * FROM alunos ORDER BY id ASC'); + res.json(alunos || []); } catch (error) { - console.error('Erro ao buscar alunos:', error.message); - res.status(500).send('Erro interno do servidor'); + console.error('Erro ao listar alunos:', error.message); + res.status(500).json({ error: 'Erro interno do servidor' }); } }); -// Rota para o formulário de cadastro -app.get('/novo', (req, res) => { - res.render('formulario', { - titulo: 'Cadastrar Aluno', - aluno: null // Indica que é um novo cadastro - }); +app.get('/api/alunos/:id', async (req, res) => { + try { + const { id } = req.params; + const db = await dbPromise; + const aluno = await db.get('SELECT * FROM alunos WHERE id = ?', [id]); + + if (!aluno) return res.status(404).json({ error: 'Aluno não encontrado' }); + res.json(aluno); + } catch (error) { + console.error('Erro ao buscar aluno:', error.message); + res.status(500).json({ error: 'Erro interno do servidor' }); + } }); -// Rota para o formulário de edição -app.get('/editar/:id', async (req, res) => { +app.post('/api/alunos', async (req, res) => { try { - const id = req.params.id; - - // Busca o aluno específico - const { data, error } = await supabase - .from('alunos') - .select('*') - .eq('id', id) - .single(); // Retorna apenas um objeto, não um array - - if (error) throw error; - if (!data) return res.status(404).send('Aluno não encontrado'); - - res.render('formulario', { - titulo: 'Editar Aluno', - aluno: data // Passa os dados do aluno para preencher o formulário - }); + const { nome, email, curso } = req.body; + if (!nome || !email || !curso) { + return res.status(400).json({ error: 'nome, email e curso são obrigatórios' }); + } + + const db = await dbPromise; + const result = await db.run( + 'INSERT INTO alunos (nome, email, curso) VALUES (?, ?, ?)', + [nome, email, curso] + ); + const aluno = await db.get('SELECT * FROM alunos WHERE id = ?', [result.lastID]); + + res.status(201).json(aluno); } catch (error) { - console.error('Erro ao buscar aluno:', error.message); - res.status(500).send('Erro interno do servidor'); + console.error('Erro ao criar aluno:', error.message); + res.status(500).json({ error: 'Erro interno ao salvar os dados' }); } }); -// Rota para processar cadastro/edição (CREATE / UPDATE) -app.post('/salvar', async (req, res) => { +app.put('/api/alunos/:id', async (req, res) => { try { - const { id, nome, email, curso } = req.body; - - // Prepara os dados - const dadosAluno = { nome, email, curso }; - - if (id) { - // Se tem ID, é uma edição (UPDATE) - const { error } = await supabase - .from('alunos') - .update(dadosAluno) - .eq('id', id); - - if (error) throw error; - } else { - // Se não tem ID, é um novo cadastro (CREATE) - const { error } = await supabase - .from('alunos') - .insert([dadosAluno]); - - if (error) throw error; + const { id } = req.params; + const { nome, email, curso } = req.body; + if (!nome || !email || !curso) { + return res.status(400).json({ error: 'nome, email e curso são obrigatórios' }); } - - res.redirect('/'); + + const db = await dbPromise; + const result = await db.run( + 'UPDATE alunos SET nome = ?, email = ?, curso = ? WHERE id = ?', + [nome, email, curso, id] + ); + + if (result.changes === 0) return res.status(404).json({ error: 'Aluno não encontrado' }); + res.json({ message: 'Aluno atualizado com sucesso' }); } catch (error) { - console.error('Erro ao salvar aluno:', error.message); - res.status(500).send('Erro interno ao salvar os dados'); + console.error('Erro ao atualizar aluno:', error.message); + res.status(500).json({ error: 'Erro interno ao atualizar' }); } }); -// Rota para remover aluno (DELETE) -// Usamos GET aqui para simplificar, pois formulários HTML padrão só suportam GET/POST -// Em uma API real, usaríamos o método DELETE -app.get('/deletar/:id', async (req, res) => { +app.delete('/api/alunos/:id', async (req, res) => { try { - const id = req.params.id; - - const { error } = await supabase - .from('alunos') - .delete() - .eq('id', id); - - if (error) throw error; - - res.redirect('/'); + const { id } = req.params; + const db = await dbPromise; + const result = await db.run('DELETE FROM alunos WHERE id = ?', [id]); + + if (result.changes === 0) return res.status(404).json({ error: 'Aluno não encontrado' }); + res.json({ message: 'Aluno deletado com sucesso' }); } catch (error) { console.error('Erro ao deletar aluno:', error.message); - res.status(500).send('Erro interno ao deletar'); + res.status(500).json({ error: 'Erro interno ao deletar' }); } }); -// Iniciar servidor app.listen(port, () => { - console.log(`🚀 Servidor (Supabase CRUD) rodando em http://localhost:${port}`); + console.log(`🚀 Aplicação rodando em http://localhost:${port}`); }); diff --git a/package-lock.json b/package-lock.json index 03fd19d5..62107bb6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,160 +1,141 @@ { - "name": "projeto3-crud-supabase", + "name": "projeto3-crud-sqlite", "version": "1.0.0", "lockfileVersion": 3, "requires": true, "packages": { "": { - "name": "projeto3-crud-supabase", + "name": "projeto3-crud-sqlite", "version": "1.0.0", "license": "ISC", "dependencies": { - "@supabase/supabase-js": "^2.39.0", "dotenv": "^16.3.1", - "ejs": "^3.1.9", - "express": "^4.18.2" + "express": "^4.18.2", + "sqlite": "^4.1.0", + "sqlite3": "^5.1.6" }, - "devDependencies": { - "supabase": "^2.95.6" - } - }, - "node_modules/@isaacs/fs-minipass": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@isaacs/fs-minipass/-/fs-minipass-4.0.1.tgz", - "integrity": "sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w==", - "dev": true, - "license": "ISC", - "dependencies": { - "minipass": "^7.0.4" - }, - "engines": { - "node": ">=18.0.0" - } + "devDependencies": {} }, - "node_modules/@supabase/auth-js": { - "version": "2.78.0", - "resolved": "https://registry.npmjs.org/@supabase/auth-js/-/auth-js-2.78.0.tgz", - "integrity": "sha512-cXDtu1U0LeZj/xfnFoV7yCze37TcbNo8FCxy1FpqhMbB9u9QxxDSW6pA5gm/07Ei7m260Lof4CZx67Cu6DPeig==", + "node_modules/@gar/promisify": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@gar/promisify/-/promisify-1.1.3.tgz", + "integrity": "sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==", "license": "MIT", - "dependencies": { - "@supabase/node-fetch": "2.6.15", - "tslib": "2.8.1" - } + "optional": true }, - "node_modules/@supabase/functions-js": { - "version": "2.78.0", - "resolved": "https://registry.npmjs.org/@supabase/functions-js/-/functions-js-2.78.0.tgz", - "integrity": "sha512-t1jOvArBsOINyqaRee1xJ3gryXLvkBzqnKfi6q3YRzzhJbGS6eXz0pXR5fqmJeB01fLC+1njpf3YhMszdPEF7g==", - "license": "MIT", + "node_modules/@npmcli/fs": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-1.1.1.tgz", + "integrity": "sha512-8KG5RD0GVP4ydEzRn/I4BNDuxDtqVbOdm8675T49OIG/NGhaK0pjPX7ZcDlvKYbA+ulvVK3ztfcF4uBdOxuJbQ==", + "license": "ISC", + "optional": true, "dependencies": { - "@supabase/node-fetch": "2.6.15", - "tslib": "2.8.1" + "@gar/promisify": "^1.0.1", + "semver": "^7.3.5" } }, - "node_modules/@supabase/node-fetch": { - "version": "2.6.15", - "resolved": "https://registry.npmjs.org/@supabase/node-fetch/-/node-fetch-2.6.15.tgz", - "integrity": "sha512-1ibVeYUacxWYi9i0cf5efil6adJ9WRyZBLivgjs+AUpewx1F3xPi7gLgaASI2SmIQxPoCEjAsLAzKPgMJVgOUQ==", + "node_modules/@npmcli/move-file": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@npmcli/move-file/-/move-file-1.1.2.tgz", + "integrity": "sha512-1SUf/Cg2GzGDyaf15aR9St9TWlb+XvbZXWpDx8YKs7MLzMH/BCeopv+y9vzrzgkfykCGuWOlSu3mZhj2+FQcrg==", + "deprecated": "This functionality has been moved to @npmcli/fs", "license": "MIT", + "optional": true, "dependencies": { - "whatwg-url": "^5.0.0" + "mkdirp": "^1.0.4", + "rimraf": "^3.0.2" }, "engines": { - "node": "4.x || >=6.0.0" + "node": ">=10" } }, - "node_modules/@supabase/postgrest-js": { - "version": "2.78.0", - "resolved": "https://registry.npmjs.org/@supabase/postgrest-js/-/postgrest-js-2.78.0.tgz", - "integrity": "sha512-AwhpYlSvJ+PSnPmIK8sHj7NGDyDENYfQGKrMtpVIEzQA2ApUjgpUGxzXWN4Z0wEtLQsvv7g4y9HVad9Hzo1TNA==", + "node_modules/@tootallnate/once": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", + "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==", "license": "MIT", - "dependencies": { - "@supabase/node-fetch": "2.6.15", - "tslib": "2.8.1" + "optional": true, + "engines": { + "node": ">= 6" } }, - "node_modules/@supabase/realtime-js": { - "version": "2.78.0", - "resolved": "https://registry.npmjs.org/@supabase/realtime-js/-/realtime-js-2.78.0.tgz", - "integrity": "sha512-rCs1zmLe7of7hj4s7G9z8rTqzWuNVtmwDr3FiCRCJFawEoa+RQO1xpZGbdeuVvVmKDyVN6b542Okci+117y/LQ==", - "license": "MIT", - "dependencies": { - "@supabase/node-fetch": "2.6.15", - "@types/phoenix": "^1.6.6", - "@types/ws": "^8.18.1", - "tslib": "2.8.1", - "ws": "^8.18.2" - } + "node_modules/abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", + "license": "ISC", + "optional": true }, - "node_modules/@supabase/storage-js": { - "version": "2.78.0", - "resolved": "https://registry.npmjs.org/@supabase/storage-js/-/storage-js-2.78.0.tgz", - "integrity": "sha512-n17P0JbjHOlxqJpkaGFOn97i3EusEKPEbWOpuk1r4t00Wg06B8Z4GUiq0O0n1vUpjiMgJUkLIMuBVp+bEgunzQ==", + "node_modules/accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", "license": "MIT", "dependencies": { - "@supabase/node-fetch": "2.6.15", - "tslib": "2.8.1" + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + }, + "engines": { + "node": ">= 0.6" } }, - "node_modules/@supabase/supabase-js": { - "version": "2.78.0", - "resolved": "https://registry.npmjs.org/@supabase/supabase-js/-/supabase-js-2.78.0.tgz", - "integrity": "sha512-xYMRNBFmKp2m1gMuwcp/gr/HlfZKqjye1Ib8kJe29XJNsgwsfO/f8skxnWiscFKTlkOKLuBexNgl5L8dzGt6vA==", + "node_modules/agentkeepalive": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.6.0.tgz", + "integrity": "sha512-kja8j7PjmncONqaTsB8fQ+wE2mSU2DJ9D4XKoJ5PFWIdRMa6SLSN1ff4mOr4jCbfRSsxR4keIiySJU0N9T5hIQ==", "license": "MIT", + "optional": true, "dependencies": { - "@supabase/auth-js": "2.78.0", - "@supabase/functions-js": "2.78.0", - "@supabase/node-fetch": "2.6.15", - "@supabase/postgrest-js": "2.78.0", - "@supabase/realtime-js": "2.78.0", - "@supabase/storage-js": "2.78.0" + "humanize-ms": "^1.2.1" + }, + "engines": { + "node": ">= 8.0.0" } }, - "node_modules/@types/node": { - "version": "25.6.0", - "resolved": "https://registry.npmjs.org/@types/node/-/node-25.6.0.tgz", - "integrity": "sha512-+qIYRKdNYJwY3vRCZMdJbPLJAtGjQBudzZzdzwQYkEPQd+PJGixUL5QfvCLDaULoLv+RhT3LDkwEfKaAkgSmNQ==", + "node_modules/aggregate-error": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", + "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", "license": "MIT", + "optional": true, "dependencies": { - "undici-types": "~7.19.0" + "clean-stack": "^2.0.0", + "indent-string": "^4.0.0" + }, + "engines": { + "node": ">=8" } }, - "node_modules/@types/phoenix": { - "version": "1.6.7", - "resolved": "https://registry.npmjs.org/@types/phoenix/-/phoenix-1.6.7.tgz", - "integrity": "sha512-oN9ive//QSBkf19rfDv45M7eZPi0eEXylht2OLEXicu5b4KoQ1OzXIw+xDSGWxSxe1JmepRR/ZH283vsu518/Q==", - "license": "MIT" - }, - "node_modules/@types/ws": { - "version": "8.18.1", - "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.18.1.tgz", - "integrity": "sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg==", + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "license": "MIT", - "dependencies": { - "@types/node": "*" + "optional": true, + "engines": { + "node": ">=8" } }, - "node_modules/accepts": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", - "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", - "license": "MIT", + "node_modules/aproba": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.1.0.tgz", + "integrity": "sha512-tLIEcj5GuR2RSTnxNKdkK0dJ/GrC7P38sUkiDmDuHfsHmbagTFAxDVIBltoklXEVIQ/f14IL8IMJ5pn9Hez1Ew==", + "license": "ISC", + "optional": true + }, + "node_modules/are-we-there-yet": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-3.0.1.tgz", + "integrity": "sha512-QZW4EDmGwlYur0Yyf/b2uGucHQMa8aFUP7eu9ddR73vvhFyt4V0Vl3QHPcTNJ8l6qYOBdxgXdnBXQrHilfRQBg==", + "deprecated": "This package is no longer supported.", + "license": "ISC", + "optional": true, "dependencies": { - "mime-types": "~2.1.34", - "negotiator": "0.6.3" + "delegates": "^1.0.0", + "readable-stream": "^3.6.0" }, "engines": { - "node": ">= 0.6" - } - }, - "node_modules/agent-base": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-9.0.0.tgz", - "integrity": "sha512-TQf59BsZnytt8GdJKLPfUZ54g/iaUL2OWDSFCCvMOhsHduDQxO8xC4PNeyIkVcA5KwL2phPSv0douC0fgWzmnA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 20" + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, "node_modules/array-flatten": { @@ -163,33 +144,51 @@ "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==", "license": "MIT" }, - "node_modules/async": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/async/-/async-3.2.6.tgz", - "integrity": "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==", - "license": "MIT" - }, "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "license": "MIT", + "optional": true + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], "license": "MIT" }, - "node_modules/bin-links": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/bin-links/-/bin-links-6.0.0.tgz", - "integrity": "sha512-X4CiKlcV2GjnCMwnKAfbVWpHa++65th9TuzAEYtZoATiOE2DQKhSp4CJlyLoTqdhBKlXjpXjCTYPNNFS33Fi6w==", - "dev": true, - "license": "ISC", + "node_modules/bindings": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "license": "MIT", "dependencies": { - "cmd-shim": "^8.0.0", - "npm-normalize-package-bin": "^5.0.0", - "proc-log": "^6.0.0", - "read-cmd-shim": "^6.0.0", - "write-file-atomic": "^7.0.0" - }, - "engines": { - "node": "^20.17.0 || >=22.9.0" + "file-uri-to-path": "1.0.0" + } + }, + "node_modules/bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "license": "MIT", + "dependencies": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" } }, "node_modules/body-parser": { @@ -231,13 +230,28 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/brace-expansion": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.0.tgz", - "integrity": "sha512-TN1kCZAgdgweJhWWpgKYrQaMNHcDULHkWwQIspdtjV4Y5aurRdZpjAqn6yX3FPqTA9ngHCc4hJxMAMgGfve85w==", + "node_modules/buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], "license": "MIT", "dependencies": { - "balanced-match": "^1.0.0" + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" } }, "node_modules/bytes": { @@ -249,6 +263,109 @@ "node": ">= 0.8" } }, + "node_modules/cacache": { + "version": "15.3.0", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-15.3.0.tgz", + "integrity": "sha512-VVdYzXEn+cnbXpFgWs5hTT7OScegHVmLhJIR8Ufqk3iFD6A6j5iSX1KuBTfNEv4tdJWE2PzA6IVFtcLC7fN9wQ==", + "license": "ISC", + "optional": true, + "dependencies": { + "@npmcli/fs": "^1.0.0", + "@npmcli/move-file": "^1.0.1", + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "glob": "^7.1.4", + "infer-owner": "^1.0.4", + "lru-cache": "^6.0.0", + "minipass": "^3.1.1", + "minipass-collect": "^1.0.2", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.2", + "mkdirp": "^1.0.3", + "p-map": "^4.0.0", + "promise-inflight": "^1.0.1", + "rimraf": "^3.0.2", + "ssri": "^8.0.1", + "tar": "^6.0.2", + "unique-filename": "^1.1.1" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/cacache/node_modules/chownr": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", + "license": "ISC", + "optional": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/cacache/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "license": "ISC", + "optional": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cacache/node_modules/minizlib": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", + "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "license": "MIT", + "optional": true, + "dependencies": { + "minipass": "^3.0.0", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/cacache/node_modules/tar": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz", + "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==", + "deprecated": "Old versions of tar are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", + "license": "ISC", + "optional": true, + "dependencies": { + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^5.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/cacache/node_modules/tar/node_modules/minipass": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "license": "ISC", + "optional": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/cacache/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "license": "ISC", + "optional": true + }, "node_modules/call-bind-apply-helpers": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", @@ -278,26 +395,40 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/chownr": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-3.0.0.tgz", - "integrity": "sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==", - "dev": true, - "license": "BlueOak-1.0.0", + "node_modules/clean-stack": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", + "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", + "license": "MIT", + "optional": true, "engines": { - "node": ">=18" + "node": ">=6" } }, - "node_modules/cmd-shim": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/cmd-shim/-/cmd-shim-8.0.0.tgz", - "integrity": "sha512-Jk/BK6NCapZ58BKUxlSI+ouKRbjH1NLZCgJkYoab+vEHUY3f6OzpNBN9u7HFSv9J6TRDGs4PLOHezoKGaFRSCA==", - "dev": true, + "node_modules/color-support": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", + "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", "license": "ISC", - "engines": { - "node": "^20.17.0 || >=22.9.0" + "optional": true, + "bin": { + "color-support": "bin.js" } }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "license": "MIT", + "optional": true + }, + "node_modules/console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==", + "license": "ISC", + "optional": true + }, "node_modules/content-disposition": { "version": "0.5.4", "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", @@ -334,16 +465,6 @@ "integrity": "sha512-NXdYc3dLr47pBkpUCHtKSwIOQXLVn8dZEuywboCOJY/osA0wFSLlSawr3KN8qXJEyX66FcONTH8EIlVuK0yyFA==", "license": "MIT" }, - "node_modules/data-uri-to-buffer": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz", - "integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 12" - } - }, "node_modules/debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", @@ -353,6 +474,37 @@ "ms": "2.0.0" } }, + "node_modules/decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "license": "MIT", + "dependencies": { + "mimic-response": "^3.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "license": "MIT", + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==", + "license": "MIT", + "optional": true + }, "node_modules/depd": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", @@ -372,6 +524,15 @@ "npm": "1.2.8000 || >= 1.4.16" } }, + "node_modules/detect-libc": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", + "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", + "license": "Apache-2.0", + "engines": { + "node": ">=8" + } + }, "node_modules/dotenv": { "version": "16.6.1", "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.6.1.tgz", @@ -404,20 +565,12 @@ "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", "license": "MIT" }, - "node_modules/ejs": { - "version": "3.1.10", - "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.10.tgz", - "integrity": "sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA==", - "license": "Apache-2.0", - "dependencies": { - "jake": "^10.8.5" - }, - "bin": { - "ejs": "bin/cli.js" - }, - "engines": { - "node": ">=0.10.0" - } + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "license": "MIT", + "optional": true }, "node_modules/encodeurl": { "version": "2.0.0", @@ -428,6 +581,55 @@ "node": ">= 0.8" } }, + "node_modules/encoding": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz", + "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==", + "license": "MIT", + "optional": true, + "dependencies": { + "iconv-lite": "^0.6.2" + } + }, + "node_modules/encoding/node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "license": "MIT", + "optional": true, + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/end-of-stream": { + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.5.tgz", + "integrity": "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==", + "license": "MIT", + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/env-paths": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", + "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/err-code": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/err-code/-/err-code-2.0.3.tgz", + "integrity": "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==", + "license": "MIT", + "optional": true + }, "node_modules/es-define-property": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", @@ -473,6 +675,15 @@ "node": ">= 0.6" } }, + "node_modules/expand-template": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", + "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==", + "license": "(MIT OR WTFPL)", + "engines": { + "node": ">=6" + } + }, "node_modules/express": { "version": "4.22.1", "resolved": "https://registry.npmjs.org/express/-/express-4.22.1.tgz", @@ -519,38 +730,11 @@ "url": "https://opencollective.com/express" } }, - "node_modules/fetch-blob": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz", - "integrity": "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/jimmywarting" - }, - { - "type": "paypal", - "url": "https://paypal.me/jimmywarting" - } - ], - "license": "MIT", - "dependencies": { - "node-domexception": "^1.0.0", - "web-streams-polyfill": "^3.0.3" - }, - "engines": { - "node": "^12.20 || >= 14.13" - } - }, - "node_modules/filelist": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.6.tgz", - "integrity": "sha512-5giy2PkLYY1cP39p17Ech+2xlpTRL9HLspOfEgm0L6CwBXBTgsK5ou0JtzYuepxkaQ/tvhCFIJ5uXo0OrM2DxA==", - "license": "Apache-2.0", - "dependencies": { - "minimatch": "^5.0.1" - } + "node_modules/file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", + "license": "MIT" }, "node_modules/finalhandler": { "version": "1.3.2", @@ -570,19 +754,6 @@ "node": ">= 0.8" } }, - "node_modules/formdata-polyfill": { - "version": "4.0.10", - "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz", - "integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==", - "dev": true, - "license": "MIT", - "dependencies": { - "fetch-blob": "^3.1.2" - }, - "engines": { - "node": ">=12.20.0" - } - }, "node_modules/forwarded": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", @@ -601,15 +772,86 @@ "node": ">= 0.6" } }, - "node_modules/function-bind": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", - "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node_modules/fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==", + "license": "MIT" + }, + "node_modules/fs-minipass": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "license": "ISC", + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" } }, + "node_modules/fs-minipass/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/fs-minipass/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "license": "ISC" + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "license": "ISC", + "optional": true + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/gauge": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-4.0.4.tgz", + "integrity": "sha512-f9m+BEN5jkg6a0fZjleidjN51VE1X+mPFQ2DJ0uv1V39oCLCbsGe6yjbBnp7eK7z/+GAon99a3nHuqbuuthyPg==", + "deprecated": "This package is no longer supported.", + "license": "ISC", + "optional": true, + "dependencies": { + "aproba": "^1.0.3 || ^2.0.0", + "color-support": "^1.1.3", + "console-control-strings": "^1.1.0", + "has-unicode": "^2.0.1", + "signal-exit": "^3.0.7", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1", + "wide-align": "^1.1.5" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/gauge/node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "license": "ISC", + "optional": true + }, "node_modules/get-intrinsic": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", @@ -647,6 +889,58 @@ "node": ">= 0.4" } }, + "node_modules/github-from-package": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", + "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==", + "license": "MIT" + }, + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", + "license": "ISC", + "optional": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob/node_modules/brace-expansion": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.14.tgz", + "integrity": "sha512-MWPGfDxnyzKU7rNOW9SP/c50vi3xrmrua/+6hfPbCS2ABNWfx24vPidzvC7krjU/RTo235sV776ymlsMtGKj8g==", + "license": "MIT", + "optional": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/glob/node_modules/minimatch": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", + "license": "ISC", + "optional": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, "node_modules/gopd": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", @@ -659,6 +953,13 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "license": "ISC", + "optional": true + }, "node_modules/has-symbols": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", @@ -671,6 +972,13 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==", + "license": "ISC", + "optional": true + }, "node_modules/hasown": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.3.tgz", @@ -683,6 +991,13 @@ "node": ">= 0.4" } }, + "node_modules/http-cache-semantics": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.2.0.tgz", + "integrity": "sha512-dTxcvPXqPvXBQpq5dUr6mEMJX4oIEFv6bwom3FDwKRDsuIjjJGANqhBuoAn9c1RQJIdAKav33ED65E2ys+87QQ==", + "license": "BSD-2-Clause", + "optional": true + }, "node_modules/http-errors": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.1.tgz", @@ -703,26 +1018,40 @@ "url": "https://opencollective.com/express" } }, - "node_modules/https-proxy-agent": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-9.0.0.tgz", - "integrity": "sha512-/MVmHp58WkOypgFhCLk4fzpPcFQvTJ/e6LBI7irpIO2HfxUbpmYoHF+KzipzJpxxzJu7aJNWQ0xojJ/dzV2G5g==", - "dev": true, + "node_modules/http-proxy-agent": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz", + "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==", "license": "MIT", + "optional": true, "dependencies": { - "agent-base": "9.0.0", - "debug": "^4.3.4" + "@tootallnate/once": "1", + "agent-base": "6", + "debug": "4" }, "engines": { - "node": ">= 20" + "node": ">= 6" } }, - "node_modules/https-proxy-agent/node_modules/debug": { + "node_modules/http-proxy-agent/node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "license": "MIT", + "optional": true, + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/http-proxy-agent/node_modules/debug": { "version": "4.4.3", "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", - "dev": true, "license": "MIT", + "optional": true, "dependencies": { "ms": "^2.1.3" }, @@ -735,12 +1064,22 @@ } } }, - "node_modules/https-proxy-agent/node_modules/ms": { + "node_modules/http-proxy-agent/node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true, - "license": "MIT" + "license": "MIT", + "optional": true + }, + "node_modules/humanize-ms": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz", + "integrity": "sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==", + "license": "MIT", + "optional": true, + "dependencies": { + "ms": "^2.0.0" + } }, "node_modules/iconv-lite": { "version": "0.4.24", @@ -754,12 +1093,87 @@ "node": ">=0.10.0" } }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "BSD-3-Clause" + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/infer-owner": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz", + "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==", + "license": "ISC", + "optional": true + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", + "license": "ISC", + "optional": true, + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, "node_modules/inherits": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", "license": "ISC" }, + "node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", + "license": "ISC" + }, + "node_modules/ip-address": { + "version": "10.1.1", + "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.1.1.tgz", + "integrity": "sha512-1FMu8/N15Ck1BL551Jf42NYIoin2unWjLQ2Fze/DXryJRl5twqtwNHlO39qERGbIOcKYWHdgRryhOC+NG4eaLw==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">= 12" + } + }, "node_modules/ipaddr.js": { "version": "1.9.1", "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", @@ -769,23 +1183,150 @@ "node": ">= 0.10" } }, - "node_modules/jake": { - "version": "10.9.4", - "resolved": "https://registry.npmjs.org/jake/-/jake-10.9.4.tgz", - "integrity": "sha512-wpHYzhxiVQL+IV05BLE2Xn34zW1S223hvjtqk0+gsPrwd/8JNLXJgZZM/iPFsYc1xyphF+6M6EvdE5E9MBGkDA==", - "license": "Apache-2.0", + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-lambda": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-lambda/-/is-lambda-1.0.1.tgz", + "integrity": "sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==", + "license": "MIT", + "optional": true + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "license": "ISC", + "optional": true + }, + "node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "license": "ISC", + "optional": true, "dependencies": { - "async": "^3.2.6", - "filelist": "^1.0.4", - "picocolors": "^1.1.1" - }, - "bin": { - "jake": "bin/cli.js" + "yallist": "^4.0.0" }, "engines": { "node": ">=10" } }, + "node_modules/lru-cache/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "license": "ISC", + "optional": true + }, + "node_modules/make-fetch-happen": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-9.1.0.tgz", + "integrity": "sha512-+zopwDy7DNknmwPQplem5lAZX/eCOzSvSNNcSKm5eVwTkOBzoktEfXsa9L23J/GIRhxRsaxzkPEhrJEpE2F4Gg==", + "license": "ISC", + "optional": true, + "dependencies": { + "agentkeepalive": "^4.1.3", + "cacache": "^15.2.0", + "http-cache-semantics": "^4.1.0", + "http-proxy-agent": "^4.0.1", + "https-proxy-agent": "^5.0.0", + "is-lambda": "^1.0.1", + "lru-cache": "^6.0.0", + "minipass": "^3.1.3", + "minipass-collect": "^1.0.2", + "minipass-fetch": "^1.3.2", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "negotiator": "^0.6.2", + "promise-retry": "^2.0.1", + "socks-proxy-agent": "^6.0.0", + "ssri": "^8.0.0" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/make-fetch-happen/node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "license": "MIT", + "optional": true, + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/make-fetch-happen/node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "license": "MIT", + "optional": true, + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/make-fetch-happen/node_modules/https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "license": "MIT", + "optional": true, + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/make-fetch-happen/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "license": "ISC", + "optional": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/make-fetch-happen/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT", + "optional": true + }, + "node_modules/make-fetch-happen/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "license": "ISC", + "optional": true + }, "node_modules/math-intrinsics": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", @@ -855,47 +1396,241 @@ "node": ">= 0.6" } }, - "node_modules/minimatch": { - "version": "5.1.9", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.9.tgz", - "integrity": "sha512-7o1wEA2RyMP7Iu7GNba9vc0RWWGACJOCZBJX2GJWip0ikV+wcOsgVuY9uE8CPiyQhkGFSlhuSkZPavN7u1c2Fw==", + "node_modules/mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/minipass-collect": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-1.0.2.tgz", + "integrity": "sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==", + "license": "ISC", + "optional": true, + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/minipass-collect/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", "license": "ISC", + "optional": true, "dependencies": { - "brace-expansion": "^2.0.1" + "yallist": "^4.0.0" }, "engines": { - "node": ">=10" + "node": ">=8" } }, - "node_modules/minipass": { - "version": "7.1.3", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.3.tgz", - "integrity": "sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==", - "dev": true, - "license": "BlueOak-1.0.0", + "node_modules/minipass-collect/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "license": "ISC", + "optional": true + }, + "node_modules/minipass-fetch": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-1.4.1.tgz", + "integrity": "sha512-CGH1eblLq26Y15+Azk7ey4xh0J/XfJfrCox5LDJiKqI2Q2iwOLOKrlmIaODiSQS8d18jalF6y2K2ePUm0CmShw==", + "license": "MIT", + "optional": true, + "dependencies": { + "minipass": "^3.1.0", + "minipass-sized": "^1.0.3", + "minizlib": "^2.0.0" + }, "engines": { - "node": ">=16 || 14 >=14.17" + "node": ">=8" + }, + "optionalDependencies": { + "encoding": "^0.1.12" } }, - "node_modules/minizlib": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-3.1.0.tgz", - "integrity": "sha512-KZxYo1BUkWD2TVFLr0MQoM8vUUigWD3LlD83a/75BqC+4qE0Hb1Vo5v1FgcfaNXvfXzr+5EhQ6ing/CaBijTlw==", - "dev": true, + "node_modules/minipass-fetch/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "license": "ISC", + "optional": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-fetch/node_modules/minizlib": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", + "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", "license": "MIT", + "optional": true, "dependencies": { - "minipass": "^7.1.2" + "minipass": "^3.0.0", + "yallist": "^4.0.0" }, "engines": { - "node": ">= 18" + "node": ">= 8" + } + }, + "node_modules/minipass-fetch/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "license": "ISC", + "optional": true + }, + "node_modules/minipass-flush": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/minipass-flush/-/minipass-flush-1.0.7.tgz", + "integrity": "sha512-TbqTz9cUwWyHS2Dy89P3ocAGUGxKjjLuR9z8w4WUTGAVgEj17/4nhgo2Du56i0Fm3Pm30g4iA8Lcqctc76jCzA==", + "license": "BlueOak-1.0.0", + "optional": true, + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" } }, + "node_modules/minipass-flush/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "license": "ISC", + "optional": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-flush/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "license": "ISC", + "optional": true + }, + "node_modules/minipass-pipeline": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz", + "integrity": "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==", + "license": "ISC", + "optional": true, + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-pipeline/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "license": "ISC", + "optional": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-pipeline/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "license": "ISC", + "optional": true + }, + "node_modules/minipass-sized": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/minipass-sized/-/minipass-sized-1.0.3.tgz", + "integrity": "sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g==", + "license": "ISC", + "optional": true, + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-sized/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "license": "ISC", + "optional": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-sized/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "license": "ISC", + "optional": true + }, + "node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "license": "MIT", + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/mkdirp-classic": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", + "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==", + "license": "MIT" + }, "node_modules/ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", "license": "MIT" }, + "node_modules/napi-build-utils": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-2.0.0.tgz", + "integrity": "sha512-GEbrYkbfF7MoNaoh2iGG84Mnf/WZfB0GdGEsM8wz7Expx/LlWf5U8t9nvJKXSp3qr5IsEbK04cBGhol/KwOsWA==", + "license": "MIT" + }, "node_modules/negotiator": { "version": "0.6.3", "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", @@ -905,54 +1640,153 @@ "node": ">= 0.6" } }, - "node_modules/node-domexception": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz", - "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==", - "deprecated": "Use your platform's native DOMException instead", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/jimmywarting" - }, - { - "type": "github", - "url": "https://paypal.me/jimmywarting" - } - ], + "node_modules/node-abi": { + "version": "3.89.0", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.89.0.tgz", + "integrity": "sha512-6u9UwL0HlAl21+agMN3YAMXcKByMqwGx+pq+P76vii5f7hTPtKDp08/H9py6DY+cfDw7kQNTGEj/rly3IgbNQA==", + "license": "MIT", + "dependencies": { + "semver": "^7.3.5" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/node-addon-api": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.1.1.tgz", + "integrity": "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==", + "license": "MIT" + }, + "node_modules/node-gyp": { + "version": "8.4.1", + "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-8.4.1.tgz", + "integrity": "sha512-olTJRgUtAb/hOXG0E93wZDs5YiJlgbXxTwQAFHyNlRsXQnYzUaF2aGgujZbw+hR8aF4ZG/rST57bWMWD16jr9w==", "license": "MIT", + "optional": true, + "dependencies": { + "env-paths": "^2.2.0", + "glob": "^7.1.4", + "graceful-fs": "^4.2.6", + "make-fetch-happen": "^9.1.0", + "nopt": "^5.0.0", + "npmlog": "^6.0.0", + "rimraf": "^3.0.2", + "semver": "^7.3.5", + "tar": "^6.1.2", + "which": "^2.0.2" + }, + "bin": { + "node-gyp": "bin/node-gyp.js" + }, + "engines": { + "node": ">= 10.12.0" + } + }, + "node_modules/node-gyp/node_modules/chownr": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", + "license": "ISC", + "optional": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/node-gyp/node_modules/minipass": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "license": "ISC", + "optional": true, "engines": { - "node": ">=10.5.0" + "node": ">=8" } }, - "node_modules/node-fetch": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz", - "integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==", - "dev": true, + "node_modules/node-gyp/node_modules/minizlib": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", + "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", "license": "MIT", + "optional": true, "dependencies": { - "data-uri-to-buffer": "^4.0.0", - "fetch-blob": "^3.1.4", - "formdata-polyfill": "^4.0.10" + "minipass": "^3.0.0", + "yallist": "^4.0.0" }, "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + "node": ">= 8" + } + }, + "node_modules/node-gyp/node_modules/minizlib/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "license": "ISC", + "optional": true, + "dependencies": { + "yallist": "^4.0.0" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/node-fetch" + "engines": { + "node": ">=8" } }, - "node_modules/npm-normalize-package-bin": { + "node_modules/node-gyp/node_modules/tar": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz", + "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==", + "deprecated": "Old versions of tar are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", + "license": "ISC", + "optional": true, + "dependencies": { + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^5.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/node-gyp/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "license": "ISC", + "optional": true + }, + "node_modules/nopt": { "version": "5.0.0", - "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-5.0.0.tgz", - "integrity": "sha512-CJi3OS4JLsNMmr2u07OJlhcrPxCeOeP/4xq67aWNai6TNWWbTrlNDgl8NcFKVlcBKp18GPj+EzbNIgrBfZhsag==", - "dev": true, + "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", + "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==", + "license": "ISC", + "optional": true, + "dependencies": { + "abbrev": "1" + }, + "bin": { + "nopt": "bin/nopt.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/npmlog": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-6.0.2.tgz", + "integrity": "sha512-/vBvz5Jfr9dT/aFWd0FIRf+T/Q2WBsLENygUaFUqstqsycmZAP/t5BvFJTK0viFmSUxiUKTUplWy5vt+rvKIxg==", + "deprecated": "This package is no longer supported.", "license": "ISC", + "optional": true, + "dependencies": { + "are-we-there-yet": "^3.0.0", + "console-control-strings": "^1.1.0", + "gauge": "^4.0.3", + "set-blocking": "^2.0.0" + }, "engines": { - "node": "^20.17.0 || >=22.9.0" + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, "node_modules/object-inspect": { @@ -979,6 +1813,31 @@ "node": ">= 0.8" } }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "license": "ISC", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/p-map": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", + "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", + "license": "MIT", + "optional": true, + "dependencies": { + "aggregate-error": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/parseurl": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", @@ -988,26 +1847,68 @@ "node": ">= 0.8" } }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/path-to-regexp": { "version": "0.1.13", "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.13.tgz", "integrity": "sha512-A/AGNMFN3c8bOlvV9RreMdrv7jsmF9XIfDeCd87+I8RNg6s78BhJxMu69NEMHBSJFxKidViTEdruRwEk/WIKqA==", "license": "MIT" }, - "node_modules/picocolors": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", - "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", - "license": "ISC" + "node_modules/prebuild-install": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.3.tgz", + "integrity": "sha512-8Mf2cbV7x1cXPUILADGI3wuhfqWvtiLA1iclTDbFRZkgRQS0NqsPZphna9V+HyTEadheuPmjaJMsbzKQFOzLug==", + "deprecated": "No longer maintained. Please contact the author of the relevant native addon; alternatives are available.", + "license": "MIT", + "dependencies": { + "detect-libc": "^2.0.0", + "expand-template": "^2.0.3", + "github-from-package": "0.0.0", + "minimist": "^1.2.3", + "mkdirp-classic": "^0.5.3", + "napi-build-utils": "^2.0.0", + "node-abi": "^3.3.0", + "pump": "^3.0.0", + "rc": "^1.2.7", + "simple-get": "^4.0.0", + "tar-fs": "^2.0.0", + "tunnel-agent": "^0.6.0" + }, + "bin": { + "prebuild-install": "bin.js" + }, + "engines": { + "node": ">=10" + } }, - "node_modules/proc-log": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/proc-log/-/proc-log-6.1.0.tgz", - "integrity": "sha512-iG+GYldRf2BQ0UDUAd6JQ/RwzaQy6mXmsk/IzlYyal4A4SNFw54MeH4/tLkF4I5WoWG9SQwuqWzS99jaFQHBuQ==", - "dev": true, + "node_modules/promise-inflight": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", + "integrity": "sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g==", "license": "ISC", + "optional": true + }, + "node_modules/promise-retry": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-2.0.1.tgz", + "integrity": "sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==", + "license": "MIT", + "optional": true, + "dependencies": { + "err-code": "^2.0.2", + "retry": "^0.12.0" + }, "engines": { - "node": "^20.17.0 || >=22.9.0" + "node": ">=10" } }, "node_modules/proxy-addr": { @@ -1023,6 +1924,16 @@ "node": ">= 0.10" } }, + "node_modules/pump": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.4.tgz", + "integrity": "sha512-VS7sjc6KR7e1ukRFhQSY5LM2uBWAUPiOPa/A3mkKmiMwSmRFUITt0xuj+/lesgnCv+dPIEYlkzrcyXgquIHMcA==", + "license": "MIT", + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, "node_modules/qs": { "version": "6.14.2", "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.2.tgz", @@ -1062,14 +1973,60 @@ "node": ">= 0.8" } }, - "node_modules/read-cmd-shim": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/read-cmd-shim/-/read-cmd-shim-6.0.0.tgz", - "integrity": "sha512-1zM5HuOfagXCBWMN83fuFI/x+T/UhZ7k+KIzhrHXcQoeX5+7gmaDYjELQHmmzIodumBHeByBJT4QYS7ufAgs7A==", - "dev": true, - "license": "ISC", + "node_modules/rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "license": "(BSD-2-Clause OR MIT OR Apache-2.0)", + "dependencies": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "bin": { + "rc": "cli.js" + } + }, + "node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/retry": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", + "integrity": "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==", + "license": "MIT", + "optional": true, "engines": { - "node": "^20.17.0 || >=22.9.0" + "node": ">= 4" + } + }, + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", + "license": "ISC", + "optional": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, "node_modules/safe-buffer": { @@ -1098,6 +2055,18 @@ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", "license": "MIT" }, + "node_modules/semver": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", + "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/send": { "version": "0.19.2", "resolved": "https://registry.npmjs.org/send/-/send-0.19.2.tgz", @@ -1143,6 +2112,13 @@ "node": ">= 0.8.0" } }, + "node_modules/set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", + "license": "ISC", + "optional": true + }, "node_modules/setprototypeof": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", @@ -1221,19 +2197,260 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/signal-exit": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", - "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", - "dev": true, + "node_modules/simple-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", + "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/simple-get": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz", + "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "decompress-response": "^6.0.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" + } + }, + "node_modules/smart-buffer": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", + "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">= 6.0.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/socks": { + "version": "2.8.8", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.8.tgz", + "integrity": "sha512-NlGELfPrgX2f1TAAcz0WawlLn+0r3FyhhCRpFFK2CemXenPYvzMWWZINv3eDNo9ucdwme7oCHRY0Jnbs4aIkog==", + "license": "MIT", + "optional": true, + "dependencies": { + "ip-address": "^10.1.1", + "smart-buffer": "^4.2.0" + }, + "engines": { + "node": ">= 10.0.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/socks-proxy-agent": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-6.2.1.tgz", + "integrity": "sha512-a6KW9G+6B3nWZ1yB8G7pJwL3ggLy1uTzKAgCb7ttblwqdz9fMGJUuTy3uFzEP48FAs9FLILlmzDlE2JJhVQaXQ==", + "license": "MIT", + "optional": true, + "dependencies": { + "agent-base": "^6.0.2", + "debug": "^4.3.3", + "socks": "^2.6.2" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/socks-proxy-agent/node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "license": "MIT", + "optional": true, + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/socks-proxy-agent/node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "license": "MIT", + "optional": true, + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/socks-proxy-agent/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT", + "optional": true + }, + "node_modules/sqlite": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/sqlite/-/sqlite-4.2.1.tgz", + "integrity": "sha512-Tll0Ndvnwkuv5Hn6WIbh26rZiYQORuH1t5m/or9LUpSmDmmyFG89G9fKrSeugMPxwmEIXoVxqTun4LbizTs4uw==", + "license": "MIT" + }, + "node_modules/sqlite3": { + "version": "5.1.7", + "resolved": "https://registry.npmjs.org/sqlite3/-/sqlite3-5.1.7.tgz", + "integrity": "sha512-GGIyOiFaG+TUra3JIfkI/zGP8yZYLPQ0pl1bH+ODjiX57sPhrLU5sQJn1y9bDKZUFYkX1crlrPfSYt0BKKdkog==", + "hasInstallScript": true, + "license": "BSD-3-Clause", + "dependencies": { + "bindings": "^1.5.0", + "node-addon-api": "^7.0.0", + "prebuild-install": "^7.1.1", + "tar": "^6.1.11" + }, + "optionalDependencies": { + "node-gyp": "8.x" + }, + "peerDependencies": { + "node-gyp": "8.x" + }, + "peerDependenciesMeta": { + "node-gyp": { + "optional": true + } + } + }, + "node_modules/sqlite3/node_modules/chownr": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", + "license": "ISC", + "engines": { + "node": ">=10" + } + }, + "node_modules/sqlite3/node_modules/minipass": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", "license": "ISC", "engines": { - "node": ">=14" + "node": ">=8" + } + }, + "node_modules/sqlite3/node_modules/minizlib": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", + "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "license": "MIT", + "dependencies": { + "minipass": "^3.0.0", + "yallist": "^4.0.0" }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "engines": { + "node": ">= 8" + } + }, + "node_modules/sqlite3/node_modules/minizlib/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/sqlite3/node_modules/tar": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz", + "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==", + "deprecated": "Old versions of tar are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", + "license": "ISC", + "dependencies": { + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^5.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/sqlite3/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "license": "ISC" + }, + "node_modules/ssri": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-8.0.1.tgz", + "integrity": "sha512-97qShzy1AiyxvPNIkLWoGua7xoQzzPjQ0HAH4B0rWKo7SZ6USuPcrUiAFrws0UH8RrbWmgq3LMTObhPIHbbBeQ==", + "license": "ISC", + "optional": true, + "dependencies": { + "minipass": "^3.1.1" + }, + "engines": { + "node": ">= 8" } }, + "node_modules/ssri/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "license": "ISC", + "optional": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/ssri/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "license": "ISC", + "optional": true + }, "node_modules/statuses": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz", @@ -1243,41 +2460,84 @@ "node": ">= 0.8" } }, - "node_modules/supabase": { - "version": "2.95.6", - "resolved": "https://registry.npmjs.org/supabase/-/supabase-2.95.6.tgz", - "integrity": "sha512-gjAT6wYBvmKoS34IjpTp9VDve1sfwcM/s+Q5rJA3OBw8d6nVTdA8edYVz/rfPEMt1V/EY40g63IL6qMBLPvrFw==", - "dev": true, - "hasInstallScript": true, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "license": "MIT", + "optional": true, "dependencies": { - "bin-links": "^6.0.0", - "https-proxy-agent": "^9.0.0", - "node-fetch": "^3.3.2", - "tar": "7.5.13" + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" }, - "bin": { - "supabase": "bin/supabase" + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "license": "MIT", + "optional": true, + "dependencies": { + "ansi-regex": "^5.0.1" }, "engines": { - "npm": ">=8" + "node": ">=8" } }, - "node_modules/tar": { - "version": "7.5.13", - "resolved": "https://registry.npmjs.org/tar/-/tar-7.5.13.tgz", - "integrity": "sha512-tOG/7GyXpFevhXVh8jOPJrmtRpOTsYqUIkVdVooZYJS/z8WhfQUX8RJILmeuJNinGAMSu1veBr4asSHFt5/hng==", - "dev": true, - "license": "BlueOak-1.0.0", + "node_modules/strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/tar-fs": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.4.tgz", + "integrity": "sha512-mDAjwmZdh7LTT6pNleZ05Yt65HC3E+NiQzl672vQG38jIrehtJk/J3mNwIg+vShQPcLF/LV7CMnDW6vjj6sfYQ==", + "license": "MIT", + "dependencies": { + "chownr": "^1.1.1", + "mkdirp-classic": "^0.5.2", + "pump": "^3.0.0", + "tar-stream": "^2.1.4" + } + }, + "node_modules/tar-fs/node_modules/chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", + "license": "ISC" + }, + "node_modules/tar-stream": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "license": "MIT", "dependencies": { - "@isaacs/fs-minipass": "^4.0.0", - "chownr": "^3.0.0", - "minipass": "^7.1.2", - "minizlib": "^3.1.0", - "yallist": "^5.0.0" + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" }, "engines": { - "node": ">=18" + "node": ">=6" } }, "node_modules/toidentifier": { @@ -1289,17 +2549,17 @@ "node": ">=0.6" } }, - "node_modules/tr46": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", - "license": "MIT" - }, - "node_modules/tslib": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", - "license": "0BSD" + "node_modules/tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", + "license": "Apache-2.0", + "dependencies": { + "safe-buffer": "^5.0.1" + }, + "engines": { + "node": "*" + } }, "node_modules/type-is": { "version": "1.6.18", @@ -1314,11 +2574,25 @@ "node": ">= 0.6" } }, - "node_modules/undici-types": { - "version": "7.19.2", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.19.2.tgz", - "integrity": "sha512-qYVnV5OEm2AW8cJMCpdV20CDyaN3g0AjDlOGf1OW4iaDEx8MwdtChUp4zu4H0VP3nDRF/8RKWH+IPp9uW0YGZg==", - "license": "MIT" + "node_modules/unique-filename": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz", + "integrity": "sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==", + "license": "ISC", + "optional": true, + "dependencies": { + "unique-slug": "^2.0.0" + } + }, + "node_modules/unique-slug": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.2.tgz", + "integrity": "sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w==", + "license": "ISC", + "optional": true, + "dependencies": { + "imurmurhash": "^0.1.4" + } }, "node_modules/unpipe": { "version": "1.0.0", @@ -1329,6 +2603,12 @@ "node": ">= 0.8" } }, + "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==", + "license": "MIT" + }, "node_modules/utils-merge": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", @@ -1347,75 +2627,37 @@ "node": ">= 0.8" } }, - "node_modules/web-streams-polyfill": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz", - "integrity": "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 8" - } - }, - "node_modules/webidl-conversions": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", - "license": "BSD-2-Clause" - }, - "node_modules/whatwg-url": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", - "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", - "license": "MIT", - "dependencies": { - "tr46": "~0.0.3", - "webidl-conversions": "^3.0.0" - } - }, - "node_modules/write-file-atomic": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-7.0.1.tgz", - "integrity": "sha512-OTIk8iR8/aCRWBqvxrzxR0hgxWpnYBblY1S5hDWBQfk/VFmJwzmJgQFN3WsoUKHISv2eAwe+PpbUzyL1CKTLXg==", - "dev": true, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", "license": "ISC", + "optional": true, "dependencies": { - "signal-exit": "^4.0.1" + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" }, "engines": { - "node": "^20.17.0 || >=22.9.0" + "node": ">= 8" } }, - "node_modules/ws": { - "version": "8.20.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.20.0.tgz", - "integrity": "sha512-sAt8BhgNbzCtgGbt2OxmpuryO63ZoDk/sqaB/znQm94T4fCEsy/yV+7CdC1kJhOU9lboAEU7R3kquuycDoibVA==", - "license": "MIT", - "engines": { - "node": ">=10.0.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": ">=5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } + "node_modules/wide-align": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", + "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", + "license": "ISC", + "optional": true, + "dependencies": { + "string-width": "^1.0.2 || 2 || 3 || 4" } }, - "node_modules/yallist": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-5.0.0.tgz", - "integrity": "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==", - "dev": true, - "license": "BlueOak-1.0.0", - "engines": { - "node": ">=18" - } + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "license": "ISC" } } } diff --git a/package.json b/package.json index 0c2a54ba..56f0c16e 100644 --- a/package.json +++ b/package.json @@ -1,28 +1,26 @@ { - "name": "projeto3-crud-supabase", + "name": "projeto3-crud-sqlite", "version": "1.0.0", - "description": "CRUD completo com Express, EJS e Supabase (PostgreSQL)", + "description": "CRUD completo com Express e SQLite", "main": "index.js", "scripts": { "start": "node index.js", - "dev": "node --watch index.js" + "dev": "node --watch index.js", + "seed": "node scripts/seed.js" }, "keywords": [ "node", "express", - "ejs", - "supabase", + "sqlite", "crud" ], "author": "", "license": "ISC", "dependencies": { - "@supabase/supabase-js": "^2.39.0", "dotenv": "^16.3.1", - "ejs": "^3.1.9", - "express": "^4.18.2" + "express": "^4.18.2", + "sqlite": "^4.1.0", + "sqlite3": "^5.1.6" }, - "devDependencies": { - "supabase": "^2.95.6" - } + "devDependencies": {} } diff --git a/public/tooplate-forge-script.js b/public/tooplate-forge-script.js new file mode 100644 index 00000000..92a541ef --- /dev/null +++ b/public/tooplate-forge-script.js @@ -0,0 +1,220 @@ +/* JavaScript Document + +Tooplate 2158 Forge Reality + +https://www.tooplate.com/view/2158-forge-reality + +*/ + +// Smooth scrolling for navigation links +document.querySelectorAll('a[href^="#"]').forEach(anchor => { + anchor.addEventListener('click', function (e) { + if (this.getAttribute('href').startsWith('#')) { + e.preventDefault(); + const target = document.querySelector(this.getAttribute('href')); + if (target) { + target.scrollIntoView({ + behavior: 'smooth', + block: 'start' + }); + } + } + }); +}); + +// Active navigation highlighting +const sections = document.querySelectorAll('section'); +const navLinks = document.querySelectorAll('.nav-link'); + +window.addEventListener('scroll', () => { + let current = ''; + sections.forEach(section => { + const sectionTop = section.offsetTop; + const sectionHeight = section.clientHeight; + if (pageYOffset >= (sectionTop - 200)) { + current = section.getAttribute('id'); + } + }); + + navLinks.forEach(link => { + link.classList.remove('active'); + if (link.getAttribute('href').slice(1) === current) { + link.classList.add('active'); + } + }); +}); + +// Navigation background on scroll +window.addEventListener('scroll', function() { + const nav = document.querySelector('nav'); + if (nav) { + if (window.scrollY > 50) { + nav.style.background = 'rgba(10, 10, 10, 0.98)'; + } else { + nav.style.background = 'linear-gradient(180deg, rgba(10,10,10,0.95) 0%, rgba(10,10,10,0.8) 100%)'; + } + } +}); + +// Parallax effect for hero backgrounds +window.addEventListener('scroll', function() { + const heroBackgrounds = document.querySelector('.hero-backgrounds'); + if (heroBackgrounds) { + const scrolled = window.pageYOffset; + heroBackgrounds.style.transform = `translateY(${scrolled * 0.5}px)`; + } +}); + +// Mobile menu toggle +const menuToggle = document.querySelector('.menu-toggle'); +const navLinks2 = document.querySelector('.nav-links'); + +if (menuToggle && navLinks2) { + menuToggle.addEventListener('click', function() { + navLinks2.classList.toggle('active'); + this.classList.toggle('active'); + }); +} + +// Pricing Toggle Functionality +const pricingToggle = document.getElementById('pricing-toggle'); +const monthlyLabel = document.getElementById('monthly-label'); +const yearlyLabel = document.getElementById('yearly-label'); +const priceAmounts = document.querySelectorAll('.price-amount'); +const pricePeriods = document.querySelectorAll('.price-period'); + +if (pricingToggle) { + pricingToggle.addEventListener('click', function() { + this.classList.toggle('yearly'); + if (this.classList.contains('yearly')) { + monthlyLabel.classList.remove('active'); + yearlyLabel.classList.add('active'); + priceAmounts.forEach(price => { + const monthlyPrice = parseInt(price.getAttribute('data-monthly')); + const yearlyPrice = Math.round(monthlyPrice * 12 * 0.80); + price.textContent = yearlyPrice.toLocaleString(); + }); + pricePeriods.forEach(period => { + period.textContent = '/anual'; + }); + } else { + monthlyLabel.classList.add('active'); + yearlyLabel.classList.remove('active'); + priceAmounts.forEach(price => { + const monthlyPrice = price.getAttribute('data-monthly'); + price.textContent = monthlyPrice; + }); + pricePeriods.forEach(period => { + period.textContent = '/mensal'; + }); + } + }); +} + +// Remove loading bar after page load +window.addEventListener('load', function() { + const loadingBar = document.querySelector('.loading-bar'); + if (loadingBar) { + setTimeout(() => { + loadingBar.style.display = 'none'; + }, 1200); + } +}); + +const track = document.querySelector('.testimonial-track'); +const slides = document.querySelectorAll('.testimonial-card'); +const nextBtn = document.querySelector('.next'); +const prevBtn = document.querySelector('.prev'); +const dotsContainer = document.querySelector('.slider-dots'); + +let index = 0; + +if (track && dotsContainer && slides.length > 0) { + slides.forEach((_, i) => { + const dot = document.createElement('span'); + dot.addEventListener('click', () => goToSlide(i)); + dotsContainer.appendChild(dot); + }); + + const dots = document.querySelectorAll('.slider-dots span'); + + function updateSlider() { + track.style.transform = `translateX(-${index * 100}%)`; + dots.forEach(dot => dot.classList.remove('active')); + dots[index].classList.add('active'); + } + + function goToSlide(i) { + index = i; + updateSlider(); + } + + nextBtn?.addEventListener('click', () => { + index = (index + 1) % slides.length; + updateSlider(); + }); + + prevBtn?.addEventListener('click', () => { + index = (index - 1 + slides.length) % slides.length; + updateSlider(); + }); + + setInterval(() => { + index = (index + 1) % slides.length; + updateSlider(); + }, 4000); + + updateSlider(); +} + +const animatedElements = document.querySelectorAll('.fade-left, .fade-right'); + +function showOnScroll() { + const trigger = window.innerHeight * 0.85; + animatedElements.forEach(el => { + const top = el.getBoundingClientRect().top; + if (top < trigger) { + el.classList.add('show'); + } + }); +} + +window.addEventListener('scroll', showOnScroll); + +const registrationForm = document.querySelector('#registration-form'); +const registrationNotice = document.querySelector('#registration-notice'); + +if (registrationForm) { + registrationForm.addEventListener('submit', async event => { + event.preventDefault(); + const formData = new FormData(registrationForm); + const data = { + nome: formData.get('nome'), + email: formData.get('email'), + curso: formData.get('curso'), + }; + + registrationNotice.textContent = 'Enviando...'; + registrationNotice.className = 'form-notice'; + + try { + const response = await fetch('/api/alunos', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify(data), + }); + if (!response.ok) { + const errorData = await response.json(); + throw new Error(errorData.error || 'Erro ao enviar o cadastro.'); + } + registrationNotice.textContent = 'Cadastro realizado com sucesso!'; + registrationNotice.classList.add('success'); + registrationForm.reset(); + } catch (error) { + registrationNotice.textContent = error.message; + registrationNotice.classList.add('error'); + } + }); +} diff --git a/public/tooplate-forge-style.css b/public/tooplate-forge-style.css new file mode 100644 index 00000000..accc411c --- /dev/null +++ b/public/tooplate-forge-style.css @@ -0,0 +1,1933 @@ +/* CSS Document + +Tooplate 2158 Forge Reality + +https://www.tooplate.com/view/2158-forge-reality + +*/ + +* { + margin: 0; + padding: 0; + box-sizing: border-box; +} + +:root { + /* Industrial Brutalist Color Palette */ + --black: #0A0A0A; + --concrete: #2C2C2C; + --steel: #404040; + --industrial-red: #E63946; + --industrial-orange: #FF6B35; + --light-gray: #A8A8A8; + --white: #F5F5F5; + --border: #1A1A1A; +} + +/* Typography */ +body { + /*font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;*/ + font-family: 'Poppins', sans-serif; + background-color: var(--black); + color: var(--white); + line-height: 1.6; + overflow-x: hidden; +} + +h1, h2, h3, h4, h5, h6 { + font-family: 'Bebas Neue', 'Impact', sans-serif; + font-weight: 400; + letter-spacing: 0.05em; + text-transform: uppercase; +} + +h1 { font-size: clamp(3rem, 8vw, 6rem); } +h2 { font-size: clamp(2rem, 5vw, 3.5rem); } +h3 { font-size: clamp(1.5rem, 3vw, 2rem); } + +p { + font-size: 1rem; + line-height: 1.8; + color: var(--light-gray); +} + +.container { + max-width: 1400px; + margin: 0 auto; + padding: 0 2rem; +} + +/* Navigation */ +nav { + position: fixed; + top: 0; + width: 100%; + background: linear-gradient(180deg, rgba(10,10,10,0.95) 0%, rgba(10,10,10,0.8) 100%); + backdrop-filter: blur(10px); + border-bottom: 1px solid var(--border); + z-index: 1000; + transition: all 0.3s ease; +} + +.nav-container { + display: flex; + justify-content: space-between; + align-items: center; + padding: 1rem 2rem; + max-width: 1400px; + margin: 0 auto; +} + +.logo { + display: flex; + align-items: center; + gap: 0.75rem; + font-size: 1.75rem; + font-weight: 900; + color: var(--industrial-red); + text-decoration: none; + letter-spacing: -0.02em; + transition: all 0.3s ease; + cursor: pointer; +} + +.logo svg { + width: 35px; + height: 35px; +} + +.logo:hover { + color: var(--industrial-orange); + transform: translateY(-2px); +} + +.logo:hover svg path { + fill: var(--industrial-orange); +} + +.nav-links { + display: flex; + list-style: none; + gap: 0; +} + +/* Mobile Navigation Styles */ +@media (max-width: 768px) { + .nav-links { + display: none; + position: fixed; + top: 70px; + left: 0; + right: 0; + background: var(--black); + flex-direction: column; + padding: 2rem 0; + border-bottom: 2px solid var(--industrial-red); + z-index: 999; + } + + .nav-links.active { + display: flex; + } + + .nav-links a { + padding: 1rem 2rem; + border-bottom: 1px solid var(--border); + } + + .nav-links a:hover { + background: var(--industrial-red); + } + + .menu-toggle.active span:nth-child(1) { + transform: rotate(45deg) translate(5px, 5px); + } + + .menu-toggle.active span:nth-child(2) { + opacity: 0; + } + + .menu-toggle.active span:nth-child(3) { + transform: rotate(-45deg) translate(7px, -6px); + } +} + +.nav-links li { + position: relative; +} + +.nav-links a { + color: var(--white); + text-decoration: none; + font-weight: 500; + text-transform: uppercase; + font-size: 0.85rem; + letter-spacing: 0.1em; + padding: 0.75rem 1.5rem; + display: block; + transition: all 0.3s ease; + position: relative; +} + +.nav-links a:hover { + color: var(--white); + background: var(--industrial-red); +} + +.nav-links a.active { + background: var(--industrial-red); + color: var(--white); +} + +.book-tour-btn { + background: transparent; + color: var(--industrial-red); + padding: 0.75rem 2rem; + text-decoration: none; + font-weight: 600; + text-transform: uppercase; + font-size: 0.85rem; + letter-spacing: 0.1em; + border: 2px solid var(--industrial-red); + cursor: pointer; + transition: all 0.3s ease; + position: relative; + overflow: hidden; +} + +.book-tour-btn:hover { + background: var(--industrial-red); + color: var(--white); + transform: translateY(-2px); +} + +/* Mobile Menu Toggle */ +.menu-toggle { + display: none; + flex-direction: column; + gap: 4px; + cursor: pointer; +} + +.menu-toggle span { + width: 25px; + height: 2px; + background: var(--white); + transition: all 0.3s ease; +} + +/* Hero Section with Rotating Backgrounds */ +.hero { + height: 100vh; + display: flex; + align-items: center; + position: relative; + overflow: hidden; +} +.hero { + background: linear-gradient(rgba(0,0,0,0.6), rgba(0,0,0,0.7)), url(https://i.imgur.com/YJ16wvt.jpeg) center/cover no-repeat; + filter: contrast(110%) brightness(85%); + animation: zoomHero 15s ease-in-out infinite alternate; +} +@keyframes zoomHero { + from { + background-size: 100%; + } + to { + background-size: 110%; + } +} + +.hero-backgrounds { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 120%; /* Extra height for parallax */ + z-index: 0; +} + +.hero-bg { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + opacity: 0; + animation: fadeRotate 9s infinite; + background-size: cover; + background-position: center; + background-attachment: fixed; + transition: transform 0.5s ease-out; +} + +.hero-bg:nth-child(1) { + background: linear-gradient(rgba(10,10,10,0.7), rgba(44,44,44,0.7)), + url('images/toopate-forge-hero-01.jpg'); + background-size: cover; + background-position: center; + background-attachment: fixed; + animation-delay: 0s; +} + +.hero-bg:nth-child(2) { + background: linear-gradient(rgba(10,10,10,0.6), rgba(230,57,70,0.2)), + url('images/toopate-forge-hero-02.jpg'); + background-size: cover; + background-position: center; + background-attachment: fixed; + animation-delay: 3s; +} + +.hero-bg:nth-child(3) { + background: linear-gradient(rgba(10,10,10,0.7), rgba(255,107,53,0.2)), + url('images/toopate-forge-hero-03.jpg'); + background-size: cover; + background-position: center; + background-attachment: fixed; + animation-delay: 6s; +} + +@keyframes fadeRotate { + 0% { + opacity: 0; + transform: scale(1.1); + } + 5% { + opacity: 1; + transform: scale(1); + } + 33.33% { + opacity: 1; + transform: scale(1); + } + 38.33% { + opacity: 0; + transform: scale(0.95); + } + 100% { + opacity: 0; + transform: scale(1.1); + } +} + +@keyframes rotateBackground { + 0%, 33.33% { opacity: 1; } + 33.34%, 100% { opacity: 0; } +} + +.hero::before { + content: ''; + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + background-image: + repeating-linear-gradient(90deg, transparent, transparent 2px, rgba(255,255,255,0.03) 2px, rgba(255,255,255,0.03) 4px), + repeating-linear-gradient(0deg, transparent, transparent 2px, rgba(255,255,255,0.03) 2px, rgba(255,255,255,0.03) 4px); + pointer-events: none; + z-index: 1; +} + +.hero-content { + position: relative; + z-index: 2; +} + +.hero h1 { + margin-bottom: 1rem; + line-height: 0.9; +} + +.hero h1 span { + color: var(--industrial-red); +} + +.hero-subtitle { + font-size: 1.25rem; + color: var(--light-gray); + margin-bottom: 2rem; + text-transform: none; +} + +.hero-subtitle.destaque { + margin-top: 10px; + font-size: 14px; + color: #ff2c2c; + font-weight: 600; +} + +.hero-buttons { + display: flex; + gap: 1rem; + margin-top: 2rem; +} + +.btn-primary { + background: var(--industrial-red); + color: var(--white); + padding: 1rem 2.5rem; + text-decoration: none; + font-weight: 600; + text-transform: uppercase; + letter-spacing: 0.1em; + transition: all 0.3s ease; + border: 2px solid var(--industrial-red); + cursor: pointer; + display: block; + margin-top: 0.5rem; + +} + +.btn-primary:hover { + background: transparent; + transform: translateX(5px); + transform: scale(1.05); + box-shadow: 0 10px 20px rgba(255,0,0,0.4); +} + +.btn-secondary { + background: transparent; + color: var(--white); + padding: 1rem 2.5rem; + text-decoration: none; + font-weight: 600; + text-transform: uppercase; + letter-spacing: 0.1em; + transition: all 0.3s ease; + border: 2px solid var(--steel); +} + +.btn-secondary:hover { + background: var(--steel); + border-color: var(--steel); +} + +/* Features Section */ +.features { + padding: 6rem 0; + background: var(--concrete); + position: relative; +} + +.features::before { + content: ''; + position: absolute; + top: 0; + left: 0; + right: 0; + height: 1px; + background: linear-gradient(90deg, transparent, var(--industrial-red), transparent); +} + +.section-header { + text-align: center; + margin-bottom: 4rem; +} + +.section-header h2 { + margin-bottom: 1rem; +} + +.section-header p { + max-width: 600px; + margin: 0 auto; +} + +.features-grid { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); + gap: 2rem; + margin-top: 3rem; +} + +.feature-card { + background: var(--black); + padding: 2.5rem; + border: 1px solid var(--border); + transition: all 0.3s ease; + position: relative; + overflow: hidden; + clip-path: polygon(0 0, calc(100% - 20px) 0, 100% 20px, 100% 100%, 20px 100%, 0 calc(100% - 20px)); +} + +.feature-card::before { + content: ''; + position: absolute; + top: 0; + left: 0; + width: 4px; + height: 0; + background: var(--industrial-red); + transition: height 0.3s ease; +} + +.feature-card::after { + content: ''; + position: absolute; + top: 0; + right: 0; + width: 20px; + height: 20px; + background: linear-gradient(135deg, transparent 50%, var(--industrial-red) 50%); + transition: all 0.3s ease; + opacity: 0; +} + +.feature-card:hover::before { + height: 100%; +} + +.feature-card:hover::after { + opacity: 1; +} + +.feature-card:hover { + transform: translateY(-5px); + border-color: var(--industrial-red); + background: linear-gradient(135deg, var(--black) 0%, rgba(230,57,70,0.05) 100%); +} + +.feature-icon { + width: 80px; + height: 80px; + background: transparent; + border: 2px solid var(--industrial-red); + margin-bottom: 1.5rem; + display: flex; + align-items: center; + justify-content: center; + font-size: 1.5rem; + font-weight: bold; + color: var(--industrial-red); + position: relative; + transition: all 0.3s ease; + clip-path: polygon(20% 0%, 100% 0%, 80% 100%, 0% 100%); +} + +.feature-icon::before { + content: ''; + position: absolute; + top: -2px; + left: -2px; + right: -2px; + bottom: -2px; + background: var(--industrial-red); + z-index: -1; + opacity: 0; + transition: opacity 0.3s ease; + clip-path: polygon(20% 0%, 100% 0%, 80% 100%, 0% 100%); +} + +.feature-card:hover .feature-icon { + color: var(--white); + transform: rotate(5deg) scale(1.1); +} + +.feature-card:hover .feature-icon::before { + opacity: 1; +} + +.feature-icon.icon-24-7::after { + content: ''; + position: absolute; + width: 100%; + height: 100%; + top: 0; + left: 0; + background: repeating-linear-gradient( + 45deg, + transparent, + transparent 3px, + rgba(230,57,70,0.3) 3px, + rgba(230,57,70,0.3) 6px + ); + z-index: -2; +} + +.feature-card h3 { + margin-bottom: 1rem; + color: var(--white); + position: relative; +} + +.feature-card h3::after { + content: ''; + position: absolute; + bottom: -5px; + left: 0; + width: 30px; + height: 2px; + background: var(--industrial-orange); + transition: width 0.3s ease; +} + +.feature-card:hover h3::after { + width: 60px; +} + +.feature-stats { + display: flex; + justify-content: space-between; + margin-top: 1.5rem; + padding-top: 1rem; + border-top: 1px solid var(--border); +} + +.stat-item { + text-align: center; +} + +.stat-number { + display: block; + font-size: 1.25rem; + font-weight: bold; + color: var(--industrial-red); +} + +.stat-label { + font-size: 0.75rem; + color: var(--light-gray); + text-transform: uppercase; + letter-spacing: 0.1em; +} + +/*about section*/ + +.about-grid { + display: grid; + grid-template-columns: 1fr 1fr; + align-items: center; + gap: 40px; +} + +.about-image img { + width: 100%; + border-radius: 15px; + margin-top: 10px; +} + +@media (max-width: 768px) { + .about-grid { + grid-template-columns: 1fr; + } +} + +/* ESTADO INICIAL */ +.fade-left, +.fade-right { + opacity: 0; + transition: all 0.8s ease; +} + +/* POSIÇÃO INICIAL */ +.fade-left { + transform: translateX(-50px); +} + +.fade-right { + transform: translateX(50px); + transition-delay: 0.2s; +} + +/* QUANDO APARECE */ +.fade-left.show, +.fade-right.show { + opacity: 1; + transform: translateX(0); +} + + + +/* Spaces Section */ +.spaces { + padding: 6rem 0; + background: var(--black); +} + +.spaces-grid { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(350px, 1fr)); + gap: 2rem; + margin-top: 3rem; +} + +.space-card { + position: relative; + height: 400px; + background: var(--concrete); + overflow: hidden; + cursor: pointer; + transition: all 0.3s ease; +} + +.space-image img { + transition: transform 0.4s ease; +} + +.space-card:hover .space-image img { + transform: scale(1.1); +} + +.space-thumbnail { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + background-size: cover; + background-position: center; + transition: transform 0.3s ease; +} + +.space-card:nth-child(1) .space-thumbnail { + background: linear-gradient(rgba(10,10,10,0.4), rgba(10,10,10,0.8)), + url(https://i.imgur.com/zgnHzAt.jpeg); + background-size: cover; + background-position: center; +} + +.space-card:nth-child(2) .space-thumbnail { + background: linear-gradient(rgba(10,10,10,0.4), rgba(10,10,10,0.8)), + url(https://i.imgur.com/LOZouPF.jpeg); + background-size: cover; + background-position: center; +} + +.space-card:nth-child(3) .space-thumbnail { + background: linear-gradient(rgba(10,10,10,0.4), rgba(10,10,10,0.8)), + url(https://i.imgur.com/rpLtLZr.jpeg); + background-size: cover; + background-position: center; +} + +.space-card:nth-child(4) .space-thumbnail { + background: linear-gradient(rgba(10,10,10,0.4), rgba(10,10,10,0.8)), + url(https://i.imgur.com/YYdbwX0.jpeg); + background-size: cover; + background-position: center; +} + +.space-card:nth-child(5) .space-thumbnail { + background: linear-gradient(rgba(10,10,10,0.4), rgba(10,10,10,0.8)), + url(https://i.imgur.com/6vOGOB5.jpeg); + background-size: cover; + background-position: center; +} + +.space-card:nth-child(6) .space-thumbnail { + background: linear-gradient(rgba(10,10,10,0.4), rgba(10,10,10,0.8)), + url(https://i.imgur.com/zQ0hW6g.jpeg); + background-size: cover; + background-position: center; +} + +.space-card::after { + content: ''; + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + background: linear-gradient(180deg, transparent 50%, rgba(10,10,10,0.9) 100%); + transition: all 0.3s ease; +} +.space-image::after { + content: ""; + position: absolute; + inset: 0; + background: rgba(0,0,0,0.4); +} + +.space-card:hover .space-thumbnail { + transform: scale(1.1); +} + +.space-card:hover::after { + background: linear-gradient(180deg, rgba(230,57,70,0.3) 0%, rgba(10,10,10,0.9) 100%); +} + +.space-info { + position: absolute; + bottom: 2rem; + left: 2rem; + right: 2rem; + z-index: 1; +} + +.space-info h3 { + color: var(--white); + margin-bottom: 0.5rem; +} + +.space-info p { + color: var(--light-gray); + margin-bottom: 1rem; +} + +.space-features { + display: flex; + gap: 1rem; + flex-wrap: wrap; +} + +.space-feature-tag { + background: var(--steel); + padding: 0.25rem 0.75rem; + font-size: 0.85rem; + text-transform: uppercase; + letter-spacing: 0.05em; +} + +/* Pricing Section */ +.pricing { + padding: 6rem 0; + background: var(--concrete); +} + +/* Pricing Toggle Switch */ +.pricing-toggle { + display: flex; + align-items: center; + justify-content: center; + gap: 1.5rem; + margin: 2rem 0 3rem; +} + +.pricing-toggle-label { + font-weight: 600; + text-transform: uppercase; + letter-spacing: 0.1em; + color: var(--light-gray); + transition: color 0.3s ease; +} + +.pricing-toggle-label.active { + color: var(--white); +} + +.toggle-switch { + position: relative; + width: 70px; + height: 35px; + background: var(--steel); + border: 2px solid var(--industrial-red); + cursor: pointer; + transition: all 0.3s ease; +} + +.toggle-switch::before { + content: ''; + position: absolute; + top: 3px; + left: 3px; + width: 25px; + height: 25px; + background: var(--industrial-red); + transition: all 0.3s ease; +} + +.toggle-switch.yearly::before { + transform: translateX(35px); +} + +.pricing-badge { + display: inline-block; + background: var(--industrial-orange); + color: var(--white); + padding: 0.25rem 0.75rem; + font-size: 0.75rem; + font-weight: 600; + text-transform: uppercase; + letter-spacing: 0.1em; + margin-left: 1rem; +} + +.pricing-grid { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); + gap: 2rem; + margin-top: 3rem; +} + +.pricing-card { + background: var(--black); + padding: 2.5rem; + border: 1px solid var(--border); + position: relative; + transition: all 0.3s ease; +} + + +.pricing-card.featured { + border-color: var(--industrial-red); + transform: scale(1.05); +} + +.pricing-card.featured::before { + content: 'MOST POPULAR'; + position: absolute; + top: -1px; + left: 50%; + transform: translateX(-50%); + background: var(--industrial-red); + padding: 0.5rem 2rem; + font-size: 0.75rem; + font-weight: 600; + letter-spacing: 0.1em; +} + +.pricing-card:hover { + transform: translateY(-10px); + border-color: var(--industrial-orange); +} + +.pricing-card.featured:hover { + transform: scale(1.05) translateY(-10px); +} + +.plan-name { + font-size: 1.5rem; + margin-bottom: 1rem; + color: var(--white); + text-transform: uppercase; +} + +.plan-price { + font-size: 3rem; + font-weight: 700; + color: var(--industrial-red); + margin-bottom: 0.5rem; +} + +.plan-price span { + font-size: 1rem; + color: var(--light-gray); +} + +.plan-features { + list-style: none; + margin: 2rem 0; +} + +.plan-features li { + padding: 0.75rem 0; + border-bottom: 1px solid var(--border); + color: var(--light-gray); +} + +.plan-features li:last-child { + border-bottom: none; +} + +.plan-features li::before { + content: '✓'; + color: var(--industrial-red); + margin-right: 0.5rem; + font-weight: bold; +} + +.special-pricing { + background: var(--black); + padding: 3rem; + margin: 3rem auto; + border: 2px solid var(--industrial-red); + text-align: center; + width: 60%; + position: relative; +} + +.special-pricing::before { + content: ''; + position: absolute; + top: -2px; + left: -2px; + right: -2px; + bottom: -2px; + background: linear-gradient(45deg, var(--industrial-red), var(--industrial-orange), var(--industrial-red)); + z-index: -1; + opacity: 0.3; +} + +.special-pricing h3 { + color: var(--industrial-red); + margin-bottom: 1rem; + font-size: 2rem; +} + +.special-pricing p { + margin-bottom: 2rem; + line-height: 1.8; +} + +.special-features { + display: flex; + justify-content: center; + gap: 3rem; + margin: 2rem 0; + flex-wrap: wrap; +} + +.special-feature { + text-align: center; +} + +.special-feature-number { + display: block; + font-size: 2rem; + font-weight: bold; + color: var(--industrial-orange); + margin-bottom: 0.25rem; +} + +.special-feature-label { + font-size: 0.85rem; + color: var(--light-gray); + text-transform: uppercase; + letter-spacing: 0.1em; +} + +@media (max-width: 1200px) { + .special-pricing { + width: 80%; + } +} + +@media (max-width: 768px) { + .special-pricing { + width: 100%; + } +} + +/*testemunhos*/ + +.testimonials { + padding: 100px 0; + text-align: center; +} + +.testimonials h2 { + font-size: 32px; + margin-bottom: 40px; +} + +/* SLIDER */ +.testimonial-slider { + position: relative; + overflow: hidden; + max-width: 900px; + margin: 0 auto; +} + +/* TRACK */ +.testimonial-track { + display: flex; + transition: transform 0.5s ease-in-out; +} + +/* CARD */ +.testimonial-card { + min-width: 100%; + padding: 50px 30px; + box-sizing: border-box; +} +.testimonial-card { + background: rgba(255,255,255,0.02); + border-radius: 20px; + backdrop-filter: blur(10px); +} + +/* FOTO MAIOR 🔥 */ +.testimonial-card img { + width: 120px; + height: 120px; + border-radius: 50%; + margin-bottom: 20px; + object-fit: cover; + + border: 3px solid red; +} + +/* TEXTO MAIOR */ +.testimonial-card p { + font-size: 18px; + line-height: 1.6; + max-width: 600px; + margin: 0 auto 15px; +} + +/* NOME */ +.testimonial-card span { + font-size: 16px; + font-weight: bold; + color: red; +} + +/* BOTÕES */ +.slider-btn { + position: absolute; + top: 50%; + transform: translateY(-50%); + background: rgba(0,0,0,0.7); + border: none; + color: #fff; + font-size: 28px; + padding: 12px; + cursor: pointer; + border-radius: 50%; +} + +.prev { left: 15px; } +.next { right: 15px; } + +/* DOTS */ +.slider-dots { + margin-top: 20px; +} + +.slider-dots span { + width: 12px; + height: 12px; +} + +.slider-dots .active { + background: red; +} + +/* Contact Form Section */ +.contact { + padding: 6rem 0; + background: linear-gradient(180deg, var(--black) 0%, #0F0F0F 100%); + position: relative; + overflow: hidden; +} + +.contact::before { + content: ''; + position: absolute; + top: -50%; + left: -50%; + width: 200%; + height: 200%; + background: radial-gradient(circle at center, rgba(230,57,70,0.03) 0%, transparent 70%); + animation: subtleRotate 30s linear infinite; +} + +@keyframes subtleRotate { + 0% { transform: rotate(0deg); } + 100% { transform: rotate(360deg); } +} + +.contact-grid { + display: grid; + grid-template-columns: 1fr 1.8fr; + gap: 3rem; + margin-top: 3rem; + position: relative; +} + +.contact-left { + display: flex; + flex-direction: column; + gap: 2rem; +} + +.contact-info { + background: linear-gradient(135deg, rgba(44,44,44,0.5) 0%, rgba(26,26,26,0.8) 100%); + backdrop-filter: blur(10px); + padding: 3rem; + border: 1px solid rgba(230,57,70,0.2); + position: relative; + overflow: hidden; + transition: all 0.3s ease; +} + +.contact-info::before { + content: ''; + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 3px; + background: linear-gradient(90deg, var(--industrial-red), var(--industrial-orange), var(--industrial-red)); + background-size: 200% 100%; + animation: shimmer 3s linear infinite; +} + +@keyframes shimmer { + 0% { background-position: -200% 0; } + 100% { background-position: 200% 0; } +} + +.contact-info:hover { + border-color: rgba(230,57,70,0.4); + transform: translateY(-2px); + box-shadow: 0 10px 40px rgba(230,57,70,0.1); +} + +.contact-info h3 { + color: var(--white); + margin-bottom: 1rem; + font-size: 1.5rem; + font-weight: 600; + letter-spacing: 1.7px; + display: flex; + align-items: center; + gap: 1rem; +} + +.contact-info h3::before { + content: ''; + width: 40px; + height: 2px; + background: var(--industrial-red); +} + +.contact-info p { + margin-bottom: 2rem; + color: rgba(255,255,255,0.7); + font-size: 0.95rem; + line-height: 1.6; +} + +.contact-details { + list-style: none; +} + +.contact-details li { + margin-bottom: 1.5rem; + color: rgba(255,255,255,0.8); + padding-left: 0; + display: flex; + align-items: center; + gap: 1rem; + font-size: 0.95rem; + transition: all 0.2s ease; +} + +.contact-details li:hover { + color: var(--white); + transform: translateX(5px); +} + +.contact-details li strong { + color: var(--industrial-orange); + font-weight: 500; + text-transform: uppercase; + font-size: 0.75rem; + letter-spacing: 0.1em; + min-width: 80px; +} + +.contact-offer { + margin-top: 2rem; + padding: 1.5rem; + background: linear-gradient(135deg, rgba(230,57,70,0.1) 0%, rgba(255,107,53,0.1) 100%); + border: 1px solid rgba(230,57,70,0.3); + position: relative; + /*overflow: hidden;*/ +} + +.contact-offer::after { + content: ''; + position: absolute; + top: 0; + right: 0; + width: 60px; + height: 60px; + background: var(--industrial-red); + clip-path: polygon(0 0, 100% 0, 100% 100%); + opacity: 0.1; +} + +.contact-offer strong { + color: var(--industrial-red); + display: block; + margin-bottom: 0.5rem; + font-size: 0.85rem; + letter-spacing: 0.1em; +} + +.contact-offer p { + margin: 0; + color: var(--white); + font-size: 1rem; +} + +.contact-map { + background: var(--concrete); + border: 1px solid rgba(230,57,70,0.2); + position: relative; + overflow: hidden; + height: 300px; + transition: all 0.3s ease; + position: relative; + width: 100%; + height: 450px; + border-radius: 20px; + box-shadow: 0 20px 40px rgba(0,0,0,0.5); + margin-top: 40px; +} + +.contact-map:hover { + border-color: rgba(230,57,70,0.4); + box-shadow: 0 10px 40px rgba(230,57,70,0.1); + transform: translateY(-5px); +} + +.contact-map iframe { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + border: none; + filter: grayscale(20%) contrast(110%) brightness(90%); + /* transition: all 0.5s ease; */ +} + +.contact-map:hover iframe { + filter: grayscale(50%) contrast(1) opacity(1); +} + +.map-overlay { + position: absolute; + top: 0; + left: 20px; + right: 0; + bottom: 20px; + background: linear-gradient(135deg, rgba(10,10,10,0.95) 0%, rgba(230,57,70,0.2) 100%); + display: flex; + align-items: center; + justify-content: center; + flex-direction: column; + backdrop-filter: blur(10px); + padding: 20px; + border-radius: 15px; + color: #fff; + max-width: 280px; + box-shadow: 0 10px 30px rgba(0,0,0,0.6); + border-left: 4px solid #ff2c2c; + /* transition: transform 0.3s ease, box-shadow 0.3s ease;*/ + /*cursor: pointer;*/ +} + +.map-overlay:hover { + opacity: 0; + pointer-events: none; + /*transform: translateY(-5px);*/ + display: none; + box-shadow: 0 15px 40px rgba(0,0,0,0.8); +} + +.map-overlay h3 { + margin-bottom: 8px; + font-size: 18px; +} + +.map-overlay p { + font-size: 14px; + margin-bottom: 10px; + color: #ccc; +} + +.map-content { + text-align: center; + padding: 2rem; + transform: translateY(0); + transition: transform 0.3s ease; +} + +.map-overlay:hover .map-content { + transform: translateY(-10px); +} + +@media (max-width: 768px) { + .contact-map { + height: 300px; + } + + .map-overlay { + left: 10px; + right: 10px; + bottom: 10px; + max-width: 100%; + } +} + +.map-icon { + width: 50px; + height: 50px; + margin: 0 auto 1rem; + background: linear-gradient(135deg, var(--industrial-red) 0%, var(--industrial-orange) 100%); + border-radius: 50%; + display: flex; + align-items: center; + justify-content: center; + font-size: 1.25rem; + color: var(--white); + box-shadow: 0 10px 30px rgba(230,57,70,0.3); + animation: floatIcon 3s ease-in-out infinite; +} + +@keyframes floatIcon { + 0%, 100% { transform: translateY(0); } + 50% { transform: translateY(-10px); } +} + +.map-content h4 { + color: var(--white); + margin-bottom: 0.5rem; + text-transform: uppercase; + letter-spacing: 0.15em; + font-size: 0.85rem; + font-weight: 600; +} + +.map-content p { + color: rgba(255,255,255,0.6); + font-size: 0.85rem; + letter-spacing: 0.05em; +} + +.contact-form-wrapper { + background: linear-gradient(135deg, rgba(44,44,44,0.3) 0%, rgba(26,26,26,0.5) 100%); + backdrop-filter: blur(10px); + padding: 1px; + position: relative; + overflow: hidden; +} + +.contact-form-wrapper::before { + content: ''; + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + background: linear-gradient(135deg, rgba(230,57,70,0.2) 0%, transparent 50%, rgba(255,107,53,0.2) 100%); + opacity: 0.5; +} + +.contact-form { + background: linear-gradient(135deg, #0A0A0A 0%, #0F0F0F 100%); + padding: 3.5rem; + position: relative; + height: 100%; +} + +.form-header { + margin-bottom: 3rem; + position: relative; +} + +.form-header h3 { + color: var(--white); + font-size: 2.5rem; + margin-bottom: 0.5rem; + font-weight: 700; + letter-spacing: 1px; + position: relative; + display: inline-block; +} + +.form-header h3::after { + content: ''; + position: absolute; + bottom: -10px; + left: 0; + width: 60px; + height: 3px; + background: linear-gradient(90deg, var(--industrial-red) 0%, var(--industrial-orange) 100%); +} + +.form-header p { + color: rgba(255,255,255,0.5); + font-size: 0.95rem; + margin-top: 1.5rem; + letter-spacing: 0.3px; +} + +.form-row { + display: grid; + grid-template-columns: 1fr 1fr; + gap: 2rem; +} + +.form-group { + margin-bottom: 2rem; +} + +.form-group.full-width { + grid-column: span 2; +} + +.form-group label { + display: block; + margin-bottom: 0.75rem; + color: rgba(255,255,255,0.5); + text-transform: uppercase; + font-size: 0.75rem; + letter-spacing: 0.15em; + font-weight: 500; +} + +.form-group input, +.form-group textarea, +.form-group select { + width: 100%; + padding: 1rem 1.25rem; + background: rgba(255,255,255,0.02); + border: 1px solid rgba(255,255,255,0.1); + color: var(--white); + font-size: 0.95rem; + font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif; + transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); +} + +.form-group select { + cursor: pointer; + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'%3E%3Cpath fill='%23ffffff' d='M6 9L1 4h10z'/%3E%3C/svg%3E"); + background-repeat: no-repeat; + background-position: right 1.25rem center; + padding-right: 3rem; + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; +} + +.form-group select option { + background: var(--concrete); + color: var(--white); + padding: 0.75rem; +} + +.form-group select option:hover { + background: var(--steel); +} + +.form-group input:focus, +.form-group textarea:focus, +.form-group select:focus { + outline: none; + border-color: rgba(230,57,70,0.5); + background: rgba(255,255,255,0.05); + box-shadow: 0 0 0 3px rgba(230,57,70,0.1); +} + +.form-group input::placeholder, +.form-group textarea::placeholder { + color: rgba(255,255,255,0.3); +} + +.form-group textarea { + min-height: 120px; + resize: vertical; +} + +.form-submit { + background: linear-gradient(135deg, var(--industrial-red) 0%, var(--industrial-orange) 100%); + color: var(--white); + padding: 1.25rem 3rem; + border: none; + text-transform: uppercase; + font-weight: 600; + letter-spacing: 0.15em; + font-size: 0.9rem; + cursor: pointer; + transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); + width: 100%; + position: relative; + overflow: hidden; + box-shadow: 0 10px 30px rgba(230,57,70,0.3); +} + +.form-submit::before { + content: ''; + position: absolute; + top: 50%; + left: 50%; + width: 0; + height: 0; + background: rgba(255,255,255,0.2); + border-radius: 50%; + transform: translate(-50%, -50%); + transition: width 0.6s, height 0.6s; +} + +.form-submit:hover::before { + width: 300%; + height: 300%; +} + +.form-submit span { + position: relative; + z-index: 1; +} + +.form-submit:hover { + transform: translateY(-2px); + box-shadow: 0 15px 40px rgba(230,57,70,0.4); +} + +@media (max-width: 1024px) { + .contact-grid { + grid-template-columns: 1fr; + gap: 2rem; + } + + .contact-left { + order: 2; + } + + .contact-form-wrapper { + order: 1; + } + + .form-row { + grid-template-columns: 1fr; + } + + .form-group.full-width { + grid-column: span 1; + } +} + +/* Amenities Section */ +.amenities { + padding: 6rem 0; + background: linear-gradient(180deg, var(--black) 0%, var(--concrete) 100%); + position: relative; +} + +.amenities::before { + content: ''; + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + background-image: + linear-gradient(45deg, transparent 49%, rgba(255,255,255,0.03) 49%, rgba(255,255,255,0.03) 51%, transparent 51%), + linear-gradient(-45deg, transparent 49%, rgba(255,255,255,0.03) 49%, rgba(255,255,255,0.03) 51%, transparent 51%); + background-size: 100px 100px; + pointer-events: none; + z-index: 1; +} + +.amenities::after { + content: ''; + position: absolute; + top: 0; + left: 0; + right: 0; + height: 2px; + background: linear-gradient(90deg, transparent, var(--industrial-red), transparent); + z-index: 2; +} + +.amenities .container { + position: relative; + z-index: 2; +} + +.amenities-grid { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); + gap: 3rem; + margin-top: 3rem; + position: relative; + z-index: 2; +} + +.amenity-item { + text-align: center; +} + +.amenity-icon { + width: 80px; + height: 80px; + margin: 0 auto 1.5rem; + background: var(--steel); + display: flex; + align-items: center; + justify-content: center; + font-size: 2rem; + font-weight: bold; + color: var(--industrial-red); + transition: all 0.3s ease; +} + +.amenity-item:hover .amenity-icon { + background: var(--industrial-red); + color: var(--white); + transform: rotate(5deg); +} + +.amenity-item h3 { + margin-bottom: 0.5rem; + color: var(--white); +} + +/* CTA Section */ +.cta { + padding: 6rem 0; + background: linear-gradient(135deg, rgba(230,57,70,0.8) 0%, rgba(255,107,53,0.7) 100%); + text-align: center; + position: relative; + overflow: hidden; +} + +.cta { + background: + linear-gradient(rgba(0,0,0,0.7), rgba(0,0,0,0.9)), + url(https://i.imgur.com/xbJ5E7D.jpeg) center/cover no-repeat; +} + +.cta::before { + content: ''; + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + background-image: + linear-gradient(45deg, transparent 49%, rgba(255,255,255,0.05) 49%, rgba(255,255,255,0.05) 51%, transparent 51%), + linear-gradient(-45deg, transparent 49%, rgba(255,255,255,0.05) 49%, rgba(255,255,255,0.05) 51%, transparent 51%); + background-size: 100px 100px; + pointer-events: none; +} + +.cta::after { + content: ''; + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + background: linear-gradient(180deg, rgba(10,10,10,0.3) 0%, rgba(10,10,10,0.5) 100%); + pointer-events: none; +} + +@keyframes slide { + 0% { transform: translateX(0); } + 100% { transform: translateX(50%); } +} + +.cta-content { + position: relative; + z-index: 1; +} + +.cta h2 { + color: var(--white); + margin-bottom: 1rem; +} + +.cta p { + color: var(--white); + font-size: 1.25rem; + margin-bottom: 2rem; + max-width: 600px; + margin-left: auto; + margin-right: auto; +} + +.cta-buttons { + display: flex; + gap: 1rem; + justify-content: center; +} + +.cta .btn-primary { + background: var(--white); + color: var(--industrial-red); + border-color: var(--white); +} + +.cta .btn-primary:hover { + background: transparent; + color: var(--white); +} + +/* Footer */ +footer { + background: var(--black); + border-top: 1px solid var(--border); + padding: 4rem 0 2rem; +} + +.footer-content { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); + gap: 3rem; + margin-bottom: 3rem; +} + +.footer-section h4 { + color: var(--industrial-red); + margin-bottom: 1rem; + text-transform: uppercase; + font-size: 1rem; + letter-spacing: 0.1em; +} + +.footer-section ul { + list-style: none; +} + +.footer-section ul li { + margin-bottom: 0.75rem; +} + +.footer-section ul li a { + color: var(--light-gray); + text-decoration: none; + transition: color 0.3s ease; +} + +.footer-section ul li a:hover { + color: var(--industrial-red); +} + +.footer-bottom { + border-top: 1px solid var(--border); + padding-top: 2rem; + display: flex; + justify-content: space-between; + align-items: center; +} + +.footer-credits { + display: flex; + gap: 2rem; + align-items: center; +} + +.footer-credits a { + color: var(--industrial-red); + text-decoration: none; + transition: color 0.3s ease; +} + +.footer-credits a:hover { + color: var(--industrial-orange); +} + +.social-links { + display: flex; + gap: 1rem; +} + +.social-links a { + width: 40px; + height: 40px; + background: var(--steel); + display: flex; + align-items: center; + justify-content: center; + text-decoration: none; + color: var(--white); + transition: all 0.3s ease; +} + +.social-links a:hover { + background: var(--industrial-red); + transform: translateY(-3px); +} + +/* Responsive Design */ +@media (max-width: 768px) { + .book-tour-btn { + display: none; + } + + .menu-toggle { + display: flex; + } + + .hero h1 { + font-size: 3rem; + } + + .hero-buttons { + flex-direction: column; + } + + .pricing-card.featured { + transform: none; + } + + .footer-bottom { + flex-direction: column; + gap: 1rem; + text-align: center; + } + + .footer-credits { + flex-direction: column; + gap: 1rem; + } + + .cta-buttons { + flex-direction: column; + align-items: center; + } + + .btn-primary, .btn-secondary { + width: 100%; + text-align: center; + } + + .feature-card { + clip-path: none; + } + + .feature-card, +.space-card, +.pricing-card { + transition: all 0.3s ease; +} + +.feature-card:hover, +.space-card:hover, +.pricing-card:hover { + transform: translateY(-8px); +} + + .feature-icon { + clip-path: none; + } +} + +/* Loading Animation */ +.loading-bar { + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 3px; + background: var(--industrial-red); + transform: scaleX(0); + transform-origin: left; + animation: loading 2s ease-out forwards; + z-index: 10000; +} + +@keyframes loading { + to { + transform: scaleX(1); + } +} + +.fade-in { + opacity: 0; + transform: translateY(20px); + transition: 0.6s; +} + +.fade-in.show { + opacity: 1; + transform: translateY(0); +} \ No newline at end of file diff --git a/scripts/seed.js b/scripts/seed.js new file mode 100644 index 00000000..d4136666 --- /dev/null +++ b/scripts/seed.js @@ -0,0 +1,25 @@ +require('dotenv').config(); +const dbPromise = require('../config/dbClient'); + +const records = [ + { nome: 'Ana Silva', email: 'ana.silva@example.com', curso: 'Geografia' }, + { nome: 'Bruno Costa', email: 'bruno.costa@example.com', curso: 'Física' }, + { nome: 'Carla Souza', email: 'carla.souza@example.com', curso: 'História' }, +]; + +(async () => { + try { + const db = await dbPromise; + for (const aluno of records) { + await db.run( + 'INSERT INTO alunos (nome, email, curso) VALUES (?, ?, ?)', + [aluno.nome, aluno.email, aluno.curso] + ); + console.log('Inserido:', aluno.nome); + } + console.log('Seed finalizado com sucesso.'); + } catch (error) { + console.error('Erro ao inserir registros:', error.message); + process.exitCode = 1; + } +})(); diff --git a/server.js b/server.js deleted file mode 100644 index e6896fe9..00000000 --- a/server.js +++ /dev/null @@ -1,127 +0,0 @@ -require('dotenv').config(); -const express = require('express'); -const path = require('path'); -const supabase = require('./config/supabaseClient'); - -const app = express(); -const port = process.env.PORT || 3000; - -// Configurar EJS -app.set('view engine', 'ejs'); -app.set('views', path.join(__dirname, 'views')); - -// Middlewares -app.use(express.urlencoded({ extended: true })); -app.use(express.static(path.join(__dirname, 'public'))); - -// Rota principal - Listar alunos (READ) -app.get('/', async (req, res) => { - try { - // Busca dados no Supabase (ordena por id) - const { data: alunos, error } = await supabase - .from('alunos') - .select('*') - .order('id', { ascending: true }); - - if (error) throw error; - - res.render('index', { - titulo: 'Gestão Escolar (Supabase)', - alunos: alunos || [] - }); - } catch (error) { - console.error('Erro ao buscar alunos:', error.message); - res.status(500).send('Erro interno do servidor'); - } -}); - -// Rota para o formulário de cadastro -app.get('/novo', (req, res) => { - res.render('formulario', { - titulo: 'Cadastrar Aluno', - aluno: null // Indica que é um novo cadastro - }); -}); - -// Rota para o formulário de edição -app.get('/editar/:id', async (req, res) => { - try { - const id = req.params.id; - - // Busca o aluno específico - const { data, error } = await supabase - .from('alunos') - .select('*') - .eq('id', id) - .single(); // Retorna apenas um objeto, não um array - - if (error) throw error; - if (!data) return res.status(404).send('Aluno não encontrado'); - - res.render('formulario', { - titulo: 'Editar Aluno', - aluno: data // Passa os dados do aluno para preencher o formulário - }); - } catch (error) { - console.error('Erro ao buscar aluno:', error.message); - res.status(500).send('Erro interno do servidor'); - } -}); - -// Rota para processar cadastro/edição (CREATE / UPDATE) -app.post('/salvar', async (req, res) => { - try { - const { id, nome, email, curso } = req.body; - - // Prepara os dados - const dadosAluno = { nome, email, curso }; - - if (id) { - // Se tem ID, é uma edição (UPDATE) - const { error } = await supabase - .from('alunos') - .update(dadosAluno) - .eq('id', id); - - if (error) throw error; - } else { - // Se não tem ID, é um novo cadastro (CREATE) - const { error } = await supabase - .from('alunos') - .insert([dadosAluno]); - - if (error) throw error; - } - - res.redirect('/'); - } catch (error) { - console.error('Erro ao salvar aluno:', error.message); - res.status(500).send('Erro interno ao salvar os dados'); - } -}); - -// Rota para remover aluno (DELETE) -// Usamos GET aqui para simplificar, pois formulários HTML padrão só suportam GET/POST -// Em uma API real, usaríamos o método DELETE -app.get('/deletar/:id', async (req, res) => { - try { - const id = req.params.id; - - const { error } = await supabase - .from('alunos') - .delete() - .eq('id', id); - - if (error) throw error; - - res.redirect('/'); - } catch (error) { - console.error('Erro ao deletar aluno:', error.message); - res.status(500).send('Erro interno ao deletar'); - } -}); - -// Iniciar servidor -app.listen(port, () => { - console.log(`🚀 Servidor (Supabase CRUD) rodando em http://localhost:${port}`); -}); diff --git a/views/cadastro.html b/views/cadastro.html new file mode 100644 index 00000000..c1b76bc6 --- /dev/null +++ b/views/cadastro.html @@ -0,0 +1,148 @@ + + + + + + Cadastro | Forge Fitness + + + + +
+ + +
+
+

Faça seu cadastro na Forge
Comece sua jornada hoje

+

Cadastre-se rapidamente e comece a aproveitar planos e treinos personalizados na sua unidade preferida.

+ +
+
+ +
+
+
+

Por que se cadastrar?

+

Receba atendimento personalizado, planos exclusivos e suporte dos nossos profissionais para atingir resultados reais.

+
    +
  • ✅ Planos ajustados ao seu objetivo
  • +
  • ✅ Acesso rápido às primeiras aulas
  • +
  • ✅ Suporte completo de equipe qualificada
  • +
+
+
+ Cadastro Forge Fitness +
+
+
+ +
+
+
+

Cadastro de aluno

+

Preencha os dados abaixo para criar sua conta e iniciar seu treinamento.

+
+ +
+
+
+
+

Dados do aluno

+

Campos obrigatórios marcados com *

+
+
+ + +
+
+ + +
+
+ + +
+ +
+
+
+ +
+
+

Como funciona

+

Após preencher o cadastro, nossos atendentes entrarão em contato para confirmar seu plano e auxiliá-lo na primeira aula.

+
    +
  • Suporte12h - 20h
  • +
  • Telefone(31) 99999-9999
  • +
  • Emailcontato@forgefitness.com
  • +
+
+
+
+
+
+ +
+
+
+

Planos disponíveis

+

Escolha o plano que melhor combina com seu ritmo e seu objetivo.

+
+
+
+

Básico

+
R$139/mês
+
    +
  • Academia completa
  • +
  • Treino personalizado
  • +
  • Acesso livre às unidades
  • +
+
+ +
+

Completo

+
R$240/mês
+
    +
  • Área Premium
  • +
  • Treinos + spa recovery
  • +
  • Suporte completo
  • +
+
+
+
+
+ +
+
+

© 2026 Forge Fitness - Todos os direitos reservados

+
+
+ + + + diff --git a/views/formulario.ejs b/views/formulario.ejs deleted file mode 100644 index 2e17dde0..00000000 --- a/views/formulario.ejs +++ /dev/null @@ -1,77 +0,0 @@ - - - - - - <%= titulo %> - - - -
-
-

Gestão Escolar Supabase DB

-
-
- -
-
-

<%= titulo %>

-

- <% if (aluno) { %> - Atualize os dados do aluno abaixo. - <% } else { %> - Preencha os dados para salvar no banco de dados Supabase. - <% } %> -

- -
- - <% if (aluno) { %> - - <% } %> - -
- - -
- -
- - -
- -
- - -
- -
- - Voltar -
-
-
-
- - diff --git a/views/index.ejs b/views/index.ejs deleted file mode 100644 index 207a9910..00000000 --- a/views/index.ejs +++ /dev/null @@ -1,60 +0,0 @@ - - - - - - <%= titulo %> - - - -
-
-

Gestão Escolar Supabase DB

-
-
- -
-
-
-

Lista de Alunos (Banco de Dados Real)

- + Novo Aluno -
- -

Estes dados estão sendo buscados diretamente do banco de dados PostgreSQL no Supabase.

- - <% if (alunos && alunos.length > 0) { %> - - - - - - - - - - - - <% alunos.forEach(function(aluno) { %> - - - - - - - - <% }); %> - -
IDNomeEmailCursoAções
<%= aluno.id %><%= aluno.nome %><%= aluno.email || 'Não informado' %><%= aluno.curso %> - Editar - Excluir -
- <% } else { %> -
-

Nenhum aluno encontrado no banco de dados.

-

Cadastre o primeiro aluno para testar o sistema!

-
- <% } %> -
-
- - diff --git a/views/index.html b/views/index.html new file mode 100644 index 00000000..c816520f --- /dev/null +++ b/views/index.html @@ -0,0 +1,503 @@ + + + + + + Forge Fitness Academia + + + + + +
+ + + + + +
+
+

Transforme seu corpo
Supere seus limites

+

+ Estrutura moderna, treinos personalizados e uma experiência completa para sua evolução. +

+

++500 alunos ativos • Resultados reais • Estrutura premium +

+ +
+
+ + +
+
+
+

DIFERENCIAL

+

Estrutura completa pensada para oferecer conforto, praticidade e bem-estar em cada treino.

+
+
+
+
1
+

Sauna

+

Saunas individuais disponíveis para relaxamento muscular e recuperação pós-treino, + proporcionando bem-estar e alívio do estresse (disponível somente em unidades Premium).

+
+
+
2
+

Estacionamento próprio

+

Estacionamento próprio para mais comodidade e segurança, + garantindo praticidade na sua rotina de treinos.

+
+
+
+
+
3
+

Aulas adicionais

+

Aulas adicionais como dança, funcional e spinning, com studio multiuso + oferecendo mais variedade e motivação para o seu treino.

+
+
+
+
+
4
+

Equipe qualificada

+

Equipe de profissionais formados em faculdades reconhecidas, + garantindo orientação segura, qualificada e eficiente em todos + os treinos.

+
+
+
+
+
5
+

Lounge Nutricional

+

Cafeteria no local com bebidas voltadas para o treino, + como shakes e isotônicos, além de opções de alimentação + saudável para antes e depois das atividades (disponível somente em unidades Premium).

+
+
+
+
+
6
+

Spa Recovery

+

Espaço exclusivo com recursos para recuperação muscular, + como massagens e terapias relaxantes, proporcionando + bem-estar completo após o treino.

+
+
+
+
+
+
+ + + + +
+
+ +
+

Treine com qualidade

+

Ambiente moderno e motivador para você evoluir todos os dias.

+
+ +
+ +
+ +
+
+ + +
+
+
+

CONHEÇA NOSSAS UNIDADES

+

Perto de você, com conforto treinos de qualidade!

+
+
+
+
+
+

Savassi

+

Unidade no coração da Savassi, ideal para quem busca praticidade e vida ativa.

+
+ Aberto das 5h às 23h + Premium + R$ 169/mês +
+
+
+
+
+
+

Belvedere

+

Academia premium, com estrutura completa e ambiente sofisticado.

+
+ Aberto das 5h às 23h + Premium + R$ 169/mês +
+
+
+
+
+
+

Pampulha

+

Próxima à lagoa, ideal para estudantes e famílias.

+
+ Aberto das 5h às 23h + Premium + R$ 169/mês +
+
+
+
+
+
+

Funcionários

+

Perfeita para quem trabalha na região e quer treinar antes ou depois do expediente.

+
+ Aberto das 6h às 22h + Ampla + R$ 139/mês +
+
+
+
+
+
+

Barreiro

+

Unidade ampla para atender toda a comunidade local, com variedade de treinos.

+
+ Aberto das 6h às 22h + Ampla + R$ 139/mês +
+
+
+
+
+
+

Centro

+

Academia prática para quem trabalha ou estuda no centro da cidade.

+
+ Aberto das 6h às 22h + Ampla + R$ 139/mês +
+
+
+
+
+
+ + +
+
+
+

Planos

+

Sem taxas ocultas, apenas um espaço de trabalho puro.

+
+
+ Mensal +
+ AnualDesconto 20% +
+
+
+

Básico

+
$160/mensal
+
    +
  • Acesso a todas unidades amplas.
  • +
  • Treino personalizado.
  • +
  • Acesso ao estacionamento (taxa de $3,50 por vez).
  • +
  • Convite para palestras informativas.
  • +
  • Avalição física inicial.
  • +
+ +
+ +
+

Completo

+
$240/Mensal
+
    +
  • Acesso a todas unidades premium.
  • +
  • Estacionamento gratuito.
  • +
  • Sauna e Aulas adicionais inclusas.
  • +
  • Mentoria e acompanhamento físico mensal.
  • +
  • Uma dose de isotônicos (diário).
  • +
  • Spa Recovery incluso.
  • +
+ +
+
+
+

Planos Personalizados

+

Nossos planos personalizados são feitos de acordo com seus objetivos e rotina, + garantindo treinos eficientes e seguros. + Você contará com personal trainers graduandos, + trazendo conhecimento atualizado e auxiliando na execução + correta dos exercícios, em um ambiente preparado para sua evolução.

+
+
+ 33-200+ + Tamanho da equipe +
+
+ Personalizado + Áreas especifícas +
+
+ Dedicado + Atenção máxima ao cliente +
+
+

Inclui: suporte prioritário, treinos qualificados, gerente de conta dedicado, condições flexíveis e segurança de nível empresarial.

+ Comece agora +
+
+
+ + +
+
+

Resultados reais

+ +
+ +
+ +
+ +

"Perdi 12kg em 3 meses. Estrutura incrível!"

+ - João Costa +
+ +
+ +

"Ambiente motivador e profissionais excelentes."

+ - Maria Lúcia +
+ +
+ +

"Melhor decisão foi começar aqui."

+ - Lucas Eduardo +
+ +
+ + + + + + +
+ +
+
+
+ + +
+
+
+

Estrutura Completa

+

Tudo que você precisa para evoluir nos seus treinos.

+
+ +
+
+
🏋️
+

Musculação

+

Equipamentos modernos e completos.

+
+ +
+
🏃
+

Cardio

+

Esteiras e bicicletas de alta performance.

+
+ +
+
🧘
+

Alongamento

+

Área exclusiva para mobilidade e recuperação.

+
+ +
+
🚿
+

Vestiários

+

Ambiente seguro e confortável.

+
+ +
+
💪
+

Personal Trainer

+

Acompanhamento profissional.

+
+ +
+
🔥
+

Treino Funcional

+

Aulas dinâmicas e intensas.

+
+
+
+
+ + +
+
+
+

Entre em Contato

+

Agende uma visita e comece sua transformação.

+
+ +
+
+
+

Visite nossa academia

+

Venha conhecer nossa estrutura moderna e equipe qualificada.

+ +
    +
  • EndereçoBelo Horizonte - MG
  • +
  • Telefone(31) 99999-9999
  • +
  • Emailcontato@forgefitness.com
  • +
  • HorárioSeg-Sáb: 5h às 23h
  • +
+
+
+ +
+

Experimente a Forge Fitness

+

Ganhe um treino experimental gratuito e conheça nossa estrutura completa antes de se matricular.

+ +
    +
  • ✔ Treino gratuito no primeiro dia
  • +
  • ✔ Avaliação física com profissional
  • +
  • ✔ Acesso a todas as áreas da academia
  • +
  • ✔ Suporte de personal trainer
  • +
+ + Agendar treino grátis +
+
+ + +
+

Unidade Centro - Belo Horizonte

+

Av. Afonso Pena, 1000
Belo Horizonte - MG

+ + 📞 (31) 99999-9999 + 🕒 Seg-Sáb: 5h às 23h +
+
+ +
+
+ +
+

Comece hoje

+

Preencha e entraremos em contato

+
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ + + +
+
+
+
+
+ + + +
+
+
+

Pronto para transformar seu corpo?

+

Treine com estrutura premium e acompanhamento profissional.

+ Começar agora +
+
+
+ + + +
+
+

© 2026 Forge Fitness - Todos os direitos reservados

+
+
+ + + + \ No newline at end of file