@expo/event-log 0.0.1-init
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 +5 -0
- package/LICENSE.md +22 -0
- package/README.md +74 -0
- package/bin/cli.js +19 -0
- package/cli/package.json +17 -0
- package/dist/chunks/tap-chunk.js +536 -0
- package/dist/chunks/tap-chunk.js.map +1 -0
- package/dist/chunks/tap-chunk.mjs +522 -0
- package/dist/chunks/tap-chunk.mjs.map +1 -0
- package/dist/event-log.d.ts +142 -0
- package/dist/event-log.js +983 -0
- package/dist/event-log.js.map +1 -0
- package/dist/event-log.mjs +977 -0
- package/dist/event-log.mjs.map +1 -0
- package/dist/expo-event-log-cli.d.ts +4 -0
- package/dist/expo-event-log-cli.js +1412 -0
- package/dist/expo-event-log-cli.js.map +1 -0
- package/dist/expo-event-log-cli.mjs +1406 -0
- package/dist/expo-event-log-cli.mjs.map +1 -0
- package/package.json +95 -0
package/CHANGELOG.md
ADDED
package/LICENSE.md
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) Phil Pluckthun,
|
|
4
|
+
Copyright (c) 650 Industries, Inc. (aka Expo),
|
|
5
|
+
|
|
6
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
7
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
8
|
+
in the Software without restriction, including without limitation the rights
|
|
9
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
10
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
11
|
+
furnished to do so, subject to the following conditions:
|
|
12
|
+
|
|
13
|
+
The above copyright notice and this permission notice shall be included in all
|
|
14
|
+
copies or substantial portions of the Software.
|
|
15
|
+
|
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
17
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
18
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
19
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
20
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
21
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
22
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
<div align="center">
|
|
2
|
+
<h2>@expo/event-log</h2>
|
|
3
|
+
<strong>Low-overhead structured event logs for Expo CLI processes</strong>
|
|
4
|
+
<br />
|
|
5
|
+
<br />
|
|
6
|
+
</div>
|
|
7
|
+
|
|
8
|
+
`@expo/event-log` is a structured event logger for command-line tools. It writes JSONL logs
|
|
9
|
+
that can be replayed, tailed, inspected, or exported to trace formats.
|
|
10
|
+
|
|
11
|
+
In short, `@expo/event-log`,
|
|
12
|
+
|
|
13
|
+
- keeps logging cheap enough to leave enabled
|
|
14
|
+
- writes bounded session logs to the system temporary directory
|
|
15
|
+
- forwards worker and child-process events into the same session
|
|
16
|
+
- lets tools and agents tap into running commands
|
|
17
|
+
- derives typed event payloads through TypeScript declaration merging
|
|
18
|
+
|
|
19
|
+
## Usage
|
|
20
|
+
|
|
21
|
+
Install logging once when a CLI command starts:
|
|
22
|
+
|
|
23
|
+
```ts
|
|
24
|
+
import { installEventLogger } from '@expo/event-log';
|
|
25
|
+
|
|
26
|
+
installEventLogger({ command: 'expo start -p web', version: '1.0.0' });
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
Create a logger in any package:
|
|
30
|
+
|
|
31
|
+
```ts
|
|
32
|
+
import { events } from '@expo/event-log';
|
|
33
|
+
|
|
34
|
+
const log = events('metro');
|
|
35
|
+
|
|
36
|
+
log('ready', { port: 8081 });
|
|
37
|
+
|
|
38
|
+
const end = log.span('bundle', { platform: 'ios' });
|
|
39
|
+
end('bundle', { cached: false });
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
Extend `EventRegistry` to type event payloads:
|
|
43
|
+
|
|
44
|
+
```ts
|
|
45
|
+
declare module '@expo/event-log' {
|
|
46
|
+
interface EventRegistry {
|
|
47
|
+
'metro:ready': { port: number };
|
|
48
|
+
'metro:bundle': { platform?: string; cached?: boolean };
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## CLI
|
|
54
|
+
|
|
55
|
+
Use the CLI to find sessions, replay logs, or export traces:
|
|
56
|
+
|
|
57
|
+
```sh
|
|
58
|
+
event-log ps --json
|
|
59
|
+
event-log tap "expo start" --filter metro:* --tail
|
|
60
|
+
event-log export "expo start" --format chrome-trace -o trace.json
|
|
61
|
+
event-log export "expo start" --format opentelemetry -o otel.json
|
|
62
|
+
event-log clean --json
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
Selectors match a session by PID, command, session directory, or working directory.
|
|
66
|
+
`tap` and `export` replay retained history first. `--tail` appends live events.
|
|
67
|
+
|
|
68
|
+
## API
|
|
69
|
+
|
|
70
|
+
- `events(category)` creates a typed logger
|
|
71
|
+
- `installEventLogger(options)` installs logging for the process
|
|
72
|
+
- `isEventLoggerActive()` returns the active destination, or `null`
|
|
73
|
+
- `list(options)` lists known sessions
|
|
74
|
+
- `tap(sessionDir, options)` replays and optionally follows a session
|
package/bin/cli.js
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
(async function main() {
|
|
4
|
+
let cli;
|
|
5
|
+
try {
|
|
6
|
+
cli = await import('../dist/expo-event-log-cli.mjs');
|
|
7
|
+
} catch {
|
|
8
|
+
cli = require('../dist/expo-event-log-cli.js');
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
try {
|
|
12
|
+
process.exitCode = await cli.main(process.argv.slice(2));
|
|
13
|
+
} catch (error) {
|
|
14
|
+
process.stderr.write(
|
|
15
|
+
`${error instanceof Error ? error.message : String(error)}\n`
|
|
16
|
+
);
|
|
17
|
+
process.exitCode = 1;
|
|
18
|
+
}
|
|
19
|
+
})();
|
package/cli/package.json
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "expo-event-log-cli",
|
|
3
|
+
"private": true,
|
|
4
|
+
"version": "0.0.0",
|
|
5
|
+
"main": "../dist/expo-event-log-cli.js",
|
|
6
|
+
"module": "../dist/expo-event-log-cli.mjs",
|
|
7
|
+
"types": "../dist/expo-event-log-cli.d.ts",
|
|
8
|
+
"source": "../src/cli.ts",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"types": "../dist/expo-event-log-cli.d.ts",
|
|
12
|
+
"import": "../dist/expo-event-log-cli.mjs",
|
|
13
|
+
"require": "../dist/expo-event-log-cli.js",
|
|
14
|
+
"source": "../src/cli.ts"
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
}
|
|
@@ -0,0 +1,536 @@
|
|
|
1
|
+
var e = require("node:console");
|
|
2
|
+
|
|
3
|
+
var t = require("node:fs/promises");
|
|
4
|
+
|
|
5
|
+
var n = require("node:path");
|
|
6
|
+
|
|
7
|
+
var r = require("node:net");
|
|
8
|
+
|
|
9
|
+
var o = require("node:readline");
|
|
10
|
+
|
|
11
|
+
var i = require("node:os");
|
|
12
|
+
|
|
13
|
+
var s = require("node:fs");
|
|
14
|
+
|
|
15
|
+
const c = n.join(i.tmpdir(), "expo-event-log");
|
|
16
|
+
|
|
17
|
+
const l = {
|
|
18
|
+
meta: "meta.json",
|
|
19
|
+
liveSocket: "live.sock",
|
|
20
|
+
ipcSocket: "ipc.sock"
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
const a = Symbol.for("@expo/event-log/session-base-dir-override");
|
|
24
|
+
|
|
25
|
+
function cleanStaleSessionsSync() {
|
|
26
|
+
const e = function getSessionEntries() {
|
|
27
|
+
try {
|
|
28
|
+
const e = getSessionBaseDir();
|
|
29
|
+
return s.readdirSync(e, {
|
|
30
|
+
withFileTypes: !0
|
|
31
|
+
}).filter(e => e.isDirectory()).map(t => {
|
|
32
|
+
const r = n.join(e, t.name);
|
|
33
|
+
return {
|
|
34
|
+
dir: r,
|
|
35
|
+
meta: readMetaSync(r),
|
|
36
|
+
alive: !1
|
|
37
|
+
};
|
|
38
|
+
}).filter(e => !!e.meta && isCompatibleSessionMeta(e.meta)).map(e => ({
|
|
39
|
+
...e,
|
|
40
|
+
alive: isPidAlive(e.meta.pid)
|
|
41
|
+
}));
|
|
42
|
+
} catch {
|
|
43
|
+
return [];
|
|
44
|
+
}
|
|
45
|
+
}();
|
|
46
|
+
const t = Date.now();
|
|
47
|
+
let r = 0;
|
|
48
|
+
for (const n of e) {
|
|
49
|
+
if (!n.alive && t - n.meta.startedAt > 6048e5) {
|
|
50
|
+
s.rmSync(n.dir, {
|
|
51
|
+
recursive: !0,
|
|
52
|
+
force: !0
|
|
53
|
+
});
|
|
54
|
+
r++;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
const o = e.filter(e => s.existsSync(e.dir)).sort((e, t) => t.meta.startedAt - e.meta.startedAt);
|
|
58
|
+
for (const e of o.filter(e => !e.alive).slice(100)) {
|
|
59
|
+
s.rmSync(e.dir, {
|
|
60
|
+
recursive: !0,
|
|
61
|
+
force: !0
|
|
62
|
+
});
|
|
63
|
+
r++;
|
|
64
|
+
}
|
|
65
|
+
return r;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function readMetaSync(e) {
|
|
69
|
+
try {
|
|
70
|
+
const t = JSON.parse(s.readFileSync(n.join(e, l.meta), "utf8"));
|
|
71
|
+
return isCompatibleSessionMeta(t) ? t : null;
|
|
72
|
+
} catch {
|
|
73
|
+
return null;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function getSessionBaseDir() {
|
|
78
|
+
return globalThis[a] || c;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
function isPidAlive(e) {
|
|
82
|
+
if (!e || e === process.pid) {
|
|
83
|
+
return !0;
|
|
84
|
+
}
|
|
85
|
+
try {
|
|
86
|
+
process.kill(e, 0);
|
|
87
|
+
return !0;
|
|
88
|
+
} catch {
|
|
89
|
+
return !1;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
function isCompatibleSessionMeta(e) {
|
|
94
|
+
return !!e && "object" == typeof e && 1 === e.formatVersion;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
async function listSessions(e = {}) {
|
|
98
|
+
cleanStaleSessionsSync();
|
|
99
|
+
const r = getSessionBaseDir();
|
|
100
|
+
const o = await t.readdir(r, {
|
|
101
|
+
withFileTypes: !0
|
|
102
|
+
}).catch(() => []);
|
|
103
|
+
const i = [];
|
|
104
|
+
for (const e of o) {
|
|
105
|
+
if (!e.isDirectory()) {
|
|
106
|
+
continue;
|
|
107
|
+
}
|
|
108
|
+
const t = n.join(r, e.name);
|
|
109
|
+
const o = readMetaSync(t);
|
|
110
|
+
if (!o) {
|
|
111
|
+
continue;
|
|
112
|
+
}
|
|
113
|
+
i.push({
|
|
114
|
+
id: e.name,
|
|
115
|
+
pid: o.pid,
|
|
116
|
+
formatVersion: o.formatVersion,
|
|
117
|
+
alive: isPidAlive(o.pid),
|
|
118
|
+
startedAt: o.startedAt,
|
|
119
|
+
command: o.command,
|
|
120
|
+
cwd: o.cwd,
|
|
121
|
+
version: o.version,
|
|
122
|
+
origin: o.origin,
|
|
123
|
+
sessionDir: t
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
return function filterSessions(e, t) {
|
|
127
|
+
const n = t?.trim();
|
|
128
|
+
if (!n) {
|
|
129
|
+
return e;
|
|
130
|
+
}
|
|
131
|
+
const r = e.filter(e => function matchesSessionExactly(e, t) {
|
|
132
|
+
return sessionSearchValues(e).some(e => e === t);
|
|
133
|
+
}(e, n));
|
|
134
|
+
if (r.length) {
|
|
135
|
+
return r;
|
|
136
|
+
}
|
|
137
|
+
const o = n.toLowerCase();
|
|
138
|
+
return e.filter(e => sessionSearchValues(e).some(e => e.toLowerCase().includes(o)));
|
|
139
|
+
}(i, e.selector).sort((e, t) => t.startedAt - e.startedAt);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
async function* readLines(e) {
|
|
143
|
+
let t = "";
|
|
144
|
+
for await (const n of e.createReadStream({
|
|
145
|
+
encoding: "utf8"
|
|
146
|
+
})) {
|
|
147
|
+
t += n;
|
|
148
|
+
let e = -1;
|
|
149
|
+
while ((e = t.indexOf("\n")) >= 0) {
|
|
150
|
+
const n = t.slice(0, e);
|
|
151
|
+
t = t.slice(e + 1);
|
|
152
|
+
if (n) {
|
|
153
|
+
yield n;
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
if (t) {
|
|
158
|
+
yield t;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
function parseEventLine(e, t = {}, n = compileEventFilter(t.filter), r = parseSince(t.since)) {
|
|
163
|
+
try {
|
|
164
|
+
const t = JSON.parse(e);
|
|
165
|
+
if (!t || "string" != typeof t._e || "number" != typeof t._t) {
|
|
166
|
+
return null;
|
|
167
|
+
}
|
|
168
|
+
if (null != r && t._t < r) {
|
|
169
|
+
return null;
|
|
170
|
+
}
|
|
171
|
+
if (!matchesEventFilter(t._e, n)) {
|
|
172
|
+
return null;
|
|
173
|
+
}
|
|
174
|
+
return t;
|
|
175
|
+
} catch {
|
|
176
|
+
return null;
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
function parseSince(e) {
|
|
181
|
+
if (null == e) {
|
|
182
|
+
return;
|
|
183
|
+
}
|
|
184
|
+
if (e instanceof Date) {
|
|
185
|
+
const t = e.getTime();
|
|
186
|
+
if (Number.isFinite(t)) {
|
|
187
|
+
return t;
|
|
188
|
+
}
|
|
189
|
+
throw new Error(`Invalid since: ${e.toString()}`);
|
|
190
|
+
}
|
|
191
|
+
if ("number" == typeof e) {
|
|
192
|
+
if (!Number.isFinite(e) || e < 0) {
|
|
193
|
+
throw new Error(`Invalid since: ${e}`);
|
|
194
|
+
}
|
|
195
|
+
return normalizeUnixTimestamp(e);
|
|
196
|
+
}
|
|
197
|
+
const t = e.trim();
|
|
198
|
+
if (!t) {
|
|
199
|
+
return;
|
|
200
|
+
}
|
|
201
|
+
if (/^\d+(?:\.\d+)?$/.test(t)) {
|
|
202
|
+
return normalizeUnixTimestamp(Number(t));
|
|
203
|
+
}
|
|
204
|
+
const n = function parseDuration(e) {
|
|
205
|
+
const t = e.trim().toLowerCase();
|
|
206
|
+
if (!t) {
|
|
207
|
+
return;
|
|
208
|
+
}
|
|
209
|
+
let n = 0;
|
|
210
|
+
let r = 0;
|
|
211
|
+
const o = /(\d+(?:\.\d+)?)\s*(milliseconds?|msecs?|ms|seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h)/gy;
|
|
212
|
+
while (r < t.length) {
|
|
213
|
+
o.lastIndex = r;
|
|
214
|
+
const e = o.exec(t);
|
|
215
|
+
if (!e) {
|
|
216
|
+
return;
|
|
217
|
+
}
|
|
218
|
+
const i = Number(e[1]);
|
|
219
|
+
if (!Number.isFinite(i)) {
|
|
220
|
+
return;
|
|
221
|
+
}
|
|
222
|
+
n += i * durationUnitToMs(e[2]);
|
|
223
|
+
r = o.lastIndex;
|
|
224
|
+
while (" " === t[r] || "," === t[r]) {
|
|
225
|
+
r++;
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
return n;
|
|
229
|
+
}(t);
|
|
230
|
+
if (null != n) {
|
|
231
|
+
return Date.now() - n;
|
|
232
|
+
}
|
|
233
|
+
const r = Date.parse(t);
|
|
234
|
+
if (Number.isFinite(r)) {
|
|
235
|
+
return r;
|
|
236
|
+
}
|
|
237
|
+
throw new Error(`Invalid since: ${e}`);
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
function compileEventFilter(e) {
|
|
241
|
+
const t = function normalizeEventFilter(e) {
|
|
242
|
+
const t = Array.isArray(e) ? e : e ? [ e ] : [];
|
|
243
|
+
return t.flatMap(e => e.split(",")).map(e => e.trim()).filter(Boolean);
|
|
244
|
+
}(e);
|
|
245
|
+
if (!t.length) {
|
|
246
|
+
return null;
|
|
247
|
+
}
|
|
248
|
+
return new RegExp(`^(?:${t.map(eventPatternToRegex).join("|")})$`);
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
function matchesEventFilter(e, t) {
|
|
252
|
+
return !t || t.test(e);
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
function formatSessionSelector(e) {
|
|
256
|
+
return `${e.pid} (${e.command})`;
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
function eventPatternToRegex(e) {
|
|
260
|
+
return (e.includes(":") || e.includes("*") ? e : `${e}:*`).split("*").map(escapeRegex).join(".*");
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
function escapeRegex(e) {
|
|
264
|
+
return e.replace(/[|\\{}()[\]^$+?.]/g, "\\$&");
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
function normalizeUnixTimestamp(e) {
|
|
268
|
+
return e < 1e10 ? 1e3 * e : e;
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
function durationUnitToMs(e) {
|
|
272
|
+
if ("ms" === e || "msec" === e || "msecs" === e || "millisecond" === e || "milliseconds" === e) {
|
|
273
|
+
return 1;
|
|
274
|
+
}
|
|
275
|
+
if ("s" === e || "sec" === e || "secs" === e || "second" === e || "seconds" === e) {
|
|
276
|
+
return 1e3;
|
|
277
|
+
}
|
|
278
|
+
if ("m" === e || "min" === e || "mins" === e || "minute" === e || "minutes" === e) {
|
|
279
|
+
return 6e4;
|
|
280
|
+
}
|
|
281
|
+
if ("h" === e || "hr" === e || "hrs" === e || "hour" === e || "hours" === e) {
|
|
282
|
+
return 36e5;
|
|
283
|
+
}
|
|
284
|
+
return 1;
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
function readLiveLine(e, t) {
|
|
288
|
+
if (!t) {
|
|
289
|
+
return e.next();
|
|
290
|
+
}
|
|
291
|
+
if (t.aborted) {
|
|
292
|
+
return Promise.resolve(null);
|
|
293
|
+
}
|
|
294
|
+
return new Promise(n => {
|
|
295
|
+
const onAbort = () => n(null);
|
|
296
|
+
t.addEventListener("abort", onAbort, {
|
|
297
|
+
once: !0
|
|
298
|
+
});
|
|
299
|
+
e.next().then(e => {
|
|
300
|
+
t.removeEventListener("abort", onAbort);
|
|
301
|
+
n(t.aborted ? null : e);
|
|
302
|
+
});
|
|
303
|
+
});
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
function resetAbortTimer(e, t, n) {
|
|
307
|
+
clearTimeout(e);
|
|
308
|
+
return setAbortTimer(t, n);
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
function setAbortTimer(e, t) {
|
|
312
|
+
const n = setTimeout(() => e.abort(), t);
|
|
313
|
+
n.unref?.();
|
|
314
|
+
return n;
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
function sessionSearchValues(e) {
|
|
318
|
+
return [ e.id, String(e.pid), e.sessionDir, e.cwd, e.command, e.origin?.cwd, e.origin?.argv.join(" "), e.origin?.execPath, e.origin?.env?.npmLifecycleEvent, e.origin?.env?.npmPackageName ].filter(e => !!e);
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
function tryConnect(e, t) {
|
|
322
|
+
return new Promise(n => {
|
|
323
|
+
const o = r.connect(e);
|
|
324
|
+
const cleanup = () => {
|
|
325
|
+
o.off("connect", onConnect);
|
|
326
|
+
o.off("error", onError);
|
|
327
|
+
t?.removeEventListener("abort", onAbort);
|
|
328
|
+
};
|
|
329
|
+
const onConnect = () => {
|
|
330
|
+
cleanup();
|
|
331
|
+
n(o);
|
|
332
|
+
};
|
|
333
|
+
const onError = () => {
|
|
334
|
+
cleanup();
|
|
335
|
+
o.destroy();
|
|
336
|
+
n(null);
|
|
337
|
+
};
|
|
338
|
+
const onAbort = () => {
|
|
339
|
+
cleanup();
|
|
340
|
+
o.destroy();
|
|
341
|
+
n(null);
|
|
342
|
+
};
|
|
343
|
+
o.once("connect", onConnect);
|
|
344
|
+
o.once("error", onError);
|
|
345
|
+
t?.addEventListener("abort", onAbort, {
|
|
346
|
+
once: !0
|
|
347
|
+
});
|
|
348
|
+
});
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
exports.DEFAULT_SEGMENTS = 3;
|
|
352
|
+
|
|
353
|
+
exports.DEFAULT_SEGMENT_SIZE = 524288;
|
|
354
|
+
|
|
355
|
+
exports.EVENT_LOG_FORMAT_VERSION = 1;
|
|
356
|
+
|
|
357
|
+
exports.EVENT_LOG_STATE_VERSION = 1;
|
|
358
|
+
|
|
359
|
+
exports.INTERNAL_IPC_ENV = "__eventLogIpc";
|
|
360
|
+
|
|
361
|
+
exports.INTERNAL_PROCESS_ORIGIN_ENV = "__eventLogProcessOrigin";
|
|
362
|
+
|
|
363
|
+
exports.LOG_EVENTS_ENV = "LOG_EVENTS";
|
|
364
|
+
|
|
365
|
+
exports.SESSION_FILES = l;
|
|
366
|
+
|
|
367
|
+
exports.cleanStaleSessionsSync = cleanStaleSessionsSync;
|
|
368
|
+
|
|
369
|
+
exports.compileEventFilter = compileEventFilter;
|
|
370
|
+
|
|
371
|
+
exports.getSessionBaseDir = getSessionBaseDir;
|
|
372
|
+
|
|
373
|
+
exports.listSessions = listSessions;
|
|
374
|
+
|
|
375
|
+
exports.matchesEventFilter = matchesEventFilter;
|
|
376
|
+
|
|
377
|
+
exports.parseEventLine = parseEventLine;
|
|
378
|
+
|
|
379
|
+
exports.parseSince = parseSince;
|
|
380
|
+
|
|
381
|
+
exports.redirectConsoleForFd = function redirectConsoleForFd(t) {
|
|
382
|
+
if (1 === t) {
|
|
383
|
+
const t = process.stderr;
|
|
384
|
+
Object.defineProperty(process, "stdout", {
|
|
385
|
+
get: () => t
|
|
386
|
+
});
|
|
387
|
+
globalThis.console = new e.Console(t, t);
|
|
388
|
+
} else if (2 === t) {
|
|
389
|
+
const t = process.stdout;
|
|
390
|
+
Object.defineProperty(process, "stderr", {
|
|
391
|
+
get: () => t
|
|
392
|
+
});
|
|
393
|
+
globalThis.console = new e.Console(t, t);
|
|
394
|
+
}
|
|
395
|
+
};
|
|
396
|
+
|
|
397
|
+
exports.redirectConsoleToStderr = function redirectConsoleToStderr() {
|
|
398
|
+
globalThis.console = new e.Console(process.stderr, process.stderr);
|
|
399
|
+
};
|
|
400
|
+
|
|
401
|
+
exports.resolveSession = async function resolveSession(e) {
|
|
402
|
+
const t = await listSessions({
|
|
403
|
+
selector: e
|
|
404
|
+
});
|
|
405
|
+
const n = 1 === t.length ? t[0] : null;
|
|
406
|
+
if (!n) {
|
|
407
|
+
throw new Error(null != e ? t.length ? `Ambiguous event-log session "${e}"; specify one of: ${t.map(formatSessionSelector).join(", ")}` : `No event-log session matching "${e}"` : t.length ? `Ambiguous event-log session; specify one of: ${t.map(formatSessionSelector).join(", ")}` : "No event-log sessions found");
|
|
408
|
+
}
|
|
409
|
+
return n;
|
|
410
|
+
};
|
|
411
|
+
|
|
412
|
+
exports.tap = async function* tap(e, r = {}) {
|
|
413
|
+
const i = !0 === r.follow;
|
|
414
|
+
const s = parseSince(r.since);
|
|
415
|
+
const c = compileEventFilter(r.filter);
|
|
416
|
+
const a = function createTapAbortController(e, t) {
|
|
417
|
+
if (!t || null == e.timeout && null == e.idleTimeout) {
|
|
418
|
+
return;
|
|
419
|
+
}
|
|
420
|
+
const n = new AbortController;
|
|
421
|
+
e.signal?.addEventListener("abort", () => n.abort(), {
|
|
422
|
+
once: !0
|
|
423
|
+
});
|
|
424
|
+
if (null != e.timeout) {
|
|
425
|
+
setAbortTimer(n, e.timeout);
|
|
426
|
+
}
|
|
427
|
+
return n;
|
|
428
|
+
}(r, i);
|
|
429
|
+
const u = a?.signal ?? r.signal;
|
|
430
|
+
const f = i ? await async function connectLive(e, t) {
|
|
431
|
+
const r = n.join(e, l.liveSocket);
|
|
432
|
+
const i = await async function connectWithRetry(e, t) {
|
|
433
|
+
for (let n = 0; n < 20 && !t?.aborted; n++) {
|
|
434
|
+
const n = await tryConnect(e, t);
|
|
435
|
+
if (n) {
|
|
436
|
+
return n;
|
|
437
|
+
}
|
|
438
|
+
await new Promise(e => setTimeout(e, 50));
|
|
439
|
+
}
|
|
440
|
+
return null;
|
|
441
|
+
}(r, t);
|
|
442
|
+
if (!i) {
|
|
443
|
+
return;
|
|
444
|
+
}
|
|
445
|
+
const s = o.createInterface({
|
|
446
|
+
input: i
|
|
447
|
+
});
|
|
448
|
+
const c = [];
|
|
449
|
+
const a = [];
|
|
450
|
+
let u = !1;
|
|
451
|
+
const push = e => {
|
|
452
|
+
const t = a.shift();
|
|
453
|
+
if (t) {
|
|
454
|
+
t(e);
|
|
455
|
+
} else if (null != e) {
|
|
456
|
+
c.push(e);
|
|
457
|
+
}
|
|
458
|
+
};
|
|
459
|
+
s.on("line", e => push(e));
|
|
460
|
+
s.on("close", () => {
|
|
461
|
+
u = !0;
|
|
462
|
+
push(null);
|
|
463
|
+
});
|
|
464
|
+
i.on("error", () => {
|
|
465
|
+
u = !0;
|
|
466
|
+
push(null);
|
|
467
|
+
});
|
|
468
|
+
t?.addEventListener("abort", () => i.destroy(), {
|
|
469
|
+
once: !0
|
|
470
|
+
});
|
|
471
|
+
return {
|
|
472
|
+
buffer: c,
|
|
473
|
+
next() {
|
|
474
|
+
if (c.length) {
|
|
475
|
+
return Promise.resolve(c.shift());
|
|
476
|
+
}
|
|
477
|
+
if (u) {
|
|
478
|
+
return Promise.resolve(null);
|
|
479
|
+
}
|
|
480
|
+
return new Promise(e => a.push(e));
|
|
481
|
+
}
|
|
482
|
+
};
|
|
483
|
+
}(e, u) : void 0;
|
|
484
|
+
const m = await async function openHistoryFiles(e) {
|
|
485
|
+
const r = readMetaSync(e)?.maxSegments ?? 3;
|
|
486
|
+
const o = await Promise.all(Array.from({
|
|
487
|
+
length: r
|
|
488
|
+
}, (r, o) => t.open(n.join(e, `${o}.jsonl`), "r").catch(() => null)));
|
|
489
|
+
return o.filter(e => null != e).reverse();
|
|
490
|
+
}(e);
|
|
491
|
+
let d;
|
|
492
|
+
try {
|
|
493
|
+
for (const e of m) {
|
|
494
|
+
for await (const t of readLines(e)) {
|
|
495
|
+
const e = parseEventLine(t, r, c, s);
|
|
496
|
+
if (e) {
|
|
497
|
+
yield e;
|
|
498
|
+
}
|
|
499
|
+
}
|
|
500
|
+
}
|
|
501
|
+
} finally {
|
|
502
|
+
await Promise.all(m.map(e => e.close().catch(() => {})));
|
|
503
|
+
}
|
|
504
|
+
if (!f) {
|
|
505
|
+
return;
|
|
506
|
+
}
|
|
507
|
+
if (null != r.idleTimeout && a) {
|
|
508
|
+
d = setAbortTimer(a, r.idleTimeout);
|
|
509
|
+
}
|
|
510
|
+
for (const e of f.buffer.splice(0)) {
|
|
511
|
+
const t = parseEventLine(e, r, c, s);
|
|
512
|
+
if (t) {
|
|
513
|
+
if (d) {
|
|
514
|
+
d = resetAbortTimer(d, a, r.idleTimeout);
|
|
515
|
+
}
|
|
516
|
+
yield t;
|
|
517
|
+
}
|
|
518
|
+
}
|
|
519
|
+
while (!u?.aborted) {
|
|
520
|
+
const e = await readLiveLine(f, u);
|
|
521
|
+
if (null == e) {
|
|
522
|
+
break;
|
|
523
|
+
}
|
|
524
|
+
if (d) {
|
|
525
|
+
d = resetAbortTimer(d, a, r.idleTimeout);
|
|
526
|
+
}
|
|
527
|
+
const t = parseEventLine(e, r, c, s);
|
|
528
|
+
if (t) {
|
|
529
|
+
yield t;
|
|
530
|
+
}
|
|
531
|
+
}
|
|
532
|
+
if (d) {
|
|
533
|
+
clearTimeout(d);
|
|
534
|
+
}
|
|
535
|
+
};
|
|
536
|
+
//# sourceMappingURL=tap-chunk.js.map
|