@hanoilab/zk-bridge 0.1.5 → 0.1.6
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 +21 -5
- package/dist/cli/daemon.js +229 -0
- package/dist/cli/daemon.js.map +1 -0
- package/dist/cli/zk-bridge.js +93 -18
- package/dist/cli/zk-bridge.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -59,10 +59,18 @@ zk-bridge start
|
|
|
59
59
|
```
|
|
60
60
|
|
|
61
61
|
```text
|
|
62
|
-
[zk-bridge]
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
62
|
+
[zk-bridge] started (PID 12345)
|
|
63
|
+
Logs: ~/.local/share/zk-bridge/zk-bridge.log
|
|
64
|
+
Stop: zk-bridge stop
|
|
65
|
+
Tail: zk-bridge logs -f
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
`start` detaches — closing the terminal won't stop the bridge. Useful one-liners:
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
zk-bridge status # is it running?
|
|
72
|
+
zk-bridge logs -f # follow the log
|
|
73
|
+
zk-bridge stop # stop it
|
|
66
74
|
```
|
|
67
75
|
|
|
68
76
|
### 3. Open the admin UI
|
|
@@ -112,7 +120,13 @@ Visit **<http://localhost:7000>**, set the backend Push URL, paste the per-devic
|
|
|
112
120
|
## CLI
|
|
113
121
|
|
|
114
122
|
```bash
|
|
115
|
-
zk-bridge start # Start
|
|
123
|
+
zk-bridge start # Start as background daemon (writes PID + log)
|
|
124
|
+
zk-bridge stop # Stop the daemon
|
|
125
|
+
zk-bridge restart # Stop + start
|
|
126
|
+
zk-bridge status # PID, uptime, log path
|
|
127
|
+
zk-bridge logs -f # Follow the log
|
|
128
|
+
zk-bridge logs -n 200 # Last 200 lines
|
|
129
|
+
zk-bridge run # Run in the foreground (debug / systemd / Docker)
|
|
116
130
|
zk-bridge poll-once # Run a single cycle then exit
|
|
117
131
|
zk-bridge reset-user # Forgot-password recovery
|
|
118
132
|
zk-bridge recent-events # Print last N events from a device
|
|
@@ -121,6 +135,8 @@ zk-bridge --help
|
|
|
121
135
|
zk-bridge --version
|
|
122
136
|
```
|
|
123
137
|
|
|
138
|
+
`start` detaches from the launching shell — `Ctrl+C` in that terminal does NOT kill the daemon. Use `zk-bridge stop`. Logs go to `<DATA_DIR>/zk-bridge.log`.
|
|
139
|
+
|
|
124
140
|
Environment overrides (otherwise default):
|
|
125
141
|
|
|
126
142
|
```bash
|
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.startDaemon = startDaemon;
|
|
37
|
+
exports.stopDaemon = stopDaemon;
|
|
38
|
+
exports.statusDaemon = statusDaemon;
|
|
39
|
+
exports.tailLog = tailLog;
|
|
40
|
+
exports.formatUptime = formatUptime;
|
|
41
|
+
const node_child_process_1 = require("node:child_process");
|
|
42
|
+
const fs = __importStar(require("node:fs"));
|
|
43
|
+
const path = __importStar(require("node:path"));
|
|
44
|
+
const env_1 = require("../config/env");
|
|
45
|
+
const PID_FILE = 'zk-bridge.pid';
|
|
46
|
+
const LOG_FILE = 'zk-bridge.log';
|
|
47
|
+
function paths() {
|
|
48
|
+
const { dataDir } = (0, env_1.loadBootEnv)();
|
|
49
|
+
fs.mkdirSync(dataDir, { recursive: true });
|
|
50
|
+
return {
|
|
51
|
+
dataDir,
|
|
52
|
+
pid: path.join(dataDir, PID_FILE),
|
|
53
|
+
log: path.join(dataDir, LOG_FILE),
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
function isAlive(pid) {
|
|
57
|
+
try {
|
|
58
|
+
process.kill(pid, 0);
|
|
59
|
+
return true;
|
|
60
|
+
}
|
|
61
|
+
catch {
|
|
62
|
+
return false;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
function readPid() {
|
|
66
|
+
const p = paths();
|
|
67
|
+
if (!fs.existsSync(p.pid))
|
|
68
|
+
return null;
|
|
69
|
+
const n = parseInt(fs.readFileSync(p.pid, 'utf8').trim(), 10);
|
|
70
|
+
if (!Number.isFinite(n) || !isAlive(n)) {
|
|
71
|
+
try {
|
|
72
|
+
fs.unlinkSync(p.pid);
|
|
73
|
+
}
|
|
74
|
+
catch {
|
|
75
|
+
// best-effort
|
|
76
|
+
}
|
|
77
|
+
return null;
|
|
78
|
+
}
|
|
79
|
+
return n;
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Spawn the bridge as a detached background child writing to a log file.
|
|
83
|
+
* Parent exits immediately — Ctrl+C in the launching shell does NOT kill
|
|
84
|
+
* the daemon (it's in a separate process group).
|
|
85
|
+
*/
|
|
86
|
+
function startDaemon() {
|
|
87
|
+
const existing = readPid();
|
|
88
|
+
if (existing) {
|
|
89
|
+
throw new Error(`Already running (PID ${existing}). Use 'zk-bridge stop' or 'zk-bridge restart' first.`);
|
|
90
|
+
}
|
|
91
|
+
const p = paths();
|
|
92
|
+
const fd = fs.openSync(p.log, 'a');
|
|
93
|
+
const node = process.execPath;
|
|
94
|
+
// dist/index.js — same entry `zk-bridge run` invokes, but spawned detached.
|
|
95
|
+
const entry = path.resolve(__dirname, '..', 'index.js');
|
|
96
|
+
const child = (0, node_child_process_1.spawn)(node, [entry], {
|
|
97
|
+
detached: true,
|
|
98
|
+
stdio: ['ignore', fd, fd],
|
|
99
|
+
env: process.env,
|
|
100
|
+
});
|
|
101
|
+
child.unref();
|
|
102
|
+
if (!child.pid)
|
|
103
|
+
throw new Error('Failed to spawn child process.');
|
|
104
|
+
fs.writeFileSync(p.pid, String(child.pid));
|
|
105
|
+
fs.closeSync(fd);
|
|
106
|
+
return { pid: child.pid, logPath: p.log, dataDir: p.dataDir };
|
|
107
|
+
}
|
|
108
|
+
function stopDaemon() {
|
|
109
|
+
const pid = readPid();
|
|
110
|
+
if (!pid)
|
|
111
|
+
return null;
|
|
112
|
+
try {
|
|
113
|
+
process.kill(pid, 'SIGTERM');
|
|
114
|
+
}
|
|
115
|
+
catch {
|
|
116
|
+
// already dead — fall through to PID cleanup
|
|
117
|
+
}
|
|
118
|
+
// Wait a moment for graceful shutdown, then verify.
|
|
119
|
+
const deadline = Date.now() + 5_000;
|
|
120
|
+
while (Date.now() < deadline && isAlive(pid)) {
|
|
121
|
+
// busy-wait short; the kill is async
|
|
122
|
+
sleepSync(100);
|
|
123
|
+
}
|
|
124
|
+
if (isAlive(pid)) {
|
|
125
|
+
try {
|
|
126
|
+
process.kill(pid, 'SIGKILL');
|
|
127
|
+
}
|
|
128
|
+
catch {
|
|
129
|
+
// ignore
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
const p = paths();
|
|
133
|
+
try {
|
|
134
|
+
fs.unlinkSync(p.pid);
|
|
135
|
+
}
|
|
136
|
+
catch {
|
|
137
|
+
// ignore
|
|
138
|
+
}
|
|
139
|
+
return { pid };
|
|
140
|
+
}
|
|
141
|
+
function statusDaemon() {
|
|
142
|
+
const p = paths();
|
|
143
|
+
const pid = readPid();
|
|
144
|
+
if (!pid) {
|
|
145
|
+
return { running: false, logPath: p.log, dataDir: p.dataDir };
|
|
146
|
+
}
|
|
147
|
+
let uptimeMs;
|
|
148
|
+
try {
|
|
149
|
+
const stat = fs.statSync(p.pid);
|
|
150
|
+
uptimeMs = Date.now() - stat.mtimeMs;
|
|
151
|
+
}
|
|
152
|
+
catch {
|
|
153
|
+
// ignore
|
|
154
|
+
}
|
|
155
|
+
return { running: true, pid, logPath: p.log, dataDir: p.dataDir, uptimeMs };
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* Print last N lines of the log file, optionally follow new appends.
|
|
159
|
+
* Cross-platform tail — doesn't shell out.
|
|
160
|
+
*/
|
|
161
|
+
function tailLog(follow, lines) {
|
|
162
|
+
const p = paths();
|
|
163
|
+
if (!fs.existsSync(p.log)) {
|
|
164
|
+
console.log('(no log yet — daemon has not started.)');
|
|
165
|
+
return;
|
|
166
|
+
}
|
|
167
|
+
const initial = readLastLines(p.log, lines);
|
|
168
|
+
process.stdout.write(initial);
|
|
169
|
+
if (!follow)
|
|
170
|
+
return;
|
|
171
|
+
let pos = fs.statSync(p.log).size;
|
|
172
|
+
const watcher = fs.watch(p.log, () => {
|
|
173
|
+
let stat;
|
|
174
|
+
try {
|
|
175
|
+
stat = fs.statSync(p.log);
|
|
176
|
+
}
|
|
177
|
+
catch {
|
|
178
|
+
return;
|
|
179
|
+
}
|
|
180
|
+
if (stat.size > pos) {
|
|
181
|
+
const fd = fs.openSync(p.log, 'r');
|
|
182
|
+
const buf = Buffer.alloc(stat.size - pos);
|
|
183
|
+
fs.readSync(fd, buf, 0, buf.length, pos);
|
|
184
|
+
fs.closeSync(fd);
|
|
185
|
+
process.stdout.write(buf.toString('utf8'));
|
|
186
|
+
pos = stat.size;
|
|
187
|
+
}
|
|
188
|
+
else if (stat.size < pos) {
|
|
189
|
+
pos = 0;
|
|
190
|
+
}
|
|
191
|
+
});
|
|
192
|
+
process.on('SIGINT', () => {
|
|
193
|
+
watcher.close();
|
|
194
|
+
process.exit(0);
|
|
195
|
+
});
|
|
196
|
+
// Keep the event loop alive.
|
|
197
|
+
setInterval(() => undefined, 1 << 30);
|
|
198
|
+
}
|
|
199
|
+
function readLastLines(file, lines) {
|
|
200
|
+
const content = fs.readFileSync(file, 'utf8');
|
|
201
|
+
const arr = content.split('\n');
|
|
202
|
+
// Trim trailing empty line caused by final newline.
|
|
203
|
+
if (arr[arr.length - 1] === '')
|
|
204
|
+
arr.pop();
|
|
205
|
+
const slice = arr.slice(-lines);
|
|
206
|
+
return slice.join('\n') + (slice.length > 0 ? '\n' : '');
|
|
207
|
+
}
|
|
208
|
+
function formatUptime(ms) {
|
|
209
|
+
const s = Math.floor(ms / 1000);
|
|
210
|
+
if (s < 60)
|
|
211
|
+
return `${s}s`;
|
|
212
|
+
const m = Math.floor(s / 60);
|
|
213
|
+
if (m < 60)
|
|
214
|
+
return `${m}m ${s % 60}s`;
|
|
215
|
+
const h = Math.floor(m / 60);
|
|
216
|
+
if (h < 24)
|
|
217
|
+
return `${h}h ${m % 60}m`;
|
|
218
|
+
const d = Math.floor(h / 24);
|
|
219
|
+
return `${d}d ${h % 24}h`;
|
|
220
|
+
}
|
|
221
|
+
function sleepSync(ms) {
|
|
222
|
+
// Atomics.wait on a SharedArrayBuffer would be precise but heavy; this
|
|
223
|
+
// ~100ms granularity is fine for stop's grace-period polling.
|
|
224
|
+
const end = Date.now() + ms;
|
|
225
|
+
while (Date.now() < end) {
|
|
226
|
+
// spin
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
//# sourceMappingURL=daemon.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"daemon.js","sourceRoot":"","sources":["../../src/cli/daemon.ts"],"names":[],"mappings":"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"}
|
package/dist/cli/zk-bridge.js
CHANGED
|
@@ -44,13 +44,19 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
44
44
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
45
45
|
const node_child_process_1 = require("node:child_process");
|
|
46
46
|
const path = __importStar(require("node:path"));
|
|
47
|
+
const daemon_1 = require("./daemon");
|
|
47
48
|
const command = process.argv[2];
|
|
48
49
|
function help() {
|
|
49
50
|
// eslint-disable-next-line no-console
|
|
50
51
|
console.log(`Usage: zk-bridge <command> [options]
|
|
51
52
|
|
|
52
53
|
Commands:
|
|
53
|
-
start Start bridge
|
|
54
|
+
start Start bridge in the background (writes PID + log)
|
|
55
|
+
stop Stop the running daemon
|
|
56
|
+
restart Stop + start
|
|
57
|
+
status Show daemon state (PID, uptime, log path)
|
|
58
|
+
logs [-f] [-n N] Print last N log lines (default 50). -f to follow.
|
|
59
|
+
run Run in the foreground (debug / systemd / Docker)
|
|
54
60
|
poll-once Run a single poll cycle then exit (no UI server)
|
|
55
61
|
reset-user Reset the local admin user (forgot password recovery)
|
|
56
62
|
recent-events Print recent events from a device
|
|
@@ -60,18 +66,18 @@ Commands:
|
|
|
60
66
|
version, --version, -v Show package version
|
|
61
67
|
|
|
62
68
|
Environment:
|
|
63
|
-
DATA_DIR
|
|
69
|
+
DATA_DIR Where SQLite + admin credentials + log live
|
|
70
|
+
(default: OS user data dir)
|
|
64
71
|
PORT=7000 UI HTTP port
|
|
65
72
|
BIND_HOST=127.0.0.1 Bind address. Set 0.0.0.0 to allow LAN access
|
|
66
73
|
|
|
67
74
|
Examples:
|
|
68
|
-
zk-bridge start
|
|
69
|
-
|
|
70
|
-
zk-bridge
|
|
71
|
-
zk-bridge
|
|
72
|
-
zk-bridge
|
|
73
|
-
zk-bridge
|
|
74
|
-
zk-bridge recent-events --device "Cửa chính" -n 30
|
|
75
|
+
zk-bridge start # daemonize
|
|
76
|
+
zk-bridge status # is it running?
|
|
77
|
+
zk-bridge logs -f # follow logs
|
|
78
|
+
zk-bridge stop # stop the daemon
|
|
79
|
+
PORT=8080 zk-bridge run # foreground on a custom port
|
|
80
|
+
zk-bridge recent-events --device "Front gate" -n 30
|
|
75
81
|
`);
|
|
76
82
|
}
|
|
77
83
|
function version() {
|
|
@@ -121,19 +127,87 @@ async function upgrade(tag = 'latest') {
|
|
|
121
127
|
});
|
|
122
128
|
// eslint-disable-next-line no-console
|
|
123
129
|
console.log(`[zk-bridge] ✓ upgraded ${target}.\n` +
|
|
124
|
-
'Restart the
|
|
125
|
-
'
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
130
|
+
'Restart the daemon to pick up the new code:\n' +
|
|
131
|
+
' zk-bridge restart');
|
|
132
|
+
}
|
|
133
|
+
function parseLogsArgs() {
|
|
134
|
+
const argv = process.argv.slice(3);
|
|
135
|
+
const follow = argv.includes('-f') || argv.includes('--follow');
|
|
136
|
+
const nIdx = argv.findIndex((a) => a === '-n' || a === '--lines');
|
|
137
|
+
const lines = nIdx >= 0 ? Number(argv[nIdx + 1]) : 50;
|
|
138
|
+
return { follow, lines: Number.isFinite(lines) && lines > 0 ? lines : 50 };
|
|
139
|
+
}
|
|
140
|
+
function cmdStart() {
|
|
141
|
+
try {
|
|
142
|
+
const r = (0, daemon_1.startDaemon)();
|
|
143
|
+
// eslint-disable-next-line no-console
|
|
144
|
+
console.log(`[zk-bridge] started (PID ${r.pid})\n` +
|
|
145
|
+
` Logs: ${r.logPath}\n` +
|
|
146
|
+
` Stop: zk-bridge stop\n` +
|
|
147
|
+
` Tail: zk-bridge logs -f`);
|
|
148
|
+
}
|
|
149
|
+
catch (err) {
|
|
150
|
+
// eslint-disable-next-line no-console
|
|
151
|
+
console.error(`[zk-bridge] ${err instanceof Error ? err.message : err}`);
|
|
152
|
+
process.exit(1);
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
function cmdStop() {
|
|
156
|
+
const r = (0, daemon_1.stopDaemon)();
|
|
157
|
+
if (!r) {
|
|
158
|
+
// eslint-disable-next-line no-console
|
|
159
|
+
console.log('[zk-bridge] not running.');
|
|
160
|
+
return;
|
|
161
|
+
}
|
|
162
|
+
// eslint-disable-next-line no-console
|
|
163
|
+
console.log(`[zk-bridge] stopped (PID ${r.pid}).`);
|
|
164
|
+
}
|
|
165
|
+
async function cmdRestart() {
|
|
166
|
+
cmdStop();
|
|
167
|
+
await new Promise((r) => setTimeout(r, 600));
|
|
168
|
+
cmdStart();
|
|
169
|
+
}
|
|
170
|
+
function cmdStatus() {
|
|
171
|
+
const s = (0, daemon_1.statusDaemon)();
|
|
172
|
+
if (!s.running) {
|
|
173
|
+
// eslint-disable-next-line no-console
|
|
174
|
+
console.log(`[zk-bridge] not running.\n` +
|
|
175
|
+
` Data dir: ${s.dataDir}\n` +
|
|
176
|
+
` Logs: ${s.logPath} (last run, if any)`);
|
|
177
|
+
return;
|
|
178
|
+
}
|
|
179
|
+
const up = s.uptimeMs !== undefined ? (0, daemon_1.formatUptime)(s.uptimeMs) : 'unknown';
|
|
180
|
+
// eslint-disable-next-line no-console
|
|
181
|
+
console.log(`[zk-bridge] running.\n` +
|
|
182
|
+
` PID: ${s.pid}\n` +
|
|
183
|
+
` Uptime: ${up}\n` +
|
|
184
|
+
` Data dir: ${s.dataDir}\n` +
|
|
185
|
+
` Logs: ${s.logPath}`);
|
|
131
186
|
}
|
|
132
187
|
async function main() {
|
|
133
188
|
switch (command) {
|
|
189
|
+
// ── daemon control ───────────────────────────────────────────────────
|
|
134
190
|
case undefined:
|
|
135
191
|
case 'start':
|
|
136
|
-
|
|
192
|
+
cmdStart();
|
|
193
|
+
return;
|
|
194
|
+
case 'stop':
|
|
195
|
+
cmdStop();
|
|
196
|
+
return;
|
|
197
|
+
case 'restart':
|
|
198
|
+
await cmdRestart();
|
|
199
|
+
return;
|
|
200
|
+
case 'status':
|
|
201
|
+
cmdStatus();
|
|
202
|
+
return;
|
|
203
|
+
case 'logs': {
|
|
204
|
+
const { follow, lines } = parseLogsArgs();
|
|
205
|
+
(0, daemon_1.tailLog)(follow, lines);
|
|
206
|
+
return;
|
|
207
|
+
}
|
|
208
|
+
// ── foreground / one-shot ────────────────────────────────────────────
|
|
209
|
+
case 'run':
|
|
210
|
+
// Foreground mode — what daemons / Docker / systemd should call.
|
|
137
211
|
process.argv.splice(2, 1);
|
|
138
212
|
await Promise.resolve().then(() => __importStar(require('../index')));
|
|
139
213
|
return;
|
|
@@ -149,11 +223,12 @@ async function main() {
|
|
|
149
223
|
process.argv.splice(2, 1);
|
|
150
224
|
await Promise.resolve().then(() => __importStar(require('./recent-events')));
|
|
151
225
|
return;
|
|
226
|
+
// ── self-update ──────────────────────────────────────────────────────
|
|
152
227
|
case 'upgrade':
|
|
153
228
|
case 'update':
|
|
154
|
-
// Optional next arg = npm dist-tag (e.g. `next`). Default `latest`.
|
|
155
229
|
await upgrade(process.argv[3] ?? 'latest');
|
|
156
230
|
return;
|
|
231
|
+
// ── meta ─────────────────────────────────────────────────────────────
|
|
157
232
|
case 'help':
|
|
158
233
|
case '--help':
|
|
159
234
|
case '-h':
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"zk-bridge.js","sourceRoot":"","sources":["../../src/cli/zk-bridge.ts"],"names":[],"mappings":";;AAEA;;;;;;;GAOG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAEH,2DAA2C;AAC3C,gDAAkC;AAElC,MAAM,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAEhC,SAAS,IAAI;IACX,sCAAsC;IACtC,OAAO,CAAC,GAAG,CAAC
|
|
1
|
+
{"version":3,"file":"zk-bridge.js","sourceRoot":"","sources":["../../src/cli/zk-bridge.ts"],"names":[],"mappings":"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"}
|