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 +10 -2
- package/README.md +602 -130
- package/assets/zyro-logo.png +0 -0
- package/bin/z-getway.js +29 -0
- package/bin/zyro-gateway.js +2 -0
- package/package.json +9 -8
- package/scripts/init-config.js +1 -1
- package/scripts/publish-all.js +92 -0
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: `
|
|
14
|
-
- Programmatic API: `require('
|
|
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
|
-
|
|
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
|
-
|
|
4
|
-
[](LICENSE)
|
|
83
|
+
## Requirements
|
|
5
84
|
|
|
6
|
-
|
|
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
|
-
|
|
92
|
+
---
|
|
9
93
|
|
|
10
|
-
|
|
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
|
-
|
|
96
|
+
### From npm (recommended)
|
|
17
97
|
|
|
18
|
-
|
|
19
|
-
|
|
98
|
+
```bash
|
|
99
|
+
npm install z-getway
|
|
100
|
+
```
|
|
20
101
|
|
|
21
|
-
|
|
102
|
+
### Global CLI (optional)
|
|
22
103
|
|
|
23
104
|
```bash
|
|
24
|
-
npm install
|
|
25
|
-
|
|
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
|
|
109
|
+
### From source
|
|
31
110
|
|
|
32
111
|
```bash
|
|
33
|
-
|
|
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
|
-
|
|
119
|
+
---
|
|
40
120
|
|
|
41
|
-
|
|
121
|
+
## Quick start
|
|
122
|
+
|
|
123
|
+
**1. Create config** (in your project folder—not committed to git):
|
|
42
124
|
|
|
43
125
|
```bash
|
|
44
|
-
|
|
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
|
-
|
|
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
|
-
|
|
52
|
-
|
|
53
|
-
|
|
|
54
|
-
|
|
55
|
-
| `
|
|
56
|
-
| `
|
|
57
|
-
| `
|
|
58
|
-
| `
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
272
|
+
Forward the gateway port to the device:
|
|
67
273
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
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
|
-
|
|
284
|
+
1. `POST /api/register` — appear in terminal **Connected** list
|
|
285
|
+
2. `POST /api/income` — push each transaction
|
|
74
286
|
|
|
75
|
-
|
|
287
|
+
Headers/query: `X-Pairing: MYSTORE` or `?pairing=MYSTORE`.
|
|
76
288
|
|
|
77
|
-
|
|
289
|
+
---
|
|
78
290
|
|
|
79
|
-
##
|
|
291
|
+
## Browser client
|
|
80
292
|
|
|
81
|
-
|
|
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://
|
|
85
|
-
<script src="http://
|
|
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: '
|
|
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 /
|
|
319
|
+
### ESM / Vite / Webpack
|
|
110
320
|
|
|
111
321
|
```javascript
|
|
112
|
-
import { connect } from '
|
|
113
|
-
|
|
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
|
-
|
|
333
|
+
### Client events
|
|
117
334
|
|
|
118
|
-
|
|
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
|
-
|
|
121
|
-
const { createGateway } = require('zyro-gateway/server');
|
|
345
|
+
---
|
|
122
346
|
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
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
|
-
|
|
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
|
-
|
|
418
|
+
#### `POST /api/income`
|
|
133
419
|
|
|
134
|
-
|
|
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
|
-
|
|
437
|
+
---
|
|
137
438
|
|
|
138
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
470
|
+
### Server → client
|
|
164
471
|
|
|
165
472
|
| Event | Description |
|
|
166
|
-
|
|
167
|
-
| `sync_ready` |
|
|
168
|
-
| `sync_error` | Invalid pairing |
|
|
169
|
-
| `history` |
|
|
170
|
-
| `notification_history` |
|
|
171
|
-
| `income_transaction` |
|
|
172
|
-
| `notification_event` |
|
|
173
|
-
| `dashboard_update` |
|
|
174
|
-
| `presence` |
|
|
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
|
-
|
|
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
|
-
##
|
|
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-
|
|
183
|
-
zyro-
|
|
184
|
-
|
|
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
|
-
|
|
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
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
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
|
-
|
|
590
|
+
---
|
|
203
591
|
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
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
|
-
|
|
606
|
+
---
|
|
212
607
|
|
|
213
|
-
|
|
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
|
-
|
|
217
|
-
|
|
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
|
-
|
|
625
|
+
Update the phone app and `zyro.config.js` to match.
|
|
626
|
+
|
|
627
|
+
### Phone shows “Connected” but terminal is empty
|
|
221
628
|
|
|
222
|
-
|
|
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
|
-
|
|
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
|
|
698
|
+
[MIT](LICENSE) © [orod-codes](https://github.com/orod-codes)
|
|
Binary file
|
package/bin/z-getway.js
ADDED
|
@@ -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
|
+
}
|
package/bin/zyro-gateway.js
CHANGED
package/package.json
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "zyro-gateway",
|
|
3
|
-
"version": "1.0.
|
|
4
|
-
"description": "Zyro Gateway — real-time
|
|
3
|
+
"version": "1.0.1",
|
|
4
|
+
"description": "Zyro Gateway — real-time sync for mobile, web, and system clients",
|
|
5
5
|
"license": "MIT",
|
|
6
|
-
"author": "
|
|
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
|
-
"
|
|
65
|
-
"ethiopia",
|
|
66
|
-
"flutter",
|
|
67
|
-
"sms-monitor"
|
|
68
|
+
"income-sync"
|
|
68
69
|
],
|
|
69
70
|
"dependencies": {
|
|
70
71
|
"express": "^4.21.2",
|
package/scripts/init-config.js
CHANGED
|
@@ -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.');
|