roast-api 1.3.0 → 1.5.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 +27 -1
- package/package.json +1 -1
- package/.github/workflows/deploy.yml +0 -37
- package/.github/workflows/release.yml +0 -30
- package/api/index.html +0 -52
- package/assets/logo.png +0 -0
- package/assets/style.css +0 -421
- package/index.html +0 -313
- package/load_test.js +0 -72
- package/postman/roast-as-a-service.postman_collection.json +0 -79
package/README.md
CHANGED
|
@@ -7,6 +7,8 @@
|
|
|
7
7
|
<img src="https://hits.sh/maijied.github.io/roast-as-a-service.svg?view=today-total&style=flat-square&label=visitors&color=ec4899&labelColor=020617" alt="Visitor Count" />
|
|
8
8
|
<a href="https://www.npmjs.com/package/roast-api"><img src="https://img.shields.io/npm/v/roast-api?style=flat-square&color=f97316&labelColor=020617" alt="npm version" /></a>
|
|
9
9
|
<a href="https://www.npmjs.com/package/roast-api"><img src="https://img.shields.io/npm/dm/roast-api?style=flat-square&color=ec4899&labelColor=020617" alt="npm downloads" /></a>
|
|
10
|
+
<a href="https://pypi.org/project/roast-api/"><img src="https://img.shields.io/pypi/v/roast-api?style=flat-square&color=3b82f6&labelColor=020617" alt="PyPI version" /></a>
|
|
11
|
+
<a href="https://packagist.org/packages/maizied/roast-api"><img src="https://img.shields.io/packagist/v/maizied/roast-api?style=flat-square&color=10b981&labelColor=020617" alt="Packagist version" /></a>
|
|
10
12
|
<a href="https://github.com/Maijied/roast-as-a-service/actions/workflows/deploy.yml"><img src="https://github.com/Maijied/roast-as-a-service/actions/workflows/deploy.yml/badge.svg" alt="Deploy to GitHub Pages" /></a>
|
|
11
13
|
</p>
|
|
12
14
|
|
|
@@ -66,7 +68,31 @@ Load the client SDK directly in your browser:
|
|
|
66
68
|
</script>
|
|
67
69
|
```
|
|
68
70
|
|
|
69
|
-
### 3.
|
|
71
|
+
### 3. Install via Composer (PHP)
|
|
72
|
+
```bash
|
|
73
|
+
composer require maizied/roast-api
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
```php
|
|
77
|
+
use Maizied\RoastApi\RaaS;
|
|
78
|
+
|
|
79
|
+
$roast = RaaS::getRandomRoast(['lang' => 'en']);
|
|
80
|
+
echo $roast['text'];
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
### 4. Install via pip (Python)
|
|
84
|
+
```bash
|
|
85
|
+
pip install roast-api
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
```python
|
|
89
|
+
from roast_api import get_random_roast
|
|
90
|
+
|
|
91
|
+
roast = get_random_roast(lang='en')
|
|
92
|
+
print(roast['text'])
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
### 5. Direct Fetch
|
|
70
96
|
Or just fetch the JSON files directly:
|
|
71
97
|
|
|
72
98
|
```javascript
|
package/package.json
CHANGED
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
name: Deploy to GitHub Pages
|
|
2
|
-
|
|
3
|
-
on:
|
|
4
|
-
push:
|
|
5
|
-
branches: ["main"]
|
|
6
|
-
workflow_dispatch:
|
|
7
|
-
|
|
8
|
-
permissions:
|
|
9
|
-
contents: read
|
|
10
|
-
pages: write
|
|
11
|
-
id-token: write
|
|
12
|
-
|
|
13
|
-
concurrency:
|
|
14
|
-
group: "pages"
|
|
15
|
-
cancel-in-progress: false
|
|
16
|
-
|
|
17
|
-
jobs:
|
|
18
|
-
deploy:
|
|
19
|
-
environment:
|
|
20
|
-
name: github-pages
|
|
21
|
-
url: ${{ steps.deployment.outputs.page_url }}
|
|
22
|
-
runs-on: ubuntu-latest
|
|
23
|
-
steps:
|
|
24
|
-
- name: Checkout
|
|
25
|
-
uses: actions/checkout@v4
|
|
26
|
-
|
|
27
|
-
- name: Setup Pages
|
|
28
|
-
uses: actions/configure-pages@v5
|
|
29
|
-
|
|
30
|
-
- name: Upload artifact
|
|
31
|
-
uses: actions/upload-pages-artifact@v3
|
|
32
|
-
with:
|
|
33
|
-
path: '.'
|
|
34
|
-
|
|
35
|
-
- name: Deploy to GitHub Pages
|
|
36
|
-
id: deployment
|
|
37
|
-
uses: actions/deploy-pages@v4
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
name: Publish Package and Release
|
|
2
|
-
|
|
3
|
-
on:
|
|
4
|
-
push:
|
|
5
|
-
tags:
|
|
6
|
-
- 'v*.*.*'
|
|
7
|
-
|
|
8
|
-
jobs:
|
|
9
|
-
publish-npm:
|
|
10
|
-
runs-on: ubuntu-latest
|
|
11
|
-
permissions:
|
|
12
|
-
contents: write
|
|
13
|
-
steps:
|
|
14
|
-
- uses: actions/checkout@v4
|
|
15
|
-
|
|
16
|
-
- uses: actions/setup-node@v4
|
|
17
|
-
with:
|
|
18
|
-
node-version: '20.x'
|
|
19
|
-
registry-url: 'https://registry.npmjs.org'
|
|
20
|
-
|
|
21
|
-
- run: npm publish --access public
|
|
22
|
-
env:
|
|
23
|
-
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
|
24
|
-
|
|
25
|
-
- name: Create Release
|
|
26
|
-
uses: softprops/action-gh-release@v1
|
|
27
|
-
with:
|
|
28
|
-
files: |
|
|
29
|
-
api/client.js
|
|
30
|
-
postman/roast-as-a-service.postman_collection.json
|
package/api/index.html
DELETED
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
<!DOCTYPE html>
|
|
2
|
-
<html lang="en">
|
|
3
|
-
|
|
4
|
-
<head>
|
|
5
|
-
<meta charset="UTF-8">
|
|
6
|
-
<title>RaaS API</title>
|
|
7
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
8
|
-
<style>
|
|
9
|
-
body {
|
|
10
|
-
background-color: #0d1117;
|
|
11
|
-
color: #c9d1d9;
|
|
12
|
-
font-family: monospace;
|
|
13
|
-
display: flex;
|
|
14
|
-
justify-content: center;
|
|
15
|
-
align-items: center;
|
|
16
|
-
height: 100vh;
|
|
17
|
-
margin: 0;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
pre {
|
|
21
|
-
background: #161b22;
|
|
22
|
-
padding: 20px;
|
|
23
|
-
border-radius: 6px;
|
|
24
|
-
border: 1px solid #30363d;
|
|
25
|
-
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.5);
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
a {
|
|
29
|
-
color: #58a6ff;
|
|
30
|
-
text-decoration: none;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
a:hover {
|
|
34
|
-
text-decoration: underline;
|
|
35
|
-
}
|
|
36
|
-
</style>
|
|
37
|
-
</head>
|
|
38
|
-
|
|
39
|
-
<body>
|
|
40
|
-
<pre>{
|
|
41
|
-
"service": "Roast as a Service (RaaS)",
|
|
42
|
-
"status": "operational",
|
|
43
|
-
"version": 1,
|
|
44
|
-
"message": "This is the base path. Please use specific endpoints.",
|
|
45
|
-
"links": {
|
|
46
|
-
"documentation": "<a href="../">../ (Website)</a>",
|
|
47
|
-
"manifest": "<a href="./manifest.json">./manifest.json</a>"
|
|
48
|
-
}
|
|
49
|
-
}</pre>
|
|
50
|
-
</body>
|
|
51
|
-
|
|
52
|
-
</html>
|
package/assets/logo.png
DELETED
|
Binary file
|
package/assets/style.css
DELETED
|
@@ -1,421 +0,0 @@
|
|
|
1
|
-
:root {
|
|
2
|
-
--bg: #020617;
|
|
3
|
-
--bg-elevated: #020617;
|
|
4
|
-
--card: #020617;
|
|
5
|
-
--border-subtle: #1e293b;
|
|
6
|
-
--accent: #f97316;
|
|
7
|
-
--accent-soft: rgba(249, 115, 22, 0.18);
|
|
8
|
-
--accent-2: #ec4899;
|
|
9
|
-
--text-main: #e5e7eb;
|
|
10
|
-
--text-muted: #9ca3af;
|
|
11
|
-
--text-soft: #6b7280;
|
|
12
|
-
--terminal-bg: #020617;
|
|
13
|
-
--terminal-border: #1f2933;
|
|
14
|
-
--font-sans: system-ui, -apple-system, BlinkMacSystemFont, "SF Pro Text",
|
|
15
|
-
"Segoe UI", sans-serif;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
*,
|
|
19
|
-
*::before,
|
|
20
|
-
*::after {
|
|
21
|
-
box-sizing: border-box;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
body {
|
|
25
|
-
margin: 0;
|
|
26
|
-
font-family: var(--font-sans);
|
|
27
|
-
background: radial-gradient(circle at top, #0f172a 0, #020617 52%);
|
|
28
|
-
color: var(--text-main);
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
.shell {
|
|
32
|
-
max-width: 1120px;
|
|
33
|
-
margin: 0 auto;
|
|
34
|
-
padding: 24px 16px 40px;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
.hero {
|
|
38
|
-
display: flex;
|
|
39
|
-
flex-wrap: wrap;
|
|
40
|
-
gap: 24px;
|
|
41
|
-
align-items: stretch;
|
|
42
|
-
justify-content: space-between;
|
|
43
|
-
margin-top: 12px;
|
|
44
|
-
margin-bottom: 32px;
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
.hero-text {
|
|
48
|
-
flex: 1 1 320px;
|
|
49
|
-
min-width: 0;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
.hero-card {
|
|
53
|
-
flex: 1 1 320px;
|
|
54
|
-
max-width: 460px;
|
|
55
|
-
background: linear-gradient(135deg, rgba(15, 23, 42, 0.9), rgba(15, 23, 42, 0.7));
|
|
56
|
-
border-radius: 18px;
|
|
57
|
-
border: 1px solid rgba(148, 163, 184, 0.18);
|
|
58
|
-
box-shadow:
|
|
59
|
-
0 20px 40px rgba(15, 23, 42, 0.8),
|
|
60
|
-
0 0 0 1px rgba(15, 23, 42, 0.8);
|
|
61
|
-
overflow: hidden;
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
h1 {
|
|
65
|
-
display: flex;
|
|
66
|
-
align-items: center;
|
|
67
|
-
gap: 12px;
|
|
68
|
-
font-size: clamp(2.1rem, 3vw, 2.6rem);
|
|
69
|
-
letter-spacing: -0.04em;
|
|
70
|
-
margin: 8px 0;
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
.logo-md {
|
|
74
|
-
width: 48px;
|
|
75
|
-
height: 48px;
|
|
76
|
-
object-fit: contain;
|
|
77
|
-
filter: drop-shadow(0 0 10px rgba(249, 115, 22, 0.5));
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
.brand-pill {
|
|
81
|
-
display: inline-flex;
|
|
82
|
-
font-size: 0.8rem;
|
|
83
|
-
font-weight: 600;
|
|
84
|
-
color: var(--accent-2);
|
|
85
|
-
margin-bottom: 4px;
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
.brand-pill a {
|
|
89
|
-
color: var(--accent-2);
|
|
90
|
-
text-decoration: none;
|
|
91
|
-
margin-left: 4px;
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
.brand-pill a:hover {
|
|
95
|
-
text-decoration: underline;
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
.subtitle {
|
|
99
|
-
margin: 0 0 18px;
|
|
100
|
-
color: var(--text-muted);
|
|
101
|
-
max-width: 480px;
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
.badge {
|
|
105
|
-
display: inline-flex;
|
|
106
|
-
align-items: center;
|
|
107
|
-
justify-content: center;
|
|
108
|
-
font-size: 0.8rem;
|
|
109
|
-
text-transform: uppercase;
|
|
110
|
-
letter-spacing: 0.12em;
|
|
111
|
-
padding: 2px 10px;
|
|
112
|
-
border-radius: 999px;
|
|
113
|
-
background: rgba(249, 115, 22, 0.15);
|
|
114
|
-
color: #fed7aa;
|
|
115
|
-
border: 1px solid rgba(249, 115, 22, 0.5);
|
|
116
|
-
margin-left: 8px;
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
.hero-actions {
|
|
120
|
-
display: flex;
|
|
121
|
-
flex-wrap: wrap;
|
|
122
|
-
gap: 10px;
|
|
123
|
-
margin-bottom: 10px;
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
.btn {
|
|
127
|
-
border-radius: 999px;
|
|
128
|
-
padding: 0.7rem 1.6rem;
|
|
129
|
-
font-size: 0.95rem;
|
|
130
|
-
font-weight: 600;
|
|
131
|
-
border: none;
|
|
132
|
-
cursor: pointer;
|
|
133
|
-
transition: transform 0.12s ease-out, box-shadow 0.12s ease-out, opacity 0.12s;
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
.btn.primary {
|
|
137
|
-
background: linear-gradient(135deg, var(--accent), var(--accent-2));
|
|
138
|
-
color: white;
|
|
139
|
-
box-shadow:
|
|
140
|
-
0 10px 25px rgba(249, 115, 22, 0.35),
|
|
141
|
-
0 0 0 1px rgba(248, 250, 252, 0.04);
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
.btn.primary:hover {
|
|
145
|
-
transform: translateY(-1px);
|
|
146
|
-
opacity: 0.94;
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
.btn.ghost {
|
|
150
|
-
background: rgba(15, 23, 42, 0.7);
|
|
151
|
-
color: var(--text-main);
|
|
152
|
-
border: 1px solid rgba(148, 163, 184, 0.5);
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
.btn.ghost:hover {
|
|
156
|
-
background: rgba(15, 23, 42, 0.9);
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
.meta {
|
|
160
|
-
margin-top: 4px;
|
|
161
|
-
font-size: 0.85rem;
|
|
162
|
-
color: var(--text-soft);
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
.card-header {
|
|
166
|
-
display: flex;
|
|
167
|
-
align-items: center;
|
|
168
|
-
gap: 8px;
|
|
169
|
-
padding: 10px 14px;
|
|
170
|
-
border-bottom: 1px solid var(--terminal-border);
|
|
171
|
-
background: radial-gradient(circle at top left, #111827, #020617);
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
.dot {
|
|
175
|
-
width: 10px;
|
|
176
|
-
height: 10px;
|
|
177
|
-
border-radius: 50%;
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
.dot.red {
|
|
181
|
-
background: #f97373;
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
.dot.amber {
|
|
185
|
-
background: #fbbf24;
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
.dot.green {
|
|
189
|
-
background: #34d399;
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
.card-title {
|
|
193
|
-
margin-left: auto;
|
|
194
|
-
font-size: 0.78rem;
|
|
195
|
-
text-transform: uppercase;
|
|
196
|
-
letter-spacing: 0.16em;
|
|
197
|
-
color: var(--text-soft);
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
.terminal {
|
|
201
|
-
margin: 0;
|
|
202
|
-
font-family: "SF Mono", ui-monospace, Menlo, Monaco, Consolas, "Liberation Mono", monospace;
|
|
203
|
-
font-size: 0.85rem;
|
|
204
|
-
background: var(--terminal-bg);
|
|
205
|
-
padding: 16px;
|
|
206
|
-
min-height: 140px;
|
|
207
|
-
white-space: pre-wrap;
|
|
208
|
-
border-radius: 0 0 18px 18px;
|
|
209
|
-
border-top: 1px solid rgba(15, 23, 42, 0.4);
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
main {
|
|
213
|
-
margin-top: 8px;
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
.section {
|
|
217
|
-
margin-bottom: 32px;
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
.section h2 {
|
|
221
|
-
margin: 0 0 6px;
|
|
222
|
-
font-size: 1.25rem;
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
.section p {
|
|
226
|
-
margin: 0 0 14px;
|
|
227
|
-
color: var(--text-muted);
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
.grid {
|
|
231
|
-
display: grid;
|
|
232
|
-
grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
|
|
233
|
-
gap: 14px;
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
.card {
|
|
237
|
-
background: rgba(15, 23, 42, 0.85);
|
|
238
|
-
border-radius: 16px;
|
|
239
|
-
border: 1px solid var(--border-subtle);
|
|
240
|
-
padding: 14px 14px 16px;
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
.card h3 {
|
|
244
|
-
margin: 0 0 6px;
|
|
245
|
-
font-size: 1rem;
|
|
246
|
-
}
|
|
247
|
-
|
|
248
|
-
.card p {
|
|
249
|
-
margin: 0;
|
|
250
|
-
font-size: 0.92rem;
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
.section-accent {
|
|
254
|
-
border-radius: 18px;
|
|
255
|
-
padding: 18px 16px 20px;
|
|
256
|
-
background: radial-gradient(circle at top left, rgba(249, 115, 22, 0.09), rgba(15, 23, 42, 0.96));
|
|
257
|
-
border: 1px solid rgba(249, 115, 22, 0.25);
|
|
258
|
-
box-shadow: 0 18px 40px rgba(15, 23, 42, 0.8);
|
|
259
|
-
}
|
|
260
|
-
|
|
261
|
-
.section-accent h2 {
|
|
262
|
-
font-size: 1.3rem;
|
|
263
|
-
}
|
|
264
|
-
|
|
265
|
-
.arch-grid {
|
|
266
|
-
margin-top: 10px;
|
|
267
|
-
}
|
|
268
|
-
|
|
269
|
-
.arch-card {
|
|
270
|
-
background: rgba(15, 23, 42, 0.96);
|
|
271
|
-
border-radius: 14px;
|
|
272
|
-
border: 1px solid rgba(148, 163, 184, 0.4);
|
|
273
|
-
}
|
|
274
|
-
|
|
275
|
-
.arch-card h3 {
|
|
276
|
-
font-size: 0.98rem;
|
|
277
|
-
}
|
|
278
|
-
|
|
279
|
-
.arch-card p {
|
|
280
|
-
font-size: 0.9rem;
|
|
281
|
-
}
|
|
282
|
-
|
|
283
|
-
.code-grid {
|
|
284
|
-
display: grid;
|
|
285
|
-
grid-template-columns: minmax(0, 1fr);
|
|
286
|
-
gap: 14px;
|
|
287
|
-
}
|
|
288
|
-
|
|
289
|
-
@media (min-width: 840px) {
|
|
290
|
-
.code-grid {
|
|
291
|
-
grid-template-columns: repeat(2, minmax(0, 1fr));
|
|
292
|
-
}
|
|
293
|
-
}
|
|
294
|
-
|
|
295
|
-
.code-card {
|
|
296
|
-
background: rgba(15, 23, 42, 0.9);
|
|
297
|
-
border-radius: 14px;
|
|
298
|
-
border: 1px solid var(--border-subtle);
|
|
299
|
-
overflow: hidden;
|
|
300
|
-
}
|
|
301
|
-
|
|
302
|
-
.code-card h3 {
|
|
303
|
-
margin: 10px 12px;
|
|
304
|
-
font-size: 0.96rem;
|
|
305
|
-
}
|
|
306
|
-
|
|
307
|
-
.code-card pre {
|
|
308
|
-
margin: 0;
|
|
309
|
-
padding: 10px 12px 12px;
|
|
310
|
-
background: #020617;
|
|
311
|
-
font-family: "SF Mono", ui-monospace, Menlo, Monaco, Consolas, "Liberation Mono", monospace;
|
|
312
|
-
font-size: 0.8rem;
|
|
313
|
-
overflow-x: auto;
|
|
314
|
-
}
|
|
315
|
-
|
|
316
|
-
.share-buttons {
|
|
317
|
-
display: flex;
|
|
318
|
-
flex-wrap: wrap;
|
|
319
|
-
gap: 8px;
|
|
320
|
-
margin-top: 6px;
|
|
321
|
-
}
|
|
322
|
-
|
|
323
|
-
.share-btn {
|
|
324
|
-
display: inline-flex;
|
|
325
|
-
align-items: center;
|
|
326
|
-
justify-content: center;
|
|
327
|
-
padding: 0.4rem 0.9rem;
|
|
328
|
-
border-radius: 999px;
|
|
329
|
-
font-size: 0.8rem;
|
|
330
|
-
text-decoration: none;
|
|
331
|
-
background: rgba(15, 23, 42, 0.9);
|
|
332
|
-
color: var(--text-main);
|
|
333
|
-
border: 1px solid rgba(148, 163, 184, 0.6);
|
|
334
|
-
}
|
|
335
|
-
|
|
336
|
-
.share-btn:hover {
|
|
337
|
-
background: rgba(15, 23, 42, 1);
|
|
338
|
-
}
|
|
339
|
-
|
|
340
|
-
.footer {
|
|
341
|
-
margin-top: 32px;
|
|
342
|
-
padding-top: 16px;
|
|
343
|
-
border-top: 1px solid rgba(15, 23, 42, 0.9);
|
|
344
|
-
font-size: 0.8rem;
|
|
345
|
-
color: var(--text-soft);
|
|
346
|
-
}
|
|
347
|
-
|
|
348
|
-
.footer a {
|
|
349
|
-
color: #93c5fd;
|
|
350
|
-
text-decoration: none;
|
|
351
|
-
}
|
|
352
|
-
|
|
353
|
-
.footer a:hover {
|
|
354
|
-
text-decoration: underline;
|
|
355
|
-
}
|
|
356
|
-
|
|
357
|
-
code {
|
|
358
|
-
font-family: "SF Mono", ui-monospace, Menlo, Monaco, Consolas, "Liberation Mono", monospace;
|
|
359
|
-
font-size: 0.85em;
|
|
360
|
-
}
|
|
361
|
-
|
|
362
|
-
@media (max-width: 600px) {
|
|
363
|
-
.shell {
|
|
364
|
-
padding: 16px 12px 32px;
|
|
365
|
-
}
|
|
366
|
-
|
|
367
|
-
.hero {
|
|
368
|
-
margin-top: 4px;
|
|
369
|
-
gap: 20px;
|
|
370
|
-
}
|
|
371
|
-
|
|
372
|
-
h1 {
|
|
373
|
-
font-size: 1.8rem;
|
|
374
|
-
flex-wrap: wrap;
|
|
375
|
-
/* Allow logo to wrap if needed, though unlikely */
|
|
376
|
-
}
|
|
377
|
-
|
|
378
|
-
.logo-md {
|
|
379
|
-
width: 36px;
|
|
380
|
-
height: 36px;
|
|
381
|
-
}
|
|
382
|
-
|
|
383
|
-
.subtitle {
|
|
384
|
-
font-size: 0.95rem;
|
|
385
|
-
}
|
|
386
|
-
|
|
387
|
-
.hero-actions {
|
|
388
|
-
width: 100%;
|
|
389
|
-
}
|
|
390
|
-
|
|
391
|
-
.btn {
|
|
392
|
-
width: 100%;
|
|
393
|
-
/* Full width buttons on mobile */
|
|
394
|
-
text-align: center;
|
|
395
|
-
padding: 0.8rem 1rem;
|
|
396
|
-
}
|
|
397
|
-
|
|
398
|
-
.hero-actions .btn {
|
|
399
|
-
flex: 1 1 100%;
|
|
400
|
-
}
|
|
401
|
-
|
|
402
|
-
.terminal {
|
|
403
|
-
font-size: 0.8rem;
|
|
404
|
-
/* Slightly smaller code font */
|
|
405
|
-
min-height: 120px;
|
|
406
|
-
}
|
|
407
|
-
|
|
408
|
-
.section h2 {
|
|
409
|
-
font-size: 1.15rem;
|
|
410
|
-
}
|
|
411
|
-
|
|
412
|
-
.share-buttons {
|
|
413
|
-
justify-content: stretch;
|
|
414
|
-
}
|
|
415
|
-
|
|
416
|
-
.share-btn {
|
|
417
|
-
flex: 1 1 40%;
|
|
418
|
-
/* 2 per row roughly */
|
|
419
|
-
text-align: center;
|
|
420
|
-
}
|
|
421
|
-
}
|
package/index.html
DELETED
|
@@ -1,313 +0,0 @@
|
|
|
1
|
-
<!DOCTYPE html>
|
|
2
|
-
<html lang="en">
|
|
3
|
-
|
|
4
|
-
<head>
|
|
5
|
-
<meta charset="UTF-8" />
|
|
6
|
-
<title>Roast as a Service · RaaS</title>
|
|
7
|
-
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
8
|
-
|
|
9
|
-
<!-- Meta -->
|
|
10
|
-
<meta name="description"
|
|
11
|
-
content="Roast as a Service (RaaS) – a CDN-backed static JSON API that serves blazing-fast developer roasts in English and Bangla. Plug it into your apps, bots, and CI.">
|
|
12
|
-
|
|
13
|
-
<!-- Open Graph -->
|
|
14
|
-
<meta property="og:title" content="Roast as a Service · RaaS" />
|
|
15
|
-
<meta property="og:description"
|
|
16
|
-
content="Blazing-fast static JSON API for developer roasts. EN + BN, CDN cached, no backend." />
|
|
17
|
-
<meta property="og:url" content="https://maijied.github.io/roast-as-a-service/" />
|
|
18
|
-
<meta property="og:type" content="website" />
|
|
19
|
-
<!-- Optional preview image -->
|
|
20
|
-
<!-- <meta property="og:image" content="https://maijied.github.io/roast-as-a-service/assets/preview.png" /> -->
|
|
21
|
-
|
|
22
|
-
<!-- Twitter -->
|
|
23
|
-
<meta name="twitter:card" content="summary_large_image" />
|
|
24
|
-
<meta name="twitter:title" content="Roast as a Service · RaaS" />
|
|
25
|
-
<meta name="twitter:description" content="Random dev roasts over a static JSON API.">
|
|
26
|
-
|
|
27
|
-
<link rel="stylesheet" href="./assets/style.css" />
|
|
28
|
-
</head>
|
|
29
|
-
|
|
30
|
-
<body>
|
|
31
|
-
<div class="shell">
|
|
32
|
-
<header class="hero">
|
|
33
|
-
<div class="hero-text">
|
|
34
|
-
<div class="brand-pill">🐛 Powered by <a href="https://github.com/Maijied/lorapok"
|
|
35
|
-
target="_blank">Lorapok</a></div>
|
|
36
|
-
<h1><img src="./assets/logo.png" alt="RaaS Logo" class="logo-md" /> Roast as a Service <span
|
|
37
|
-
class="badge">RaaS</span></h1>
|
|
38
|
-
<p class="subtitle">
|
|
39
|
-
CDN‑served static JSON API for developer roasts. Zero backend, ultra‑low latency, English &
|
|
40
|
-
Bangla support.
|
|
41
|
-
</p>
|
|
42
|
-
<div class="hero-actions">
|
|
43
|
-
<button id="btn-en" class="btn primary">🔥 Roast me (EN)</button>
|
|
44
|
-
<button id="btn-bn" class="btn ghost">🔥 Roast me (BN)</button>
|
|
45
|
-
</div>
|
|
46
|
-
<p class="meta">
|
|
47
|
-
Served from GitHub Pages edge cache. Designed for bots, CLIs, dashboards, and CI pipelines.
|
|
48
|
-
</p>
|
|
49
|
-
<div style="display: flex; gap: 8px; flex-wrap: wrap; margin-top: 8px;">
|
|
50
|
-
<a href="https://www.npmjs.com/package/roast-api" target="_blank"><img
|
|
51
|
-
src="https://img.shields.io/npm/v/roast-api?style=flat-square&color=f97316&labelColor=020617"
|
|
52
|
-
alt="npm version" /></a>
|
|
53
|
-
<a href="https://www.npmjs.com/package/roast-api" target="_blank"><img
|
|
54
|
-
src="https://img.shields.io/npm/dm/roast-api?style=flat-square&color=ec4899&labelColor=020617"
|
|
55
|
-
alt="npm downloads" /></a>
|
|
56
|
-
<a href="https://github.com/Maijied/roast-as-a-service" target="_blank"><img
|
|
57
|
-
src="https://img.shields.io/github/stars/Maijied/roast-as-a-service?style=flat-square&color=f97316&labelColor=020617"
|
|
58
|
-
alt="GitHub stars" /></a>
|
|
59
|
-
</div>
|
|
60
|
-
</div>
|
|
61
|
-
|
|
62
|
-
<div class="hero-card">
|
|
63
|
-
<div class="card-header">
|
|
64
|
-
<span class="dot red"></span>
|
|
65
|
-
<span class="dot amber"></span>
|
|
66
|
-
<span class="dot green"></span>
|
|
67
|
-
<span class="card-title">RaaS Console</span>
|
|
68
|
-
</div>
|
|
69
|
-
<pre id="roast-box" class="terminal">
|
|
70
|
-
$ raas get --lang=en
|
|
71
|
-
# Press "Roast me" to receive fire...
|
|
72
|
-
</pre>
|
|
73
|
-
</div>
|
|
74
|
-
</header>
|
|
75
|
-
|
|
76
|
-
<main>
|
|
77
|
-
<section class="section">
|
|
78
|
-
<h2>How it works</h2>
|
|
79
|
-
RaaS exposes sharded JSON datasets over GitHub Pages, then a tiny client SDK picks, filters, and caches
|
|
80
|
-
roasts in the browser, giving you an API‑like experience with pure static hosting.
|
|
81
|
-
</p>
|
|
82
|
-
<div class="grid">
|
|
83
|
-
<div class="card">
|
|
84
|
-
<h3>Static API</h3>
|
|
85
|
-
<p>
|
|
86
|
-
Roasts are stored in language‑specific shards (<code>en</code>, <code>bn</code>) and served
|
|
87
|
-
as JSON over GitHub Pages’ global CDN for low TTFB.
|
|
88
|
-
</p>
|
|
89
|
-
</div>
|
|
90
|
-
<div class="card">
|
|
91
|
-
<h3>Smart client</h3>
|
|
92
|
-
<p>
|
|
93
|
-
The bundled client fetches a small shard, caches it, and returns random roasts with optional
|
|
94
|
-
intensity and length filters.
|
|
95
|
-
</p>
|
|
96
|
-
</div>
|
|
97
|
-
<div class="card">
|
|
98
|
-
<h3>Zero ops</h3>
|
|
99
|
-
<p>
|
|
100
|
-
No servers, no cold starts, no scaling issues. Push to main, let Pages deploy and cache
|
|
101
|
-
everything at the edge.
|
|
102
|
-
</p>
|
|
103
|
-
</div>
|
|
104
|
-
</div>
|
|
105
|
-
</section>
|
|
106
|
-
|
|
107
|
-
<section class="section section-accent">
|
|
108
|
-
<h2>Why this architecture feels overkill (in a good way)</h2>
|
|
109
|
-
<p>
|
|
110
|
-
RaaS is not a toy endpoint glued to a random server. It is a static API designed to exploit CDN edge
|
|
111
|
-
caching, sharded JSON, and a smart client so you get API-level UX without any backend attached.
|
|
112
|
-
</p>
|
|
113
|
-
|
|
114
|
-
<div class="grid arch-grid">
|
|
115
|
-
<div class="card arch-card">
|
|
116
|
-
<h3>Edge-first delivery</h3>
|
|
117
|
-
<p>
|
|
118
|
-
All JSON and JS is served from GitHub Pages’ global PoPs, so most requests are satisfied
|
|
119
|
-
from edge cache with minimal latency and no application server in the path.
|
|
120
|
-
</p>
|
|
121
|
-
</div>
|
|
122
|
-
<div class="card arch-card">
|
|
123
|
-
<h3>Static API, dynamic feel</h3>
|
|
124
|
-
<p>
|
|
125
|
-
The API surface is just files, but the client SDK handles randomness, filtering, and caching
|
|
126
|
-
to make it behave like a dynamic service while staying 100% static.
|
|
127
|
-
</p>
|
|
128
|
-
</div>
|
|
129
|
-
<div class="card arch-card">
|
|
130
|
-
<h3>Shard & scale</h3>
|
|
131
|
-
<p>
|
|
132
|
-
Roasts are split into language shards, which keeps payloads small, cache hit rates high, and
|
|
133
|
-
lets you grow the dataset without slowing down clients.
|
|
134
|
-
</p>
|
|
135
|
-
</div>
|
|
136
|
-
<div class="card arch-card">
|
|
137
|
-
<h3>Operationally boring</h3>
|
|
138
|
-
<p>
|
|
139
|
-
No servers, no containers, no warmup, no autoscaling rules. Git pushes become deployments,
|
|
140
|
-
and the CDN takes care of distribution, caching, and reliability.
|
|
141
|
-
</p>
|
|
142
|
-
</div>
|
|
143
|
-
</div>
|
|
144
|
-
</section>
|
|
145
|
-
|
|
146
|
-
<section class="section">
|
|
147
|
-
<h2>Quick start</h2>
|
|
148
|
-
<div class="code-grid">
|
|
149
|
-
<div class="code-card">
|
|
150
|
-
<h3>npm install</h3>
|
|
151
|
-
<pre><code>npm install roast-api
|
|
152
|
-
|
|
153
|
-
// Usage
|
|
154
|
-
const RaaS = require('roast-api');
|
|
155
|
-
RaaS.getRandomRoast({ lang: 'en' })
|
|
156
|
-
.then(r => console.log(r.text));</code></pre>
|
|
157
|
-
</div>
|
|
158
|
-
<div class="code-card">
|
|
159
|
-
<h3>Script include</h3>
|
|
160
|
-
<pre><code><script src="https://maijied.github.io/roast-as-a-service/api/client.js"></script>
|
|
161
|
-
|
|
162
|
-
<script>
|
|
163
|
-
RaaS.getRandomRoast({ lang: 'bn', intensity: 2 })
|
|
164
|
-
.then(r => console.log(r.text));
|
|
165
|
-
</script></code></pre>
|
|
166
|
-
</div>
|
|
167
|
-
</div>
|
|
168
|
-
</section>
|
|
169
|
-
|
|
170
|
-
<section class="section">
|
|
171
|
-
<h2>API usage</h2>
|
|
172
|
-
<p>
|
|
173
|
-
RaaS is a read‑only static API, so you interact with it using simple GET requests or the client SDK.
|
|
174
|
-
</p>
|
|
175
|
-
<div class="code-grid">
|
|
176
|
-
<div class="code-card">
|
|
177
|
-
<h3>cURL</h3>
|
|
178
|
-
<pre><code># Get English shard 1
|
|
179
|
-
curl https://maijied.github.io/roast-as-a-service/api/en/roasts-en-1.json
|
|
180
|
-
|
|
181
|
-
# Pretty-print first roast (requires jq)
|
|
182
|
-
curl -s https://maijied.github.io/roast-as-a-service/api/en/roasts-en-1.json \
|
|
183
|
-
| jq '.roasts[0].text'</code></pre>
|
|
184
|
-
</div>
|
|
185
|
-
<div class="code-card">
|
|
186
|
-
<h3>Node.js</h3>
|
|
187
|
-
<pre><code>import fetch from 'node-fetch';
|
|
188
|
-
|
|
189
|
-
async function getRandomRoast(lang = 'en') {
|
|
190
|
-
const url = `https://maijied.github.io/roast-as-a-service/api/${lang}/roasts-${lang}-1.json`;
|
|
191
|
-
const res = await fetch(url);
|
|
192
|
-
const data = await res.json();
|
|
193
|
-
const list = data.roasts;
|
|
194
|
-
const pick = list[Math.floor(Math.random() * list.length)];
|
|
195
|
-
return pick.text;
|
|
196
|
-
}</code></pre>
|
|
197
|
-
</div>
|
|
198
|
-
</div>
|
|
199
|
-
</section>
|
|
200
|
-
|
|
201
|
-
<section class="section">
|
|
202
|
-
<h2>Performance</h2>
|
|
203
|
-
<div class="code-card"
|
|
204
|
-
style="background: linear-gradient(135deg, rgba(249,115,22,0.1), rgba(236,72,153,0.1)); border: 1px solid var(--border-subtle);">
|
|
205
|
-
<div style="padding: 16px;">
|
|
206
|
-
<div
|
|
207
|
-
style="display: grid; grid-template-columns: repeat(auto-fit, minmax(140px, 1fr)); gap: 20px; text-align: center;">
|
|
208
|
-
<div>
|
|
209
|
-
<div style="font-size: 1.8rem; font-weight: 800; color: var(--accent);">2,000+</div>
|
|
210
|
-
<div style="font-size: 0.8rem; text-transform: uppercase; color: var(--text-muted);">
|
|
211
|
-
Requests / Sec</div>
|
|
212
|
-
</div>
|
|
213
|
-
<div>
|
|
214
|
-
<div style="font-size: 1.8rem; font-weight: 800; color: var(--accent-2);">100%</div>
|
|
215
|
-
<div style="font-size: 0.8rem; text-transform: uppercase; color: var(--text-muted);">
|
|
216
|
-
Success Rate</div>
|
|
217
|
-
</div>
|
|
218
|
-
<div>
|
|
219
|
-
<div style="font-size: 1.8rem; font-weight: 800; color: #10b981;">~50ms</div>
|
|
220
|
-
<div style="font-size: 0.8rem; text-transform: uppercase; color: var(--text-muted);">Avg
|
|
221
|
-
Latency</div>
|
|
222
|
-
</div>
|
|
223
|
-
<div>
|
|
224
|
-
<div style="font-size: 1.8rem; font-weight: 800; color: #3b82f6;">90%</div>
|
|
225
|
-
<div style="font-size: 0.8rem; text-transform: uppercase; color: var(--text-muted);">
|
|
226
|
-
Cache Hits</div>
|
|
227
|
-
</div>
|
|
228
|
-
</div>
|
|
229
|
-
<p style="font-size: 0.85rem; margin-top: 20px; color: var(--text-soft); text-align: center;">
|
|
230
|
-
Zero backend, zero cold starts. Optimized for extreme throughput and low TTFB using GitHub
|
|
231
|
-
Pages' edge CDN.
|
|
232
|
-
</p>
|
|
233
|
-
</div>
|
|
234
|
-
</div>
|
|
235
|
-
</section>
|
|
236
|
-
|
|
237
|
-
<section class="section">
|
|
238
|
-
<h2>Postman collection</h2>
|
|
239
|
-
<p>
|
|
240
|
-
Prefer GUI testing? Import the Postman collection and hit the static endpoints directly.
|
|
241
|
-
</p>
|
|
242
|
-
<div class="code-card">
|
|
243
|
-
<h3>Download</h3>
|
|
244
|
-
<div style="padding: 0 12px 14px;">
|
|
245
|
-
<a href="./postman/roast-as-a-service.postman_collection.json" download class="btn primary"
|
|
246
|
-
style="width: 100%; display: block; text-align: center; text-decoration: none; margin-bottom: 10px;">
|
|
247
|
-
Download Postman Collection
|
|
248
|
-
</a>
|
|
249
|
-
<p style="font-size: 0.8rem; margin: 0; color: var(--text-muted);">
|
|
250
|
-
Import this JSON file into Postman to test all endpoints instantly.
|
|
251
|
-
</p>
|
|
252
|
-
</div>
|
|
253
|
-
</div>
|
|
254
|
-
</section>
|
|
255
|
-
|
|
256
|
-
<section class="section">
|
|
257
|
-
<h2>Share RaaS</h2>
|
|
258
|
-
<p>Like what you see? Share the service with your friends, team, or followers.</p>
|
|
259
|
-
<div class="share-buttons">
|
|
260
|
-
<a id="share-twitter" class="share-btn">X / Twitter</a>
|
|
261
|
-
<a id="share-facebook" class="share-btn">Facebook</a>
|
|
262
|
-
<a id="share-whatsapp" class="share-btn">WhatsApp</a>
|
|
263
|
-
<a id="share-linkedin" class="share-btn">LinkedIn</a>
|
|
264
|
-
</div>
|
|
265
|
-
</section>
|
|
266
|
-
</main>
|
|
267
|
-
|
|
268
|
-
<footer class="footer">
|
|
269
|
-
<p>Roast as a Service · Static JSON over CDN · Built on GitHub Pages.</p>
|
|
270
|
-
<p>A <a href="https://github.com/Maijied/lorapok">Lorapok</a> Project · <a
|
|
271
|
-
href="https://github.com/maijied/roast-as-a-service">View source</a> · Made by <a
|
|
272
|
-
href="mailto:mdshuvo40@gmail.com">Maizied</a></p>
|
|
273
|
-
<div style="margin-top: 10px; opacity: 0.8;">
|
|
274
|
-
<img src="https://hits.sh/maijied.github.io/roast-as-a-service.svg?view=today-total&style=flat-square&label=visitors&color=ec4899&labelColor=020617"
|
|
275
|
-
alt="Visitor Count" />
|
|
276
|
-
</div>
|
|
277
|
-
</footer>
|
|
278
|
-
</div>
|
|
279
|
-
|
|
280
|
-
<script src="./api/client.js"></script>
|
|
281
|
-
<script>
|
|
282
|
-
const roastBox = document.getElementById('roast-box');
|
|
283
|
-
const btnEn = document.getElementById('btn-en');
|
|
284
|
-
const btnBn = document.getElementById('btn-bn');
|
|
285
|
-
|
|
286
|
-
async function showRoast(lang) {
|
|
287
|
-
roastBox.textContent = 'Loading...';
|
|
288
|
-
try {
|
|
289
|
-
const data = await RaaS.getRandomRoast({ lang });
|
|
290
|
-
roastBox.textContent = data.text;
|
|
291
|
-
} catch (err) {
|
|
292
|
-
roastBox.textContent = 'Error: ' + err.message;
|
|
293
|
-
}
|
|
294
|
-
}
|
|
295
|
-
|
|
296
|
-
btnEn.addEventListener('click', () => showRoast('en'));
|
|
297
|
-
btnBn.addEventListener('click', () => showRoast('bn'));
|
|
298
|
-
|
|
299
|
-
const pageUrl = encodeURIComponent('https://maijied.github.io/roast-as-a-service/');
|
|
300
|
-
const text = encodeURIComponent('Roast as a Service (RaaS): CDN-backed static JSON API for developer roasts.');
|
|
301
|
-
|
|
302
|
-
document.getElementById('share-twitter').href =
|
|
303
|
-
`https://twitter.com/intent/tweet?url=${pageUrl}&text=${text}`;
|
|
304
|
-
document.getElementById('share-facebook').href =
|
|
305
|
-
`https://www.facebook.com/sharer/sharer.php?u=${pageUrl}`;
|
|
306
|
-
document.getElementById('share-whatsapp').href =
|
|
307
|
-
`https://api.whatsapp.com/send?text=${text}%20${pageUrl}`;
|
|
308
|
-
document.getElementById('share-linkedin').href =
|
|
309
|
-
`https://www.linkedin.com/sharing/share-offsite/?url=${pageUrl}`;
|
|
310
|
-
</script>
|
|
311
|
-
</body>
|
|
312
|
-
|
|
313
|
-
</html>
|
package/load_test.js
DELETED
|
@@ -1,72 +0,0 @@
|
|
|
1
|
-
const RaaS = require('./api/client.js');
|
|
2
|
-
|
|
3
|
-
async function runLoadTest(totalRequests = 1000, concurrency = 50) {
|
|
4
|
-
console.log(`🚀 Starting Load Test: ${totalRequests} total requests, Concurrency: ${concurrency}\n`);
|
|
5
|
-
|
|
6
|
-
const results = {
|
|
7
|
-
latencies: [],
|
|
8
|
-
errors: 0,
|
|
9
|
-
networkRequests: 0,
|
|
10
|
-
startTime: Date.now()
|
|
11
|
-
};
|
|
12
|
-
|
|
13
|
-
// Instrument RaaS fetch to count network hits
|
|
14
|
-
const originalFetch = global.fetch;
|
|
15
|
-
global.fetch = async (...args) => {
|
|
16
|
-
results.networkRequests++;
|
|
17
|
-
return originalFetch(...args);
|
|
18
|
-
};
|
|
19
|
-
|
|
20
|
-
const languages = ['en', 'bn'];
|
|
21
|
-
let count = totalRequests;
|
|
22
|
-
|
|
23
|
-
async function worker() {
|
|
24
|
-
while (count > 0) {
|
|
25
|
-
count--;
|
|
26
|
-
const start = Date.now();
|
|
27
|
-
try {
|
|
28
|
-
const lang = languages[Math.floor(Math.random() * languages.length)];
|
|
29
|
-
await RaaS.getRandomRoast({ lang });
|
|
30
|
-
results.latencies.push(Date.now() - start);
|
|
31
|
-
} catch (err) {
|
|
32
|
-
results.errors++;
|
|
33
|
-
console.error(`❌ Request failed: ${err.message}`);
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
// Spawn workers
|
|
39
|
-
const workers = Array(concurrency).fill(0).map(() => worker());
|
|
40
|
-
await Promise.all(workers);
|
|
41
|
-
|
|
42
|
-
// Restore fetch
|
|
43
|
-
global.fetch = originalFetch;
|
|
44
|
-
|
|
45
|
-
// Results Calculation
|
|
46
|
-
const totalTime = (Date.now() - results.startTime) / 1000;
|
|
47
|
-
const avgLatency = results.latencies.reduce((a, b) => a + b, 0) / results.latencies.length;
|
|
48
|
-
results.latencies.sort((a, b) => a - b);
|
|
49
|
-
const p95 = results.latencies[Math.floor(results.latencies.length * 0.95)] || 0;
|
|
50
|
-
const p99 = results.latencies[Math.floor(results.latencies.length * 0.99)] || 0;
|
|
51
|
-
|
|
52
|
-
console.log('-------------------------------------------');
|
|
53
|
-
console.log('📊 LOAD TEST RESULTS (INSTRUMENTED)');
|
|
54
|
-
console.log('-------------------------------------------');
|
|
55
|
-
console.log(`Total Time: ${totalTime.toFixed(2)}s`);
|
|
56
|
-
console.log(`Requests/sec: ${(totalRequests / totalTime).toFixed(2)}`);
|
|
57
|
-
console.log(`Success Rate: ${((totalRequests - results.errors) / totalRequests * 100).toFixed(2)}%`);
|
|
58
|
-
console.log(`Avg Latency: ${avgLatency.toFixed(2)}ms`);
|
|
59
|
-
console.log(`P95 Latency: ${p95}ms`);
|
|
60
|
-
console.log(`P99 Latency: ${p99}ms`);
|
|
61
|
-
console.log(`Network Requests: ${results.networkRequests}`);
|
|
62
|
-
console.log(`Cache Hits: ${totalRequests - results.networkRequests}`);
|
|
63
|
-
console.log(`Cache Efficiency: ${((1 - results.networkRequests / totalRequests) * 100).toFixed(2)}%`);
|
|
64
|
-
console.log(`Total Errors: ${results.errors}`);
|
|
65
|
-
console.log('-------------------------------------------');
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
// Get args or defaults
|
|
69
|
-
const requests = parseInt(process.argv[2]) || 1000;
|
|
70
|
-
const concurrency = parseInt(process.argv[3]) || 50;
|
|
71
|
-
|
|
72
|
-
runLoadTest(requests, concurrency);
|
|
@@ -1,79 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"info": {
|
|
3
|
-
"name": "Roast as a Service (RaaS)",
|
|
4
|
-
"_postman_id": "8c5a4e1b-aaaa-bbbb-cccc-112233445566",
|
|
5
|
-
"description": "Postman collection for testing Roast as a Service (RaaS) static JSON API on GitHub Pages.",
|
|
6
|
-
"schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
|
|
7
|
-
},
|
|
8
|
-
"item": [
|
|
9
|
-
{
|
|
10
|
-
"name": "Get manifest",
|
|
11
|
-
"request": {
|
|
12
|
-
"method": "GET",
|
|
13
|
-
"header": [],
|
|
14
|
-
"url": {
|
|
15
|
-
"raw": "https://maijied.github.io/roast-as-a-service/api/manifest.json",
|
|
16
|
-
"protocol": "https",
|
|
17
|
-
"host": [
|
|
18
|
-
"maijied",
|
|
19
|
-
"github",
|
|
20
|
-
"io"
|
|
21
|
-
],
|
|
22
|
-
"path": [
|
|
23
|
-
"roast-as-a-service",
|
|
24
|
-
"api",
|
|
25
|
-
"manifest.json"
|
|
26
|
-
]
|
|
27
|
-
}
|
|
28
|
-
},
|
|
29
|
-
"response": []
|
|
30
|
-
},
|
|
31
|
-
{
|
|
32
|
-
"name": "Get English shard 1",
|
|
33
|
-
"request": {
|
|
34
|
-
"method": "GET",
|
|
35
|
-
"header": [],
|
|
36
|
-
"url": {
|
|
37
|
-
"raw": "https://maijied.github.io/roast-as-a-service/api/en/roasts-en-1.json",
|
|
38
|
-
"protocol": "https",
|
|
39
|
-
"host": [
|
|
40
|
-
"maijied",
|
|
41
|
-
"github",
|
|
42
|
-
"io"
|
|
43
|
-
],
|
|
44
|
-
"path": [
|
|
45
|
-
"roast-as-a-service",
|
|
46
|
-
"api",
|
|
47
|
-
"en",
|
|
48
|
-
"roasts-en-1.json"
|
|
49
|
-
]
|
|
50
|
-
}
|
|
51
|
-
},
|
|
52
|
-
"response": []
|
|
53
|
-
},
|
|
54
|
-
{
|
|
55
|
-
"name": "Get Bangla shard 1",
|
|
56
|
-
"request": {
|
|
57
|
-
"method": "GET",
|
|
58
|
-
"header": [],
|
|
59
|
-
"url": {
|
|
60
|
-
"raw": "https://maijied.github.io/roast-as-a-service/api/bn/roasts-bn-1.json",
|
|
61
|
-
"protocol": "https",
|
|
62
|
-
"host": [
|
|
63
|
-
"maijied",
|
|
64
|
-
"github",
|
|
65
|
-
"io"
|
|
66
|
-
],
|
|
67
|
-
"path": [
|
|
68
|
-
"roast-as-a-service",
|
|
69
|
-
"api",
|
|
70
|
-
"bn",
|
|
71
|
-
"roasts-bn-1.json"
|
|
72
|
-
]
|
|
73
|
-
}
|
|
74
|
-
},
|
|
75
|
-
"response": []
|
|
76
|
-
}
|
|
77
|
-
],
|
|
78
|
-
"variable": []
|
|
79
|
-
}
|