@20syldev/api 2.7.0 → 2.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/README.md +31 -4
  2. package/app.js +107 -67
  3. package/package.json +13 -12
package/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
  <a href="https://api.sylvain.pro"><img src="https://api.sylvain.pro/favicon.ico" alt="Logo" width="25%" height="auto"/></a>
3
3
 
4
4
  # API Personnelle
5
- [![Version](https://custom-icon-badges.demolab.com/badge/Version%20:-v2.7.0-6479ee?logo=api.sylvain.pro&labelColor=23272A)](https://github.com/20syldev/api/releases/latest)
5
+ [![Version](https://custom-icon-badges.demolab.com/badge/Version%20:-v2.9.0-6479ee?logo=api.sylvain.pro&labelColor=23272A)](https://github.com/20syldev/api/releases/latest)
6
6
  </div>
7
7
 
8
8
  ---
@@ -12,12 +12,39 @@ Voici mon API personnelle, disponible sur le domaine [api.sylvain.pro](https://a
12
12
  L'API est développée avec Node.js et hébergée **24h/7j**. Elle est **simple d'utilisation** et a une **documentation** disponible sur [docs.sylvain.pro](https://docs.sylvain.pro) !
13
13
  > *Une limite de **1000** requêtes maximum chaque **10 secondes** est fixée.*
14
14
 
15
- ## Tester l'API localement
15
+ ## Installer le paquet de l'API sur votre machine
16
+ ```console
17
+ $ sudo apt install nodejs npm
18
+ $ npm install @20syldev/api
19
+ ```
20
+
21
+ Pour utiliser le **paquet** dans votre projet, **créez** un fichier **JavaScript**. Par exemple, `index.js` :
22
+ ```js
23
+ require('@20syldev/api');
24
+ ```
25
+
26
+ Puis, **démarrez** un serveur [Node.js](http://nodejs.org) pour utiliser l'**API** :
27
+ ```console
28
+ $ node index.js
29
+ API is running on
30
+ - http://127.0.0.1:3000
31
+ - http://localhost:3000
32
+ ```
33
+ > *Remplacez `index.js` par le nom de votre fichier JavaScript.*
34
+
35
+ ## Tester l'API sur votre machine
36
+ **Téléchargez** la [dernière mise à jour](https://github.com/20syldev/api/releases/latest) de l'API, puis **extrayez** le contenu du fichier `.zip` ou `.tar.gz` dans un de vos **répertoires**.
37
+ Ensuite, **déplacez-vous** dans le dossier du projet, via un terminal **Linux**, **Windows** ou **macOS** :
38
+ ```console
39
+ $ cd /chemin/vers/le/projet
40
+ ```
41
+
42
+ Enfin, **exécutez** le script de build, qui installera les **dépendances** et lancera le **serveur** de l'[API](https://api.sylvain.pro) :
16
43
  ```console
17
44
  $ npm run build
18
45
  ```
19
46
  ```console
20
- > @20syldev/api@2.7.0 build
47
+ > @20syldev/api@2.9.0 build
21
48
  > npm install && node app.js
22
49
 
23
50
  [...]
@@ -28,4 +55,4 @@ API is running on
28
55
  - http://localhost:3000
29
56
  ```
30
57
 
31
- *Visitez la [documentation](https://docs.sylvain.pro) dédiée, vous y retrouverez des exemples de requêtes et des codes simples pour tester l'[API](https://api.sylvain.pro) !*
58
+ *Visitez la [documentation](https://docs.sylvain.pro) dédiée, vous y retrouverez des exemples de requêtes et des codes simples pour tester l'[API](https://api.sylvain.pro) !*
package/app.js CHANGED
@@ -1,23 +1,35 @@
1
- require('dotenv').config();
2
-
3
- // Built-in module
4
- const crypto = require('crypto');
5
-
6
- // Imported module
7
- const { createCanvas } = require('canvas');
8
- const cors = require('cors');
9
- const express = require('express');
10
- const fetch = require('node-fetch');
11
- const math = require('mathjs');
12
- const path = require('path');
13
- const qrcode = require('qrcode');
14
- const random = require('random');
15
- const uuid = require('uuid');
1
+ import { createCanvas } from 'canvas';
2
+ import cors from 'cors';
3
+ import dotenv from 'dotenv';
4
+ import { randomBytes, getHashes, createHash } from 'crypto';
5
+ import express, { urlencoded, json } from 'express';
6
+ import { factorial } from 'mathjs';
7
+ import fetch from 'node-fetch';
8
+ import { dirname, join } from 'path';
9
+ import { toDataURL } from 'qrcode';
10
+ import { fileURLToPath } from 'url';
11
+ import { v4 } from 'uuid';
12
+
13
+ const __filename = fileURLToPath(import.meta.url);
14
+ const __dirname = dirname(__filename);
16
15
  const app = express();
17
16
 
18
- // Define allowed versions & endpoints
19
- const versions = ['v1'];
20
- const endpoints = ['algorithms', 'captcha', 'chat', 'color', 'convert', 'domain', 'hash', 'infos', 'personal', 'qrcode', 'tic-tac-toe', 'token', 'username', 'website'];
17
+ // Define allowed versions & endpoints for each version
18
+ const versions = ['v1', 'v2'];
19
+ const endpoints = {
20
+ v1: ['algorithms', 'captcha', 'color', 'convert', 'domain', 'infos', 'personal', 'qrcode', 'token', 'username', 'website'],
21
+ v2: ['algorithms', 'captcha', 'chat', 'color', 'convert', 'domain', 'hash', 'infos', 'personal', 'qrcode', 'tic-tac-toe', 'token', 'username', 'website']
22
+ };
23
+
24
+ // Arrowed functions (math & random)
25
+ const gcd = (a, b) => b === 0 ? a : gcd(b, a % b);
26
+ const genID = () => {
27
+ const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
28
+ return Array.from(randomBytes(5)).map(b => chars[b % chars.length]).join('');
29
+ };
30
+ const genIP = () => `${Math.floor(Math.random() * 256)}.${Math.floor(Math.random() * 256)}.${Math.floor(Math.random() * 256)}.${Math.floor(Math.random() * 256)}`;
31
+ const genToken = (chars, length) => Array.from({ length }, () => chars[Math.floor(Math.random() * chars.length)]).join('');
32
+ const random = (arr) => arr[Math.floor(Math.random() * arr.length)];
21
33
 
22
34
  // Store data
23
35
  const logs = [], chat = [], privateChats = {}, sessions = {}, rateLimits = {}, games = {};
@@ -27,16 +39,18 @@ let lastFetch = 0, requests = 0, resetTime = Date.now() + 10000;
27
39
 
28
40
  // ----------- ----------- MIDDLEWARES SETUP ----------- ----------- //
29
41
 
42
+ dotenv.config();
43
+
30
44
  // CORS & Express setup
31
45
  app.use(cors({ methods: ['GET', 'POST'] }));
32
- app.use(express.urlencoded({ extended: true }));
33
- app.use(express.json());
46
+ app.use(urlencoded({ extended: true }));
47
+ app.use(json());
34
48
 
35
49
  // Set favicon for API
36
- app.use('/favicon.ico', express.static(path.join(__dirname, 'src', 'favicon.ico')));
50
+ app.use('/favicon.ico', express.static(join(__dirname, 'src', 'favicon.ico')));
37
51
 
38
52
  // Display robots.txt
39
- app.use('/robots.txt', express.static(path.join(__dirname, 'robots.txt')));
53
+ app.use('/robots.txt', express.static(join(__dirname, 'robots.txt')));
40
54
 
41
55
  // Return formatted JSON
42
56
  app.use((req, res, next) => {
@@ -101,7 +115,7 @@ app.use('/:version', (req, res, next) => {
101
115
  return res.status(404).jsonResponse({
102
116
  message: 'Not Found',
103
117
  error: `Invalid API version (${version}).`,
104
- documentation: 'https://docs.sylvain.pro',
118
+ documentation: `https://docs.sylvain.pro/${versions.at(-1)}`,
105
119
  status: '404'
106
120
  });
107
121
  }
@@ -112,11 +126,11 @@ app.use('/:version', (req, res, next) => {
112
126
  app.use('/:version/:endpoint', (req, res, next) => {
113
127
  const { version, endpoint } = req.params;
114
128
 
115
- if (!versions.includes(version) || !endpoints.includes(endpoint)) {
129
+ if (!versions.includes(version) || !endpoints[version].includes(endpoint)) {
116
130
  return res.status(404).jsonResponse({
117
131
  message: 'Not Found',
118
132
  error: `Endpoint '${endpoint}' does not exist in ${version}.`,
119
- documentation: 'https://docs.sylvain.pro',
133
+ documentation: `https://docs.sylvain.pro/${versions.at(-1)}`,
120
134
  status: '404'
121
135
  });
122
136
  }
@@ -133,7 +147,8 @@ app.get('/', (req, res) => {
133
147
  latest: 'https://api.sylvain.pro/latest',
134
148
  logs: 'https://api.sylvain.pro/logs',
135
149
  versions: {
136
- v1: 'https://api.sylvain.pro/v1'
150
+ v1: 'https://api.sylvain.pro/v1',
151
+ v2: 'https://api.sylvain.pro/v2'
137
152
  }
138
153
  });
139
154
  });
@@ -146,7 +161,6 @@ app.get('/v1', (req, res) => {
146
161
  get: {
147
162
  algorithm: '/v1/algorithms?method={algorithm}&value={value}(&value2={value2})',
148
163
  captcha: '/v1/captcha?text={text}',
149
- chat: '/v1/chat',
150
164
  color: '/v1/color',
151
165
  convert: '/v1/convert?value={value}&from={unit}&to={unit}',
152
166
  domain: '/v1/domain',
@@ -156,14 +170,45 @@ app.get('/v1', (req, res) => {
156
170
  username: '/v1/username'
157
171
  },
158
172
  post: {
159
- chat: '/v1/chat',
160
- hash: '/v1/hash',
161
173
  token: '/v1/token'
162
174
  }
163
175
  }
164
176
  });
165
177
  });
166
178
 
179
+ // Display v2 endpoints
180
+ app.get('/v2', (req, res) => {
181
+ res.jsonResponse({
182
+ version: 'v2',
183
+ endpoints: {
184
+ get: {
185
+ algorithm: '/v2/algorithms?method={algorithm}&value={value}(&value2={value2})',
186
+ captcha: '/v2/captcha?text={text}',
187
+ chat: '/v2/chat',
188
+ color: '/v2/color',
189
+ convert: '/v2/convert?value={value}&from={unit}&to={unit}',
190
+ domain: '/v2/domain',
191
+ infos: '/v2/infos',
192
+ personal: '/v2/personal',
193
+ qrcode: '/v2/qrcode?url={URL}',
194
+ username: '/v2/username'
195
+ },
196
+ post: {
197
+ chat: {
198
+ chat: '/v2/chat',
199
+ private: '/v2/chat/private'
200
+ },
201
+ hash: '/v2/hash',
202
+ tic_tac_toe: {
203
+ tic_tac_toe: '/v2/tic-tac-toe',
204
+ fetch: '/v2/tic-tac-toe/fetch'
205
+ },
206
+ token: '/v2/token'
207
+ }
208
+ }
209
+ });
210
+ });
211
+
167
212
  // Display logs
168
213
  app.get('/logs', (req, res) => res.jsonResponse(logs));
169
214
 
@@ -172,11 +217,12 @@ app.get('/logs', (req, res) => res.jsonResponse(logs));
172
217
  // Algorithms
173
218
  app.get('/:version/algorithms', (req, res) => {
174
219
  const { method, value, value2 } = req.query;
220
+ const { version } = req.params;
175
221
 
176
222
  if (!['anagram', 'bubblesort', 'factorial', 'fibonacci', 'gcd', 'isprime', 'palindrome', 'primefactors', 'primelist', 'reverse'].includes(method)) {
177
223
  return res.jsonResponse({
178
224
  error: 'Please provide a valid algorithm (?method={algorithm})',
179
- documentation: 'https://docs.sylvain.pro/v1/algorithms'
225
+ documentation: `https://docs.sylvain.pro/${version}/algorithms`
180
226
  });
181
227
  }
182
228
  if (!value) return res.jsonResponse({ error: 'Please provide a valid value (&value={value})' });
@@ -199,7 +245,7 @@ app.get('/:version/algorithms', (req, res) => {
199
245
 
200
246
  if (method === 'factorial') {
201
247
  if (isNaN(value) || value < 0 || value > 170) return res.jsonResponse({ error: 'Please provide a valid number between 0 and 170.' });
202
- return res.jsonResponse({ answer: math.factorial(value) });
248
+ return res.jsonResponse({ answer: factorial(value) });
203
249
  }
204
250
 
205
251
  if (method === 'fibonacci') {
@@ -209,7 +255,6 @@ app.get('/:version/algorithms', (req, res) => {
209
255
  }
210
256
 
211
257
  if (method === 'gcd') {
212
- const gcd = (a, b) => b === 0 ? a : gcd(b, a % b);
213
258
  if (!value2) return res.jsonResponse({ error: 'Please provide a second value (&value2={value})' });
214
259
  if (isNaN(value) || isNaN(value2)) return res.jsonResponse({ error: 'Invalid numbers.' });
215
260
  return res.jsonResponse({ answer: gcd(value, value2) });
@@ -320,7 +365,7 @@ app.get('/:version/chat/private', (req, res) => {
320
365
 
321
366
  // Generate color
322
367
  app.get('/:version/color', (req, res) => {
323
- const r = random.int(0, 255), g = random.int(0, 255), b = random.int(0, 255);
368
+ const r = Math.floor(Math.random() * 256), g = Math.floor(Math.random() * 256), b = Math.floor(Math.random() * 256);
324
369
  const hsl = (() => {
325
370
  const r1 = r / 255, g1 = g / 255, b1 = b / 255, max = Math.max(r1, g1, b1), min = Math.min(r1, g1, b1), l = (max + min) / 2;
326
371
  if (max === min) return [0, 0, l * 100];
@@ -373,17 +418,15 @@ app.get('/:version/convert', (req, res) => {
373
418
 
374
419
  // Generate domain informations
375
420
  app.get('/:version/domain', (req, res) => {
376
- const random = (arr) => arr[Math.floor(Math.random() * arr.length)];
377
421
  const subdomains = ['fr.', 'en.', 'docs.', 'api.', 'projects.', 'app.', 'web.', 'info.', 'dev.', 'shop.', 'blog.', 'support.', 'mail.', 'forum.'];
378
422
  const domains = ['example', 'site', 'test', 'demo', 'page', 'store', 'portfolio', 'platform', 'hub', 'network', 'service', 'cloud', 'solutions', 'company'];
379
423
  const tlds = ['.com', '.fr', '.eu', '.dev', '.net', '.org', '.io', '.tech', '.biz', '.info', '.co', '.app', '.store', '.online', '.shop', '.tv'];
380
424
 
381
425
  const domain = `${random(domains)}${random(tlds)}`;
382
426
  const fulldomain = `${random(subdomains)}${domain}`;
383
-
384
- const getRandomIp = () => `${Math.floor(Math.random() * 256)}.${Math.floor(Math.random() * 256)}.${Math.floor(Math.random() * 256)}.${Math.floor(Math.random() * 256)}`;
385
- const ips = Array.from({ length: Math.floor(Math.random() * 3) + 1 }, getRandomIp);
386
- const dns = Array.from({ length: Math.floor(Math.random() * 5) + 1 }, getRandomIp);
427
+
428
+ const ips = Array.from({ length: Math.floor(Math.random() * 3) + 1 }, genIP);
429
+ const dns = Array.from({ length: Math.floor(Math.random() * 5) + 1 }, genIP);
387
430
 
388
431
  res.jsonResponse({
389
432
  domain,
@@ -415,7 +458,7 @@ app.get('/:version/hash', (req, res) => {
415
458
  // Display API informations
416
459
  app.get('/:version/infos', (req, res) => {
417
460
  res.jsonResponse({
418
- endpoints: endpoints.length,
461
+ endpoints: endpoints[versions.at(-1)].length,
419
462
  last_version: versions.at(-1),
420
463
  documentation: 'https://docs.sylvain.pro',
421
464
  github: 'https://github.com/20syldev/api',
@@ -425,8 +468,6 @@ app.get('/:version/infos', (req, res) => {
425
468
 
426
469
  // Generate personal data
427
470
  app.get('/:version/personal', (req, res) => {
428
- const random = (arr) => arr[Math.floor(Math.random() * arr.length)];
429
-
430
471
  const people = [
431
472
  { name: 'John Doe', social: 'john_doe', email: 'john@example.com', country: 'US' },
432
473
  { name: 'Jane Martin', social: 'jane_martin', email: 'jane@example.com', country: 'FR' },
@@ -545,7 +586,7 @@ app.get('/:version/qrcode', async (req, res) => {
545
586
 
546
587
  if (!url) return res.jsonResponse({ error: 'Please provide a valid url (?url={URL})' });
547
588
 
548
- try { res.jsonResponse({ qr: await qrcode.toDataURL(url) }); }
589
+ try { res.jsonResponse({ qr: await toDataURL(url) }); }
549
590
  catch { res.jsonResponse({ error: 'Error generating QR code.' }); }
550
591
  });
551
592
 
@@ -570,7 +611,6 @@ app.get('/:version/username', (req, res) => {
570
611
  const ani = ['Cat', 'Dog', 'Tiger', 'Elephant', 'Monkey', 'Penguin', 'Dolphin', 'Lion', 'Bear', 'Fox', 'Owl', 'Giraffe', 'Zebra', 'Koala', 'Rabbit', 'Squirrel', 'Panda', 'Horse', 'Wolf', 'Eagle'];
571
612
  const job = ['Writer', 'Artist', 'Musician', 'Explorer', 'Scientist', 'Engineer', 'Athlete', 'Chef', 'Doctor', 'Teacher', 'Lawyer', 'Entrepreneur', 'Actor', 'Dancer', 'Photographer', 'Architect', 'Pilot', 'Designer', 'Journalist', 'Veterinarian'];
572
613
 
573
- const random = (arr) => arr[Math.floor(Math.random() * arr.length)];
574
614
  const nombre = Math.floor(Math.random() * 100);
575
615
  const choix = {
576
616
  adj_num: () => random(adj) + nombre,
@@ -651,13 +691,16 @@ app.get('/:version/website', async (req, res) => {
651
691
  doc_coopbot: process.env.DOC_COOPBOT,
652
692
  docs: process.env.DOCS,
653
693
  donut: process.env.DONUT,
694
+ drawio_plugin: process.env.DRAWIO_PLUGIN,
654
695
  flowers: process.env.FLOWERS,
655
696
  gemsync: process.env.GEMSYNC,
656
697
  gitsite: process.env.GITSITE,
657
698
  logs: process.env.LOGS,
699
+ morpion: process.env.MORPION,
658
700
  nitrogen: process.env.NITROGEN,
659
701
  old_database: process.env.OLD_DATABASE,
660
702
  php: process.env.PHP,
703
+ ping: process.env.PING,
661
704
  portfolio: process.env.PORTFOLIO,
662
705
  python_api: process.env.PYTHON_API,
663
706
  readme: process.env.README,
@@ -792,12 +835,7 @@ app.post('/:version/tic-tac-toe/fetch', (req, res) => {
792
835
 
793
836
  if (!username) return res.jsonResponse({ error: 'Please provide a username (?username={username})' });
794
837
 
795
- const generateId = () => {
796
- const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
797
- return Array.from(crypto.randomBytes(5)).map(b => chars[b % chars.length]).join('');
798
- };
799
-
800
- const ID = game || generateId();
838
+ const ID = game || genID();
801
839
  const u = username.toLowerCase(), now = Date.now();
802
840
 
803
841
  rateLimits[u] = (rateLimits[u] || []).filter(ts => now - ts < 10000);
@@ -818,40 +856,42 @@ app.post('/:version/tic-tac-toe/fetch', (req, res) => {
818
856
  // Generate hash
819
857
  app.post('/:version/hash', (req, res) => {
820
858
  const { text, method } = req.body;
859
+ const { version } = req.params;
821
860
 
822
861
  if (!text) return res.jsonResponse({ error: 'Please provide a text (?text={text})' });
823
862
  if (!method) return res.jsonResponse({
824
863
  error: 'Please provide a valid hash algorithm (?method={algorithm})',
825
- documentation: 'https://docs.sylvain.pro/v1/hash'
864
+ documentation: `https://docs.sylvain.pro/${version}/hash`
826
865
  });
827
866
 
828
- const methods = crypto.getHashes();
867
+ const methods = getHashes();
829
868
  if (!methods.includes(method)) return res.jsonResponse({ error: `Unsupported method. Use one of: ${methods.join(', ')}` });
830
869
 
831
- const hash = crypto.createHash(method).update(text).digest('hex');
870
+ const hash = createHash(method).update(text).digest('hex');
832
871
  res.jsonResponse({ method, hash });
833
872
  });
834
873
 
835
874
  // Generate Token
836
875
  app.post('/:version/token', (req, res) => {
837
- const length = parseInt(req.body.len || 24, 10);
838
- const type = req.body.type || 'alpha';
876
+ let { len, type } = req.body;
877
+
878
+ len = parseInt(len || 24, 10);
879
+ type = type ? type.toLowerCase() : 'alpha';
839
880
 
840
- if (isNaN(length) || length < 0) return res.jsonResponse({ error: 'Invalid number.' });
841
- if (length > 4096) return res.jsonResponse({ error: 'Length cannot exceed 4096.' });
842
- if (length < 12) return res.jsonResponse({ error: 'Length cannot be less than 12.' });
881
+ if (isNaN(len) || len < 0) return res.jsonResponse({ error: 'Invalid number.' });
882
+ if (len > 4096) return res.jsonResponse({ error: 'Length cannot exceed 4096.' });
883
+ if (len < 12) return res.jsonResponse({ error: 'Length cannot be less than 12.' });
843
884
 
844
- const generateToken = (chars) => Array.from({ length }, () => chars[Math.floor(Math.random() * chars.length)]).join('');
845
885
  const token = {
846
- alpha: generateToken('abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'),
847
- alphanum: generateToken('abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'),
848
- base64: crypto.randomBytes(length).toString('base64').slice(0, length),
849
- hex: crypto.randomBytes(length).toString('hex').slice(0, length),
850
- num: generateToken('0123456789'),
851
- punct: generateToken('!"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~'),
852
- urlsafe: generateToken('abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_'),
853
- uuid: uuid.v4().replace(/-/g, '').slice(0, length)
854
- }[type] || generateToken('abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789');
886
+ alpha: genToken('abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ', len),
887
+ alphanum: genToken('abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789', len),
888
+ base64: randomBytes(len).toString('base64').slice(0, len),
889
+ hex: randomBytes(len).toString('hex').slice(0, len),
890
+ num: genToken('0123456789', len),
891
+ punct: genToken('!"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~', len),
892
+ urlsafe: genToken('abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_', len),
893
+ uuid: v4().replace(/-/g, '').slice(0, len)
894
+ }[type] || genToken('abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789', len);
855
895
 
856
896
  res.jsonResponse({ token });
857
897
  });
package/package.json CHANGED
@@ -1,8 +1,9 @@
1
1
  {
2
- "version": "2.7.0",
2
+ "version": "2.9.0",
3
3
  "name": "@20syldev/api",
4
- "description": "Personnal API",
4
+ "description": "Node.js API with multiple features. Check the documentation at https://docs.sylvain.pro",
5
5
  "main": "app.js",
6
+ "type": "module",
6
7
  "scripts": {
7
8
  "start": "node app.js",
8
9
  "build": "npm install && node app.js",
@@ -11,16 +12,16 @@
11
12
  "upgrade:build": "npm upgrade && npm install && node app.js"
12
13
  },
13
14
  "dependencies": {
14
- "canvas": "^3.1.0",
15
- "cors": "2.8.5",
16
- "dotenv": "^16.4.7",
17
- "express": "^4.21.2",
18
- "mathjs": "^14.2.0",
19
- "node-fetch": "^2.7.0",
20
- "prettier": "^3.4.2",
21
- "qrcode": "^1.5.4",
22
- "random": "^5.1.1",
23
- "uuid": "^11.0.5"
15
+ "canvas": "latest",
16
+ "cors": "latest",
17
+ "dotenv": "latest",
18
+ "express": "latest",
19
+ "mathjs": "latest",
20
+ "node-fetch": "latest",
21
+ "prettier": "latest",
22
+ "qrcode": "latest",
23
+ "random": "latest",
24
+ "uuid": "latest"
24
25
  },
25
26
  "repository": {
26
27
  "type": "git",