@20syldev/api 4.5.0 → 4.7.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.
- package/README.md +11 -4
- package/eslint.config.js +4 -0
- package/package.json +3 -2
- package/src/app.ts +7 -6
- package/src/config/env.ts +1 -0
- package/src/config/versions.ts +10 -2
- package/src/middleware/error.ts +2 -1
- package/src/middleware/json.ts +1 -1
- package/src/middleware/logger.ts +2 -1
- package/src/middleware/ratelimit.ts +4 -3
- package/src/middleware/version.ts +2 -1
- package/src/modules/v3.js +1 -1
- package/src/modules/v4/address.ts +413 -0
- package/src/modules/v4/agent.ts +104 -0
- package/src/modules/v4/algorithms.ts +79 -0
- package/src/modules/v4/captcha.ts +8 -0
- package/src/modules/v4/chat.ts +10 -2
- package/src/modules/v4/color.ts +8 -1
- package/src/modules/v4/convert.ts +9 -0
- package/src/modules/v4/dice.ts +7 -0
- package/src/modules/v4/domain.ts +6 -1
- package/src/modules/v4/encode.ts +71 -0
- package/src/modules/v4/geo.ts +10 -0
- package/src/modules/v4/hash.ts +10 -1
- package/src/modules/v4/hyperplanning.ts +10 -1
- package/src/modules/v4/ip.ts +134 -0
- package/src/modules/v4/levenshtein.ts +8 -0
- package/src/modules/v4/palette.ts +9 -1
- package/src/modules/v4/password.ts +381 -0
- package/src/modules/v4/personal.ts +9 -16
- package/src/modules/v4/placeholder.ts +8 -0
- package/src/modules/v4/qrcode.ts +9 -1
- package/src/modules/v4/statistics.ts +7 -0
- package/src/modules/v4/text.ts +30 -0
- package/src/modules/v4/tic_tac_toe.ts +11 -2
- package/src/modules/v4/time.ts +11 -0
- package/src/modules/v4/token.ts +18 -8
- package/src/modules/v4/username.ts +5 -0
- package/src/modules/v4/validate.ts +21 -0
- package/src/modules/v4.ts +5 -1
- package/src/routes/delete.ts +2 -1
- package/src/routes/get.ts +115 -7
- package/src/routes/index.ts +4 -3
- package/src/routes/patch.ts +2 -1
- package/src/routes/post.ts +5 -4
- package/src/storage/index.ts +1 -1
- package/src/utils/response.ts +1 -0
- package/tests/integration/api.test.ts +142 -2
- package/tests/unit/address.test.ts +84 -0
- package/tests/unit/agent.test.ts +113 -0
- package/tests/unit/algorithms.test.ts +2 -1
- package/tests/unit/captcha.test.ts +2 -1
- package/tests/unit/chat.test.ts +2 -1
- package/tests/unit/color.test.ts +2 -1
- package/tests/unit/convert.test.ts +2 -1
- package/tests/unit/dice.test.ts +2 -1
- package/tests/unit/domain.test.ts +2 -1
- package/tests/unit/encode.test.ts +8 -7
- package/tests/unit/geo.test.ts +2 -1
- package/tests/unit/hash.test.ts +2 -1
- package/tests/unit/hyperplanning.test.ts +2 -1
- package/tests/unit/ip.test.ts +140 -0
- package/tests/unit/levenshtein.test.ts +2 -1
- package/tests/unit/palette.test.ts +2 -1
- package/tests/unit/password.test.ts +86 -0
- package/tests/unit/personal.test.ts +2 -1
- package/tests/unit/placeholder.test.ts +2 -1
- package/tests/unit/qrcode.test.ts +2 -1
- package/tests/unit/statistics.test.ts +2 -1
- package/tests/unit/text.test.ts +3 -2
- package/tests/unit/tic_tac_toe.test.ts +2 -1
- package/tests/unit/time.test.ts +2 -1
- package/tests/unit/token.test.ts +2 -1
- package/tests/unit/username.test.ts +2 -1
- package/tests/unit/validate.test.ts +3 -2
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
<a href="https://api.sylvain.sh"><img src="https://api.sylvain.sh/favicon.ico" alt="Logo" width="25%" height="auto"/></a>
|
|
3
3
|
|
|
4
4
|
# API Personnelle
|
|
5
|
-
[](https://github.com/20syldev/api/releases/latest)
|
|
6
6
|
</div>
|
|
7
7
|
|
|
8
8
|
---
|
|
@@ -32,10 +32,10 @@ Pour démarrer un serveur local avec tous les endpoints :
|
|
|
32
32
|
$ npm run build && npm start
|
|
33
33
|
```
|
|
34
34
|
```console
|
|
35
|
-
> @20syldev/api@4.
|
|
35
|
+
> @20syldev/api@4.7.0 build
|
|
36
36
|
> tsc
|
|
37
37
|
|
|
38
|
-
> @20syldev/api@4.
|
|
38
|
+
> @20syldev/api@4.7.0 start
|
|
39
39
|
> node dist/app.js
|
|
40
40
|
|
|
41
41
|
API is running on
|
|
@@ -88,6 +88,8 @@ L'API v4 expose plusieurs modules que vous pouvez importer :
|
|
|
88
88
|
|
|
89
89
|
```js
|
|
90
90
|
import {
|
|
91
|
+
address, // Génération d'adresses postales aléatoires
|
|
92
|
+
agent, // Analyse de User-Agent (navigateur, OS, appareil)
|
|
91
93
|
algorithms, // Fonctions algorithmiques diverses
|
|
92
94
|
captcha, // Génération d'images captcha
|
|
93
95
|
chat, // Système de chat temporaire
|
|
@@ -96,15 +98,20 @@ import {
|
|
|
96
98
|
dice, // Lanceur de dés RPG
|
|
97
99
|
domain, // Informations de domaine aléatoires
|
|
98
100
|
encode, // Encodage / décodage (base64, morse, rot13, caesar, binaire)
|
|
101
|
+
geo, // Informations de géolocalisation
|
|
99
102
|
hash, // Hachage de texte
|
|
100
103
|
hyperplanning, // Analyse de calendriers
|
|
104
|
+
ip, // Analyse d'adresses IPv4/IPv6
|
|
101
105
|
levenshtein, // Distance entre chaînes
|
|
106
|
+
palette, // Génération de palettes de couleurs
|
|
107
|
+
password, // Génération de mots de passe sécurisés
|
|
102
108
|
personal, // Informations personnelles aléatoires
|
|
109
|
+
placeholder, // Génération d'images placeholder
|
|
103
110
|
qrcode, // Génération de QR codes
|
|
104
111
|
statistics, // Statistiques descriptives
|
|
112
|
+
text, // Utilitaires texte (slug, stats, lorem, nombre en lettres)
|
|
105
113
|
tic_tac_toe, // Jeu de morpion
|
|
106
114
|
time, // Informations temporelles
|
|
107
|
-
text, // Utilitaires texte (slug, stats, lorem, nombre en lettres)
|
|
108
115
|
token, // Génération de jetons sécurisés
|
|
109
116
|
username, // Génération de noms d'utilisateur
|
|
110
117
|
validate // Validation (Luhn, IBAN, email)
|
package/eslint.config.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import eslint from '@eslint/js';
|
|
2
|
+
import simpleImportSort from 'eslint-plugin-simple-import-sort';
|
|
2
3
|
import tseslint from 'typescript-eslint';
|
|
3
4
|
import eslintConfigPrettier from 'eslint-config-prettier';
|
|
4
5
|
|
|
@@ -7,7 +8,10 @@ export default tseslint.config(
|
|
|
7
8
|
...tseslint.configs.strict,
|
|
8
9
|
eslintConfigPrettier,
|
|
9
10
|
{
|
|
11
|
+
plugins: { 'simple-import-sort': simpleImportSort },
|
|
10
12
|
rules: {
|
|
13
|
+
'simple-import-sort/imports': 'error',
|
|
14
|
+
'simple-import-sort/exports': 'error',
|
|
11
15
|
'@typescript-eslint/no-explicit-any': 'warn',
|
|
12
16
|
'@typescript-eslint/no-unused-vars': ['error', { argsIgnorePattern: '^_' }],
|
|
13
17
|
'@typescript-eslint/no-non-null-assertion': 'off',
|
package/package.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "4.
|
|
2
|
+
"version": "4.7.0",
|
|
3
3
|
"name": "@20syldev/api",
|
|
4
4
|
"description": "Node.js API with multiple features. Check the documentation at https://docs.sylvain.sh",
|
|
5
5
|
"main": "dist/app.js",
|
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
"ical.js": "^2.1.0",
|
|
33
33
|
"qrcode": "^1.5.4",
|
|
34
34
|
"random": "^5.3.0",
|
|
35
|
-
"uuid": "^
|
|
35
|
+
"uuid": "^14.0.0"
|
|
36
36
|
},
|
|
37
37
|
"devDependencies": {
|
|
38
38
|
"@eslint/js": "^9.24.0",
|
|
@@ -43,6 +43,7 @@
|
|
|
43
43
|
"@types/uuid": "^10.0.0",
|
|
44
44
|
"eslint": "^9.24.0",
|
|
45
45
|
"eslint-config-prettier": "^10.1.1",
|
|
46
|
+
"eslint-plugin-simple-import-sort": "^13.0.0",
|
|
46
47
|
"npm-check-updates": "^18.0.1",
|
|
47
48
|
"prettier": "^3.5.3",
|
|
48
49
|
"tsx": "^4.19.0",
|
package/src/app.ts
CHANGED
|
@@ -1,16 +1,17 @@
|
|
|
1
1
|
import express from 'express';
|
|
2
|
+
|
|
2
3
|
import { env } from './config/env.js';
|
|
3
4
|
import { setupCors } from './middleware/cors.js';
|
|
5
|
+
import { errorHandler } from './middleware/error.js';
|
|
4
6
|
import { jsonResponseMiddleware } from './middleware/json.js';
|
|
5
|
-
import { rateLimitMiddleware } from './middleware/ratelimit.js';
|
|
6
7
|
import { loggerMiddleware } from './middleware/logger.js';
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import
|
|
8
|
+
import { rateLimitMiddleware } from './middleware/ratelimit.js';
|
|
9
|
+
import { endpointCheckMiddleware, versionCheckMiddleware } from './middleware/version.js';
|
|
10
|
+
import deleteRoutes from './routes/delete.js';
|
|
10
11
|
import getRoutes from './routes/get.js';
|
|
11
|
-
import
|
|
12
|
+
import indexRoutes from './routes/index.js';
|
|
12
13
|
import patchRoutes from './routes/patch.js';
|
|
13
|
-
import
|
|
14
|
+
import postRoutes from './routes/post.js';
|
|
14
15
|
|
|
15
16
|
const app = express();
|
|
16
17
|
|
package/src/config/env.ts
CHANGED
package/src/config/versions.ts
CHANGED
|
@@ -78,6 +78,8 @@ const v3 = {
|
|
|
78
78
|
|
|
79
79
|
const v4 = {
|
|
80
80
|
get: merge(v3.get, [
|
|
81
|
+
{ name: 'address', path: '/address(&country={code}&count={n})' },
|
|
82
|
+
{ name: 'agent', path: '/agent(&ua={string})' },
|
|
81
83
|
{
|
|
82
84
|
name: 'captcha',
|
|
83
85
|
path: '/captcha(&text={text}&length={n}&width={px}&height={px}&noise={low|medium|high}&bg={hex}&color={hex})',
|
|
@@ -87,15 +89,21 @@ const v4 = {
|
|
|
87
89
|
{ name: 'dice', path: '/dice?roll={NdX+M}' },
|
|
88
90
|
{ name: 'encode', path: '/encode?method={method}&text={text}(&shift={shift})' },
|
|
89
91
|
{ name: 'geo', path: '/geo?lat1={lat}&lon1={lon}&lat2={lat}&lon2={lon}' },
|
|
92
|
+
{ name: 'headers', path: '/headers(&filter={header1,header2})' },
|
|
93
|
+
{ name: 'ip', path: '/ip(&address={ip})' },
|
|
90
94
|
{ name: 'palette', path: '/palette?color={#hex}&type={type}' },
|
|
91
95
|
{
|
|
92
|
-
name: '
|
|
93
|
-
path: '/
|
|
96
|
+
name: 'password',
|
|
97
|
+
path: '/password(&type={random|passphrase}&length={n}&uppercase={bool}&lowercase={bool}&digits={bool}&symbols={bool}&exclude={chars}&count={n}&separator={char})',
|
|
94
98
|
},
|
|
95
99
|
{
|
|
96
100
|
name: 'placeholder',
|
|
97
101
|
path: '/placeholder?type={image|skeleton}&width={w}&height={h}(&bg={hex}&color={hex}&text={text}&rows={n}&avatar={bool})',
|
|
98
102
|
},
|
|
103
|
+
{
|
|
104
|
+
name: 'qrcode',
|
|
105
|
+
path: '/qrcode?url={URL}(&size={px}&margin={n}&correction={L|M|Q|H}&dark={hex}&light={hex}&icon={URL}&iconSize={px}&iconPadding={px}&iconRadius={px}&format={png|base64})',
|
|
106
|
+
},
|
|
99
107
|
{ name: 'statistics', path: '/statistics?values={n1,n2,n3,...}' },
|
|
100
108
|
{ name: 'text', path: '/text?method={method}(&value={value}&type={type}&count={count}&lang={lang})' },
|
|
101
109
|
{ name: 'validate', path: '/validate?type={type}&value={value}' },
|
package/src/middleware/error.ts
CHANGED
package/src/middleware/json.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { Request, Response
|
|
1
|
+
import type { NextFunction, Request, Response } from 'express';
|
|
2
2
|
|
|
3
3
|
export function jsonResponseMiddleware(_req: Request, res: Response, next: NextFunction): void {
|
|
4
4
|
res.setHeader('Content-Type', 'application/json');
|
package/src/middleware/logger.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { createLogger } from '@20syldev/logger.ts';
|
|
2
|
-
import type { Request, Response
|
|
2
|
+
import type { NextFunction, Request, Response } from 'express';
|
|
3
|
+
|
|
3
4
|
import { MAX_LOG_ENTRIES } from '../constants.js';
|
|
4
5
|
|
|
5
6
|
export const logger = createLogger({
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import type { Request, Response
|
|
2
|
-
|
|
1
|
+
import type { NextFunction, Request, Response } from 'express';
|
|
2
|
+
|
|
3
|
+
import { getPlan, globalLimit } from '../config/plans.js';
|
|
3
4
|
import { RATE_LIMIT_WINDOW, SESSION_TTL } from '../constants.js';
|
|
5
|
+
import { ipLimits } from '../storage/index.js';
|
|
4
6
|
import { error } from '../utils/response.js';
|
|
5
|
-
import { getPlan, globalLimit } from '../config/plans.js';
|
|
6
7
|
|
|
7
8
|
let requests = 0;
|
|
8
9
|
let resetTime = Date.now() + SESSION_TTL;
|
package/src/modules/v3.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export * as algorithms from './v3/algorithms.js';
|
|
2
|
-
export { default as chat } from './v3/chat.js';
|
|
3
2
|
export { default as captcha } from './v3/captcha.js';
|
|
3
|
+
export { default as chat } from './v3/chat.js';
|
|
4
4
|
export { default as color } from './v3/color.js';
|
|
5
5
|
export { default as convert } from './v3/convert.js';
|
|
6
6
|
export { default as domain } from './v3/domain.js';
|
|
@@ -0,0 +1,413 @@
|
|
|
1
|
+
import { random, randomNumber } from '../../utils/helpers.js';
|
|
2
|
+
|
|
3
|
+
const MAX_COUNT = 10;
|
|
4
|
+
|
|
5
|
+
interface CountryData {
|
|
6
|
+
name: string;
|
|
7
|
+
streetTypes: string[];
|
|
8
|
+
streetNames: string[];
|
|
9
|
+
cities: string[];
|
|
10
|
+
regions: string[];
|
|
11
|
+
zipFormat: () => string;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
function randomChar(chars: string): string {
|
|
15
|
+
return chars[Math.floor(Math.random() * chars.length)]!;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const ALPHA = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
|
|
19
|
+
|
|
20
|
+
const countries: Record<string, CountryData> = {
|
|
21
|
+
fr: {
|
|
22
|
+
name: 'France',
|
|
23
|
+
streetTypes: ['Rue', 'Avenue', 'Boulevard', 'Allée', 'Impasse', 'Place', 'Chemin', 'Route', 'Voie', 'Passage'],
|
|
24
|
+
streetNames: [
|
|
25
|
+
'de la Paix',
|
|
26
|
+
'Victor Hugo',
|
|
27
|
+
'Jean Jaurès',
|
|
28
|
+
'de la République',
|
|
29
|
+
'du Général de Gaulle',
|
|
30
|
+
'de la Liberté',
|
|
31
|
+
'des Fleurs',
|
|
32
|
+
'du Moulin',
|
|
33
|
+
'de la Forêt',
|
|
34
|
+
'des Lilas',
|
|
35
|
+
'du Château',
|
|
36
|
+
'de la Mairie',
|
|
37
|
+
'de la Gare',
|
|
38
|
+
'du Commerce',
|
|
39
|
+
'de la Fontaine',
|
|
40
|
+
'de la Croix',
|
|
41
|
+
'des Vignes',
|
|
42
|
+
'du Marché',
|
|
43
|
+
"de l'Église",
|
|
44
|
+
'des Acacias',
|
|
45
|
+
],
|
|
46
|
+
cities: [
|
|
47
|
+
'Paris',
|
|
48
|
+
'Lyon',
|
|
49
|
+
'Marseille',
|
|
50
|
+
'Toulouse',
|
|
51
|
+
'Nice',
|
|
52
|
+
'Nantes',
|
|
53
|
+
'Strasbourg',
|
|
54
|
+
'Montpellier',
|
|
55
|
+
'Bordeaux',
|
|
56
|
+
'Lille',
|
|
57
|
+
'Rennes',
|
|
58
|
+
'Reims',
|
|
59
|
+
'Le Havre',
|
|
60
|
+
'Saint-Étienne',
|
|
61
|
+
'Toulon',
|
|
62
|
+
'Grenoble',
|
|
63
|
+
'Dijon',
|
|
64
|
+
'Angers',
|
|
65
|
+
'Nîmes',
|
|
66
|
+
'Villeurbanne',
|
|
67
|
+
],
|
|
68
|
+
regions: [
|
|
69
|
+
'Île-de-France',
|
|
70
|
+
'Auvergne-Rhône-Alpes',
|
|
71
|
+
"Provence-Alpes-Côte d'Azur",
|
|
72
|
+
'Occitanie',
|
|
73
|
+
'Hauts-de-France',
|
|
74
|
+
'Nouvelle-Aquitaine',
|
|
75
|
+
'Grand Est',
|
|
76
|
+
'Pays de la Loire',
|
|
77
|
+
'Bretagne',
|
|
78
|
+
'Normandie',
|
|
79
|
+
'Bourgogne-Franche-Comté',
|
|
80
|
+
'Centre-Val de Loire',
|
|
81
|
+
],
|
|
82
|
+
zipFormat: () => String(randomNumber(10000, 99999)).padStart(5, '0'),
|
|
83
|
+
},
|
|
84
|
+
us: {
|
|
85
|
+
name: 'United States',
|
|
86
|
+
streetTypes: ['Street', 'Avenue', 'Boulevard', 'Drive', 'Road', 'Lane', 'Court', 'Way', 'Place', 'Circle'],
|
|
87
|
+
streetNames: [
|
|
88
|
+
'Main',
|
|
89
|
+
'Oak',
|
|
90
|
+
'Maple',
|
|
91
|
+
'Cedar',
|
|
92
|
+
'Pine',
|
|
93
|
+
'Elm',
|
|
94
|
+
'Washington',
|
|
95
|
+
'Lincoln',
|
|
96
|
+
'Park',
|
|
97
|
+
'Lake',
|
|
98
|
+
'Hill',
|
|
99
|
+
'River',
|
|
100
|
+
'Sunset',
|
|
101
|
+
'Forest',
|
|
102
|
+
'Meadow',
|
|
103
|
+
'Valley',
|
|
104
|
+
'Highland',
|
|
105
|
+
'Willow',
|
|
106
|
+
'Spring',
|
|
107
|
+
'Church',
|
|
108
|
+
],
|
|
109
|
+
cities: [
|
|
110
|
+
'New York',
|
|
111
|
+
'Los Angeles',
|
|
112
|
+
'Chicago',
|
|
113
|
+
'Houston',
|
|
114
|
+
'Phoenix',
|
|
115
|
+
'Philadelphia',
|
|
116
|
+
'San Antonio',
|
|
117
|
+
'San Diego',
|
|
118
|
+
'Dallas',
|
|
119
|
+
'San Jose',
|
|
120
|
+
'Austin',
|
|
121
|
+
'Jacksonville',
|
|
122
|
+
'Fort Worth',
|
|
123
|
+
'Columbus',
|
|
124
|
+
'Charlotte',
|
|
125
|
+
'Indianapolis',
|
|
126
|
+
'San Francisco',
|
|
127
|
+
'Seattle',
|
|
128
|
+
'Denver',
|
|
129
|
+
'Nashville',
|
|
130
|
+
],
|
|
131
|
+
regions: [
|
|
132
|
+
'California',
|
|
133
|
+
'Texas',
|
|
134
|
+
'Florida',
|
|
135
|
+
'New York',
|
|
136
|
+
'Pennsylvania',
|
|
137
|
+
'Illinois',
|
|
138
|
+
'Ohio',
|
|
139
|
+
'Georgia',
|
|
140
|
+
'North Carolina',
|
|
141
|
+
'Michigan',
|
|
142
|
+
'New Jersey',
|
|
143
|
+
'Virginia',
|
|
144
|
+
'Washington',
|
|
145
|
+
'Arizona',
|
|
146
|
+
'Massachusetts',
|
|
147
|
+
'Tennessee',
|
|
148
|
+
'Indiana',
|
|
149
|
+
'Colorado',
|
|
150
|
+
'Missouri',
|
|
151
|
+
'Maryland',
|
|
152
|
+
],
|
|
153
|
+
zipFormat: () => String(randomNumber(10000, 99999)).padStart(5, '0'),
|
|
154
|
+
},
|
|
155
|
+
uk: {
|
|
156
|
+
name: 'United Kingdom',
|
|
157
|
+
streetTypes: ['Street', 'Road', 'Avenue', 'Lane', 'Close', 'Drive', 'Way', 'Court', 'Grove', 'Place'],
|
|
158
|
+
streetNames: [
|
|
159
|
+
'High',
|
|
160
|
+
'Church',
|
|
161
|
+
'Station',
|
|
162
|
+
'Park',
|
|
163
|
+
'Manor',
|
|
164
|
+
'Mill',
|
|
165
|
+
'Victoria',
|
|
166
|
+
'King',
|
|
167
|
+
'Queen',
|
|
168
|
+
'Albert',
|
|
169
|
+
'George',
|
|
170
|
+
'York',
|
|
171
|
+
'Oxford',
|
|
172
|
+
'Cambridge',
|
|
173
|
+
'Windsor',
|
|
174
|
+
'Richmond',
|
|
175
|
+
'Elm',
|
|
176
|
+
'Oak',
|
|
177
|
+
'Ash',
|
|
178
|
+
'Rose',
|
|
179
|
+
],
|
|
180
|
+
cities: [
|
|
181
|
+
'London',
|
|
182
|
+
'Birmingham',
|
|
183
|
+
'Manchester',
|
|
184
|
+
'Glasgow',
|
|
185
|
+
'Liverpool',
|
|
186
|
+
'Bristol',
|
|
187
|
+
'Sheffield',
|
|
188
|
+
'Leeds',
|
|
189
|
+
'Edinburgh',
|
|
190
|
+
'Leicester',
|
|
191
|
+
'Coventry',
|
|
192
|
+
'Bradford',
|
|
193
|
+
'Cardiff',
|
|
194
|
+
'Belfast',
|
|
195
|
+
'Nottingham',
|
|
196
|
+
'Kingston upon Hull',
|
|
197
|
+
'Newcastle',
|
|
198
|
+
'Stoke-on-Trent',
|
|
199
|
+
'Southampton',
|
|
200
|
+
'Derby',
|
|
201
|
+
],
|
|
202
|
+
regions: [
|
|
203
|
+
'England',
|
|
204
|
+
'Scotland',
|
|
205
|
+
'Wales',
|
|
206
|
+
'Northern Ireland',
|
|
207
|
+
'Greater London',
|
|
208
|
+
'South East',
|
|
209
|
+
'North West',
|
|
210
|
+
'East of England',
|
|
211
|
+
'West Midlands',
|
|
212
|
+
'South West',
|
|
213
|
+
'Yorkshire',
|
|
214
|
+
'East Midlands',
|
|
215
|
+
'North East',
|
|
216
|
+
],
|
|
217
|
+
zipFormat: () =>
|
|
218
|
+
`${randomChar(ALPHA)}${randomChar(ALPHA)}${randomNumber(1, 9)} ${randomNumber(1, 9)}${randomChar(ALPHA)}${randomChar(ALPHA)}`,
|
|
219
|
+
},
|
|
220
|
+
de: {
|
|
221
|
+
name: 'Germany',
|
|
222
|
+
streetTypes: ['Straße', 'Allee', 'Weg', 'Platz', 'Gasse', 'Ring', 'Damm', 'Ufer', 'Stieg', 'Pfad'],
|
|
223
|
+
streetNames: [
|
|
224
|
+
'Haupt',
|
|
225
|
+
'Bahnhof',
|
|
226
|
+
'Schul',
|
|
227
|
+
'Kirch',
|
|
228
|
+
'Garten',
|
|
229
|
+
'Berg',
|
|
230
|
+
'Wald',
|
|
231
|
+
'Wiesen',
|
|
232
|
+
'Tal',
|
|
233
|
+
'See',
|
|
234
|
+
'Bismarck',
|
|
235
|
+
'Goethe',
|
|
236
|
+
'Schiller',
|
|
237
|
+
'Kant',
|
|
238
|
+
'Hegel',
|
|
239
|
+
'Mozart',
|
|
240
|
+
'Beethoven',
|
|
241
|
+
'Bach',
|
|
242
|
+
'Brahms',
|
|
243
|
+
'Handel',
|
|
244
|
+
],
|
|
245
|
+
cities: [
|
|
246
|
+
'Berlin',
|
|
247
|
+
'Hamburg',
|
|
248
|
+
'Munich',
|
|
249
|
+
'Cologne',
|
|
250
|
+
'Frankfurt',
|
|
251
|
+
'Stuttgart',
|
|
252
|
+
'Düsseldorf',
|
|
253
|
+
'Leipzig',
|
|
254
|
+
'Dortmund',
|
|
255
|
+
'Essen',
|
|
256
|
+
'Bremen',
|
|
257
|
+
'Dresden',
|
|
258
|
+
'Hanover',
|
|
259
|
+
'Nuremberg',
|
|
260
|
+
'Duisburg',
|
|
261
|
+
'Bochum',
|
|
262
|
+
'Wuppertal',
|
|
263
|
+
'Bielefeld',
|
|
264
|
+
'Bonn',
|
|
265
|
+
'Münster',
|
|
266
|
+
],
|
|
267
|
+
regions: [
|
|
268
|
+
'Bayern',
|
|
269
|
+
'Nordrhein-Westfalen',
|
|
270
|
+
'Baden-Württemberg',
|
|
271
|
+
'Niedersachsen',
|
|
272
|
+
'Hessen',
|
|
273
|
+
'Sachsen',
|
|
274
|
+
'Rheinland-Pfalz',
|
|
275
|
+
'Berlin',
|
|
276
|
+
'Schleswig-Holstein',
|
|
277
|
+
'Brandenburg',
|
|
278
|
+
'Sachsen-Anhalt',
|
|
279
|
+
'Thüringen',
|
|
280
|
+
'Hamburg',
|
|
281
|
+
'Mecklenburg-Vorpommern',
|
|
282
|
+
'Bremen',
|
|
283
|
+
'Saarland',
|
|
284
|
+
],
|
|
285
|
+
zipFormat: () => String(randomNumber(10000, 99999)).padStart(5, '0'),
|
|
286
|
+
},
|
|
287
|
+
es: {
|
|
288
|
+
name: 'Spain',
|
|
289
|
+
streetTypes: [
|
|
290
|
+
'Calle',
|
|
291
|
+
'Avenida',
|
|
292
|
+
'Plaza',
|
|
293
|
+
'Paseo',
|
|
294
|
+
'Rambla',
|
|
295
|
+
'Carretera',
|
|
296
|
+
'Camino',
|
|
297
|
+
'Vía',
|
|
298
|
+
'Travesía',
|
|
299
|
+
'Callejón',
|
|
300
|
+
],
|
|
301
|
+
streetNames: [
|
|
302
|
+
'Mayor',
|
|
303
|
+
'Real',
|
|
304
|
+
'Nueva',
|
|
305
|
+
'del Sol',
|
|
306
|
+
'de la Luna',
|
|
307
|
+
'del Rey',
|
|
308
|
+
'de la Reina',
|
|
309
|
+
'del Mar',
|
|
310
|
+
'de la Paz',
|
|
311
|
+
'de la Victoria',
|
|
312
|
+
'Cervantes',
|
|
313
|
+
'Goya',
|
|
314
|
+
'Velázquez',
|
|
315
|
+
'Picasso',
|
|
316
|
+
'Dalí',
|
|
317
|
+
'de España',
|
|
318
|
+
'de Colón',
|
|
319
|
+
'de la Constitución',
|
|
320
|
+
'del Prado',
|
|
321
|
+
'de las Flores',
|
|
322
|
+
],
|
|
323
|
+
cities: [
|
|
324
|
+
'Madrid',
|
|
325
|
+
'Barcelona',
|
|
326
|
+
'Valencia',
|
|
327
|
+
'Seville',
|
|
328
|
+
'Zaragoza',
|
|
329
|
+
'Málaga',
|
|
330
|
+
'Murcia',
|
|
331
|
+
'Palma',
|
|
332
|
+
'Las Palmas',
|
|
333
|
+
'Bilbao',
|
|
334
|
+
'Alicante',
|
|
335
|
+
'Córdoba',
|
|
336
|
+
'Valladolid',
|
|
337
|
+
'Vigo',
|
|
338
|
+
'Gijón',
|
|
339
|
+
'Hospitalet',
|
|
340
|
+
'A Coruña',
|
|
341
|
+
'Granada',
|
|
342
|
+
'Vitoria',
|
|
343
|
+
'Elche',
|
|
344
|
+
],
|
|
345
|
+
regions: [
|
|
346
|
+
'Andalucía',
|
|
347
|
+
'Cataluña',
|
|
348
|
+
'Madrid',
|
|
349
|
+
'Comunidad Valenciana',
|
|
350
|
+
'Galicia',
|
|
351
|
+
'Castilla y León',
|
|
352
|
+
'País Vasco',
|
|
353
|
+
'Castilla-La Mancha',
|
|
354
|
+
'Canarias',
|
|
355
|
+
'Murcia',
|
|
356
|
+
'Aragón',
|
|
357
|
+
'Extremadura',
|
|
358
|
+
'Asturias',
|
|
359
|
+
'Navarra',
|
|
360
|
+
'Cantabria',
|
|
361
|
+
'La Rioja',
|
|
362
|
+
'Baleares',
|
|
363
|
+
],
|
|
364
|
+
zipFormat: () => String(randomNumber(10000, 52999)).padStart(5, '0'),
|
|
365
|
+
},
|
|
366
|
+
};
|
|
367
|
+
|
|
368
|
+
const countryKeys = Object.keys(countries);
|
|
369
|
+
|
|
370
|
+
export interface Address {
|
|
371
|
+
street: string;
|
|
372
|
+
city: string;
|
|
373
|
+
zip: string;
|
|
374
|
+
state: string;
|
|
375
|
+
country: string;
|
|
376
|
+
countryCode: string;
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
export interface AddressResult {
|
|
380
|
+
addresses: Address[];
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
/**
|
|
384
|
+
* Generates one or more fictional postal addresses for a given country.
|
|
385
|
+
*
|
|
386
|
+
* @param countryCode - Country code: "fr", "us", "uk", "de", or "es" (random if omitted)
|
|
387
|
+
* @param count - Number of addresses to generate (1–10)
|
|
388
|
+
* @returns Array of addresses with street, city, zip, state, country, and countryCode
|
|
389
|
+
* @throws Error if the country code is invalid or count is out of range
|
|
390
|
+
*/
|
|
391
|
+
export default function address(countryCode?: string, count: number = 1): AddressResult {
|
|
392
|
+
if (count < 1 || count > MAX_COUNT) {
|
|
393
|
+
throw new Error(`Count must be between 1 and ${MAX_COUNT}`);
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
const code = (countryCode ?? random(countryKeys)).toLowerCase();
|
|
397
|
+
if (!countries[code]) {
|
|
398
|
+
throw new Error(`Unknown country code "${code}". Supported: ${countryKeys.join(', ')}`);
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
const data = countries[code]!;
|
|
402
|
+
|
|
403
|
+
const addresses: Address[] = Array.from({ length: count }, () => ({
|
|
404
|
+
street: `${randomNumber(1, 200)} ${random(data.streetTypes)} ${random(data.streetNames)}`,
|
|
405
|
+
city: random(data.cities),
|
|
406
|
+
zip: data.zipFormat(),
|
|
407
|
+
state: random(data.regions),
|
|
408
|
+
country: data.name,
|
|
409
|
+
countryCode: code.toUpperCase(),
|
|
410
|
+
}));
|
|
411
|
+
|
|
412
|
+
return { addresses };
|
|
413
|
+
}
|