zyro-gateway 1.0.0 → 1.0.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/CHANGELOG.md CHANGED
@@ -5,13 +5,21 @@ All notable changes to this project are documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [1.0.2] - 2026-05-17
9
+
10
+ ### Changed
11
+
12
+ - npm README sync (logo, docs, web/system wording) on **`z-getway`** and **`zyro-gateway@1.0.1`**.
13
+ - `npm run release` publishes both package names via `scripts/publish-all.js`.
14
+
8
15
  ## [1.0.0] - 2026-05-17
9
16
 
10
17
  ### Added
11
18
 
19
+ - Published on npm as **`z-getway`** (CLI: `z-getway`, alias: `zyro-gateway`).
12
20
  - Modular server under `src/` (config, routes, Socket.IO, terminal logging).
13
- - CLI: `zyro-gateway`, `zyro-gateway config`, `zyro-gateway help`.
14
- - Programmatic API: `require('zyro-gateway/server')` → `createGateway()`, `start()`.
21
+ - CLI: `z-getway config`, `z-getway help`, `npm run release` for publish.
22
+ - Programmatic API: `require('z-getway/server')` → `createGateway()`, `start()`.
15
23
  - HTTP fallback: `POST /api/register`, `POST /api/income`, `POST /api/notification`.
16
24
  - REST: dashboard, devices, transactions, notifications.
17
25
  - Browser client (`Zyro.connect`) bundled to `dist/zyro.js`.
