api-ape 0.0.0 → 1.0.2

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 (64) hide show
  1. package/README.md +458 -0
  2. package/client/README.md +69 -0
  3. package/client/browser.js +17 -0
  4. package/client/connectSocket.js +260 -0
  5. package/dist/ape.js +454 -0
  6. package/example/ExpressJs/README.md +97 -0
  7. package/example/ExpressJs/api/message.js +11 -0
  8. package/example/ExpressJs/backend.js +37 -0
  9. package/example/ExpressJs/index.html +88 -0
  10. package/example/ExpressJs/package-lock.json +834 -0
  11. package/example/ExpressJs/package.json +10 -0
  12. package/example/ExpressJs/styles.css +128 -0
  13. package/example/NextJs/.dockerignore +29 -0
  14. package/example/NextJs/Dockerfile +52 -0
  15. package/example/NextJs/Dockerfile.dev +27 -0
  16. package/example/NextJs/README.md +113 -0
  17. package/example/NextJs/ape/client.js +66 -0
  18. package/example/NextJs/ape/embed.js +12 -0
  19. package/example/NextJs/ape/index.js +23 -0
  20. package/example/NextJs/ape/logic/chat.js +62 -0
  21. package/example/NextJs/ape/onConnect.js +69 -0
  22. package/example/NextJs/ape/onDisconnect.js +13 -0
  23. package/example/NextJs/ape/onError.js +9 -0
  24. package/example/NextJs/ape/onReceive.js +15 -0
  25. package/example/NextJs/ape/onSend.js +15 -0
  26. package/example/NextJs/api/message.js +44 -0
  27. package/example/NextJs/docker-compose.yml +22 -0
  28. package/example/NextJs/next-env.d.ts +5 -0
  29. package/example/NextJs/next.config.js +8 -0
  30. package/example/NextJs/package-lock.json +5107 -0
  31. package/example/NextJs/package.json +25 -0
  32. package/example/NextJs/pages/Info.tsx +153 -0
  33. package/example/NextJs/pages/_app.tsx +6 -0
  34. package/example/NextJs/pages/index.tsx +264 -0
  35. package/example/NextJs/public/favicon.ico +0 -0
  36. package/example/NextJs/public/vercel.svg +4 -0
  37. package/example/NextJs/server.js +40 -0
  38. package/example/NextJs/styles/Chat.module.css +448 -0
  39. package/example/NextJs/styles/Home.module.css +129 -0
  40. package/example/NextJs/styles/globals.css +26 -0
  41. package/example/NextJs/tsconfig.json +20 -0
  42. package/example/README.md +66 -0
  43. package/index.d.ts +179 -0
  44. package/index.js +11 -0
  45. package/package.json +11 -4
  46. package/server/README.md +93 -0
  47. package/server/index.js +6 -0
  48. package/server/lib/broadcast.js +63 -0
  49. package/server/lib/loader.js +10 -0
  50. package/server/lib/main.js +23 -0
  51. package/server/lib/wiring.js +94 -0
  52. package/server/security/extractRootDomain.js +21 -0
  53. package/server/security/origin.js +13 -0
  54. package/server/security/reply.js +21 -0
  55. package/server/socket/open.js +10 -0
  56. package/server/socket/receive.js +66 -0
  57. package/server/socket/send.js +55 -0
  58. package/server/utils/deepRequire.js +45 -0
  59. package/server/utils/genId.js +24 -0
  60. package/todo.md +85 -0
  61. package/utils/jss.js +273 -0
  62. package/utils/jss.test.js +261 -0
  63. package/utils/messageHash.js +43 -0
  64. package/utils/messageHash.test.js +56 -0
