This commit is contained in:
2026-01-10 18:39:55 +00:00
parent 0a0969b8af
commit 70ea1894d4
928 changed files with 5187 additions and 3121 deletions

2
.env
View File

@@ -1,6 +1,8 @@
DATABASE_URL=postgres://postgres:123QWEasd@localhost:5432/evstation
PORT=4000
NODE_ENV=production
JWT_SECRET=umaChaveMuitoForteESegura123!
MQTT_URL=mqtt://localhost:1883

49
app.js
View File

@@ -1,49 +0,0 @@
// app.js
require('dotenv').config();
// Enforce presence of JWT_SECRET
if (!process.env.JWT_SECRET) {
console.error('Error: JWT_SECRET is not defined in environment.');
process.exit(1);
}
const express = require('express');
// Route modules
const usersRoutes = require('./routes/users');
const chargerRoutes = require('./routes/chargers');
const sessionsRoutes = require('./routes/charger_sessions');
const pushRoutes = require('./routes/push'); // ✅ ADICIONA ISTO
const app = express();
// Global middlewares
app.use(express.json());
// Public routes (no auth)
app.use('/api/users', usersRoutes);
// Protected routes
// ✅ NOTA: chargers/sessions/push já têm router.use(verifyToken) internamente
// portanto não precisas passar verifyToken aqui.
app.use('/api/chargers', chargerRoutes);
app.use('/api/charger_sessions', sessionsRoutes);
app.use('/api/push', pushRoutes); // ✅ ISTO resolve /api/push/vapid-public-key
// Health check opcional (bom para produção)
app.get('/api/health', (req, res) => {
res.json({ success: true, ok: true });
});
// Error handler (catch-all)
app.use((err, req, res, next) => {
console.error('Unhandled error:', err);
res
.status(err.status || 500)
.json({
success: false,
message: err.message || 'Internal Server Error',
});
});
module.exports = app;

15
db.js
View File

@@ -1,15 +0,0 @@
// ./db.js
require('dotenv').config();
const knex = require('knex');
const knexfile = require('./knexfile');
// Pega o ambiente (default pra 'development')
const environment = process.env.NODE_ENV || 'development';
// Recupera só as configurações daquele ambiente
const config = knexfile[environment];
// Inicializa o Knex com esse config
const db = knex(config);
module.exports = db;

View File

@@ -1,11 +1,55 @@
// knexfile.js
require('dotenv').config();
function must(name) {
const v = process.env[name];
if (!v) throw new Error(`${name} não definido no .env`);
return v;
}
const shared = {
client: 'pg',
migrations: {
directory: './src/db/migrations',
},
};
function buildConnectionFromEnv() {
// Se houver DATABASE_URL, usa-o.
// Se PGSSL=true, aplica ssl no formato esperado pelo driver pg (dentro de connection).
const ssl =
process.env.PGSSL === 'true' ? { rejectUnauthorized: false } : undefined;
if (process.env.DATABASE_URL) {
// knex aceita string, mas o ssl precisa estar no objeto:
return ssl
? { connectionString: process.env.DATABASE_URL, ssl }
: process.env.DATABASE_URL;
}
// fallback para vars soltas
return {
host: process.env.PGHOST || '127.0.0.1',
port: Number(process.env.PGPORT || 5432),
user: process.env.PGUSER || 'postgres',
password: process.env.PGPASSWORD || 'postgres',
database: process.env.PGDATABASE || 'evse',
...(ssl ? { ssl } : {}),
};
}
module.exports = {
development: {
client: 'pg',
connection: process.env.DATABASE_URL,
migrations: {
directory: './migrations',
},
...shared,
connection: buildConnectionFromEnv(),
},
production: {
...shared,
// Em produção normalmente queres obrigar DATABASE_URL (se for o teu caso):
// connection: must('DATABASE_URL'),
// Mas mantendo compatível com vars soltas:
connection: buildConnectionFromEnv(),
pool: { min: 2, max: 10 },
},
};

View File