package/README.md CHANGED
@@ -1,226 +1,698 @@
1
- # Zyro Gateway
1
+ <p align="center">
2
+ <img src="./assets/zyro-logo.png" alt="Zyro Gateway" width="140" height="140" />
3
+ </p>
4
+
5
+ <p align="center">
6
+ <a href="https://www.npmjs.com/package/z-getway">
7
+ <img src="https://img.shields.io/npm/dm/z-getway?style=flat&colorA=000000&colorB=000000" alt="npm downloads" />
8
+ </a>
9
+ <a href="https://www.npmjs.com/package/z-getway">
10
+ <img src="https://img.shields.io/npm/v/z-getway.svg?style=flat&colorA=000000&colorB=000000" alt="npm version" />
11
+ </a>
12
+ <a href="https://github.com/orod-codes/zyro-getway/stargazers">
13
+ <img src="https://img.shields.io/github/stars/orod-codes/zyro-getway?style=flat&colorA=000000&colorB=000000" alt="GitHub stars" />
14
+ </a>
15
+ </p>
16
+
17
+ <p align="center">
18
+ <a href="https://www.npmjs.com/package/z-getway">npm (z-getway)</a>
19
+ ·
20
+ <a href="https://www.npmjs.com/package/zyro-gateway">npm (zyro-gateway)</a>
21
+ ·
22
+ <a href="https://github.com/orod-codes/zyro-getway">Website</a>
23
+ ·
24
+ <a href="https://github.com/orod-codes/zyro-getway/issues">Issues</a>
25
+ </p>
26
+
27
+ > Install either package — same gateway: `npm install z-getway` **(recommended)** or `npm install zyro-gateway`
28
+
29
+ ## Zyro Gateway
30
+
31
+ Zyro Gateway is a framework-agnostic real-time sync layer for TypeScript and JavaScript. It moves **payment and income events** from mobile clients to **web clients and systems** over Socket.IO, with HTTP fallback when long-lived connections are unavailable. Pairing rooms, a REST surface, and a bundled browser SDK (`Zyro.connect`) ship in one npm package so you can integrate income sync without building transport, discovery, and fan-out yourself.
32
+
33
+ ### Why Zyro Gateway
34
+
35
+ Reliable delivery of **transaction data** across devices on a local network is rarely a single library—it is usually custom sockets, polling endpoints, and fragile “connected” states that diverge from what the server actually sees. Zyro Gateway treats that as one problem: authenticate a pairing code, register clients, broadcast income and notifications, and expose the same events to **web and system** consumers from a small Node process—hence, Zyro Gateway.
36
+
37
+ <p align="center">
38
+ <a href="#quick-start">Quick start</a>
39
+ ·
40
+ <a href="#architecture">Architecture</a>
41
+ ·
42
+ <a href="#configuration">Configuration</a>
43
+ ·
44
+ <a href="#http-api">HTTP API</a>
45
+ ·
46
+ <a href="#browser-client">Browser client</a>
47
+ ·
48
+ <a href="#troubleshooting">Troubleshooting</a>
49
+ ·
50
+ <a href="CHANGELOG.md">Changelog</a>
51
+ </p>
52
+
53
+ | Capability | Description |
54
+ |------------|-------------|
55
+ | Income sync | Push payment fields from mobile to gateway in real time |
56
+ | Dual transport | Socket.IO primary; HTTP register + POST when sockets drop |
57
+ | Isolated rooms | `pairingCode` scopes clients and event streams per deployment |
58
+
59
+ ---
60
+
61
+ ## Table of contents
62
+
63
+ - [Requirements](#requirements)
64
+ - [Installation](#installation)
65
+ - [Quick start](#quick-start)
66
+ - [Architecture](#architecture)
67
+ - [Configuration](#configuration)
68
+ - [Phone app setup](#phone-app-setup)
69
+ - [Browser client](#browser-client)
70
+ - [HTTP API](#http-api)
71
+ - [Socket.IO protocol](#socketio-protocol)
72
+ - [Programmatic server API](#programmatic-server-api)
73
+ - [CLI reference](#cli-reference)
74
+ - [Project structure](#project-structure)
75
+ - [Development](#development)
76
+ - [Publishing updates](#publishing-updates)
77
+ - [Troubleshooting](#troubleshooting)
78
+ - [Security](#security)
79
+ - [License](#license)
80
+
81
+ ---
2
82
 
3
- [![npm version](https://img.shields.io/npm/v/zyro-gateway)](https://www.npmjs.com/package/zyro-gateway)
4
- [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)
83
+ ## Requirements
5
84
 
6
- Real-time sync between a **phone monitor app** (Flutter) and your **desktop terminal / website**. Income transactions and notifications flow over Socket.IO, with HTTP fallback when sockets are unavailable.
85
+ | Requirement | Notes |
86
+ |-------------|--------|
87
+ | **Node.js 18+** | LTS recommended |
88
+ | **Same LAN** | Phone, PC, and browser clients must reach the gateway IP |
89
+ | **Open port** | Default `3001` (configurable); only one process per port |
90
+ | **Pairing code** | 4–12 alphanumeric characters, shared across all clients |
7
91
 
8
- ## Features
92
+ ---
9
93
 
10
- - Terminal server with live **connected devices** and **income logs** (name, amount, sender, ref)
11
- - Browser client (`Zyro.connect`) for dashboards and stores
12
- - Pairing rooms — isolate traffic per store with a short pairing code
13
- - REST API for polling clients and HTTP-only phones
14
- - Config via `zyro.config.js` in your project (not committed)
94
+ ## Installation
15
95
 
16
- ## Requirements
96
+ ### From npm (recommended)
17
97
 
18
- - Node.js **18+**
19
- - Phone app and website on the same LAN as the gateway (or USB `adb reverse` for local dev)
98
+ ```bash
99
+ npm install z-getway
100
+ ```
20
101
 
21
- ## Quick start
102
+ ### Global CLI (optional)
22
103
 
23
104
  ```bash
24
- npm install zyro-gateway
25
- npx zyro-gateway config # creates ./zyro.config.js
26
- # Edit ip, port, pairingCode in zyro.config.js
27
- npx zyro-gateway # start server
105
+ npm install -g z-getway
106
+ z-getway --help
28
107
  ```
29
108
 
30
- From a git clone:
109
+ ### From source
31
110
 
32
111
  ```bash
33
- cd zyrogetway
112
+ git clone https://github.com/orod-codes/zyro-getway.git
113
+ cd zyro-getway
34
114
  npm install
35
115
  npm run config
36
116
  npm start
37
117
  ```
38
118
 
39
- The terminal prints **config path**, **pairing code**, **IP**, and **port**. Use those in your phone app under **Setup → Zyro Gateway**.
119
+ ---
40
120
 
41
- ### USB debugging (Android)
121
+ ## Quick start
122
+
123
+ **1. Create config** (in your project folder—not committed to git):
42
124
 
43
125
  ```bash
44
- adb reverse tcp:3001 tcp:3001
126
+ npx z-getway config
127
+ ```
128
+
129
+ **2. Edit `zyro.config.js`:**
130
+
131
+ ```javascript
132
+ module.exports = {
133
+ ip: '', // auto-detect LAN IP
134
+ port: 3001,
135
+ pairingCode: 'MYSTORE',
136
+ deviceName: 'My Website',
137
+ };
138
+ ```
139
+
140
+ **3. Start the gateway:**
141
+
142
+ ```bash
143
+ npx z-getway
144
+ ```
145
+
146
+ **4. Terminal output** (example):
147
+
148
+ ```text
149
+ Zyro Gateway
150
+ ───────────────────────
151
+ Config /path/to/zyro.config.js
152
+ Pairing MYSTORE
153
+ App IP 192.168.1.10 port 3001
154
+
155
+ Connected: (waiting…)
156
+ Income: name · amount · sender · ref
157
+ ```
158
+
159
+ **5. Phone app** → **Setup → Zyro Gateway** → enter the same **IP**, **port**, and **pairing code**.
160
+
161
+ **6. Website** → load scripts from the gateway (see [Browser client](#browser-client)).
162
+
163
+ ### One-liner (no install)
164
+
165
+ ```bash
166
+ npx z-getway@latest config
167
+ npx z-getway@latest
168
+ ```
169
+
170
+ ### Get the latest version (after you publish an update)
171
+
172
+ | How you installed | Update command |
173
+ |-------------------|----------------|
174
+ | In a project | `npm update z-getway` |
175
+ | One-off run | `npx z-getway@latest` |
176
+ | Global CLI | `npm install -g z-getway@latest` |
177
+
178
+ ---
179
+
180
+ ## Architecture
181
+
182
+ ```mermaid
183
+ flowchart LR
184
+ subgraph Phone["Mobile client"]
185
+ PAY[Income events]
186
+ end
187
+
188
+ subgraph Gateway["Zyro Gateway (Node.js)"]
189
+ HTTP[REST API]
190
+ WS[Socket.IO]
191
+ ROOM[Pairing rooms]
192
+ TERM[Terminal logs]
193
+ HTTP --> ROOM
194
+ WS --> ROOM
195
+ ROOM --> TERM
196
+ end
197
+
198
+ subgraph Clients["Clients"]
199
+ WEB[Website / Zyro.connect]
200
+ TTY[Developer terminal]
201
+ end
202
+
203
+ PAY -->|socket or HTTP| Gateway
204
+ WEB -->|socket| Gateway
205
+ ROOM --> WEB
206
+ TERM --> TTY
45
207
  ```
46
208
 
47
- On the phone, set gateway IP to `127.0.0.1` and port `3001` (match `zyro.config.js`).
209
+ ### Data flow
210
+
211
+ 1. Phone joins room `pairing:MYSTORE` (Socket.IO) or calls `POST /api/register` + `POST /api/income` (HTTP).
212
+ 2. Gateway stores transactions in memory (per pairing room), broadcasts to all web and system clients in that room.
213
+ 3. Terminal prints each income: **amount**, **name**, **sender**, **reference**.
214
+ 4. Web clients receive `income_transaction`, `dashboard_update`, and `presence` events.
215
+
216
+ ### Transport priority
217
+
218
+ | Client | Primary | Fallback |
219
+ |--------|---------|----------|
220
+ | Phone | Socket.IO (`income_transaction`) | `POST /api/income`, `POST /api/register` |
221
+ | Website | Socket.IO + `Zyro.connect` | HTTP polling (`pollIntervalMs`) |
222
+ | Web / system probe | `GET /api/info` | — |
223
+
224
+ ---
48
225
 
49
226
  ## Configuration
50
227
 
51
- | Field | Description |
52
- |--------|-------------|
53
- | `ip` | PC LAN address. Leave `''` to auto-detect. |
54
- | `port` | Listen port (default `3000` if unset; example uses `3001`). |
55
- | `pairingCode` | 4–12 letters/numbers; must match the phone app. |
56
- | `deviceName` | Optional label for web clients. |
57
- | `autoConnect` | Browser client: connect on load. |
58
- | `pollIntervalMs` | HTTP polling interval when sockets fail. |
228
+ ### `zyro.config.js` fields
229
+
230
+ | Field | Type | Default | Description |
231
+ |-------|------|---------|-------------|
232
+ | `ip` | `string` | `''` | LAN IP shown to the phone. Empty = auto-detect. |
233
+ | `port` | `number` | `3000` | Listen port (example uses `3001`). |
234
+ | `pairingCode` | `string` | `''` | Room id (4–12 chars, `A–Z`, `0–9`). Required for API unless sent per request. |
235
+ | `deviceName` | `string` | `''` | Default label for web clients. |
236
+ | `autoConnect` | `boolean` | `true` | Browser client connects on load. |
237
+ | `pollIntervalMs` | `number` | `1500` | HTTP poll interval when sockets fail. |
238
+
239
+ ### Config file resolution order
240
+
241
+ 1. `ZYRO_CONFIG` — absolute path via environment variable
242
+ 2. `./zyro.config.js` — current working directory (where you run `npx z-getway`)
243
+ 3. Package directory — fallback when running from `node_modules`
244
+
245
+ ### Environment variables
246
+
247
+ | Variable | Effect |
248
+ |----------|--------|
249
+ | `PORT` | Overrides `port` in config |
250
+ | `ZYRO_CONFIG` | Path to a custom config file |
251
+
252
+ Example:
253
+
254
+ ```bash
255
+ PORT=3002 ZYRO_CONFIG=/etc/zyro/prod.config.js npx z-getway
256
+ ```
257
+
258
+ ---
259
+
260
+ ## Phone app setup
261
+
262
+ Configure your mobile client under **Setup → Zyro Gateway** (or equivalent settings screen):
59
263
 
60
- **Load order**
264
+ | Field | Value |
265
+ |-------|--------|
266
+ | IP | Terminal `App IP` (or `127.0.0.1` with USB reverse) |
267
+ | Port | Same as `zyro.config.js` |
268
+ | Pairing code | Exact match, case-insensitive (`mystore` → `MYSTORE`) |
61
269
 
62
- 1. `ZYRO_CONFIG` environment variable (absolute path)
63
- 2. `./zyro.config.js` in the current working directory
64
- 3. `zyro.config.js` inside the installed package
270
+ ### Android USB debugging
65
271
 
66
- **Environment**
272
+ Forward the gateway port to the device:
67
273
 
68
- | Variable | Purpose |
69
- |----------|---------|
70
- | `PORT` | Override listen port |
71
- | `ZYRO_CONFIG` | Path to config file |
274
+ ```bash
275
+ adb reverse tcp:3001 tcp:3001
276
+ ```
277
+
278
+ On the phone, use **IP `127.0.0.1`** and **port `3001`**.
279
+
280
+ ### HTTP fallback
281
+
282
+ If Socket.IO cannot connect, the app should:
72
283
 
73
- ## Phone app
284
+ 1. `POST /api/register` — appear in terminal **Connected** list
285
+ 2. `POST /api/income` — push each transaction
74
286
 
75
- Point **Setup Zyro Gateway** at the same **IP**, **port**, and **pairing code** shown in the terminal.
287
+ Headers/query: `X-Pairing: MYSTORE` or `?pairing=MYSTORE`.
76
288
 
77
- When Socket.IO is blocked, the app can register and post income over HTTP (`/api/register`, `/api/income`). The terminal still lists the device and logs income.
289
+ ---
78
290
 
79
- ## Website integration
291
+ ## Browser client
80
292
 
81
- Serve the bundled client from the gateway (after `npm run build` / install):
293
+ The gateway serves a bundled IIFE at **`/zyro/zyro.js`** (global `Zyro`).
294
+
295
+ ### HTML (vanilla)
82
296
 
83
297
  ```html
84
- <script src="http://YOUR-IP:3001/socket.io/socket.io.js"></script>
85
- <script src="http://YOUR-IP:3001/zyro/zyro.js"></script>
298
+ <script src="http://192.168.1.10:3001/socket.io/socket.io.js"></script>
299
+ <script src="http://192.168.1.10:3001/zyro/zyro.js"></script>
86
300
  <script>
87
301
  const sync = Zyro.connect({
88
302
  ip: '192.168.1.10',
89
303
  port: 3001,
90
304
  pairingCode: 'MYSTORE',
91
305
  role: 'desktop',
92
- deviceName: 'My Store',
306
+ deviceName: 'Front Desk',
93
307
  });
94
308
 
309
+ sync.on('ready', () => console.log('Linked to gateway'));
95
310
  sync.on('transaction', (tx) => {
96
- console.log('Income', tx.amount, tx.name);
97
- });
98
-
99
- sync.on('notification', (note) => {
100
- console.log('Notification', note.title);
101
- });
102
-
103
- sync.on('dashboard', (data) => {
104
- console.log('Today total', data.stats.todayTotal);
311
+ console.log('Income', tx.amount, tx.name, tx.transactionNumber);
105
312
  });
313
+ sync.on('notification', (note) => console.log('Push', note.title));
314
+ sync.on('dashboard', (d) => console.log('Today', d.stats.todayTotal));
315
+ sync.on('devices', (list) => console.log('Devices', list));
106
316
  </script>
107
317
  ```
108
318
 
109
- ### ESM / bundlers
319
+ ### ESM / Vite / Webpack
110
320
 
111
321
  ```javascript
112
- import { connect } from 'zyro-gateway';
113
- const sync = connect({ ip: '192.168.1.10', port: 3001, pairingCode: 'MYSTORE', role: 'desktop' });
322
+ import { connect, EVENTS } from 'z-getway';
323
+
324
+ const sync = connect({
325
+ serverUrl: 'http://192.168.1.10:3001',
326
+ pairingCode: 'MYSTORE',
327
+ role: 'desktop',
328
+ });
329
+
330
+ sync.on(EVENTS.TRANSACTION, handler);
114
331
  ```
115
332
 
116
- ## Programmatic server
333
+ ### Client events
117
334
 
118
- Embed the gateway in your own Node process:
335
+ | Event | When |
336
+ |-------|------|
337
+ | `ready` | Socket handshake complete |
338
+ | `status` | Connection state changed |
339
+ | `error` | Auth or network error |
340
+ | `transaction` | New income |
341
+ | `notification` | New notification |
342
+ | `dashboard` | Stats snapshot |
343
+ | `presence` / `devices` | Device list updated |
119
344
 
120
- ```javascript
121
- const { createGateway } = require('zyro-gateway/server');
345
+ ---
122
346
 
123
- async function main() {
124
- const gateway = createGateway({ packageRoot: __dirname });
125
- const { url, pairingCode } = await gateway.start();
126
- console.log('Listening at', url, 'pairing', pairingCode);
347
+ ## HTTP API
348
+
349
+ Base URL: `http://<ip>:<port>`
350
+
351
+ **Pairing** — required on protected routes unless set in config:
352
+
353
+ - Query: `?pairing=MYSTORE`
354
+ - Header: `X-Pairing: MYSTORE`
355
+
356
+ ### Discovery
357
+
358
+ #### `GET /`
359
+
360
+ Service index and endpoint list.
361
+
362
+ #### `GET /api/info`
363
+
364
+ Server metadata for health checks and app probes.
365
+
366
+ ```json
367
+ {
368
+ "name": "Zyro Gateway",
369
+ "httpUrl": "http://192.168.1.10:3001",
370
+ "wsUrl": "ws://192.168.1.10:3001",
371
+ "pairingCode": "MYSTORE",
372
+ "features": ["transactions", "notifications", "dashboard", "devices"],
373
+ "reachable": true
127
374
  }
375
+ ```
376
+
377
+ #### `GET /api/config`
378
+
379
+ Effective IP, port, and pairing from config (no secrets).
380
+
381
+ ---
382
+
383
+ ### Data
384
+
385
+ #### `GET /api/dashboard?pairing=MYSTORE`
386
+
387
+ Today’s totals and recent activity.
128
388
 
129
- main();
389
+ #### `GET /api/devices?pairing=MYSTORE`
390
+
391
+ Connected mobile, web, and system clients in the room.
392
+
393
+ #### `GET /api/transactions?pairing=MYSTORE&after=2026-05-17T08:00:00.000Z`
394
+
395
+ | Query | Behavior |
396
+ |-------|----------|
397
+ | (none) | Last 50 transactions |
398
+ | `after` | ISO timestamp — only newer rows (polling) |
399
+
400
+ #### `GET /api/notifications?pairing=MYSTORE`
401
+
402
+ Same pattern as transactions.
403
+
404
+ ---
405
+
406
+ ### Write (phone / integrations)
407
+
408
+ #### `POST /api/register`
409
+
410
+ Register a phone when using HTTP-only transport.
411
+
412
+ ```bash
413
+ curl -X POST "http://127.0.0.1:3001/api/register?pairing=MYSTORE" \
414
+ -H "Content-Type: application/json" \
415
+ -d '{"deviceName":"Cashier Phone","platform":"android","deviceId":"pixel-7"}'
130
416
  ```
131
417
 
132
- `createGateway()` returns `{ app, server, io, start(), stop() }` without listening until you call `start()`.
418
+ #### `POST /api/income`
133
419
 
134
- ## HTTP API
420
+ Push a transaction (same shape as socket `income_transaction`).
421
+
422
+ ```bash
423
+ curl -X POST "http://127.0.0.1:3001/api/income?pairing=MYSTORE" \
424
+ -H "Content-Type: application/json" \
425
+ -d '{
426
+ "amount": 1500,
427
+ "name": "John Doe",
428
+ "sender": "2519****1234",
429
+ "transactionNumber": "FT260501234"
430
+ }'
431
+ ```
432
+
433
+ #### `POST /api/notification`
434
+
435
+ Push a notification payload.
135
436
 
136
- All pairing-scoped routes accept `?pairing=CODE` or header `X-Pairing: CODE`. If `pairingCode` is set in `zyro.config.js`, it becomes the default.
437
+ ---
137
438
 
138
- | Method | Path | Description |
139
- |--------|------|-------------|
140
- | GET | `/` | Service index + endpoint list |
141
- | GET | `/api/info` | Server info, URLs, features |
142
- | GET | `/api/config` | IP, port, pairing from config |
143
- | GET | `/api/dashboard` | Today stats + recent activity |
144
- | GET | `/api/devices` | Connected devices for pairing room |
145
- | GET | `/api/transactions` | Transactions (`?after=ISO` for incremental) |
146
- | GET | `/api/notifications` | Notifications (`?after=ISO`) |
147
- | POST | `/api/register` | Register phone via HTTP |
148
- | POST | `/api/income` | Post income JSON body |
149
- | POST | `/api/notification` | Post notification JSON body |
439
+ ### Static assets
150
440
 
151
- Static client: `GET /zyro/zyro.js`
441
+ | Path | Description |
442
+ |------|-------------|
443
+ | `/zyro/zyro.js` | Browser client bundle |
444
+ | `/socket.io/socket.io.js` | Socket.IO client (served by Socket.IO) |
445
+
446
+ ---
447
+
448
+ ## Socket.IO protocol
449
+
450
+ ### Connection URL
451
+
452
+ ```
453
+ ws://<ip>:<port>/socket.io/?pairing=MYSTORE&role=phone&deviceName=My%20Phone
454
+ ```
152
455
 
153
- ## Socket.IO events
456
+ | Query | Values |
457
+ |-------|--------|
458
+ | `pairing` | Required, 4–12 alphanumeric |
459
+ | `role` | `phone` (mobile) \| `desktop` (web / system client) |
460
+ | `deviceName` | Optional display name |
154
461
 
155
- **Client → server**
462
+ ### Client → server
156
463
 
157
464
  | Event | Payload |
158
- |--------|---------|
465
+ |-------|---------|
159
466
  | `register` | `{ deviceName, platform, ... }` |
160
467
  | `income_transaction` | Transaction object |
161
468
  | `notification_event` | Notification object |
162
469
 
163
- **Server → client**
470
+ ### Server → client
164
471
 
165
472
  | Event | Description |
166
- |--------|-------------|
167
- | `sync_ready` | Handshake OK |
168
- | `sync_error` | Invalid pairing |
169
- | `history` | Recent transactions |
170
- | `notification_history` | Recent notifications |
171
- | `income_transaction` | New transaction |
172
- | `notification_event` | New notification |
173
- | `dashboard_update` | Stats snapshot |
174
- | `presence` | Device counts |
473
+ |-------|-------------|
474
+ | `sync_ready` | Joined room successfully |
475
+ | `sync_error` | Invalid or missing pairing |
476
+ | `history` | Up to 50 recent transactions |
477
+ | `notification_history` | Up to 50 recent notifications |
478
+ | `income_transaction` | Live transaction |
479
+ | `notification_event` | Live notification |
480
+ | `dashboard_update` | Aggregated stats |
481
+ | `presence` | Client counts by role + device list |
175
482
  | `device_joined` / `device_left` / `device_updated` | Device lifecycle |
176
483
 
177
- Connect query: `?pairing=MYSTORE&role=phone|desktop&deviceName=Label`
484
+ ### Transaction payload (recommended fields)
485
+
486
+ | Field | Type | Description |
487
+ |-------|------|-------------|
488
+ | `amount` | `number` | Income amount |
489
+ | `name` | `string` | Payer / customer name |
490
+ | `sender` | `string` | Source address or account |
491
+ | `transactionNumber` | `string` | Provider / bank reference |
492
+ | `timestamp` | `string` | ISO time (optional) |
493
+ | `smsAddress` | `string` | Optional alias for `sender` (API field name) |
494
+
495
+ ---
496
+
497
+ ## Programmatic server API
498
+
499
+ Embed the gateway in your own Node process:
500
+
501
+ ```javascript
502
+ const { createGateway } = require('z-getway/server');
503
+
504
+ async function main() {
505
+ const gateway = createGateway({
506
+ packageRoot: __dirname, // folder containing dist/ and zyro.config.js
507
+ });
508
+
509
+ const { url, port, pairingCode } = await gateway.start();
510
+ console.log(`Gateway at ${url} (pairing: ${pairingCode})`);
511
+
512
+ // gateway.app — Express instance
513
+ // gateway.io — Socket.IO server
514
+ // await gateway.stop();
515
+ }
516
+
517
+ main().catch(console.error);
518
+ ```
519
+
520
+ Useful for tests, Electron backends, or custom hosting.
521
+
522
+ ---
523
+
524
+ ## CLI reference
525
+
526
+ | Command | Description |
527
+ |---------|-------------|
528
+ | `z-getway` | Start server (builds client if needed) |
529
+ | `z-getway config` | Copy `zyro.config.example.js` → `./zyro.config.js` |
530
+ | `z-getway help` | Show usage |
531
+
532
+ ### npm scripts (repository)
533
+
534
+ | Script | Action |
535
+ |--------|--------|
536
+ | `npm start` | Build + run `server.js` |
537
+ | `npm run dev` | Run with `--watch` |
538
+ | `npm run build` | Bundle `zyro/zyro.js` → `dist/zyro.js` |
539
+ | `npm run config` | Init config in cwd |
540
+
541
+ ---
178
542
 
179
- ## CLI
543
+ ## Project structure
544
+
545
+ ```
546
+ zyro-getway/
547
+ ├── bin/z-getway.js # CLI entry (`zyro-gateway` alias)
548
+ ├── src/
549
+ │ ├── config/ # load-config.js, pairing.js
550
+ │ ├── server/ # routes, socket, broadcast, terminal
551
+ │ ├── utils/ # network, formatting
552
+ │ └── index.js # createGateway(), start()
553
+ ├── zyro/zyro.js # ESM browser client (source)
554
+ ├── dist/zyro.js # IIFE bundle (published)
555
+ ├── scripts/ # build, init-config
556
+ ├── server.js # npm start shim
557
+ ├── zyro.config.example.js
558
+ ├── README.md
559
+ ├── CHANGELOG.md
560
+ └── LICENSE
561
+ ```
562
+
563
+ ---
564
+
565
+ ## Development
180
566
 
181
567
  ```bash
182
- zyro-gateway # Start server
183
- zyro-gateway config # Create zyro.config.js in cwd
184
- zyro-gateway help # Usage
568
+ git clone https://github.com/orod-codes/zyro-getway.git
569
+ cd zyro-getway
570
+ npm install
571
+ cp zyro.config.example.js zyro.config.js # or: npm run config
572
+ npm run dev
185
573
  ```
186
574
 
187
- ## Project layout
575
+ ### Link locally into another project
188
576
 
577
+ ```bash
578
+ cd zyro-getway && npm link
579
+ cd ~/my-app && npm link z-getway
580
+ npx z-getway
189
581
  ```
190
- bin/zyro-gateway.js CLI entry
191
- src/
192
- config/ load-config, pairing helpers
193
- server/ routes, socket, broadcast, terminal
194
- utils/ network, formatting
195
- index.js start() + exports
196
- zyro/zyro.js ESM browser client (source)
197
- dist/zyro.js IIFE bundle (published)
198
- scripts/ build, init-config
199
- server.js npm start shim
582
+
583
+ ### Run tests manually
584
+
585
+ ```bash
586
+ curl http://localhost:3001/api/info
587
+ curl "http://localhost:3001/api/dashboard?pairing=MYSTORE"
200
588
  ```
201
589
 
202
- ## npm scripts (development)
590
+ ---
203
591
 
204
- | Script | Action |
205
- |--------|--------|
206
- | `npm run config` | Create `zyro.config.js` in cwd |
207
- | `npm run build` | Bundle browser client to `dist/zyro.js` |
208
- | `npm start` | Build + start gateway |
209
- | `npm run dev` | Start with `--watch` |
592
+ ## Publishing updates (maintainers)
593
+
594
+ From the package root, after code changes:
595
+
596
+ ```bash
597
+ npm run release
598
+ ```
599
+
600
+ That bumps the patch version, builds, and publishes **`z-getway`** to npm. Users then run `npm update z-getway` or `npx z-getway@latest`.
601
+
602
+ See [CHANGELOG.md](CHANGELOG.md) for version history.
603
+
604
+ Both **`z-getway`** and **`zyro-gateway`** are published from this repo. Prefer `z-getway` for new projects; `zyro-gateway` stays available for existing installs.
210
605
 
211
- ## Publish to npm
606
+ ---
212
607
 
213
- The package name on npm is **`zyro-gateway`** (`zyro` is already registered).
608
+ ## Troubleshooting
609
+
610
+ ### `EADDRINUSE` — port already in use
611
+
612
+ Another gateway (or app) is on that port.
214
613
 
215
614
  ```bash
216
- npm run build
217
- npm publish --access public
615
+ # Find process
616
+ ss -tlnp | grep 3001
617
+
618
+ # Stop it (replace PID)
619
+ kill <PID>
620
+
621
+ # Or use another port
622
+ PORT=3002 npx z-getway
218
623
  ```
219
624
 
220
- ## License
625
+ Update the phone app and `zyro.config.js` to match.
626
+
627
+ ### Phone shows “Connected” but terminal is empty
221
628
 
222
- MIT see [LICENSE](LICENSE).
629
+ - Confirm **pairing code** matches exactly.
630
+ - Check gateway logs for `Connected [MYSTORE]`.
631
+ - If Socket.IO fails, ensure the app calls `POST /api/register`.
223
632
 
224
- ## Repository
633
+ ### Website not receiving events
634
+
635
+ - Same LAN and firewall allows inbound TCP on the gateway port.
636
+ - Use the PC’s LAN IP, not `localhost`, unless the browser runs on the same machine.
637
+ - Pairing query must match: `pairingCode: 'MYSTORE'`.
638
+
639
+ ### `npm whoami` / publish auth errors
640
+
641
+ ```bash
642
+ npm login
643
+ npm whoami
644
+ ```
645
+
646
+ Enable 2FA on [npm settings](https://www.npmjs.com/settings) for publish.
647
+
648
+ ### Wrong config loaded
649
+
650
+ `npx z-getway` reads **`./zyro.config.js` in the current directory**. Run `npx z-getway config` in each project, or set `ZYRO_CONFIG`.
651
+
652
+ ---
653
+
654
+ ## Security
655
+
656
+ - **LAN-only by design** — do not expose the gateway directly to the public internet without a reverse proxy, TLS, and auth.
657
+ - **Pairing codes** are shared secrets; use unique codes per tenant.
658
+ - **No persistence** — transactions live in memory; restart clears history.
659
+ - **CORS** is open (`*`) for local dashboards; tighten if you expose beyond LAN.
660
+ - Never commit `zyro.config.js` (see `.gitignore`).
661
+
662
+ ---
663
+
664
+ ## Related projects
665
+
666
+ | Project | Role |
667
+ |---------|------|
668
+ | [zyro-getway](https://github.com/orod-codes/zyro-getway) | This repository (server + browser client) |
669
+ | Mobile monitor | Client that captures income and posts events to the gateway |
670
+
671
+ ---
672
+
673
+ ## Contributing
674
+
675
+ 1. Fork the repo
676
+ 2. Create a branch: `git checkout -b feature/my-change`
677
+ 3. Commit with a clear message
678
+ 4. Open a PR against `main`
679
+
680
+ Issues and feature requests: [GitHub Issues](https://github.com/orod-codes/zyro-getway/issues).
681
+
682
+ ---
683
+
684
+ ## Contribution
685
+
686
+ Zyro Gateway is free and open source under the [MIT License](LICENSE). You are welcome to:
687
+
688
+ - Fork the repo and open pull requests
689
+ - [Report bugs or request features](https://github.com/orod-codes/zyro-getway/issues)
690
+ - Improve docs and examples
691
+
692
+ ## Security
693
+
694
+ Do not expose the gateway to the public internet without TLS and authentication. Pairing codes are shared secrets—rotate them per tenant. If you find a vulnerability, please open a [private security advisory](https://github.com/orod-codes/zyro-getway/security/advisories/new) on GitHub.
695
+
696
+ ## License
225
697
 
226
- https://github.com/orod-codes/zyro-getway
698
+ [MIT](LICENSE) © [orod-codes](https://github.com/orod-codes)
Binary file
@@ -0,0 +1,29 @@
1
+ #!/usr/bin/env node
2
+ 'use strict';
3
+
4
+ const cmd = process.argv[2];
5
+
6
+ if (cmd === 'config' || cmd === 'init') {
7
+ require('../scripts/init-config.js');
8
+ } else if (cmd === 'help' || cmd === '--help' || cmd === '-h') {
9
+ console.log(`
10
+ Zyro Gateway (z-getway)
11
+
12
+ Usage:
13
+ z-getway Start the gateway server
14
+ z-getway config Create zyro.config.js in the current directory
15
+ z-getway help Show this message
16
+
17
+ Update to latest:
18
+ npm update z-getway
19
+ npx z-getway@latest
20
+
21
+ Environment:
22
+ PORT Override listen port
23
+ ZYRO_CONFIG Path to zyro.config.js
24
+
25
+ Docs: https://github.com/orod-codes/zyro-getway#readme
26
+ `);
27
+ } else {
28
+ require('../src/index').start();
29
+ }
@@ -18,6 +18,8 @@ Environment:
18
18
  PORT Override listen port
19
19
  ZYRO_CONFIG Path to zyro.config.js
20
20
 
21
+ Update: npm update z-getway | npx z-getway@latest
22
+
21
23
  Docs: https://github.com/orod-codes/zyro-getway#readme
22
24
  `);
23
25
  } else {
package/package.json CHANGED
@@ -1,9 +1,9 @@
1
1
  {
2
2
  "name": "zyro-gateway",
3
- "version": "1.0.0",
4
- "description": "Zyro Gateway — real-time phone desktop sync (Node server + browser client)",
3
+ "version": "1.0.1",
4
+ "description": "Zyro Gateway — real-time sync for mobile, web, and system clients",
5
5
  "license": "MIT",
6
- "author": "orod-codes",
6
+ "author": "dorsis",
7
7
  "repository": {
8
8
  "type": "git",
9
9
  "url": "git+https://github.com/orod-codes/zyro-getway.git"
@@ -29,6 +29,7 @@
29
29
  "./package.json": "./package.json"
30
30
  },
31
31
  "files": [
32
+ "assets",
32
33
  "bin",
33
34
  "dist",
34
35
  "src",
@@ -47,24 +48,24 @@
47
48
  "config": "node scripts/init-config.js",
48
49
  "prestart": "npm run build",
49
50
  "prepare": "npm run build",
50
- "prepublishOnly": "npm run build"
51
+ "prepublishOnly": "npm run build",
52
+ "release": "node scripts/publish-all.js"
51
53
  },
52
54
  "bin": {
55
+ "z-getway": "bin/z-getway.js",
53
56
  "zyro-gateway": "bin/zyro-gateway.js"
54
57
  },
55
58
  "engines": {
56
59
  "node": ">=18"
57
60
  },
58
61
  "keywords": [
62
+ "z-getway",
59
63
  "zyro",
60
64
  "zyro-gateway",
61
65
  "socket.io",
62
66
  "real-time",
63
67
  "payment-sync",
64
- "telebirr",
65
- "ethiopia",
66
- "flutter",
67
- "sms-monitor"
68
+ "income-sync"
68
69
  ],
69
70
  "dependencies": {
70
71
  "express": "^4.21.2",
@@ -18,4 +18,4 @@ if (!fs.existsSync(example)) {
18
18
 
19
19
  fs.copyFileSync(example, target);
20
20
  console.log('Created', target);
21
- console.log('Edit ip, port, pairingCode then run: npx zyro-gateway');
21
+ console.log('Edit ip, port, pairingCode then run: npx z-getway');
@@ -0,0 +1,92 @@
1
+ #!/usr/bin/env node
2
+ 'use strict';
3
+
4
+ const fs = require('fs');
5
+ const path = require('path');
6
+ const { execSync } = require('child_process');
7
+
8
+ const root = path.join(__dirname, '..');
9
+ const pkgPath = path.join(root, 'package.json');
10
+ const original = fs.readFileSync(pkgPath, 'utf8');
11
+ const base = JSON.parse(original);
12
+
13
+ const otp =
14
+ process.env.NPM_OTP ||
15
+ process.argv.find((a) => a.startsWith('--otp='))?.split('=').slice(1).join('=');
16
+
17
+ function npmWhoami() {
18
+ try {
19
+ return execSync('npm whoami', {
20
+ encoding: 'utf8',
21
+ stdio: ['ignore', 'pipe', 'pipe'],
22
+ }).trim();
23
+ } catch {
24
+ return null;
25
+ }
26
+ }
27
+
28
+ const user = npmWhoami();
29
+
30
+ if (!user && (!otp || !/^\d{6,8}$/.test(otp))) {
31
+ console.error(`
32
+ Not logged in to npm.
33
+
34
+ Option A — token (recommended):
35
+ npm config set //registry.npmjs.org/:_authToken=YOUR_TOKEN
36
+ npm run release
37
+
38
+ Option B — OTP from authenticator app:
39
+ npm run release -- --otp=123456
40
+ `);
41
+ process.exit(1);
42
+ }
43
+
44
+ if (user) {
45
+ console.log(`npm user: ${user}`);
46
+ } else {
47
+ console.log('Publishing with OTP…');
48
+ }
49
+
50
+ /** @type {{ name: string, version: string }[]} */
51
+ const targets = [
52
+ { name: 'z-getway', version: '1.0.2' },
53
+ { name: 'zyro-gateway', version: '1.0.1' },
54
+ ];
55
+
56
+ function publishPackage(name, version) {
57
+ const publishPkg = { ...base, name, version };
58
+ fs.writeFileSync(pkgPath, JSON.stringify(publishPkg, null, 2) + '\n');
59
+
60
+ const env = { ...process.env };
61
+ if (otp) env.NPM_CONFIG_OTP = otp;
62
+
63
+ execSync('npm publish --access public', {
64
+ cwd: root,
65
+ stdio: 'inherit',
66
+ env,
67
+ });
68
+ }
69
+
70
+ console.log('Building browser client…');
71
+ execSync('npm run build', { cwd: root, stdio: 'inherit' });
72
+
73
+ for (const { name, version } of targets) {
74
+ console.log(`\nPublishing ${name}@${version}…`);
75
+ try {
76
+ publishPackage(name, version);
77
+ console.log(`✓ ${name}@${version}`);
78
+ } catch {
79
+ fs.writeFileSync(pkgPath, original);
80
+ console.error(`\n✗ Failed ${name}@${version}`);
81
+ console.error(
82
+ 'Try: npm whoami then npm run release -- --otp=CODE (fresh 6 digits from auth app)',
83
+ );
84
+ process.exit(1);
85
+ }
86
+ }
87
+
88
+ fs.writeFileSync(
89
+ pkgPath,
90
+ JSON.stringify({ ...base, name: 'z-getway', version: '1.0.2' }, null, 2) + '\n',
91
+ );
92
+ console.log('\nDone. Both packages published.');