@20syldev/api 3.4.0 → 3.4.1
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.
- package/.github/FUNDING.yml +1 -1
- package/.github/workflows/publish.yml +27 -27
- package/LICENSE +27 -27
- package/README.md +110 -110
- package/app.js +818 -817
- package/modules/v3/algorithms.js +217 -217
- package/modules/v3/captcha.js +54 -54
- package/modules/v3/chat.js +108 -108
- package/modules/v3/color.js +40 -40
- package/modules/v3/convert.js +38 -38
- package/modules/v3/domain.js +38 -38
- package/modules/v3/hash.js +15 -15
- package/modules/v3/hyperplanning.js +50 -50
- package/modules/v3/levenshtein.js +45 -45
- package/modules/v3/personal.js +126 -126
- package/modules/v3/qrcode.js +19 -19
- package/modules/v3/tic_tac_toe.js +166 -166
- package/modules/v3/time.js +86 -86
- package/modules/v3/token.js +47 -47
- package/modules/v3/username.js +31 -31
- package/modules/v3/utils.js +65 -65
- package/modules/v3.js +14 -14
- package/package.json +53 -53
- package/robots.txt +73 -73
|
@@ -1,167 +1,167 @@
|
|
|
1
|
-
import { randomBytes } from 'crypto';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Manages a Tic-Tac-Toe game session
|
|
5
|
-
*
|
|
6
|
-
* @param {string} action - The action to perform ('play' or 'fetch')
|
|
7
|
-
* @param {Object} params - The parameters for the action
|
|
8
|
-
* @returns {Object} - The result of the action
|
|
9
|
-
* @throws {Error} - If parameters are invalid
|
|
10
|
-
*/
|
|
11
|
-
export default function tic_tac_toe(action, params = {}) {
|
|
12
|
-
// In-memory storage
|
|
13
|
-
const storage = params.storage || {};
|
|
14
|
-
|
|
15
|
-
// Initialize storage
|
|
16
|
-
storage.games ??= {};
|
|
17
|
-
storage.sessions ??= {};
|
|
18
|
-
storage.rateLimits ??= {};
|
|
19
|
-
|
|
20
|
-
// Reference the storage properties
|
|
21
|
-
const { games, sessions, rateLimits } = storage;
|
|
22
|
-
|
|
23
|
-
// Input validation for common parameters
|
|
24
|
-
if (!params.username) throw new Error('Please provide a username');
|
|
25
|
-
|
|
26
|
-
const u = params.username.toLowerCase();
|
|
27
|
-
const now = Date.now();
|
|
28
|
-
|
|
29
|
-
// Rate limiting
|
|
30
|
-
rateLimits[u] = (rateLimits[u] || []).filter(ts => now - ts < 10000);
|
|
31
|
-
if (rateLimits[u].length > 50) {
|
|
32
|
-
const remainingTime = Math.ceil((rateLimits[u][0] + 10000 - now) / 1000);
|
|
33
|
-
throw new Error(`Rate limit exceeded. Try again in ${remainingTime} seconds.`);
|
|
34
|
-
}
|
|
35
|
-
rateLimits[u].push(now);
|
|
36
|
-
|
|
37
|
-
// Handle different actions
|
|
38
|
-
if (action === 'play') {
|
|
39
|
-
return playMove(params, games, sessions, u, now);
|
|
40
|
-
} else if (action === 'fetch') {
|
|
41
|
-
return fetchGame(params, games, u);
|
|
42
|
-
} else {
|
|
43
|
-
throw new Error('Invalid action. Use "play" or "fetch"');
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
/**
|
|
48
|
-
* Process a player's move
|
|
49
|
-
*/
|
|
50
|
-
function playMove(params, games, sessions, u, now) {
|
|
51
|
-
const { move, session, game } = params;
|
|
52
|
-
const validMoves = ['1-1', '1-2', '1-3', '2-1', '2-2', '2-3', '3-1', '3-2', '3-3'];
|
|
53
|
-
|
|
54
|
-
// Input validation for play action
|
|
55
|
-
if (!move) throw new Error('Please provide a valid move');
|
|
56
|
-
if (!session) throw new Error('Please provide a valid session ID');
|
|
57
|
-
if (!game) throw new Error('Please provide a valid game ID');
|
|
58
|
-
if (!validMoves.includes(move)) throw new Error('Invalid move. Please provide a valid move (e.g., 1-1, 2-2, 3-3).');
|
|
59
|
-
|
|
60
|
-
// Session validation
|
|
61
|
-
if (sessions[u] && sessions[u].user !== session) {
|
|
62
|
-
throw new Error('Session ID mismatch');
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
// Initialize game if needed
|
|
66
|
-
games[game] = games[game] || [];
|
|
67
|
-
|
|
68
|
-
// Check if game is full
|
|
69
|
-
const players = [...new Set(games[game].map(play => play.username))];
|
|
70
|
-
if (players.length >= 2 && !players.includes(params.username)) {
|
|
71
|
-
throw new Error('Game is full, you can only watch.');
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
// Check if it's player's turn
|
|
75
|
-
if (games[game].length > 0 && games[game][games[game].length - 1].username === params.username) {
|
|
76
|
-
throw new Error('Please wait for the other player to make a move.');
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
// Check if move is already made
|
|
80
|
-
if (games[game].some(play => play.move === move)) {
|
|
81
|
-
throw new Error('Move already made. Please choose a different move.');
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
// Add move to game
|
|
85
|
-
const play = { username: params.username, move, session };
|
|
86
|
-
games[game].push(play);
|
|
87
|
-
|
|
88
|
-
// Check game result
|
|
89
|
-
const result = checkGame(games[game]);
|
|
90
|
-
if (result.winner || result.tie) {
|
|
91
|
-
setTimeout(() => delete games[game], 600000);
|
|
92
|
-
return {
|
|
93
|
-
message: `Move sent successfully. ${result.winner ? result.winner + ' wins. ' + result.loser + ' loses.' : 'It\'s a tie.'}`,
|
|
94
|
-
...result
|
|
95
|
-
};
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
// Set cleanup timeout
|
|
99
|
-
setTimeout(() => delete games[game], 3600000);
|
|
100
|
-
|
|
101
|
-
// Update session
|
|
102
|
-
sessions[u] = sessions[u] || { user: session, last: now };
|
|
103
|
-
sessions[u].last = now;
|
|
104
|
-
setTimeout(() => { if (now - sessions[u].last >= 3600000) delete sessions[u]; }, 3600000);
|
|
105
|
-
|
|
106
|
-
return { message: 'Move sent successfully' };
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
/**
|
|
110
|
-
* Fetch a game state
|
|
111
|
-
*/
|
|
112
|
-
function fetchGame(params, games, u) {
|
|
113
|
-
const ID = params.game || generateGameId();
|
|
114
|
-
|
|
115
|
-
// Initialize game if needed
|
|
116
|
-
if (!games[ID]) games[ID] = [];
|
|
117
|
-
|
|
118
|
-
const data = games[ID];
|
|
119
|
-
const last = data.length ? data[data.length - 1].username : null;
|
|
120
|
-
const players = [...new Set(data.map(p => p.username))];
|
|
121
|
-
const turn = players.find(p => p !== last);
|
|
122
|
-
const result = data.length ? checkGame(data) : {};
|
|
123
|
-
|
|
124
|
-
return { game: data, turn, ID, ...result };
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
/**
|
|
128
|
-
* Generate a random game ID
|
|
129
|
-
*/
|
|
130
|
-
function generateGameId() {
|
|
131
|
-
const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
|
|
132
|
-
return Array.from(randomBytes(5)).map(b => chars[b % chars.length]).join('');
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
/**
|
|
136
|
-
* Check the game result
|
|
137
|
-
*/
|
|
138
|
-
function checkGame(moves) {
|
|
139
|
-
let board = Array(3).fill().map(() => Array(3).fill(null));
|
|
140
|
-
let playerSymbols = {};
|
|
141
|
-
let playersOrder = [];
|
|
142
|
-
|
|
143
|
-
moves.forEach(({ username, move }) => {
|
|
144
|
-
if (!playerSymbols[username]) {
|
|
145
|
-
playersOrder.push(username);
|
|
146
|
-
playerSymbols[username] = playersOrder.length === 1 ? 'X' : 'O';
|
|
147
|
-
}
|
|
148
|
-
let [row, col] = move.split('-').map(Number);
|
|
149
|
-
board[row - 1][col - 1] = playerSymbols[username];
|
|
150
|
-
});
|
|
151
|
-
|
|
152
|
-
const checkWinner = (symbol) => {
|
|
153
|
-
for (let i = 0; i < 3; i++) {
|
|
154
|
-
if (board[i][0] === symbol && board[i][1] === symbol && board[i][2] === symbol) return true;
|
|
155
|
-
if (board[0][i] === symbol && board[1][i] === symbol && board[2][i] === symbol) return true;
|
|
156
|
-
}
|
|
157
|
-
if (board[0][0] === symbol && board[1][1] === symbol && board[2][2] === symbol) return true;
|
|
158
|
-
if (board[0][2] === symbol && board[1][1] === symbol && board[2][0] === symbol) return true;
|
|
159
|
-
return false;
|
|
160
|
-
};
|
|
161
|
-
|
|
162
|
-
let winner = Object.keys(playerSymbols).find(player => checkWinner(playerSymbols[player]));
|
|
163
|
-
let isTie = !winner && moves.length === 9;
|
|
164
|
-
let loser = winner && playersOrder.length === 2 ? playersOrder.find(player => player !== winner) : null;
|
|
165
|
-
|
|
166
|
-
return { winner, loser, tie: isTie };
|
|
1
|
+
import { randomBytes } from 'crypto';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Manages a Tic-Tac-Toe game session
|
|
5
|
+
*
|
|
6
|
+
* @param {string} action - The action to perform ('play' or 'fetch')
|
|
7
|
+
* @param {Object} params - The parameters for the action
|
|
8
|
+
* @returns {Object} - The result of the action
|
|
9
|
+
* @throws {Error} - If parameters are invalid
|
|
10
|
+
*/
|
|
11
|
+
export default function tic_tac_toe(action, params = {}) {
|
|
12
|
+
// In-memory storage
|
|
13
|
+
const storage = params.storage || {};
|
|
14
|
+
|
|
15
|
+
// Initialize storage
|
|
16
|
+
storage.games ??= {};
|
|
17
|
+
storage.sessions ??= {};
|
|
18
|
+
storage.rateLimits ??= {};
|
|
19
|
+
|
|
20
|
+
// Reference the storage properties
|
|
21
|
+
const { games, sessions, rateLimits } = storage;
|
|
22
|
+
|
|
23
|
+
// Input validation for common parameters
|
|
24
|
+
if (!params.username) throw new Error('Please provide a username');
|
|
25
|
+
|
|
26
|
+
const u = params.username.toLowerCase();
|
|
27
|
+
const now = Date.now();
|
|
28
|
+
|
|
29
|
+
// Rate limiting
|
|
30
|
+
rateLimits[u] = (rateLimits[u] || []).filter(ts => now - ts < 10000);
|
|
31
|
+
if (rateLimits[u].length > 50) {
|
|
32
|
+
const remainingTime = Math.ceil((rateLimits[u][0] + 10000 - now) / 1000);
|
|
33
|
+
throw new Error(`Rate limit exceeded. Try again in ${remainingTime} seconds.`);
|
|
34
|
+
}
|
|
35
|
+
rateLimits[u].push(now);
|
|
36
|
+
|
|
37
|
+
// Handle different actions
|
|
38
|
+
if (action === 'play') {
|
|
39
|
+
return playMove(params, games, sessions, u, now);
|
|
40
|
+
} else if (action === 'fetch') {
|
|
41
|
+
return fetchGame(params, games, u);
|
|
42
|
+
} else {
|
|
43
|
+
throw new Error('Invalid action. Use "play" or "fetch"');
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Process a player's move
|
|
49
|
+
*/
|
|
50
|
+
function playMove(params, games, sessions, u, now) {
|
|
51
|
+
const { move, session, game } = params;
|
|
52
|
+
const validMoves = ['1-1', '1-2', '1-3', '2-1', '2-2', '2-3', '3-1', '3-2', '3-3'];
|
|
53
|
+
|
|
54
|
+
// Input validation for play action
|
|
55
|
+
if (!move) throw new Error('Please provide a valid move');
|
|
56
|
+
if (!session) throw new Error('Please provide a valid session ID');
|
|
57
|
+
if (!game) throw new Error('Please provide a valid game ID');
|
|
58
|
+
if (!validMoves.includes(move)) throw new Error('Invalid move. Please provide a valid move (e.g., 1-1, 2-2, 3-3).');
|
|
59
|
+
|
|
60
|
+
// Session validation
|
|
61
|
+
if (sessions[u] && sessions[u].user !== session) {
|
|
62
|
+
throw new Error('Session ID mismatch');
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// Initialize game if needed
|
|
66
|
+
games[game] = games[game] || [];
|
|
67
|
+
|
|
68
|
+
// Check if game is full
|
|
69
|
+
const players = [...new Set(games[game].map(play => play.username))];
|
|
70
|
+
if (players.length >= 2 && !players.includes(params.username)) {
|
|
71
|
+
throw new Error('Game is full, you can only watch.');
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// Check if it's player's turn
|
|
75
|
+
if (games[game].length > 0 && games[game][games[game].length - 1].username === params.username) {
|
|
76
|
+
throw new Error('Please wait for the other player to make a move.');
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// Check if move is already made
|
|
80
|
+
if (games[game].some(play => play.move === move)) {
|
|
81
|
+
throw new Error('Move already made. Please choose a different move.');
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// Add move to game
|
|
85
|
+
const play = { username: params.username, move, session };
|
|
86
|
+
games[game].push(play);
|
|
87
|
+
|
|
88
|
+
// Check game result
|
|
89
|
+
const result = checkGame(games[game]);
|
|
90
|
+
if (result.winner || result.tie) {
|
|
91
|
+
setTimeout(() => delete games[game], 600000);
|
|
92
|
+
return {
|
|
93
|
+
message: `Move sent successfully. ${result.winner ? result.winner + ' wins. ' + result.loser + ' loses.' : 'It\'s a tie.'}`,
|
|
94
|
+
...result
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// Set cleanup timeout
|
|
99
|
+
setTimeout(() => delete games[game], 3600000);
|
|
100
|
+
|
|
101
|
+
// Update session
|
|
102
|
+
sessions[u] = sessions[u] || { user: session, last: now };
|
|
103
|
+
sessions[u].last = now;
|
|
104
|
+
setTimeout(() => { if (now - sessions[u].last >= 3600000) delete sessions[u]; }, 3600000);
|
|
105
|
+
|
|
106
|
+
return { message: 'Move sent successfully' };
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Fetch a game state
|
|
111
|
+
*/
|
|
112
|
+
function fetchGame(params, games, u) {
|
|
113
|
+
const ID = params.game || generateGameId();
|
|
114
|
+
|
|
115
|
+
// Initialize game if needed
|
|
116
|
+
if (!games[ID]) games[ID] = [];
|
|
117
|
+
|
|
118
|
+
const data = games[ID];
|
|
119
|
+
const last = data.length ? data[data.length - 1].username : null;
|
|
120
|
+
const players = [...new Set(data.map(p => p.username))];
|
|
121
|
+
const turn = players.find(p => p !== last);
|
|
122
|
+
const result = data.length ? checkGame(data) : {};
|
|
123
|
+
|
|
124
|
+
return { game: data, turn, ID, ...result };
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* Generate a random game ID
|
|
129
|
+
*/
|
|
130
|
+
function generateGameId() {
|
|
131
|
+
const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
|
|
132
|
+
return Array.from(randomBytes(5)).map(b => chars[b % chars.length]).join('');
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* Check the game result
|
|
137
|
+
*/
|
|
138
|
+
function checkGame(moves) {
|
|
139
|
+
let board = Array(3).fill().map(() => Array(3).fill(null));
|
|
140
|
+
let playerSymbols = {};
|
|
141
|
+
let playersOrder = [];
|
|
142
|
+
|
|
143
|
+
moves.forEach(({ username, move }) => {
|
|
144
|
+
if (!playerSymbols[username]) {
|
|
145
|
+
playersOrder.push(username);
|
|
146
|
+
playerSymbols[username] = playersOrder.length === 1 ? 'X' : 'O';
|
|
147
|
+
}
|
|
148
|
+
let [row, col] = move.split('-').map(Number);
|
|
149
|
+
board[row - 1][col - 1] = playerSymbols[username];
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
const checkWinner = (symbol) => {
|
|
153
|
+
for (let i = 0; i < 3; i++) {
|
|
154
|
+
if (board[i][0] === symbol && board[i][1] === symbol && board[i][2] === symbol) return true;
|
|
155
|
+
if (board[0][i] === symbol && board[1][i] === symbol && board[2][i] === symbol) return true;
|
|
156
|
+
}
|
|
157
|
+
if (board[0][0] === symbol && board[1][1] === symbol && board[2][2] === symbol) return true;
|
|
158
|
+
if (board[0][2] === symbol && board[1][1] === symbol && board[2][0] === symbol) return true;
|
|
159
|
+
return false;
|
|
160
|
+
};
|
|
161
|
+
|
|
162
|
+
let winner = Object.keys(playerSymbols).find(player => checkWinner(playerSymbols[player]));
|
|
163
|
+
let isTie = !winner && moves.length === 9;
|
|
164
|
+
let loser = winner && playersOrder.length === 2 ? playersOrder.find(player => player !== winner) : null;
|
|
165
|
+
|
|
166
|
+
return { winner, loser, tie: isTie };
|
|
167
167
|
}
|
package/modules/v3/time.js
CHANGED
|
@@ -1,87 +1,87 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Generate time information based on specified parameters.
|
|
3
|
-
*
|
|
4
|
-
* @param {string} type - The type of time information ('live' or 'random')
|
|
5
|
-
* @param {string} start - Start date for random generation (ISO format)
|
|
6
|
-
* @param {string} end - End date for random generation (ISO format)
|
|
7
|
-
* @param {string} format - Specific time format to return
|
|
8
|
-
* @param {string} timezone - Timezone to use
|
|
9
|
-
* @returns {object} - Time information in various formats
|
|
10
|
-
* @throws {Error} - If inputs are invalid
|
|
11
|
-
*/
|
|
12
|
-
export default function time(type = 'live', start, end, format, timezone) {
|
|
13
|
-
const validFormats = [
|
|
14
|
-
'iso', 'utc', 'timestamp', 'locale', 'date', 'time',
|
|
15
|
-
'year', 'month', 'day', 'hour', 'minute', 'second',
|
|
16
|
-
'ms', 'dayOfWeek', 'dayOfYear', 'weekNumber',
|
|
17
|
-
'timezone', 'timezoneOffset'
|
|
18
|
-
];
|
|
19
|
-
|
|
20
|
-
const validTimezones = [
|
|
21
|
-
'UTC', 'America/New_York', 'Europe/Paris',
|
|
22
|
-
'Asia/Tokyo', 'Australia/Sydney'
|
|
23
|
-
];
|
|
24
|
-
|
|
25
|
-
// Input validation
|
|
26
|
-
if (type !== 'live' && type !== 'random') {
|
|
27
|
-
throw new Error('Please provide a valid type (live or random)');
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
if (start && !Date.parse(start)) {
|
|
31
|
-
throw new Error('Please provide a valid start date (YYYY-MM-DD)');
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
if (end && !Date.parse(end)) {
|
|
35
|
-
throw new Error('Please provide a valid end date (YYYY-MM-DD)');
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
if (format && !validFormats.includes(format)) {
|
|
39
|
-
throw new Error(`Please provide a valid format. Options: ${validFormats.join(', ')}`);
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
if (timezone && !validTimezones.includes(timezone)) {
|
|
43
|
-
throw new Error(`Please provide a valid timezone. Options: ${validTimezones.join(', ')}`);
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
// Helper function to get all time formats for a date
|
|
47
|
-
const getTimeFormats = (date, tz) => {
|
|
48
|
-
return {
|
|
49
|
-
iso: date.toISOString(),
|
|
50
|
-
utc: date.toUTCString(),
|
|
51
|
-
timestamp: date.getTime(),
|
|
52
|
-
locale: date.toLocaleString('en-US', { timeZone: tz, timeZoneName: 'long' }),
|
|
53
|
-
date: date.toLocaleDateString('en-US', { timeZone: tz }),
|
|
54
|
-
time: date.toLocaleTimeString('en-US', { timeZone: tz }),
|
|
55
|
-
year: date.getFullYear(),
|
|
56
|
-
month: date.getMonth() + 1,
|
|
57
|
-
day: date.getDate(),
|
|
58
|
-
hour: date.getHours(),
|
|
59
|
-
minute: date.getMinutes(),
|
|
60
|
-
second: date.getSeconds(),
|
|
61
|
-
ms: date.getMilliseconds(),
|
|
62
|
-
dayOfWeek: date.getDay(),
|
|
63
|
-
dayOfYear: Math.floor((date - new Date(date.getFullYear(), 0, 0)) / 86400000),
|
|
64
|
-
weekNumber: Math.ceil((((date - new Date(date.getFullYear(), 0, 0)) / 86400000) + 1) / 7),
|
|
65
|
-
timezone: tz,
|
|
66
|
-
timezoneOffset: date.getTimezoneOffset()
|
|
67
|
-
};
|
|
68
|
-
};
|
|
69
|
-
|
|
70
|
-
// Generate time information based on type
|
|
71
|
-
if (type === 'random') {
|
|
72
|
-
const startDate = start ? new Date(start).getTime() : new Date('1900-01-01').getTime();
|
|
73
|
-
const endDate = end ? new Date(end).getTime() : new Date('2100-12-31').getTime();
|
|
74
|
-
const randomDate = new Date(startDate + Math.random() * (endDate - startDate));
|
|
75
|
-
const tz = timezone || validTimezones[Math.floor(Math.random() * validTimezones.length)];
|
|
76
|
-
const formats = getTimeFormats(randomDate, tz);
|
|
77
|
-
|
|
78
|
-
return format ? { date: formats[format] } : formats;
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
// Live time information
|
|
82
|
-
const now = new Date();
|
|
83
|
-
const tz = timezone || 'UTC';
|
|
84
|
-
const formats = getTimeFormats(now, tz);
|
|
85
|
-
|
|
86
|
-
return format ? { date: formats[format] } : formats;
|
|
1
|
+
/**
|
|
2
|
+
* Generate time information based on specified parameters.
|
|
3
|
+
*
|
|
4
|
+
* @param {string} type - The type of time information ('live' or 'random')
|
|
5
|
+
* @param {string} start - Start date for random generation (ISO format)
|
|
6
|
+
* @param {string} end - End date for random generation (ISO format)
|
|
7
|
+
* @param {string} format - Specific time format to return
|
|
8
|
+
* @param {string} timezone - Timezone to use
|
|
9
|
+
* @returns {object} - Time information in various formats
|
|
10
|
+
* @throws {Error} - If inputs are invalid
|
|
11
|
+
*/
|
|
12
|
+
export default function time(type = 'live', start, end, format, timezone) {
|
|
13
|
+
const validFormats = [
|
|
14
|
+
'iso', 'utc', 'timestamp', 'locale', 'date', 'time',
|
|
15
|
+
'year', 'month', 'day', 'hour', 'minute', 'second',
|
|
16
|
+
'ms', 'dayOfWeek', 'dayOfYear', 'weekNumber',
|
|
17
|
+
'timezone', 'timezoneOffset'
|
|
18
|
+
];
|
|
19
|
+
|
|
20
|
+
const validTimezones = [
|
|
21
|
+
'UTC', 'America/New_York', 'Europe/Paris',
|
|
22
|
+
'Asia/Tokyo', 'Australia/Sydney'
|
|
23
|
+
];
|
|
24
|
+
|
|
25
|
+
// Input validation
|
|
26
|
+
if (type !== 'live' && type !== 'random') {
|
|
27
|
+
throw new Error('Please provide a valid type (live or random)');
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
if (start && !Date.parse(start)) {
|
|
31
|
+
throw new Error('Please provide a valid start date (YYYY-MM-DD)');
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
if (end && !Date.parse(end)) {
|
|
35
|
+
throw new Error('Please provide a valid end date (YYYY-MM-DD)');
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
if (format && !validFormats.includes(format)) {
|
|
39
|
+
throw new Error(`Please provide a valid format. Options: ${validFormats.join(', ')}`);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
if (timezone && !validTimezones.includes(timezone)) {
|
|
43
|
+
throw new Error(`Please provide a valid timezone. Options: ${validTimezones.join(', ')}`);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// Helper function to get all time formats for a date
|
|
47
|
+
const getTimeFormats = (date, tz) => {
|
|
48
|
+
return {
|
|
49
|
+
iso: date.toISOString(),
|
|
50
|
+
utc: date.toUTCString(),
|
|
51
|
+
timestamp: date.getTime(),
|
|
52
|
+
locale: date.toLocaleString('en-US', { timeZone: tz, timeZoneName: 'long' }),
|
|
53
|
+
date: date.toLocaleDateString('en-US', { timeZone: tz }),
|
|
54
|
+
time: date.toLocaleTimeString('en-US', { timeZone: tz }),
|
|
55
|
+
year: date.getFullYear(),
|
|
56
|
+
month: date.getMonth() + 1,
|
|
57
|
+
day: date.getDate(),
|
|
58
|
+
hour: date.getHours(),
|
|
59
|
+
minute: date.getMinutes(),
|
|
60
|
+
second: date.getSeconds(),
|
|
61
|
+
ms: date.getMilliseconds(),
|
|
62
|
+
dayOfWeek: date.getDay(),
|
|
63
|
+
dayOfYear: Math.floor((date - new Date(date.getFullYear(), 0, 0)) / 86400000),
|
|
64
|
+
weekNumber: Math.ceil((((date - new Date(date.getFullYear(), 0, 0)) / 86400000) + 1) / 7),
|
|
65
|
+
timezone: tz,
|
|
66
|
+
timezoneOffset: date.getTimezoneOffset()
|
|
67
|
+
};
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
// Generate time information based on type
|
|
71
|
+
if (type === 'random') {
|
|
72
|
+
const startDate = start ? new Date(start).getTime() : new Date('1900-01-01').getTime();
|
|
73
|
+
const endDate = end ? new Date(end).getTime() : new Date('2100-12-31').getTime();
|
|
74
|
+
const randomDate = new Date(startDate + Math.random() * (endDate - startDate));
|
|
75
|
+
const tz = timezone || validTimezones[Math.floor(Math.random() * validTimezones.length)];
|
|
76
|
+
const formats = getTimeFormats(randomDate, tz);
|
|
77
|
+
|
|
78
|
+
return format ? { date: formats[format] } : formats;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// Live time information
|
|
82
|
+
const now = new Date();
|
|
83
|
+
const tz = timezone || 'UTC';
|
|
84
|
+
const formats = getTimeFormats(now, tz);
|
|
85
|
+
|
|
86
|
+
return format ? { date: formats[format] } : formats;
|
|
87
87
|
}
|
package/modules/v3/token.js
CHANGED
|
@@ -1,48 +1,48 @@
|
|
|
1
|
-
import { randomBytes } from 'crypto';
|
|
2
|
-
import { v4 } from 'uuid';
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Generate a random token of specified length and type.
|
|
6
|
-
*
|
|
7
|
-
* @param {number} len - Length of the token
|
|
8
|
-
* @param {string} type - Type of token to generate
|
|
9
|
-
* @returns {string} - The generated token
|
|
10
|
-
* @throws {Error} - If inputs are invalid
|
|
11
|
-
*/
|
|
12
|
-
export default function token(len, type = 'alphanum') {
|
|
13
|
-
// Input validation
|
|
14
|
-
if (isNaN(len) || len < 12) {
|
|
15
|
-
throw new Error('Length must be a number greater than or equal to 12');
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
if (len > 4096) {
|
|
19
|
-
throw new Error('Length cannot exceed 4096');
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
// Helper function to generate token from character set
|
|
23
|
-
const genToken = (chars, length) => {
|
|
24
|
-
return Array.from({ length }, () => {
|
|
25
|
-
return chars[Math.floor(Math.random() * chars.length)];
|
|
26
|
-
}).join('');
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
// Token type definitions
|
|
30
|
-
const tokenTypes = {
|
|
31
|
-
alpha: () => genToken('abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ', len),
|
|
32
|
-
alphanum: () => genToken('abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789', len),
|
|
33
|
-
base64: () => randomBytes(Math.ceil(len * 0.75)).toString('base64').slice(0, len),
|
|
34
|
-
hex: () => randomBytes(Math.ceil(len * 0.5)).toString('hex').slice(0, len),
|
|
35
|
-
num: () => genToken('0123456789', len),
|
|
36
|
-
punct: () => genToken('!"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~', len),
|
|
37
|
-
urlsafe: () => genToken('abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_', len),
|
|
38
|
-
uuid: () => v4().replace(/-/g, '').slice(0, len)
|
|
39
|
-
};
|
|
40
|
-
|
|
41
|
-
// Generate token based on type or default to alphanum
|
|
42
|
-
if (!tokenTypes[type.toLowerCase()]) {
|
|
43
|
-
throw new Error(`Invalid token type. Valid types: ${Object.keys(tokenTypes).join(', ')}`);
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
// Generate token based on type or default to alphanum
|
|
47
|
-
return (tokenTypes[type.toLowerCase()] || tokenTypes.alphanum)();
|
|
1
|
+
import { randomBytes } from 'crypto';
|
|
2
|
+
import { v4 } from 'uuid';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Generate a random token of specified length and type.
|
|
6
|
+
*
|
|
7
|
+
* @param {number} len - Length of the token
|
|
8
|
+
* @param {string} type - Type of token to generate
|
|
9
|
+
* @returns {string} - The generated token
|
|
10
|
+
* @throws {Error} - If inputs are invalid
|
|
11
|
+
*/
|
|
12
|
+
export default function token(len, type = 'alphanum') {
|
|
13
|
+
// Input validation
|
|
14
|
+
if (isNaN(len) || len < 12) {
|
|
15
|
+
throw new Error('Length must be a number greater than or equal to 12');
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
if (len > 4096) {
|
|
19
|
+
throw new Error('Length cannot exceed 4096');
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// Helper function to generate token from character set
|
|
23
|
+
const genToken = (chars, length) => {
|
|
24
|
+
return Array.from({ length }, () => {
|
|
25
|
+
return chars[Math.floor(Math.random() * chars.length)];
|
|
26
|
+
}).join('');
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// Token type definitions
|
|
30
|
+
const tokenTypes = {
|
|
31
|
+
alpha: () => genToken('abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ', len),
|
|
32
|
+
alphanum: () => genToken('abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789', len),
|
|
33
|
+
base64: () => randomBytes(Math.ceil(len * 0.75)).toString('base64').slice(0, len),
|
|
34
|
+
hex: () => randomBytes(Math.ceil(len * 0.5)).toString('hex').slice(0, len),
|
|
35
|
+
num: () => genToken('0123456789', len),
|
|
36
|
+
punct: () => genToken('!"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~', len),
|
|
37
|
+
urlsafe: () => genToken('abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_', len),
|
|
38
|
+
uuid: () => v4().replace(/-/g, '').slice(0, len)
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
// Generate token based on type or default to alphanum
|
|
42
|
+
if (!tokenTypes[type.toLowerCase()]) {
|
|
43
|
+
throw new Error(`Invalid token type. Valid types: ${Object.keys(tokenTypes).join(', ')}`);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// Generate token based on type or default to alphanum
|
|
47
|
+
return (tokenTypes[type.toLowerCase()] || tokenTypes.alphanum)();
|
|
48
48
|
}
|