@@ -1,41 +0,0 @@
const jwt = require('jsonwebtoken');
if (!process.env.JWT_SECRET) {
throw new Error('JWT_SECRET não definido no .env');
}
function verifyToken(req, res, next) {
const authHeader =
req.headers['authorization'] || req.headers['Authorization'];
if (!authHeader) {
return res.status(403).json({ error: 'Token não fornecido' });
}
const match = authHeader.match(/^Bearer\s+(.+)$/i);
if (!match) {
return res
.status(403)
.json({ error: 'Token malformado. Use "Bearer <token>"' });
}
const token = match[1];
jwt.verify(token, process.env.JWT_SECRET, (err, payload) => {
if (err) {
if (err.name === 'TokenExpiredError') {
return res.status(403).json({ error: 'Sessão expirada' });
}
return res.status(403).json({ error: 'Token inválido' });
}
if (!payload?.id) {
return res.status(403).json({ error: 'Token inválido' });
}
req.user = payload;
next();
});
}
module.exports = verifyToken;

59
migrate_structure.sh Executable file
View File

@@ -0,0 +1,59 @@
#!/usr/bin/env bash
set -euo pipefail
echo "==> 0) Criar branch (opcional)"
# git checkout -b refactor/estrutura-src
echo "==> 1) Criar pastas da nova estrutura"
mkdir -p src/{config,db,repositories,services,domain/normalize,mqtt/handlers,middleware,routes}
mkdir -p src/db/migrations
echo "==> 2) Mover ficheiros principais"
# app/server
mv app.js src/app.js
mv server.js src/server.js
# db
mv db.js src/db/knex.js
# knexfile continua na raiz (ok)
echo "==> 3) Mover routes"
mv routes/chargers.js src/routes/chargers.routes.js
mv routes/charger_sessions.js src/routes/sessions.routes.js
mv routes/push.js src/routes/push.routes.js
mv routes/users.js src/routes/users.routes.js
echo "==> 4) Mover middleware"
mv middleware/verifyToken.js src/middleware/auth.js
echo "==> 5) Mover MQTT"
mv mqtt/client.js src/mqtt/index.js
echo "==> 6) Mover pushService (utils -> services)"
mv utils/pushService.js src/services/push.service.js
echo "==> 7) Mover migrations"
mv migrations/* src/db/migrations/
echo "==> 8) Limpar pastas antigas (se vazias)"
rmdir routes 2>/dev/null || true
rmdir middleware 2>/dev/null || true
rmdir mqtt 2>/dev/null || true
rmdir utils 2>/dev/null || true
rmdir migrations 2>/dev/null || true
echo "==> 9) Criar placeholders úteis (opcional)"
touch src/config/index.js
touch src/services/{chargers.service.js,configs.service.js,sessions.service.js}
touch src/repositories/{chargers.repo.js,sessions.repo.js,push.repo.js}
touch src/domain/normalize/{chargingStatus.js,chargingConfig.js}
touch src/middleware/{validate.js,errorHandler.js}
touch src/mqtt/publishers.js
touch src/mqtt/handlers/{evse.handler.js,meter.handler.js,legacy.handler.js}
echo "==> 10) Mostrar nova árvore (até 4 níveis)"
tree -a -L 4 src || true
echo "✅ Estrutura criada e ficheiros movidos."
echo "⚠️ Próximo passo: corrigir os imports/paths (vai quebrar até ajustar)."

View File

@@ -1,74 +0,0 @@
// migrations/20250619_create_tables.js
exports.up = async function(knex) {
// Create 'users' table
await knex.schema.createTable('users', (table) => {
table.increments('id').primary();
table.string('username', 255).notNullable().unique();
table.string('password', 255).notNullable();
table.timestamp('created_at').defaultTo(knex.fn.now());
});
// Create 'chargers' table with new fields
await knex.schema.createTable('chargers', (table) => {
table.uuid('id').primary().defaultTo(knex.raw('gen_random_uuid()'));
table.integer('user_id').unsigned().notNullable()
.references('id').inTable('users').onDelete('CASCADE');
table.string('location', 255).notNullable();
table.string('status', 50).notNullable().defaultTo('offline');
table.integer('charging_current').notNullable().defaultTo(32);
table.timestamp('updated_at').notNullable().defaultTo(knex.fn.now());
table.string('mqtt_user', 255).notNullable();
table.string('mqtt_pass', 255).notNullable();
table.string('mqtt_topic', 255).notNullable().unique();
table.timestamp('created_at').defaultTo(knex.fn.now());
// Add power and current for 3 phases, voltage and other new fields
table.integer('charging_time').notNullable().defaultTo(0); // Total charging time
table.decimal('consumption', 8, 2).notNullable().defaultTo(0); // Consumption (kWh)
// Power for 3 phases (L1, L2, L3)
table.decimal('power_l1', 8, 2).notNullable().defaultTo(0);
table.decimal('power_l2', 8, 2).notNullable().defaultTo(0);
table.decimal('power_l3', 8, 2).notNullable().defaultTo(0);
// Voltage for 3 phases (L1, L2, L3)
table.decimal('voltage_l1', 8, 2).notNullable().defaultTo(0);
table.decimal('voltage_l2', 8, 2).notNullable().defaultTo(0);
table.decimal('voltage_l3', 8, 2).notNullable().defaultTo(0);
// Current for 3 phases (L1, L2, L3)
table.decimal('current_l1', 8, 2).notNullable().defaultTo(0);
table.decimal('current_l2', 8, 2).notNullable().defaultTo(0);
table.decimal('current_l3', 8, 2).notNullable().defaultTo(0);
});
// Create 'charger_configs' table
await knex.schema.createTable('charger_configs', (table) => {
table.uuid('charger_id').primary()
.references('id').inTable('chargers').onDelete('CASCADE');
table.integer('max_charging_current').notNullable().defaultTo(32);
table.boolean('require_auth').notNullable().defaultTo(false);
table.boolean('rcm_enabled').notNullable().defaultTo(false);
table.integer('temperature_limit').notNullable().defaultTo(60);
table.timestamp('config_received_at').notNullable().defaultTo(knex.fn.now());
});
// Create 'charger_sessions' table
await knex.schema.createTable('charger_sessions', (table) => {
table.increments('id').primary();
table.uuid('charger_id').notNullable()
.references('id').inTable('chargers').onDelete('CASCADE');
table.timestamp('started_at').notNullable();
table.timestamp('ended_at');
table.decimal('kwh', 8, 2).notNullable().defaultTo(0);
table.decimal('cost', 10, 2);
table.timestamp('created_at').defaultTo(knex.fn.now());
});
};
exports.down = async function(knex) {
await knex.schema.dropTableIfExists('charger_sessions');
await knex.schema.dropTableIfExists('charger_configs');
await knex.schema.dropTableIfExists('chargers');
await knex.schema.dropTableIfExists('users');
};

View File

@@ -1,436 +0,0 @@
// mqtt/client.js
const mqtt = require('mqtt');
const EventEmitter = require('events');
const db = require('../db');
const { sendPushToUser } = require('../utils/pushService');
require('dotenv').config();
const emitter = new EventEmitter();
const MQTT_URL = process.env.MQTT_URL || 'mqtt://localhost:1883';
const mqttUser = process.env.MQTT_USER || 'admin';
const mqttPass = process.env.MQTT_PASS || '123QWEasd';
const client = mqtt.connect(MQTT_URL, {
username: mqttUser,
password: mqttPass,
reconnectPeriod: 2000,
});
// --------------------
// Helpers
// --------------------
const lastEnabled = {}; // por chargerId
function getStatusFromStateCode(code) {
const map = {
A1: '🔌 Not Conn.',
B1: '🟡 Unauth.',
B2: '🟢 Ready',
C1: '⚡ Wait',
C2: '⚡ Charging',
D1: '💨 Vent (req)',
D2: '💨 Vent',
E: '❌ CP Error',
F: '⚠️ Fault',
};
return map[code] || '❓ Unknown';
}
function getTriple(arr) {
return Array.isArray(arr)
? arr.slice(0, 3).map((n) => Math.round((Number(n) || 0) * 10) / 10)
: [0, 0, 0];
}
function toOneDecimal(v) {
const n = Number(v);
if (!Number.isFinite(n)) return 0;
return Math.round(n * 10) / 10;
}
function shallowEqual(a, b) {
if (a === b) return true;
if (!a || !b) return false;
const ak = Object.keys(a);
const bk = Object.keys(b);
if (ak.length !== bk.length) return false;
for (const k of ak) {
const av = a[k];
const bv = b[k];
if (Array.isArray(av) || Array.isArray(bv)) {
if (!Array.isArray(av) || !Array.isArray(bv)) return false;
if (av.length !== bv.length) return false;
for (let i = 0; i < av.length; i++) {
if (av[i] !== bv[i]) return false;
}
} else if (av !== bv) {
return false;
}
}
return true;
}
// --------------------
// Caches
// --------------------
// último estado normalizado por chargerId
const lastStateByChargerId = new Map(); // chargerId -> normalizedState
// cache charger por mqttTopic (evita SELECT a cada msg)
const chargerCache = new Map(); // mqttTopic -> { charger, fetchedAt }
const CHARGER_CACHE_TTL_MS = Number(process.env.CHARGER_CACHE_TTL_MS || 30000);
async function getChargerByMqttTopic(mqttTopic) {
const cached = chargerCache.get(mqttTopic);
const now = Date.now();
if (cached && now - cached.fetchedAt < CHARGER_CACHE_TTL_MS) {
return cached.charger;
}
const charger = await db('chargers').where({ mqtt_topic: mqttTopic }).first();
if (charger) {
chargerCache.set(mqttTopic, { charger, fetchedAt: now });
}
return charger;
}
// --------------------
// Subscribe
// --------------------
client.on('connect', () => {
console.log('[MQTT] Conectado ao broker:', MQTT_URL);
// ✅ tópicos fixos que TU pediste manter
const fixedTopics = ['+/state', '+/response/config/evse'];
// opcional via env (mas não substitui os fixos)
const envTopics = (process.env.MQTT_SUB_TOPICS || '')
.split(',')
.map((s) => s.trim())
.filter(Boolean);
const topicsToSub = [...new Set([...fixedTopics, ...envTopics])];
topicsToSub.forEach((t) => {
client.subscribe(t, { qos: 0 }, (err, granted) => {
if (err) {
console.error('[MQTT] Falha ao subscrever', t, err.message);
} else {
console.log('[MQTT] Subscrito:', granted?.map((g) => g.topic).join(', ') || t);
}
});
});
});
// --------------------
// Messages
// --------------------
client.on('message', async (topic, message) => {
// LOG para garantir que está a consumir
console.log('[MQTT] msg recebida em:', topic);
const parts = topic.split('/');
const mqttTopic = parts[0]; // ex: bf92842c365a
const subtopic = parts.slice(1).join('/'); // ex: state ou response/config/evse
// --------------------
// STATE
// --------------------
if (subtopic === 'state') {
try {
const payload = JSON.parse(message.toString());
const charger = await getChargerByMqttTopic(mqttTopic);
if (!charger) {
console.warn(`[MQTT] Charger não encontrado para topic: ${mqttTopic}`);
return;
}
const chargerId = charger.id;
const now = new Date();
const stateCode = String(payload.state || '').split(' ')[0];
if (!stateCode) {
console.warn(`[MQTT] Estado ausente/inválido para charger ID ${chargerId}`);
return;
}
const status = getStatusFromStateCode(stateCode);
const [p1, p2, p3] = getTriple(payload.power);
const [v1, v2, v3] = getTriple(payload.voltage);
const [c1, c2, c3] = getTriple(payload.current);
const consumption = toOneDecimal(payload.consumption);
const chargingTime = toOneDecimal(
payload.chargingTime ?? payload.sessionTime
);
const normalizedState = {
status,
charging_current: c1,
consumption,
charging_time: chargingTime,
power_l1: p1,
power_l2: p2,
power_l3: p3,
voltage_l1: v1,
voltage_l2: v2,
voltage_l3: v3,
current_l1: c1,
current_l2: c2,
current_l3: c3,
};
const prevState = lastStateByChargerId.get(chargerId);
const changed = !prevState || !shallowEqual(prevState, normalizedState);
if (changed) {
await db('chargers')
.where({ id: chargerId })
.update({
...normalizedState,
updated_at: now.toISOString(),
});
lastStateByChargerId.set(chargerId, normalizedState);
console.log(`[DB] Estado atualizado para charger ID ${chargerId}`);
} else {
// só para debug — podes remover depois
console.log(`[MQTT] Estado repetido, sem write (charger ${chargerId})`);
}
// sessões start/stop (mantido)
const previouslyEnabled = lastEnabled[chargerId] || false;
const currentlyEnabled = stateCode === 'C2';
if (!previouslyEnabled && currentlyEnabled) {
const activeSession = await db('charger_sessions')
.where({ charger_id: chargerId })
.whereNull('ended_at')
.first();
if (!activeSession) {
await db('charger_sessions').insert({
charger_id: chargerId,
started_at: now,
kwh: consumption,
});
console.log(`[DB] Sessão iniciada para charger ID ${chargerId}`);
}
}
if (previouslyEnabled && !currentlyEnabled) {
const session = await db('charger_sessions')
.where({ charger_id: chargerId })
.whereNull('ended_at')
.first();
if (session) {
await db('charger_sessions')
.where({ id: session.id })
.update({ ended_at: now, kwh: consumption });
console.log(`[DB] Sessão finalizada para charger ID ${chargerId}`);
}
}
lastEnabled[chargerId] = currentlyEnabled;
// emit para socket
emitter.emit('charging-status', {
charger_id: chargerId,
mqtt_topic: mqttTopic,
status,
stateCode,
consumption,
chargingTime,
power: [p1, p2, p3],
voltage: [v1, v2, v3],
current: [c1, c2, c3],
raw: payload,
});
// push (mantido)
if (status === '⚠️ Fault' || status === '❌ CP Error') {
await sendPushToUser(charger.user_id, {
title: '⚠️ Erro no carregador',
body: `${charger.location || 'Carregador'} entrou em falha.`,
url: `/charger/${charger.id}`,
});
}
if (previouslyEnabled && !currentlyEnabled) {
await sendPushToUser(charger.user_id, {
title: '✅ Carregamento concluído',
body: `${charger.location || 'Carregador'} terminou o carregamento.`,
url: `/history`,
});
}
} catch (err) {
console.error(`[MQTT] Erro ao processar state '${mqttTopic}':`, err);
console.error('Payload recebido:', message.toString());
}
}
// --------------------
// CONFIG RESPONSE
// --------------------
else if (subtopic === 'response/config/evse') {
try {
const payload = JSON.parse(message.toString());
const charger = await getChargerByMqttTopic(mqttTopic);
if (!charger) {
console.warn(`[MQTT] Charger não encontrado para topic: ${mqttTopic}`);
return;
}
const configData = {
charger_id: charger.id,
max_charging_current: payload.maxChargingCurrent || 32,
require_auth: !!payload.requireAuth,
rcm_enabled: !!payload.rcm,
temperature_limit: payload.temperatureThreshold || 60,
config_received_at: new Date().toISOString(),
};
const existingConfig = await db('charger_configs')
.where({ charger_id: charger.id })
.first();
const prevCfgNorm = existingConfig
? {
max_charging_current: Number(existingConfig.max_charging_current) || 32,
require_auth: !!existingConfig.require_auth,
rcm_enabled: !!existingConfig.rcm_enabled,
temperature_limit: Number(existingConfig.temperature_limit) || 60,
}
: null;
const nextCfgNorm = {
max_charging_current: Number(configData.max_charging_current) || 32,
require_auth: !!configData.require_auth,
rcm_enabled: !!configData.rcm_enabled,
temperature_limit: Number(configData.temperature_limit) || 60,
};
const cfgChanged = !prevCfgNorm || !shallowEqual(prevCfgNorm, nextCfgNorm);
if (cfgChanged) {
if (existingConfig) {
await db('charger_configs')
.where({ charger_id: charger.id })
.update(configData);
console.log(`[DB] Configuração atualizada para charger ID ${charger.id}`);
} else {
await db('charger_configs').insert(configData);
console.log(`[DB] Nova configuração inserida para charger ID ${charger.id}`);
}
} else {
console.log(`[MQTT] Config repetida, sem write (charger ${charger.id})`);
}
emitter.emit('charging-config', {
...configData,
mqtt_topic: mqttTopic,
raw: payload,
});
} catch (err) {
console.error(`[MQTT] Erro ao processar config '${mqttTopic}':`, err);
console.error('Payload recebido:', message.toString());
}
}
});
// --------------------
// Broker offline / checker (igual ao teu)
// --------------------
client.on('offline', async () => {
console.warn('[MQTT] Broker offline');
try {
const chargers = await db('chargers').select('id', 'user_id', 'location');
const uniqueUsers = [...new Set(chargers.map((c) => c.user_id))];
await Promise.allSettled(
uniqueUsers.map((userId) =>
sendPushToUser(userId, {
title: '📡 Broker MQTT offline',
body: 'O sistema perdeu ligação ao broker. Alguns estados podem estar desatualizados.',
url: '/',
})
)
);
} catch (err) {
console.error('[MQTT] erro offline push:', err.message);
}
});
setInterval(async () => {
try {
const timeoutMinutes = Number(process.env.CHARGER_OFFLINE_MINUTES || 5);
const limitDate = new Date(Date.now() - timeoutMinutes * 60 * 1000);
const offlineChargers = await db('chargers')
.where('updated_at', '<', limitDate.toISOString())
.andWhereNot({ status: 'offline' })
.select('*');
for (const ch of offlineChargers) {
await db('chargers')
.where({ id: ch.id })
.update({ status: 'offline' });
lastStateByChargerId.delete(ch.id);
lastEnabled[ch.id] = false;
await sendPushToUser(ch.user_id, {
title: '🔌 Carregador offline',
body: `${ch.location || 'Carregador'} está offline há mais de ${timeoutMinutes} min.`,
url: `/charger/${ch.id}`,
});
}
} catch (err) {
console.error('[MQTT] offline checker erro:', err.message);
}
}, 60 * 1000);
// --------------------
// API pública
// --------------------
function on(event, handler) {
emitter.on(event, handler);
}
function sendConfig(chargerTopic, property, value) {
const payload = { [property]: value };
client.publish(`${chargerTopic}/set/config/evse`, JSON.stringify(payload), {
qos: 1,
});
}
function sendEnable(chargerTopic, enable) {
client.publish(
`${chargerTopic}/enable`,
JSON.stringify({ enable: !!enable }),
{ qos: 1 }
);
}
function requestConfig(chargerTopic) {
client.publish(`${chargerTopic}/request/config/evse`, null, { qos: 1 });
}
module.exports = {
on,
sendConfig,
sendEnable,
requestConfig,
};

0
node_modules/@socket.io/component-emitter/LICENSE generated vendored Normal file → Executable file
View File

0
node_modules/@socket.io/component-emitter/Readme.md generated vendored Normal file → Executable file
View File

0
node_modules/@socket.io/component-emitter/lib/cjs/index.d.ts generated vendored Normal file → Executable file
View File

0
node_modules/@socket.io/component-emitter/lib/cjs/index.js generated vendored Normal file → Executable file
View File

0
node_modules/@socket.io/component-emitter/lib/cjs/package.json generated vendored Normal file → Executable file
View File

0
node_modules/@socket.io/component-emitter/lib/esm/index.d.ts generated vendored Normal file → Executable file
View File

0
node_modules/@socket.io/component-emitter/lib/esm/index.js generated vendored Normal file → Executable file
View File

0
node_modules/@socket.io/component-emitter/lib/esm/package.json generated vendored Normal file → Executable file
View File

0
node_modules/@socket.io/component-emitter/package.json generated vendored Normal file → Executable file
View File

0
node_modules/@types/cors/LICENSE generated vendored Normal file → Executable file
View File

0
node_modules/@types/cors/README.md generated vendored Normal file → Executable file
View File

0
node_modules/@types/cors/index.d.ts generated vendored Normal file → Executable file
View File

0
node_modules/@types/cors/package.json generated vendored Normal file → Executable file
View File

0
node_modules/agent-base/LICENSE generated vendored Normal file → Executable file
View File

0
node_modules/agent-base/README.md generated vendored Normal file → Executable file
View File

0
node_modules/agent-base/dist/helpers.d.ts generated vendored Normal file → Executable file
View File

0
node_modules/agent-base/dist/helpers.d.ts.map generated vendored Normal file → Executable file
View File

0
node_modules/agent-base/dist/helpers.js generated vendored Normal file → Executable file
View File

0
node_modules/agent-base/dist/helpers.js.map generated vendored Normal file → Executable file
View File

0
node_modules/agent-base/dist/index.d.ts generated vendored Normal file → Executable file
View File

0
node_modules/agent-base/dist/index.d.ts.map generated vendored Normal file → Executable file
View File

0
node_modules/agent-base/dist/index.js generated vendored Normal file → Executable file
View File

0
node_modules/agent-base/dist/index.js.map generated vendored Normal file → Executable file
View File

0
node_modules/agent-base/package.json generated vendored Normal file → Executable file
View File

0
node_modules/asn1.js/.eslintrc.js generated vendored Normal file → Executable file
View File

0
node_modules/asn1.js/LICENSE generated vendored Normal file → Executable file
View File

0
node_modules/asn1.js/README.md generated vendored Normal file → Executable file
View File

0
node_modules/asn1.js/lib/asn1.js generated vendored Normal file → Executable file
View File

0
node_modules/asn1.js/lib/asn1/api.js generated vendored Normal file → Executable file
View File

0
node_modules/asn1.js/lib/asn1/base/buffer.js generated vendored Normal file → Executable file
View File

0
node_modules/asn1.js/lib/asn1/base/index.js generated vendored Normal file → Executable file
View File

0
node_modules/asn1.js/lib/asn1/base/node.js generated vendored Normal file → Executable file
View File

0
node_modules/asn1.js/lib/asn1/base/reporter.js generated vendored Normal file → Executable file
View File

0
node_modules/asn1.js/lib/asn1/constants/der.js generated vendored Normal file → Executable file
View File

0
node_modules/asn1.js/lib/asn1/constants/index.js generated vendored Normal file → Executable file
View File

0
node_modules/asn1.js/lib/asn1/decoders/der.js generated vendored Normal file → Executable file
View File

0
node_modules/asn1.js/lib/asn1/decoders/index.js generated vendored Normal file → Executable file
View File

0
node_modules/asn1.js/lib/asn1/decoders/pem.js generated vendored Normal file → Executable file
View File

0
node_modules/asn1.js/lib/asn1/encoders/der.js generated vendored Normal file → Executable file
View File

0
node_modules/asn1.js/lib/asn1/encoders/index.js generated vendored Normal file → Executable file
View File

0
node_modules/asn1.js/lib/asn1/encoders/pem.js generated vendored Normal file → Executable file
View File

0
node_modules/asn1.js/package.json generated vendored Normal file → Executable file
View File

0
node_modules/asynckit/LICENSE generated vendored Normal file → Executable file
View File

0
node_modules/asynckit/README.md generated vendored Normal file → Executable file
View File

0
node_modules/asynckit/bench.js generated vendored Normal file → Executable file
View File

0
node_modules/asynckit/index.js generated vendored Normal file → Executable file
View File

0
node_modules/asynckit/lib/abort.js generated vendored Normal file → Executable file
View File

0
node_modules/asynckit/lib/async.js generated vendored Normal file → Executable file
View File

0
node_modules/asynckit/lib/defer.js generated vendored Normal file → Executable file
View File

0
node_modules/asynckit/lib/iterate.js generated vendored Normal file → Executable file
View File

0
node_modules/asynckit/lib/readable_asynckit.js generated vendored Normal file → Executable file
View File

0
node_modules/asynckit/lib/readable_parallel.js generated vendored Normal file → Executable file
View File

0
node_modules/asynckit/lib/readable_serial.js generated vendored Normal file → Executable file
View File

0
node_modules/asynckit/lib/readable_serial_ordered.js generated vendored Normal file → Executable file
View File

0
node_modules/asynckit/lib/state.js generated vendored Normal file → Executable file
View File

0
node_modules/asynckit/lib/streamify.js generated vendored Normal file → Executable file
View File

0
node_modules/asynckit/lib/terminator.js generated vendored Normal file → Executable file
View File

0
node_modules/asynckit/package.json generated vendored Normal file → Executable file
View File

0
node_modules/asynckit/parallel.js generated vendored Normal file → Executable file
View File

0
node_modules/asynckit/serial.js generated vendored Normal file → Executable file
View File

0
node_modules/asynckit/serialOrdered.js generated vendored Normal file → Executable file
View File

0
node_modules/asynckit/stream.js generated vendored Normal file → Executable file
View File

0
node_modules/axios/CHANGELOG.md generated vendored Normal file → Executable file
View File

0
node_modules/axios/LICENSE generated vendored Normal file → Executable file
View File

0
node_modules/axios/MIGRATION_GUIDE.md generated vendored Normal file → Executable file
View File

0
node_modules/axios/README.md generated vendored Normal file → Executable file
View File

0
node_modules/axios/dist/axios.js generated vendored Normal file → Executable file
View File

0
node_modules/axios/dist/axios.js.map generated vendored Normal file → Executable file
View File

0
node_modules/axios/dist/axios.min.js generated vendored Normal file → Executable file
View File

0
node_modules/axios/dist/axios.min.js.map generated vendored Normal file → Executable file
View File

0
node_modules/axios/dist/browser/axios.cjs generated vendored Normal file → Executable file
View File

0
node_modules/axios/dist/browser/axios.cjs.map generated vendored Normal file → Executable file
View File

0
node_modules/axios/dist/esm/axios.js generated vendored Normal file → Executable file
View File

0
node_modules/axios/dist/esm/axios.js.map generated vendored Normal file → Executable file
View File

0
node_modules/axios/dist/esm/axios.min.js generated vendored Normal file → Executable file
View File

0
node_modules/axios/dist/esm/axios.min.js.map generated vendored Normal file → Executable file
View File

0
node_modules/axios/dist/node/axios.cjs generated vendored Normal file → Executable file
View File

0
node_modules/axios/dist/node/axios.cjs.map generated vendored Normal file → Executable file
View File

0
node_modules/axios/index.d.cts generated vendored Normal file → Executable file
View File

0
node_modules/axios/index.d.ts generated vendored Normal file → Executable file
View File

0
node_modules/axios/index.js generated vendored Normal file → Executable file
View File

0
node_modules/axios/lib/adapters/README.md generated vendored Normal file → Executable file
View File

0
node_modules/axios/lib/adapters/adapters.js generated vendored Normal file → Executable file
View File

0
node_modules/axios/lib/adapters/fetch.js generated vendored Normal file → Executable file
View File

0
node_modules/axios/lib/adapters/xhr.js generated vendored Normal file → Executable file
View File

0
node_modules/axios/lib/axios.js generated vendored Normal file → Executable file
View File

0
node_modules/axios/lib/cancel/CancelToken.js generated vendored Normal file → Executable file
View File

0
node_modules/axios/lib/cancel/CanceledError.js generated vendored Normal file → Executable file
View File

0
node_modules/axios/lib/cancel/isCancel.js generated vendored Normal file → Executable file
View File

0
node_modules/axios/lib/core/Axios.js generated vendored Normal file → Executable file
View File

0
node_modules/axios/lib/core/AxiosError.js generated vendored Normal file → Executable file
View File

0
node_modules/axios/lib/core/AxiosHeaders.js generated vendored Normal file → Executable file
View File

Some files were not shown because too many files have changed in this diff Show More