@@ -0,0 +1,448 @@
1
+ .container {
2
+ min-height: 100vh;
3
+ background: linear-gradient(135deg, #1a1a2e 0%, #16213e 50%, #0f3460 100%);
4
+ color: #fff;
5
+ font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, sans-serif;
6
+ }
7
+
8
+ .main {
9
+ max-width: 1400px;
10
+ margin: 0 auto;
11
+ padding: 2rem;
12
+ width: 100%;
13
+ }
14
+
15
+ .title {
16
+ font-size: 2.5rem;
17
+ text-align: center;
18
+ margin-bottom: 0.5rem;
19
+ }
20
+
21
+ .gradient {
22
+ background: linear-gradient(90deg, #00d2ff, #3a7bd5);
23
+ -webkit-background-clip: text;
24
+ -webkit-text-fill-color: transparent;
25
+ background-clip: text;
26
+ }
27
+
28
+ .subtitle {
29
+ text-align: center;
30
+ color: #0f0;
31
+ margin-bottom: 2rem;
32
+ font-weight: bold;
33
+ }
34
+
35
+ .joinForm {
36
+ display: flex;
37
+ gap: 1rem;
38
+ justify-content: center;
39
+ }
40
+
41
+ .input {
42
+ padding: 1rem 1.5rem;
43
+ font-size: 1rem;
44
+ border: none;
45
+ border-radius: 50px;
46
+ background: rgba(255, 255, 255, 0.1);
47
+ color: #fff;
48
+ outline: none;
49
+ width: 250px;
50
+ }
51
+
52
+ .input::placeholder {
53
+ color: rgba(255, 255, 255, 0.5);
54
+ }
55
+
56
+ .button {
57
+ padding: 1rem 2rem;
58
+ font-size: 1rem;
59
+ border: none;
60
+ border-radius: 50px;
61
+ background: linear-gradient(90deg, #00d2ff, #3a7bd5);
62
+ color: #fff;
63
+ cursor: pointer;
64
+ font-weight: bold;
65
+ }
66
+
67
+ .button:hover {
68
+ opacity: 0.9;
69
+ }
70
+
71
+ .chatContainer {
72
+ background: rgba(255, 255, 255, 0.05);
73
+ border-radius: 20px;
74
+ overflow: hidden;
75
+ box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3);
76
+ }
77
+
78
+ .header {
79
+ display: flex;
80
+ justify-content: space-between;
81
+ padding: 1rem 1.5rem;
82
+ background: rgba(255, 255, 255, 0.1);
83
+ font-weight: bold;
84
+ }
85
+
86
+ .userCount {
87
+ font-size: 0.85rem;
88
+ color: #0f0;
89
+ }
90
+
91
+ .messages {
92
+ height: 300px;
93
+ overflow-y: auto;
94
+ padding: 1rem;
95
+ }
96
+
97
+ .emptyState {
98
+ text-align: center;
99
+ color: #666;
100
+ margin-top: 120px;
101
+ }
102
+
103
+ .message {
104
+ display: flex;
105
+ flex-direction: column;
106
+ gap: 0.25rem;
107
+ padding: 0.75rem 1rem;
108
+ margin-bottom: 0.5rem;
109
+ background: rgba(255, 255, 255, 0.05);
110
+ border-radius: 12px;
111
+ border-left: 3px solid #3a7bd5;
112
+ }
113
+
114
+ .myMessage {
115
+ background: rgba(0, 210, 255, 0.15);
116
+ border-left: 3px solid #00d2ff;
117
+ }
118
+
119
+ .username {
120
+ color: #00d2ff;
121
+ font-size: 0.85rem;
122
+ }
123
+
124
+ .time {
125
+ color: #666;
126
+ font-size: 0.7rem;
127
+ }
128
+
129
+ .inputForm {
130
+ display: flex;
131
+ gap: 0.5rem;
132
+ padding: 1rem;
133
+ border-top: 1px solid rgba(255, 255, 255, 0.1);
134
+ }
135
+
136
+ .messageInput {
137
+ flex: 1;
138
+ padding: 0.75rem 1rem;
139
+ font-size: 1rem;
140
+ border: none;
141
+ border-radius: 50px;
142
+ background: rgba(255, 255, 255, 0.1);
143
+ color: #fff;
144
+ outline: none;
145
+ }
146
+
147
+ .messageInput::placeholder {
148
+ color: rgba(255, 255, 255, 0.5);
149
+ }
150
+
151
+ .sendButton {
152
+ padding: 0.75rem 1.5rem;
153
+ font-size: 1rem;
154
+ border: none;
155
+ border-radius: 50px;
156
+ background: #3a7bd5;
157
+ color: #fff;
158
+ cursor: pointer;
159
+ font-weight: bold;
160
+ }
161
+
162
+ .sendButton:hover {
163
+ opacity: 0.9;
164
+ }
165
+
166
+ .codeSection {
167
+ margin-top: 2rem;
168
+ }
169
+
170
+ .codeTitle {
171
+ margin-bottom: 0.5rem;
172
+ color: #0f0;
173
+ }
174
+
175
+ .code {
176
+ background: rgba(0, 0, 0, 0.4);
177
+ padding: 1.5rem;
178
+ border-radius: 12px;
179
+ font-size: 0.75rem;
180
+ color: #0f0;
181
+ overflow: auto;
182
+ }
183
+
184
+ .clientInfo {
185
+ text-align: center;
186
+ margin-top: 1rem;
187
+ font-size: 0.85rem;
188
+ color: #888;
189
+ }
190
+
191
+ .clientInfo code {
192
+ background: rgba(0, 0, 0, 0.3);
193
+ padding: 0.2rem 0.5rem;
194
+ border-radius: 4px;
195
+ }
196
+
197
+ .gridContainer {
198
+ max-width: 1200px;
199
+ margin: 1.5rem auto 0;
200
+ padding: 0 1rem;
201
+ width: 100%;
202
+ box-sizing: border-box;
203
+ }
204
+
205
+ .gridLayout {
206
+ display: grid;
207
+ grid-template-columns: 1fr;
208
+ gap: 2rem;
209
+ width: 100%;
210
+ }
211
+
212
+ @media (min-width: 768px) {
213
+ .gridLayout {
214
+ grid-template-columns: 1fr 1fr;
215
+ }
216
+ }
217
+
218
+ @media (max-width: 767px) {
219
+ .gridContainer {
220
+ padding: 0 0.5rem;
221
+ }
222
+
223
+ .main {
224
+ padding: 1rem;
225
+ }
226
+ }
227
+
228
+ /* Info component styles */
229
+ .sectionHeading {
230
+ margin-bottom: 0.5rem;
231
+ font-size: 0.9rem;
232
+ font-weight: bold;
233
+ }
234
+
235
+ .sectionHeadingLarge {
236
+ margin-bottom: 1rem;
237
+ font-size: 0.9rem;
238
+ font-weight: bold;
239
+ }
240
+
241
+ .dataFlowGrid {
242
+ display: grid;
243
+ grid-template-columns: 200px 1fr 200px;
244
+ grid-template-rows: auto auto auto auto auto;
245
+ gap: 1rem;
246
+ align-items: stretch;
247
+ }
248
+
249
+ .columnHeaderClient {
250
+ font-size: 0.8rem;
251
+ font-weight: bold;
252
+ text-align: center;
253
+ grid-row: 1;
254
+ grid-column: 1;
255
+ color: #00d2ff;
256
+ }
257
+
258
+ .columnHeaderServer {
259
+ font-size: 0.8rem;
260
+ font-weight: bold;
261
+ text-align: center;
262
+ grid-row: 1;
263
+ grid-column: 3;
264
+ color: #00e676;
265
+ }
266
+
267
+ .gridCell {
268
+ grid-row: 1;
269
+ grid-column: 2;
270
+ }
271
+
272
+ .clientBoxSpan3 {
273
+ background: linear-gradient(135deg, #3a7bd5, #00d2ff);
274
+ padding: 0.75rem 1rem;
275
+ border-radius: 8px;
276
+ color: #fff;
277
+ font-size: 0.75rem;
278
+ font-weight: bold;
279
+ box-shadow: 0 4px 12px rgba(58, 123, 213, 0.4);
280
+ display: flex;
281
+ align-items: center;
282
+ justify-content: center;
283
+ grid-column: 1;
284
+ grid-row: 2 / 5;
285
+ }
286
+
287
+ .clientBoxSingle {
288
+ background: linear-gradient(135deg, #3a7bd5, #00d2ff);
289
+ padding: 0.75rem 1rem;
290
+ border-radius: 8px;
291
+ color: #fff;
292
+ font-size: 0.75rem;
293
+ font-weight: bold;
294
+ box-shadow: 0 4px 12px rgba(58, 123, 213, 0.4);
295
+ display: flex;
296
+ align-items: center;
297
+ justify-content: center;
298
+ grid-column: 1;
299
+ grid-row: 5;
300
+ }
301
+
302
+ .serverBoxSpan2 {
303
+ background: linear-gradient(135deg, #00c851, #00e676);
304
+ padding: 0.75rem 1rem;
305
+ border-radius: 8px;
306
+ color: #fff;
307
+ font-size: 0.75rem;
308
+ font-weight: bold;
309
+ box-shadow: 0 4px 12px rgba(0, 200, 81, 0.4);
310
+ display: flex;
311
+ align-items: center;
312
+ justify-content: center;
313
+ grid-column: 3;
314
+ grid-row: 2 / 4;
315
+ }
316
+
317
+ .serverBoxSpan3 {
318
+ background: linear-gradient(135deg, #00c851, #00e676);
319
+ padding: 0.75rem 1rem;
320
+ border-radius: 8px;
321
+ color: #fff;
322
+ font-size: 0.75rem;
323
+ font-weight: bold;
324
+ box-shadow: 0 4px 12px rgba(0, 200, 81, 0.4);
325
+ display: flex;
326
+ align-items: center;
327
+ justify-content: center;
328
+ grid-column: 3;
329
+ grid-row: 4 / 6;
330
+ }
331
+
332
+ .arrowContainerRow2 {
333
+ display: flex;
334
+ align-items: center;
335
+ justify-content: center;
336
+ gap: 0.5rem;
337
+ grid-column: 2;
338
+ grid-row: 2;
339
+ }
340
+
341
+ .arrowContainerRow3 {
342
+ display: flex;
343
+ align-items: center;
344
+ justify-content: center;
345
+ gap: 0.5rem;
346
+ grid-column: 2;
347
+ grid-row: 3;
348
+ }
349
+
350
+ .arrowContainerRow4 {
351
+ display: flex;
352
+ align-items: center;
353
+ justify-content: center;
354
+ gap: 0.5rem;
355
+ grid-column: 2;
356
+ grid-row: 4;
357
+ }
358
+
359
+ .arrowContainerRow5 {
360
+ display: flex;
361
+ align-items: center;
362
+ justify-content: center;
363
+ gap: 0.5rem;
364
+ grid-column: 2;
365
+ grid-row: 5;
366
+ }
367
+
368
+ .arrowLineSend {
369
+ flex: 1;
370
+ height: 2px;
371
+ background: linear-gradient(90deg, #00d2ff, #00e676);
372
+ }
373
+
374
+ .arrowLineReturn {
375
+ flex: 1;
376
+ height: 2px;
377
+ background: linear-gradient(90deg, #00e676, transparent);
378
+ }
379
+
380
+ .arrowLineBroadcast {
381
+ flex: 1;
382
+ height: 2px;
383
+ background: linear-gradient(90deg, transparent, #00e676);
384
+ }
385
+
386
+ .arrowLineBroadcastReturn {
387
+ flex: 1;
388
+ height: 2px;
389
+ background: linear-gradient(90deg, #00d2ff, transparent);
390
+ }
391
+
392
+ .arrowLabelBlue {
393
+ font-size: 0.7rem;
394
+ white-space: nowrap;
395
+ padding: 0 0.5rem;
396
+ color: #00d2ff;
397
+ }
398
+
399
+ .arrowLabelGreen {
400
+ font-size: 0.7rem;
401
+ white-space: nowrap;
402
+ padding: 0 0.5rem;
403
+ color: #00e676;
404
+ }
405
+
406
+ .arrowHeadRight {
407
+ width: 0;
408
+ height: 0;
409
+ border-top: 4px solid transparent;
410
+ border-bottom: 4px solid transparent;
411
+ border-left: 8px solid #00e676;
412
+ }
413
+
414
+ .arrowHeadLeft {
415
+ width: 0;
416
+ height: 0;
417
+ border-top: 4px solid transparent;
418
+ border-bottom: 4px solid transparent;
419
+ border-right: 8px solid #00e676;
420
+ }
421
+
422
+ .arrowHeadLeftBlue {
423
+ width: 0;
424
+ height: 0;
425
+ border-top: 4px solid transparent;
426
+ border-bottom: 4px solid transparent;
427
+ border-right: 8px solid #00d2ff;
428
+ }
429
+
430
+ .emptyGridCell {
431
+ grid-row: 2;
432
+ grid-column: 3;
433
+ }
434
+
435
+ .emptyGridCellRow3 {
436
+ grid-row: 3;
437
+ grid-column: 1;
438
+ }
439
+
440
+ .emptyGridCellRow4 {
441
+ grid-row: 4;
442
+ grid-column: 1;
443
+ }
444
+
445
+ .emptyGridCellRow5 {
446
+ grid-row: 5;
447
+ grid-column: 3;
448
+ }
@@ -0,0 +1,129 @@
1
+ .container {
2
+ padding: 0 2rem;
3
+ }
4
+
5
+ .main {
6
+ min-height: 100vh;
7
+ padding: 4rem 0;
8
+ flex: 1;
9
+ display: flex;
10
+ flex-direction: column;
11
+ justify-content: center;
12
+ align-items: center;
13
+ }
14
+
15
+ .footer {
16
+ display: flex;
17
+ flex: 1;
18
+ padding: 2rem 0;
19
+ border-top: 1px solid #eaeaea;
20
+ justify-content: center;
21
+ align-items: center;
22
+ }
23
+
24
+ .footer a {
25
+ display: flex;
26
+ justify-content: center;
27
+ align-items: center;
28
+ flex-grow: 1;
29
+ }
30
+
31
+ .title a {
32
+ color: #0070f3;
33
+ text-decoration: none;
34
+ }
35
+
36
+ .title a:hover,
37
+ .title a:focus,
38
+ .title a:active {
39
+ text-decoration: underline;
40
+ }
41
+
42
+ .title {
43
+ margin: 0;
44
+ line-height: 1.15;
45
+ font-size: 4rem;
46
+ }
47
+
48
+ .title,
49
+ .description {
50
+ text-align: center;
51
+ }
52
+
53
+ .description {
54
+ margin: 4rem 0;
55
+ line-height: 1.5;
56
+ font-size: 1.5rem;
57
+ }
58
+
59
+ .code {
60
+ background: #fafafa;
61
+ border-radius: 5px;
62
+ padding: 0.75rem;
63
+ font-size: 1.1rem;
64
+ font-family: Menlo, Monaco, Lucida Console, Liberation Mono, DejaVu Sans Mono,
65
+ Bitstream Vera Sans Mono, Courier New, monospace;
66
+ }
67
+
68
+ .grid {
69
+ display: flex;
70
+ align-items: center;
71
+ justify-content: center;
72
+ flex-wrap: wrap;
73
+ max-width: 800px;
74
+ }
75
+
76
+ .card {
77
+ margin: 1rem;
78
+ padding: 1.5rem;
79
+ text-align: left;
80
+ color: inherit;
81
+ text-decoration: none;
82
+ border: 1px solid #eaeaea;
83
+ border-radius: 10px;
84
+ transition: color 0.15s ease, border-color 0.15s ease;
85
+ max-width: 300px;
86
+ }
87
+
88
+ .card:hover,
89
+ .card:focus,
90
+ .card:active {
91
+ color: #0070f3;
92
+ border-color: #0070f3;
93
+ }
94
+
95
+ .card h2 {
96
+ margin: 0 0 1rem 0;
97
+ font-size: 1.5rem;
98
+ }
99
+
100
+ .card p {
101
+ margin: 0;
102
+ font-size: 1.25rem;
103
+ line-height: 1.5;
104
+ }
105
+
106
+ .logo {
107
+ height: 1em;
108
+ margin-left: 0.5rem;
109
+ }
110
+
111
+ @media (max-width: 600px) {
112
+ .grid {
113
+ width: 100%;
114
+ flex-direction: column;
115
+ }
116
+ }
117
+
118
+ @media (prefers-color-scheme: dark) {
119
+ .card,
120
+ .footer {
121
+ border-color: #222;
122
+ }
123
+ .code {
124
+ background: #111;
125
+ }
126
+ .logo img {
127
+ filter: invert(1);
128
+ }
129
+ }
@@ -0,0 +1,26 @@
1
+ html,
2
+ body {
3
+ padding: 0;
4
+ margin: 0;
5
+ font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen,
6
+ Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif;
7
+ }
8
+
9
+ a {
10
+ color: inherit;
11
+ text-decoration: none;
12
+ }
13
+
14
+ * {
15
+ box-sizing: border-box;
16
+ }
17
+
18
+ @media (prefers-color-scheme: dark) {
19
+ html {
20
+ color-scheme: dark;
21
+ }
22
+ body {
23
+ color: white;
24
+ background: black;
25
+ }
26
+ }
@@ -0,0 +1,20 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "es5",
4
+ "lib": ["dom", "dom.iterable", "esnext"],
5
+ "allowJs": true,
6
+ "skipLibCheck": true,
7
+ "strict": true,
8
+ "forceConsistentCasingInFileNames": true,
9
+ "noEmit": true,
10
+ "esModuleInterop": true,
11
+ "module": "esnext",
12
+ "moduleResolution": "node",
13
+ "resolveJsonModule": true,
14
+ "isolatedModules": true,
15
+ "jsx": "preserve",
16
+ "incremental": true
17
+ },
18
+ "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"],
19
+ "exclude": ["node_modules"]
20
+ }
@@ -0,0 +1,66 @@
1
+ # 🦍 api-ape Examples
2
+
3
+ Complete working examples demonstrating api-ape usage.
4
+
5
+ ## Examples
6
+
7
+ | Example | Description | Complexity |
8
+ |---------|-------------|------------|
9
+ | [ExpressJs/](./ExpressJs/) | Basic real-time chat | Minimal setup |
10
+ | [NextJs/](./NextJs/) | Full-featured chat app | Production-ready |
11
+
12
+ ---
13
+
14
+ ## ExpressJs — Basic Example
15
+
16
+ A minimal real-time chat demonstrating core api-ape concepts.
17
+
18
+ **Features:**
19
+ - Simple Express.js server with api-ape
20
+ - Broadcast messages to other clients
21
+ - Message history
22
+
23
+ **Quick Start:**
24
+ ```bash
25
+ cd ExpressJs
26
+ npm install
27
+ npm start
28
+ ```
29
+
30
+ **Key Files:**
31
+ - `backend.js` — Server setup (22 lines)
32
+ - `api/message.js` — Message handler with `this.broadcastOthers()`
33
+ - `index.html` — Browser client using `window.ape`
34
+
35
+ ---
36
+
37
+ ## NextJs — Complete Example
38
+
39
+ A production-ready chat application with Next.js integration.
40
+
41
+ **Features:**
42
+ - Custom Next.js server with api-ape
43
+ - React hooks integration
44
+ - User presence tracking
45
+ - Docker support
46
+ - Connection lifecycle hooks
47
+
48
+ **Quick Start:**
49
+ ```bash
50
+ cd NextJs
51
+ npm install
52
+ npm run dev
53
+ ```
54
+
55
+ **Or with Docker:**
56
+ ```bash
57
+ cd NextJs
58
+ docker-compose up --build
59
+ ```
60
+
61
+ **Key Files:**
62
+ - `server.js` — Custom Next.js server with api-ape
63
+ - `api/message.js` — Message controller with validation
64
+ - `ape/client.js` — React client wrapper
65
+ - `ape/onConnect.js` — Connection lifecycle hooks
66
+ - `pages/index.tsx` — Chat UI with React hooks