Removing all global variables and add database insertion of access token

main
Félix MIELCAREK 12 months ago
parent c0dbba4e10
commit 17d3c0d12f

@ -4,26 +4,23 @@ const fs = require('node:fs');
const path = require('path'); const path = require('path');
//#endregion //#endregion
//#region VARIABLES //#region CONSTANTS
const commonDir = path.join(__dirname, '../common'); const commonDir = path.join(__dirname, '../common');
const spotifyRequestsLimit = 50; const spotifyRequestsLimit = 50;
const thresholdLove = 0.6; const thresholdLove = 0.6;
//#endregion
var albums = {}; //#region STRUCTURE
var albumDataStructure = { var albumDataStructure = {
savedTracks: [], savedTracks: [],
totalTracks: 0, totalTracks: 0,
name: "", name: "",
artistsNames: [] artistsNames: []
}; };
var accessToken;
try { accessToken = fs.readFileSync(commonDir + '/spotify_access_token', 'utf8') }
catch (err) { console.error(err) }
//#endregion //#endregion
//#region GET SAVED TRACKS //#region GET SAVED TRACKS
async function getOffsetSavedTracks(href=`https://api.spotify.com/v1/me/tracks?offset=0&limit=${spotifyRequestsLimit}`) { async function getSavedTracks(accessToken, albums, href=`https://api.spotify.com/v1/me/tracks?offset=0&limit=${spotifyRequestsLimit}`) {
try { try {
const response = await axios.get(href, { headers: { 'Authorization': 'Bearer ' + accessToken, } }); const response = await axios.get(href, { headers: { 'Authorization': 'Bearer ' + accessToken, } });
response.data.items.forEach(t => { response.data.items.forEach(t => {
@ -40,23 +37,19 @@ async function getOffsetSavedTracks(href=`https://api.spotify.com/v1/me/tracks?o
albums[t.track.album.id].savedTracks.push(t.track.id); albums[t.track.album.id].savedTracks.push(t.track.id);
} }
}); });
if(response.data.next) await getOffsetSavedTracks(response.data.next); if(response.data.next) await getSavedTracks(accessToken, albums, response.data.next);
} catch (error) { webError("Get saved tracks", error) } } catch (error) { webError("Get saved tracks", error) }
} }
async function getSavedTracks() {
await getOffsetSavedTracks();
}
//#endregion //#endregion
//#region TRESHOLD ALGORITHM //#region TRESHOLD ALGORITHM
async function addAlbums(idsString) { async function addAlbums(accessToken, idsString) {
try { try {
await axios.put(`https://api.spotify.com/v1/me/albums?ids=${idsString}`, { x: 'x' } , { headers: { 'Authorization': 'Bearer ' + accessToken, } }); await axios.put(`https://api.spotify.com/v1/me/albums?ids=${idsString}`, { x: 'x' } , { headers: { 'Authorization': 'Bearer ' + accessToken, } });
} catch (error) { webError("Check and add album", error) } } catch (error) { webError("Check and add album", error) }
} }
async function tresholdAlgorithm() { async function tresholdAlgorithm(albums, accessToken) {
var lovedAlbum = [] var lovedAlbum = []
for(let album in albums) { for(let album in albums) {
if(albums[album].savedTracks.length >= albums[album].totalTracks * thresholdLove) { if(albums[album].savedTracks.length >= albums[album].totalTracks * thresholdLove) {
@ -73,25 +66,25 @@ async function tresholdAlgorithm() {
idsCounter = idsCounter+1; idsCounter = idsCounter+1;
if(idsCounter == 20){ if(idsCounter == 20){
await addAlbums(idsString); await addAlbums(accessToken, idsString);
idsString = ""; idsString = "";
idsList = []; idsList = [];
idsCounter = 0; idsCounter = 0;
} }
} }
if(idsCounter > 0) if(idsCounter > 0)
await addAlbums(idsString); await addAlbums(accessToken, idsString);
} }
//#endregion //#endregion
//#region REMOVE SAVED TRACKS FROM SAVED ALBUMS //#region REMOVE SAVED TRACKS FROM SAVED ALBUMS
async function removeTracks(idsToDelete) { async function removeTracks(accessToken, idsToDelete) {
try { try {
await axios.delete(`https://api.spotify.com/v1/me/tracks?ids=${idsToDelete}`, { headers: { 'Authorization': 'Bearer ' + accessToken, } }); await axios.delete(`https://api.spotify.com/v1/me/tracks?ids=${idsToDelete}`, { headers: { 'Authorization': 'Bearer ' + accessToken, } });
} catch (error) { webError("Remove tracks", error) } } catch (error) { webError("Remove tracks", error) }
} }
async function checkAlbums(idsString, idsList) { async function checkAlbums(accessToken, idsString, idsList, albums) {
try { try {
const response = await axios.get(`https://api.spotify.com/v1/me/albums/contains?ids=${idsString}`, { headers: { 'Authorization': 'Bearer ' + accessToken, } }); const response = await axios.get(`https://api.spotify.com/v1/me/albums/contains?ids=${idsString}`, { headers: { 'Authorization': 'Bearer ' + accessToken, } });
@ -103,7 +96,7 @@ async function checkAlbums(idsString, idsList) {
idsToDelete = idsToDelete.concat(track, ','); idsToDelete = idsToDelete.concat(track, ',');
idsCounter = idsCounter+1; idsCounter = idsCounter+1;
if(idsCounter == 50) { if(idsCounter == 50) {
await removeTracks(idsToDelete); await removeTracks(accessToken, idsToDelete);
var idsToDelete = ""; var idsToDelete = "";
var idsCounter = 0; var idsCounter = 0;
} }
@ -111,11 +104,11 @@ async function checkAlbums(idsString, idsList) {
} }
} }
if(idsCounter > 0) if(idsCounter > 0)
await removeTracks(idsToDelete); await removeTracks(accessToken, idsToDelete);
} catch (error) { webError("Check albums", error) } } catch (error) { webError("Check albums", error) }
} }
async function removeTracksAlgorithm() { async function removeTracksAlgorithm(albums, accessToken) {
var idsString = ""; var idsString = "";
var idsList = []; var idsList = [];
var idsCounter = 0; var idsCounter = 0;
@ -126,7 +119,7 @@ async function removeTracksAlgorithm() {
idsCounter = idsCounter+1; idsCounter = idsCounter+1;
if(idsCounter == 20){ if(idsCounter == 20){
await checkAlbums(idsString, idsList); await checkAlbums(accessToken, idsString, idsList, albums);
idsString = ""; idsString = "";
idsList = []; idsList = [];
@ -134,7 +127,7 @@ async function removeTracksAlgorithm() {
} }
} }
if(idsCounter > 0) if(idsCounter > 0)
await checkAlbums(idsString, idsList); await checkAlbums(accessToken, idsString, idsList, albums);
} }
//#endregion //#endregion
@ -152,23 +145,32 @@ function stepBeggining(step) {
const sptor = "=".repeat(5); const sptor = "=".repeat(5);
console.log(`\n${sptor} ${step} ${sptor}`); console.log(`\n${sptor} ${step} ${sptor}`);
} }
async function stepExecution(stepName, stepFunc) {
stepBeggining(stepName);
await stepFunc()
stepSuccess(stepName);
}
//#endregion //#endregion
//#region MAIN //#region MAIN
async function main() { async function main() {
var albums = {};
var accessToken;
try { accessToken = fs.readFileSync(commonDir + '/spotify_access_token', 'utf8') }
catch (err) { console.error(err) }
// ======================================================
const step1 = "Get liked tracks"; const step1 = "Get liked tracks";
const step2 = "Apply treshold algorithm"; const step2 = "Apply treshold algorithm";
const step3 = "Remove saved tracks from saved albums"; const step3 = "Remove saved tracks from saved albums";
try { try {
await stepExecution(step1, getSavedTracks); stepBeggining(step1);
await stepExecution(step2, tresholdAlgorithm); await getSavedTracks(accessToken, albums);
await stepExecution(step3, removeTracksAlgorithm); stepSuccess(step1);
stepBeggining(step2);
await tresholdAlgorithm(albums, accessToken);
stepSuccess(step2);
stepBeggining(step3);
await removeTracksAlgorithm(albums, accessToken);
stepSuccess(step3);
} catch (error) { } } catch (error) { }
} }
//#endregion //#endregion

@ -9,7 +9,8 @@
"version": "1.0.0", "version": "1.0.0",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"axios": "^1.6.7" "axios": "^1.6.7",
"pg": "^8.11.5"
}, },
"devDependencies": { "devDependencies": {
"jest": "^29.7.0" "jest": "^29.7.0"
@ -3141,6 +3142,87 @@
"integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
"dev": true "dev": true
}, },
"node_modules/pg": {
"version": "8.11.5",
"resolved": "https://registry.npmjs.org/pg/-/pg-8.11.5.tgz",
"integrity": "sha512-jqgNHSKL5cbDjFlHyYsCXmQDrfIX/3RsNwYqpd4N0Kt8niLuNoRNH+aazv6cOd43gPh9Y4DjQCtb+X0MH0Hvnw==",
"dependencies": {
"pg-connection-string": "^2.6.4",
"pg-pool": "^3.6.2",
"pg-protocol": "^1.6.1",
"pg-types": "^2.1.0",
"pgpass": "1.x"
},
"engines": {
"node": ">= 8.0.0"
},
"optionalDependencies": {
"pg-cloudflare": "^1.1.1"
},
"peerDependencies": {
"pg-native": ">=3.0.1"
},
"peerDependenciesMeta": {
"pg-native": {
"optional": true
}
}
},
"node_modules/pg-cloudflare": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/pg-cloudflare/-/pg-cloudflare-1.1.1.tgz",
"integrity": "sha512-xWPagP/4B6BgFO+EKz3JONXv3YDgvkbVrGw2mTo3D6tVDQRh1e7cqVGvyR3BE+eQgAvx1XhW/iEASj4/jCWl3Q==",
"optional": true
},
"node_modules/pg-connection-string": {
"version": "2.6.4",
"resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.6.4.tgz",
"integrity": "sha512-v+Z7W/0EO707aNMaAEfiGnGL9sxxumwLl2fJvCQtMn9Fxsg+lPpPkdcyBSv/KFgpGdYkMfn+EI1Or2EHjpgLCA=="
},
"node_modules/pg-int8": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/pg-int8/-/pg-int8-1.0.1.tgz",
"integrity": "sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==",
"engines": {
"node": ">=4.0.0"
}
},
"node_modules/pg-pool": {
"version": "3.6.2",
"resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-3.6.2.tgz",
"integrity": "sha512-Htjbg8BlwXqSBQ9V8Vjtc+vzf/6fVUuak/3/XXKA9oxZprwW3IMDQTGHP+KDmVL7rtd+R1QjbnCFPuTHm3G4hg==",
"peerDependencies": {
"pg": ">=8.0"
}
},
"node_modules/pg-protocol": {
"version": "1.6.1",
"resolved": "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.6.1.tgz",
"integrity": "sha512-jPIlvgoD63hrEuihvIg+tJhoGjUsLPn6poJY9N5CnlPd91c2T18T/9zBtLxZSb1EhYxBRoZJtzScCaWlYLtktg=="
},
"node_modules/pg-types": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/pg-types/-/pg-types-2.2.0.tgz",
"integrity": "sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==",
"dependencies": {
"pg-int8": "1.0.1",
"postgres-array": "~2.0.0",
"postgres-bytea": "~1.0.0",
"postgres-date": "~1.0.4",
"postgres-interval": "^1.1.0"
},
"engines": {
"node": ">=4"
}
},
"node_modules/pgpass": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/pgpass/-/pgpass-1.0.5.tgz",
"integrity": "sha512-FdW9r/jQZhSeohs1Z3sI1yxFQNFvMcnmfuj4WBMUTxOrAyLMaTcE1aAMBiTlbMNaXvBCQuVi0R7hd8udDSP7ug==",
"dependencies": {
"split2": "^4.1.0"
}
},
"node_modules/picocolors": { "node_modules/picocolors": {
"version": "1.0.0", "version": "1.0.0",
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz",
@ -3180,6 +3262,41 @@
"node": ">=8" "node": ">=8"
} }
}, },
"node_modules/postgres-array": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-2.0.0.tgz",
"integrity": "sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==",
"engines": {
"node": ">=4"
}
},
"node_modules/postgres-bytea": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-1.0.0.tgz",
"integrity": "sha512-xy3pmLuQqRBZBXDULy7KbaitYqLcmxigw14Q5sj8QBVLqEwXfeybIKVWiqAXTlcvdvb0+xkOtDbfQMOf4lST1w==",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/postgres-date": {
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/postgres-date/-/postgres-date-1.0.7.tgz",
"integrity": "sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q==",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/postgres-interval": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/postgres-interval/-/postgres-interval-1.2.0.tgz",
"integrity": "sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==",
"dependencies": {
"xtend": "^4.0.0"
},
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/pretty-format": { "node_modules/pretty-format": {
"version": "29.7.0", "version": "29.7.0",
"resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz",
@ -3372,6 +3489,14 @@
"source-map": "^0.6.0" "source-map": "^0.6.0"
} }
}, },
"node_modules/split2": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz",
"integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==",
"engines": {
"node": ">= 10.x"
}
},
"node_modules/sprintf-js": { "node_modules/sprintf-js": {
"version": "1.0.3", "version": "1.0.3",
"resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
@ -3655,6 +3780,14 @@
"node": "^12.13.0 || ^14.15.0 || >=16.0.0" "node": "^12.13.0 || ^14.15.0 || >=16.0.0"
} }
}, },
"node_modules/xtend": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
"integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==",
"engines": {
"node": ">=0.4"
}
},
"node_modules/y18n": { "node_modules/y18n": {
"version": "5.0.8", "version": "5.0.8",
"resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",

@ -13,7 +13,8 @@
"author": "Félix Mielcarek", "author": "Félix Mielcarek",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"axios": "^1.6.7" "axios": "^1.6.7",
"pg": "^8.11.5"
}, },
"devDependencies": { "devDependencies": {
"jest": "^29.7.0" "jest": "^29.7.0"

@ -5,6 +5,7 @@ const cookieParser = require('cookie-parser');
const axios = require('axios'); const axios = require('axios');
const queryString = require('querystring'); const queryString = require('querystring');
const fs = require('node:fs'); const fs = require('node:fs');
const pg = require('pg');
//#endregion //#endregion
//#region CONSTANTS //#region CONSTANTS
@ -15,6 +16,18 @@ const clientId = process.env.CLIENT_ID;
const clientSecret = process.env.CLIENT_SECRET; const clientSecret = process.env.CLIENT_SECRET;
const redirectUri = 'http://localhost:3000/callback'; const redirectUri = 'http://localhost:3000/callback';
const scope = 'user-read-private user-read-email user-library-read user-library-modify'; const scope = 'user-read-private user-read-email user-library-read user-library-modify';
const { Client } = pg
const client = new Client({
user: process.env.DB_USER,
host: 'localhost',
database: 'bigbrother',
password: process.env.DB_PASSWORD,
port: 5432
})
//#endregion
//#region VARIABLES
let state = '';
//#endregion //#endregion
//#region APP INIT //#region APP INIT
@ -44,7 +57,7 @@ function generateRandomString(length) {
} }
app.get('/login', function (req, res) { app.get('/login', function (req, res) {
const state = generateRandomString(16); state = generateRandomString(16);
res.redirect('https://accounts.spotify.com/authorize?' + res.redirect('https://accounts.spotify.com/authorize?' +
queryString.stringify({ queryString.stringify({
@ -60,8 +73,12 @@ app.get('/login', function (req, res) {
//#region ACCESS TOKEN //#region ACCESS TOKEN
app.get('/callback', (req, res) => { app.get('/callback', (req, res) => {
res.cookie('account', 'true', { maxAge: 360000 }); res.cookie('account', 'true', { maxAge: 360000 });
const code = req.query.code; const code = req.query.code;
const state = req.query.state; if(state != req.query.state) {
console.error("Spotify state error.")
return
}
res.redirect('/'); res.redirect('/');
@ -81,14 +98,43 @@ app.get('/callback', (req, res) => {
}; };
axios(authOptions) axios(authOptions)
.then(response => { .then(async response => {
fs.writeFile(commonDir + '/spotify_access_token', response.data.access_token, err => { /*fs.writeFile(commonDir + '/spotify_access_token', response.data.access_token, err => {
if (err) { if (err) {
console.error(err); console.error(err);
} else { } else {
console.log("Spotify access token recovered.") console.log("Spotify access token recovered.")
} }
}); });*/
const accessToken = response.data.access_token
try {
const response = await axios.get(`https://api.spotify.com/v1/me`, { headers: { 'Authorization': 'Bearer ' + accessToken, } });
const data = {
SpotifyId: response.data.id,
AccessToken: accessToken
};
await client.connect()
const sqlQuery = `
INSERT INTO public.users (spotifyid,accesstoken)
VALUES ($1,$2)
ON CONFLICT (spotifyid) DO UPDATE SET
accesstoken = EXCLUDED.accesstoken
`;
client.query(sqlQuery, [data.SpotifyId, data.AccessToken], (err, res) => {
if (err) {
console.error('Error executing query', err);
return;
}
console.log('Data inserted/updated successfully');
client.end();
});
} catch (error) { console.log('Error getting user Spotify id') }
}) })
.catch(error => { .catch(error => {
console.log('Error:', error); console.log('Error:', error);

@ -7,7 +7,8 @@
"dependencies": { "dependencies": {
"axios": "^1.6.7", "axios": "^1.6.7",
"cookie-parser": "^1.4.6", "cookie-parser": "^1.4.6",
"express": "^4.18.3" "express": "^4.18.3",
"pg": "^8.11.5"
} }
}, },
"node_modules/accepts": { "node_modules/accepts": {
@ -570,6 +571,122 @@
"resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz",
"integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==" "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ=="
}, },
"node_modules/pg": {
"version": "8.11.5",
"resolved": "https://registry.npmjs.org/pg/-/pg-8.11.5.tgz",
"integrity": "sha512-jqgNHSKL5cbDjFlHyYsCXmQDrfIX/3RsNwYqpd4N0Kt8niLuNoRNH+aazv6cOd43gPh9Y4DjQCtb+X0MH0Hvnw==",
"dependencies": {
"pg-connection-string": "^2.6.4",
"pg-pool": "^3.6.2",
"pg-protocol": "^1.6.1",
"pg-types": "^2.1.0",
"pgpass": "1.x"
},
"engines": {
"node": ">= 8.0.0"
},
"optionalDependencies": {
"pg-cloudflare": "^1.1.1"
},
"peerDependencies": {
"pg-native": ">=3.0.1"
},
"peerDependenciesMeta": {
"pg-native": {
"optional": true
}
}
},
"node_modules/pg-cloudflare": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/pg-cloudflare/-/pg-cloudflare-1.1.1.tgz",
"integrity": "sha512-xWPagP/4B6BgFO+EKz3JONXv3YDgvkbVrGw2mTo3D6tVDQRh1e7cqVGvyR3BE+eQgAvx1XhW/iEASj4/jCWl3Q==",
"optional": true
},
"node_modules/pg-connection-string": {
"version": "2.6.4",
"resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.6.4.tgz",
"integrity": "sha512-v+Z7W/0EO707aNMaAEfiGnGL9sxxumwLl2fJvCQtMn9Fxsg+lPpPkdcyBSv/KFgpGdYkMfn+EI1Or2EHjpgLCA=="
},
"node_modules/pg-int8": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/pg-int8/-/pg-int8-1.0.1.tgz",
"integrity": "sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==",
"engines": {
"node": ">=4.0.0"
}
},
"node_modules/pg-pool": {
"version": "3.6.2",
"resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-3.6.2.tgz",
"integrity": "sha512-Htjbg8BlwXqSBQ9V8Vjtc+vzf/6fVUuak/3/XXKA9oxZprwW3IMDQTGHP+KDmVL7rtd+R1QjbnCFPuTHm3G4hg==",
"peerDependencies": {
"pg": ">=8.0"
}
},
"node_modules/pg-protocol": {
"version": "1.6.1",
"resolved": "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.6.1.tgz",
"integrity": "sha512-jPIlvgoD63hrEuihvIg+tJhoGjUsLPn6poJY9N5CnlPd91c2T18T/9zBtLxZSb1EhYxBRoZJtzScCaWlYLtktg=="
},
"node_modules/pg-types": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/pg-types/-/pg-types-2.2.0.tgz",
"integrity": "sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==",
"dependencies": {
"pg-int8": "1.0.1",
"postgres-array": "~2.0.0",
"postgres-bytea": "~1.0.0",
"postgres-date": "~1.0.4",
"postgres-interval": "^1.1.0"
},
"engines": {
"node": ">=4"
}
},
"node_modules/pgpass": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/pgpass/-/pgpass-1.0.5.tgz",
"integrity": "sha512-FdW9r/jQZhSeohs1Z3sI1yxFQNFvMcnmfuj4WBMUTxOrAyLMaTcE1aAMBiTlbMNaXvBCQuVi0R7hd8udDSP7ug==",
"dependencies": {
"split2": "^4.1.0"
}
},
"node_modules/postgres-array": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-2.0.0.tgz",
"integrity": "sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==",
"engines": {
"node": ">=4"
}
},
"node_modules/postgres-bytea": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-1.0.0.tgz",
"integrity": "sha512-xy3pmLuQqRBZBXDULy7KbaitYqLcmxigw14Q5sj8QBVLqEwXfeybIKVWiqAXTlcvdvb0+xkOtDbfQMOf4lST1w==",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/postgres-date": {
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/postgres-date/-/postgres-date-1.0.7.tgz",
"integrity": "sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q==",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/postgres-interval": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/postgres-interval/-/postgres-interval-1.2.0.tgz",
"integrity": "sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==",
"dependencies": {
"xtend": "^4.0.0"
},
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/proxy-addr": { "node_modules/proxy-addr": {
"version": "2.0.7", "version": "2.0.7",
"resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz",
@ -727,6 +844,14 @@
"url": "https://github.com/sponsors/ljharb" "url": "https://github.com/sponsors/ljharb"
} }
}, },
"node_modules/split2": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz",
"integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==",
"engines": {
"node": ">= 10.x"
}
},
"node_modules/statuses": { "node_modules/statuses": {
"version": "2.0.1", "version": "2.0.1",
"resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz",
@ -778,6 +903,14 @@
"engines": { "engines": {
"node": ">= 0.8" "node": ">= 0.8"
} }
},
"node_modules/xtend": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
"integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==",
"engines": {
"node": ">=0.4"
}
} }
} }
} }

@ -2,6 +2,7 @@
"dependencies": { "dependencies": {
"axios": "^1.6.7", "axios": "^1.6.7",
"cookie-parser": "^1.4.6", "cookie-parser": "^1.4.6",
"express": "^4.18.3" "express": "^4.18.3",
"pg": "^8.11.5"
} }
} }

Loading…
Cancel
Save