@logbrew/sdk 0.1.0
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 +225 -0
- package/examples/index.mjs +123 -0
- package/examples/package.json +14 -0
- package/examples/readme-example.cjs +59 -0
- package/examples/readme-example.mjs +51 -0
- package/examples/real-user-smoke.cjs +59 -0
- package/examples/real-user-smoke.mjs +51 -0
- package/index.cjs +1099 -0
- package/index.d.cts +307 -0
- package/index.d.ts +307 -0
- package/index.js +20 -0
- package/package.json +49 -0
package/README.md
ADDED
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
# @logbrew/sdk
|
|
2
|
+
|
|
3
|
+
Public JavaScript SDK for creating LogBrew event batches, validating them locally, and flushing them through a transport.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @logbrew/sdk
|
|
9
|
+
pnpm add @logbrew/sdk
|
|
10
|
+
npm --prefix node_modules/@logbrew/sdk/examples run
|
|
11
|
+
npm --prefix node_modules/@logbrew/sdk/examples run list
|
|
12
|
+
npm --prefix node_modules/@logbrew/sdk/examples run help
|
|
13
|
+
npm --prefix node_modules/@logbrew/sdk/examples run readme-example
|
|
14
|
+
npm --prefix node_modules/@logbrew/sdk/examples run readme-example:cjs
|
|
15
|
+
npm --prefix node_modules/@logbrew/sdk/examples run real-user-smoke
|
|
16
|
+
npm --prefix node_modules/@logbrew/sdk/examples run real-user-smoke:cjs
|
|
17
|
+
pnpm --dir node_modules/@logbrew/sdk/examples run
|
|
18
|
+
pnpm --dir node_modules/@logbrew/sdk/examples run list
|
|
19
|
+
pnpm --dir node_modules/@logbrew/sdk/examples run help
|
|
20
|
+
pnpm --dir node_modules/@logbrew/sdk/examples run readme-example
|
|
21
|
+
pnpm --dir node_modules/@logbrew/sdk/examples run readme-example:cjs
|
|
22
|
+
pnpm --dir node_modules/@logbrew/sdk/examples run real-user-smoke
|
|
23
|
+
pnpm --dir node_modules/@logbrew/sdk/examples run real-user-smoke:cjs
|
|
24
|
+
node node_modules/@logbrew/sdk/examples/index.mjs --help
|
|
25
|
+
node node_modules/@logbrew/sdk/examples/index.mjs --list
|
|
26
|
+
node node_modules/@logbrew/sdk/examples/index.mjs readme-example
|
|
27
|
+
node node_modules/@logbrew/sdk/examples/index.mjs readme-example:cjs
|
|
28
|
+
node node_modules/@logbrew/sdk/examples/index.mjs real-user-smoke
|
|
29
|
+
node node_modules/@logbrew/sdk/examples/index.mjs
|
|
30
|
+
node node_modules/@logbrew/sdk/examples/index.mjs real-user-smoke:cjs
|
|
31
|
+
node node_modules/@logbrew/sdk/examples/readme-example.mjs
|
|
32
|
+
node node_modules/@logbrew/sdk/examples/readme-example.cjs
|
|
33
|
+
node node_modules/@logbrew/sdk/examples/real-user-smoke.mjs
|
|
34
|
+
node node_modules/@logbrew/sdk/examples/real-user-smoke.cjs
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
The package supports both ESM `import` and CommonJS `require`.
|
|
38
|
+
The shipped package also includes `.d.ts` and `.d.cts` declarations so ESM and CommonJS TypeScript consumers can install it directly without a separate build step.
|
|
39
|
+
The packed tarball and installed package both ship `README.md`, package metadata, an explicit ESM/CommonJS `exports` map, runnable `examples/readme-example.mjs`, `examples/readme-example.cjs`, `examples/real-user-smoke.mjs`, and `examples/real-user-smoke.cjs` files, a tiny `examples/package.json` helper surface, a packaged `examples/index.mjs` launcher, declaration comments in `index.d.ts`, and the CommonJS `index.d.cts` declaration path that TypeScript-aware tools can inspect. Those packed and installed README, example, and declaration surfaces should still include the normal `npm` and `pnpm` install commands, the fake `LOGBREW_API_KEY` placeholder guidance, the `previewJson()` usage note, the optional `parseTraceparent()`, `createTraceparent()`, `spanAttributesFromTraceparent()`, `installLogBrewConsoleCapture()`, `createLogBrewPinoDestination()`, and `createLogBrewWinstonTransport()` guidance, the helper discovery commands, helper runtime commands, and launcher commands shown above, and the typed API docs for shapes like `ReleaseAttributes`, `SpanAttributes`, `TraceparentContext`, `TraceparentInput`, `TraceparentSpanInput`, `Event`, `ConsoleCaptureConfig`, `ConsoleCaptureHandle`, `PinoDestinationConfig`, `PinoDestinationHandle`, `PinoLogRecord`, `WinstonTransportConfig`, `WinstonTransportHandle`, `WinstonLogInfo`, `SdkError`, `TransportError`, `TransportResponse`, `alwaysAccept()`, `lastBody()`, `pendingEvents()`, `flush()`, and `shutdown()`. Real installs should also start from a package-manager-native app bootstrap, using `npm init -y` on the npm path and `pnpm init` on the pnpm path, then rewrite the temp app `package.json` dependencies plus the lockfiles so they point back to the packed `.tgz` with the expected file target and integrity metadata, while npm’s own `npm pack --dry-run --json` and `npm pack --json` outputs still report the expected tarball name, integrity, shasum, and file list, and those generated lockfiles should retain that same tarball integrity value before recreating the install through `npm ci` and `pnpm install --frozen-lockfile`. The temp app should also survive a package-manager-native removal step, with `npm uninstall @logbrew/sdk` and `pnpm remove @logbrew/sdk` dropping the SDK from `package.json`, the top-level installed-package list, and `node_modules` before the tarball is added back. The consumer graph should also stay explicit in package-manager-native output, with plain `npm ls @logbrew/sdk` and `pnpm ls @logbrew/sdk` showing the direct installed SDK tree a user reads in the terminal, `npm explain @logbrew/sdk` showing the direct root-project edge, `pnpm why @logbrew/sdk` showing the temp app dependency relationship, plain `npm list --depth=0` and `pnpm list --depth=0` showing the top-level installed dependency summary, and `npm list --json --depth=0` plus `pnpm list --json --depth=0` still listing the temp app and direct installed dependencies, while small installed-user script entries in the temp app still exercise the shipped package through `npm run` and `pnpm run`, including a TypeScript typecheck script that compiles both an ESM `.ts` consumer and a CommonJS `.cts` consumer plus a script that mirrors the published README example before and after reinstall. The installed package should also let a consumer run the shipped README-style and stronger happy-path ESM and CommonJS example files directly from `node_modules/@logbrew/sdk/examples/`, and it now ships a small Node launcher at `node node_modules/@logbrew/sdk/examples/index.mjs` so users can discover packaged examples through `--help`, list them through `--list`, run the default no-argument `real-user-smoke` path, or select named examples like `readme-example` and `real-user-smoke` without going through package-manager scripts. The helper commands in `node_modules/@logbrew/sdk/examples/package.json` should still be discoverable enough that plain `npm --prefix node_modules/@logbrew/sdk/examples run` and `pnpm --dir node_modules/@logbrew/sdk/examples run` list the available example entrypoints before users run `npm --prefix node_modules/@logbrew/sdk/examples run help`, where that help output should print copy-pasteable installed-user commands for both npm and pnpm across the README and `real-user-smoke` default, ESM, and CommonJS example paths, including `npm --prefix node_modules/@logbrew/sdk/examples run readme-example` or `pnpm --dir node_modules/@logbrew/sdk/examples run readme-example`, `npm --prefix node_modules/@logbrew/sdk/examples run readme-example:esm` or `pnpm --dir node_modules/@logbrew/sdk/examples run readme-example:esm`, `npm --prefix node_modules/@logbrew/sdk/examples run readme-example:cjs` or `pnpm --dir node_modules/@logbrew/sdk/examples run readme-example:cjs`, `npm --prefix node_modules/@logbrew/sdk/examples run real-user-smoke` or `pnpm --dir node_modules/@logbrew/sdk/examples run real-user-smoke`, `npm --prefix node_modules/@logbrew/sdk/examples run real-user-smoke:esm` or `pnpm --dir node_modules/@logbrew/sdk/examples run real-user-smoke:esm`, and `npm --prefix node_modules/@logbrew/sdk/examples run real-user-smoke:cjs` or `pnpm --dir node_modules/@logbrew/sdk/examples run real-user-smoke:cjs`, while the launcher surface itself should still reveal `node node_modules/@logbrew/sdk/examples/index.mjs --help`, `node node_modules/@logbrew/sdk/examples/index.mjs --list`, `node node_modules/@logbrew/sdk/examples/index.mjs`, `node node_modules/@logbrew/sdk/examples/index.mjs readme-example`, `node node_modules/@logbrew/sdk/examples/index.mjs real-user-smoke`, and `node node_modules/@logbrew/sdk/examples/index.mjs real-user-smoke:cjs`.
|
|
40
|
+
|
|
41
|
+
## Example
|
|
42
|
+
|
|
43
|
+
```js
|
|
44
|
+
import { LogBrewClient, RecordingTransport } from "@logbrew/sdk";
|
|
45
|
+
|
|
46
|
+
const client = LogBrewClient.create({
|
|
47
|
+
apiKey: "LOGBREW_API_KEY",
|
|
48
|
+
sdkName: "logbrew-js",
|
|
49
|
+
sdkVersion: "0.1.0"
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
client.release("evt_release_001", "2026-06-02T10:00:00Z", {
|
|
53
|
+
version: "1.2.3",
|
|
54
|
+
commit: "abc123def456",
|
|
55
|
+
notes: "Public release marker"
|
|
56
|
+
});
|
|
57
|
+
client.environment("evt_environment_001", "2026-06-02T10:00:01Z", {
|
|
58
|
+
name: "production",
|
|
59
|
+
region: "global"
|
|
60
|
+
});
|
|
61
|
+
client.issue("evt_issue_001", "2026-06-02T10:00:02Z", {
|
|
62
|
+
title: "Checkout timeout",
|
|
63
|
+
level: "error",
|
|
64
|
+
message: "Request timed out after retry budget"
|
|
65
|
+
});
|
|
66
|
+
client.log("evt_log_001", "2026-06-02T10:00:03Z", {
|
|
67
|
+
message: "worker started",
|
|
68
|
+
level: "info",
|
|
69
|
+
logger: "job-runner"
|
|
70
|
+
});
|
|
71
|
+
client.span("evt_span_001", "2026-06-02T10:00:04Z", {
|
|
72
|
+
name: "GET /health",
|
|
73
|
+
traceId: "trace_001",
|
|
74
|
+
spanId: "span_001",
|
|
75
|
+
status: "ok",
|
|
76
|
+
durationMs: 12.5
|
|
77
|
+
});
|
|
78
|
+
client.action("evt_action_001", "2026-06-02T10:00:05Z", {
|
|
79
|
+
name: "deploy",
|
|
80
|
+
status: "success"
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
console.log(client.previewJson());
|
|
84
|
+
|
|
85
|
+
const transport = RecordingTransport.alwaysAccept();
|
|
86
|
+
const response = await client.shutdown(transport);
|
|
87
|
+
console.error(JSON.stringify({ ok: true, status: response.statusCode, attempts: response.attempts, events: 6 }));
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
## W3C Trace Context
|
|
91
|
+
|
|
92
|
+
Use `parseTraceparent()`, `createTraceparent()`, and `spanAttributesFromTraceparent()` when a JavaScript service needs to continue trace context from OpenTelemetry-compatible services or pass a W3C `traceparent` value downstream.
|
|
93
|
+
|
|
94
|
+
```js
|
|
95
|
+
import {
|
|
96
|
+
createTraceparent,
|
|
97
|
+
LogBrewClient,
|
|
98
|
+
RecordingTransport,
|
|
99
|
+
spanAttributesFromTraceparent
|
|
100
|
+
} from "@logbrew/sdk";
|
|
101
|
+
|
|
102
|
+
const client = LogBrewClient.create({
|
|
103
|
+
apiKey: "LOGBREW_API_KEY",
|
|
104
|
+
sdkName: "checkout-api",
|
|
105
|
+
sdkVersion: "1.0.0"
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
const incomingTraceparent = "00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01";
|
|
109
|
+
const span = spanAttributesFromTraceparent(incomingTraceparent, {
|
|
110
|
+
name: "POST /checkout",
|
|
111
|
+
spanId: "b7ad6b7169203331",
|
|
112
|
+
status: "ok",
|
|
113
|
+
durationMs: 18.4,
|
|
114
|
+
metadata: { service: "checkout" }
|
|
115
|
+
});
|
|
116
|
+
client.span("evt_checkout_span", "2026-06-02T10:00:04Z", span);
|
|
117
|
+
|
|
118
|
+
const downstreamTraceparent = createTraceparent({
|
|
119
|
+
traceId: span.traceId,
|
|
120
|
+
spanId: span.spanId,
|
|
121
|
+
traceFlags: "01"
|
|
122
|
+
});
|
|
123
|
+
await fetch("https://example.invalid/payments", {
|
|
124
|
+
headers: { traceparent: downstreamTraceparent }
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
await client.flush(RecordingTransport.alwaysAccept());
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
The helpers validate the W3C `version-traceId-parentSpanId-traceFlags` shape, reject all-zero trace/span ids, normalize valid ids to lowercase, expose the sampled flag from `traceFlags`, and keep span metadata primitive-only. They do not install OpenTelemetry or patch HTTP clients; use them when you need explicit interop in code you own.
|
|
131
|
+
|
|
132
|
+
## Console Capture
|
|
133
|
+
|
|
134
|
+
If an app already uses `console.info()`, `console.warn()`, or `console.error()`, install explicit capture on the console object you own:
|
|
135
|
+
|
|
136
|
+
```js
|
|
137
|
+
import { installLogBrewConsoleCapture, LogBrewClient, RecordingTransport } from "@logbrew/sdk";
|
|
138
|
+
|
|
139
|
+
const client = LogBrewClient.create({
|
|
140
|
+
apiKey: "LOGBREW_API_KEY",
|
|
141
|
+
sdkName: "checkout-web",
|
|
142
|
+
sdkVersion: "1.0.0"
|
|
143
|
+
});
|
|
144
|
+
const transport = RecordingTransport.alwaysAccept();
|
|
145
|
+
const capture = installLogBrewConsoleCapture({
|
|
146
|
+
client,
|
|
147
|
+
console,
|
|
148
|
+
transport,
|
|
149
|
+
levels: ["warn", "error"],
|
|
150
|
+
logger: "console",
|
|
151
|
+
metadata: { service: "checkout" }
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
console.warn("cart queued", { orderId: 42 });
|
|
155
|
+
console.error("checkout failed", new Error("database unavailable"));
|
|
156
|
+
await capture.flush();
|
|
157
|
+
capture.uninstall();
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
Console capture is opt-in. It calls the original console method first, captures only the configured levels, returns `uninstall()` so apps can stop capture cleanly, and omits error stack text unless `includeErrorStack: true` is set.
|
|
161
|
+
|
|
162
|
+
## Pino Destination
|
|
163
|
+
|
|
164
|
+
If a Node app already uses Pino, pass the dependency-free LogBrew destination as Pino's output stream:
|
|
165
|
+
|
|
166
|
+
```js
|
|
167
|
+
import pino from "pino";
|
|
168
|
+
import { createLogBrewPinoDestination, LogBrewClient, RecordingTransport } from "@logbrew/sdk";
|
|
169
|
+
|
|
170
|
+
const client = LogBrewClient.create({
|
|
171
|
+
apiKey: "LOGBREW_API_KEY",
|
|
172
|
+
sdkName: "checkout-api",
|
|
173
|
+
sdkVersion: "1.0.0"
|
|
174
|
+
});
|
|
175
|
+
const transport = RecordingTransport.alwaysAccept();
|
|
176
|
+
const destination = createLogBrewPinoDestination({
|
|
177
|
+
client,
|
|
178
|
+
transport,
|
|
179
|
+
logger: "pino",
|
|
180
|
+
metadata: { service: "checkout" }
|
|
181
|
+
});
|
|
182
|
+
|
|
183
|
+
const logger = pino(destination);
|
|
184
|
+
logger.warn({ orderId: 42 }, "checkout slow");
|
|
185
|
+
logger.error(new Error("payment failed"), "checkout failed");
|
|
186
|
+
await destination.flush();
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
The Pino adapter reads JSON log lines, maps `trace`/`debug`/`info`/`warn`/`error`/`fatal` into LogBrew levels, captures primitive Pino fields as `context.*`, captures serialized error name/message, skips noisy runtime defaults, and omits stack text unless `includeErrorStack: true` is set. It does not patch Pino or replace application logger ownership.
|
|
190
|
+
|
|
191
|
+
## Winston Transport
|
|
192
|
+
|
|
193
|
+
If a Node app already uses Winston, add the dependency-free LogBrew transport to the app-owned logger:
|
|
194
|
+
|
|
195
|
+
```js
|
|
196
|
+
import winston from "winston";
|
|
197
|
+
import { createLogBrewWinstonTransport, LogBrewClient, RecordingTransport } from "@logbrew/sdk";
|
|
198
|
+
|
|
199
|
+
const client = LogBrewClient.create({
|
|
200
|
+
apiKey: "LOGBREW_API_KEY",
|
|
201
|
+
sdkName: "checkout-api",
|
|
202
|
+
sdkVersion: "1.0.0"
|
|
203
|
+
});
|
|
204
|
+
const transport = RecordingTransport.alwaysAccept();
|
|
205
|
+
const logbrewTransport = createLogBrewWinstonTransport({
|
|
206
|
+
client,
|
|
207
|
+
transport,
|
|
208
|
+
logger: "winston",
|
|
209
|
+
metadata: { service: "checkout" }
|
|
210
|
+
});
|
|
211
|
+
|
|
212
|
+
const logger = winston.createLogger({
|
|
213
|
+
level: "info",
|
|
214
|
+
format: winston.format.combine(winston.format.errors({ stack: true }), winston.format.timestamp()),
|
|
215
|
+
transports: [logbrewTransport]
|
|
216
|
+
});
|
|
217
|
+
|
|
218
|
+
logger.warn("checkout slow", { orderId: 42 });
|
|
219
|
+
logger.error(new Error("payment failed"));
|
|
220
|
+
await logbrewTransport.flush();
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
The Winston adapter receives Winston `info` objects, maps `debug`/`silly` to `debug`, `warn` to `warning`, `error`/`fatal` to `error`, and other common Winston levels to `info`. It captures primitive info fields as `context.*`, captures nested `err`/`error` objects or formatted error stack name/message, omits stack text unless `includeErrorStack: true` is set, and exposes `onError` for capture failures. It does not mutate Winston globals or replace the app's logger.
|
|
224
|
+
|
|
225
|
+
Use a clearly fake placeholder like `LOGBREW_API_KEY` in local examples and tests. Call `flush` or `shutdown` to send queued events through a transport, and use `previewJson()` when you want a stable local JSON preview without sending anything.
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import process from "node:process";
|
|
2
|
+
|
|
3
|
+
const repoPrefix = "cd js/logbrew-js";
|
|
4
|
+
const repoExamplesPrefix = "cd js/logbrew-js/examples";
|
|
5
|
+
const repoNpmHelperPrefix = "npm run";
|
|
6
|
+
const repoPnpmHelperPrefix = "pnpm run";
|
|
7
|
+
const installedHelperPrefix = "npm --prefix node_modules/@logbrew/sdk/examples run";
|
|
8
|
+
const installedPnpmHelperPrefix = "pnpm --dir node_modules/@logbrew/sdk/examples run";
|
|
9
|
+
const installedLauncherPrefix = "node node_modules/@logbrew/sdk/examples/index.mjs";
|
|
10
|
+
const repoLauncherPrefix = "node examples/index.mjs";
|
|
11
|
+
|
|
12
|
+
const examples = {
|
|
13
|
+
"readme-example": new URL("./readme-example.mjs", import.meta.url),
|
|
14
|
+
"readme-example:esm": new URL("./readme-example.mjs", import.meta.url),
|
|
15
|
+
"readme-example:cjs": new URL("./readme-example.cjs", import.meta.url),
|
|
16
|
+
"real-user-smoke": new URL("./real-user-smoke.mjs", import.meta.url),
|
|
17
|
+
"real-user-smoke:esm": new URL("./real-user-smoke.mjs", import.meta.url),
|
|
18
|
+
"real-user-smoke:cjs": new URL("./real-user-smoke.cjs", import.meta.url)
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
function isInstalledPackageContext() {
|
|
22
|
+
return import.meta.url.includes("/node_modules/@logbrew/sdk/examples/");
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function exampleCommands() {
|
|
26
|
+
if (!isInstalledPackageContext()) {
|
|
27
|
+
return {
|
|
28
|
+
"readme-example": `${repoPrefix} && ${repoLauncherPrefix} readme-example`,
|
|
29
|
+
"readme-example:esm": `${repoPrefix} && ${repoLauncherPrefix} readme-example:esm`,
|
|
30
|
+
"readme-example:cjs": `${repoPrefix} && ${repoLauncherPrefix} readme-example:cjs`,
|
|
31
|
+
"real-user-smoke": `${repoPrefix} && ${repoLauncherPrefix} real-user-smoke`,
|
|
32
|
+
"real-user-smoke:esm": `${repoPrefix} && ${repoLauncherPrefix} real-user-smoke:esm`,
|
|
33
|
+
"real-user-smoke:cjs": `${repoPrefix} && ${repoLauncherPrefix} real-user-smoke:cjs`,
|
|
34
|
+
"default (real-user-smoke)": `${repoPrefix} && ${repoLauncherPrefix}`
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
return {
|
|
39
|
+
"readme-example": `${installedLauncherPrefix} readme-example`,
|
|
40
|
+
"readme-example:esm": `${installedLauncherPrefix} readme-example:esm`,
|
|
41
|
+
"readme-example:cjs": `${installedLauncherPrefix} readme-example:cjs`,
|
|
42
|
+
"real-user-smoke": `${installedLauncherPrefix} real-user-smoke`,
|
|
43
|
+
"real-user-smoke:esm": `${installedLauncherPrefix} real-user-smoke:esm`,
|
|
44
|
+
"real-user-smoke:cjs": `${installedLauncherPrefix} real-user-smoke:cjs`,
|
|
45
|
+
"default (real-user-smoke)": installedLauncherPrefix
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function helperCommands() {
|
|
50
|
+
if (!isInstalledPackageContext()) {
|
|
51
|
+
return {
|
|
52
|
+
"readme-example": `${repoExamplesPrefix} && ${repoNpmHelperPrefix} readme-example | ${repoExamplesPrefix} && ${repoPnpmHelperPrefix} readme-example`,
|
|
53
|
+
"readme-example:esm": `${repoExamplesPrefix} && ${repoNpmHelperPrefix} readme-example:esm | ${repoExamplesPrefix} && ${repoPnpmHelperPrefix} readme-example:esm`,
|
|
54
|
+
"readme-example:cjs": `${repoExamplesPrefix} && ${repoNpmHelperPrefix} readme-example:cjs | ${repoExamplesPrefix} && ${repoPnpmHelperPrefix} readme-example:cjs`,
|
|
55
|
+
"real-user-smoke": `${repoExamplesPrefix} && ${repoNpmHelperPrefix} real-user-smoke | ${repoExamplesPrefix} && ${repoPnpmHelperPrefix} real-user-smoke`,
|
|
56
|
+
"real-user-smoke:esm": `${repoExamplesPrefix} && ${repoNpmHelperPrefix} real-user-smoke:esm | ${repoExamplesPrefix} && ${repoPnpmHelperPrefix} real-user-smoke:esm`,
|
|
57
|
+
"real-user-smoke:cjs": `${repoExamplesPrefix} && ${repoNpmHelperPrefix} real-user-smoke:cjs | ${repoExamplesPrefix} && ${repoPnpmHelperPrefix} real-user-smoke:cjs`
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
return {
|
|
62
|
+
"readme-example": `${installedHelperPrefix} readme-example | ${installedPnpmHelperPrefix} readme-example`,
|
|
63
|
+
"readme-example:esm": `${installedHelperPrefix} readme-example:esm | ${installedPnpmHelperPrefix} readme-example:esm`,
|
|
64
|
+
"readme-example:cjs": `${installedHelperPrefix} readme-example:cjs | ${installedPnpmHelperPrefix} readme-example:cjs`,
|
|
65
|
+
"real-user-smoke": `${installedHelperPrefix} real-user-smoke | ${installedPnpmHelperPrefix} real-user-smoke`,
|
|
66
|
+
"real-user-smoke:esm": `${installedHelperPrefix} real-user-smoke:esm | ${installedPnpmHelperPrefix} real-user-smoke:esm`,
|
|
67
|
+
"real-user-smoke:cjs": `${installedHelperPrefix} real-user-smoke:cjs | ${installedPnpmHelperPrefix} real-user-smoke:cjs`
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function printList() {
|
|
72
|
+
for (const [name, command] of Object.entries(exampleCommands())) {
|
|
73
|
+
console.log(`${name} -> ${command}`);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function printHelp() {
|
|
78
|
+
if (isInstalledPackageContext()) {
|
|
79
|
+
console.log("Usage: node node_modules/@logbrew/sdk/examples/index.mjs [--list] [example]");
|
|
80
|
+
console.log("Run the packaged LogBrew SDK JavaScript examples that ship with the installed package.");
|
|
81
|
+
} else {
|
|
82
|
+
console.log("Usage: node examples/index.mjs [--list] [example]");
|
|
83
|
+
console.log("Run the repo-checkout LogBrew SDK JavaScript examples before install.");
|
|
84
|
+
}
|
|
85
|
+
console.log("");
|
|
86
|
+
console.log("Launcher commands:");
|
|
87
|
+
for (const [name, command] of Object.entries(exampleCommands())) {
|
|
88
|
+
console.log(` ${name} -> ${command}`);
|
|
89
|
+
}
|
|
90
|
+
console.log("");
|
|
91
|
+
console.log("Package-manager helper commands:");
|
|
92
|
+
for (const [name, command] of Object.entries(helperCommands())) {
|
|
93
|
+
console.log(` ${name} -> ${command}`);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
async function main(argv = process.argv.slice(2)) {
|
|
98
|
+
if (argv.includes("--help") || argv.includes("-h")) {
|
|
99
|
+
printHelp();
|
|
100
|
+
return 0;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
if (argv.includes("--list")) {
|
|
104
|
+
printList();
|
|
105
|
+
return 0;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
const [example = "real-user-smoke"] = argv;
|
|
109
|
+
const target = examples[example];
|
|
110
|
+
if (!target) {
|
|
111
|
+
console.error(`unknown example: ${example}`);
|
|
112
|
+
printHelp();
|
|
113
|
+
return 1;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
await import(target.href);
|
|
117
|
+
return 0;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
const exitCode = await main();
|
|
121
|
+
if (exitCode !== 0) {
|
|
122
|
+
process.exit(exitCode);
|
|
123
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
{
|
|
2
|
+
"private": true,
|
|
3
|
+
"type": "module",
|
|
4
|
+
"scripts": {
|
|
5
|
+
"help": "node ./index.mjs --help",
|
|
6
|
+
"list": "node ./index.mjs --list",
|
|
7
|
+
"readme-example": "node ./index.mjs readme-example",
|
|
8
|
+
"readme-example:esm": "node ./index.mjs readme-example:esm",
|
|
9
|
+
"readme-example:cjs": "node ./index.mjs readme-example:cjs",
|
|
10
|
+
"real-user-smoke": "node ./index.mjs real-user-smoke",
|
|
11
|
+
"real-user-smoke:esm": "node ./index.mjs real-user-smoke:esm",
|
|
12
|
+
"real-user-smoke:cjs": "node ./index.mjs real-user-smoke:cjs"
|
|
13
|
+
}
|
|
14
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
let sdk;
|
|
2
|
+
try {
|
|
3
|
+
sdk = require("@logbrew/sdk");
|
|
4
|
+
} catch (error) {
|
|
5
|
+
if (error && error.code === "MODULE_NOT_FOUND") {
|
|
6
|
+
sdk = require("../index.cjs");
|
|
7
|
+
} else {
|
|
8
|
+
throw error;
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const { LogBrewClient, RecordingTransport } = sdk;
|
|
13
|
+
|
|
14
|
+
const client = LogBrewClient.create({
|
|
15
|
+
apiKey: "LOGBREW_API_KEY",
|
|
16
|
+
sdkName: "logbrew-js",
|
|
17
|
+
sdkVersion: "0.1.0"
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
client.release("evt_release_001", "2026-06-02T10:00:00Z", {
|
|
21
|
+
version: "1.2.3",
|
|
22
|
+
commit: "abc123def456",
|
|
23
|
+
notes: "Public release marker"
|
|
24
|
+
});
|
|
25
|
+
client.environment("evt_environment_001", "2026-06-02T10:00:01Z", {
|
|
26
|
+
name: "production",
|
|
27
|
+
region: "global"
|
|
28
|
+
});
|
|
29
|
+
client.issue("evt_issue_001", "2026-06-02T10:00:02Z", {
|
|
30
|
+
title: "Checkout timeout",
|
|
31
|
+
level: "error",
|
|
32
|
+
message: "Request timed out after retry budget"
|
|
33
|
+
});
|
|
34
|
+
client.log("evt_log_001", "2026-06-02T10:00:03Z", {
|
|
35
|
+
message: "worker started",
|
|
36
|
+
level: "info",
|
|
37
|
+
logger: "job-runner"
|
|
38
|
+
});
|
|
39
|
+
client.span("evt_span_001", "2026-06-02T10:00:04Z", {
|
|
40
|
+
name: "GET /health",
|
|
41
|
+
traceId: "trace_001",
|
|
42
|
+
spanId: "span_001",
|
|
43
|
+
status: "ok",
|
|
44
|
+
durationMs: 12.5
|
|
45
|
+
});
|
|
46
|
+
client.action("evt_action_001", "2026-06-02T10:00:05Z", {
|
|
47
|
+
name: "deploy",
|
|
48
|
+
status: "success"
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
console.log(client.previewJson());
|
|
52
|
+
|
|
53
|
+
const transport = RecordingTransport.alwaysAccept();
|
|
54
|
+
client.shutdown(transport).then((response) => {
|
|
55
|
+
console.error(JSON.stringify({ ok: true, status: response.statusCode, attempts: response.attempts, events: 6 }));
|
|
56
|
+
}).catch((error) => {
|
|
57
|
+
console.error(error);
|
|
58
|
+
process.exit(1);
|
|
59
|
+
});
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
const sdk = await import("@logbrew/sdk").catch(async (error) => {
|
|
2
|
+
if (error && error.code === "ERR_MODULE_NOT_FOUND") {
|
|
3
|
+
return import("../index.js");
|
|
4
|
+
}
|
|
5
|
+
throw error;
|
|
6
|
+
});
|
|
7
|
+
|
|
8
|
+
const { LogBrewClient, RecordingTransport } = sdk;
|
|
9
|
+
|
|
10
|
+
const client = LogBrewClient.create({
|
|
11
|
+
apiKey: "LOGBREW_API_KEY",
|
|
12
|
+
sdkName: "logbrew-js",
|
|
13
|
+
sdkVersion: "0.1.0"
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
client.release("evt_release_001", "2026-06-02T10:00:00Z", {
|
|
17
|
+
version: "1.2.3",
|
|
18
|
+
commit: "abc123def456",
|
|
19
|
+
notes: "Public release marker"
|
|
20
|
+
});
|
|
21
|
+
client.environment("evt_environment_001", "2026-06-02T10:00:01Z", {
|
|
22
|
+
name: "production",
|
|
23
|
+
region: "global"
|
|
24
|
+
});
|
|
25
|
+
client.issue("evt_issue_001", "2026-06-02T10:00:02Z", {
|
|
26
|
+
title: "Checkout timeout",
|
|
27
|
+
level: "error",
|
|
28
|
+
message: "Request timed out after retry budget"
|
|
29
|
+
});
|
|
30
|
+
client.log("evt_log_001", "2026-06-02T10:00:03Z", {
|
|
31
|
+
message: "worker started",
|
|
32
|
+
level: "info",
|
|
33
|
+
logger: "job-runner"
|
|
34
|
+
});
|
|
35
|
+
client.span("evt_span_001", "2026-06-02T10:00:04Z", {
|
|
36
|
+
name: "GET /health",
|
|
37
|
+
traceId: "trace_001",
|
|
38
|
+
spanId: "span_001",
|
|
39
|
+
status: "ok",
|
|
40
|
+
durationMs: 12.5
|
|
41
|
+
});
|
|
42
|
+
client.action("evt_action_001", "2026-06-02T10:00:05Z", {
|
|
43
|
+
name: "deploy",
|
|
44
|
+
status: "success"
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
console.log(client.previewJson());
|
|
48
|
+
|
|
49
|
+
const transport = RecordingTransport.alwaysAccept();
|
|
50
|
+
const response = await client.shutdown(transport);
|
|
51
|
+
console.error(JSON.stringify({ ok: true, status: response.statusCode, attempts: response.attempts, events: 6 }));
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
let sdk;
|
|
2
|
+
try {
|
|
3
|
+
sdk = require("@logbrew/sdk");
|
|
4
|
+
} catch (error) {
|
|
5
|
+
if (error && error.code === "MODULE_NOT_FOUND") {
|
|
6
|
+
sdk = require("../index.cjs");
|
|
7
|
+
} else {
|
|
8
|
+
throw error;
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const { LogBrewClient, RecordingTransport } = sdk;
|
|
13
|
+
|
|
14
|
+
const client = LogBrewClient.create({
|
|
15
|
+
apiKey: "LOGBREW_API_KEY",
|
|
16
|
+
sdkName: "smoke-app-cjs",
|
|
17
|
+
sdkVersion: "0.1.0"
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
client.release("evt_release_001", "2026-06-02T10:00:00Z", {
|
|
21
|
+
version: "1.2.3",
|
|
22
|
+
commit: "abc123def456",
|
|
23
|
+
notes: "Public release marker"
|
|
24
|
+
});
|
|
25
|
+
client.environment("evt_environment_001", "2026-06-02T10:00:01Z", {
|
|
26
|
+
name: "production",
|
|
27
|
+
region: "global"
|
|
28
|
+
});
|
|
29
|
+
client.issue("evt_issue_001", "2026-06-02T10:00:02Z", {
|
|
30
|
+
title: "Checkout timeout",
|
|
31
|
+
level: "error",
|
|
32
|
+
message: "Request timed out after retry budget"
|
|
33
|
+
});
|
|
34
|
+
client.log("evt_log_001", "2026-06-02T10:00:03Z", {
|
|
35
|
+
message: "worker started",
|
|
36
|
+
level: "info",
|
|
37
|
+
logger: "job-runner"
|
|
38
|
+
});
|
|
39
|
+
client.span("evt_span_001", "2026-06-02T10:00:04Z", {
|
|
40
|
+
name: "GET /health",
|
|
41
|
+
traceId: "trace_001",
|
|
42
|
+
spanId: "span_001",
|
|
43
|
+
status: "ok",
|
|
44
|
+
durationMs: 12.5
|
|
45
|
+
});
|
|
46
|
+
client.action("evt_action_001", "2026-06-02T10:00:05Z", {
|
|
47
|
+
name: "deploy",
|
|
48
|
+
status: "success"
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
console.log(client.previewJson());
|
|
52
|
+
|
|
53
|
+
const transport = RecordingTransport.alwaysAccept();
|
|
54
|
+
client.shutdown(transport).then((response) => {
|
|
55
|
+
console.error(JSON.stringify({ ok: true, status: response.statusCode, attempts: response.attempts, events: 6 }));
|
|
56
|
+
}).catch((error) => {
|
|
57
|
+
console.error(error);
|
|
58
|
+
process.exit(1);
|
|
59
|
+
});
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
const sdk = await import("@logbrew/sdk").catch(async (error) => {
|
|
2
|
+
if (error && error.code === "ERR_MODULE_NOT_FOUND") {
|
|
3
|
+
return import("../index.js");
|
|
4
|
+
}
|
|
5
|
+
throw error;
|
|
6
|
+
});
|
|
7
|
+
|
|
8
|
+
const { LogBrewClient, RecordingTransport } = sdk;
|
|
9
|
+
|
|
10
|
+
const client = LogBrewClient.create({
|
|
11
|
+
apiKey: "LOGBREW_API_KEY",
|
|
12
|
+
sdkName: "smoke-app",
|
|
13
|
+
sdkVersion: "0.1.0"
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
client.release("evt_release_001", "2026-06-02T10:00:00Z", {
|
|
17
|
+
version: "1.2.3",
|
|
18
|
+
commit: "abc123def456",
|
|
19
|
+
notes: "Public release marker"
|
|
20
|
+
});
|
|
21
|
+
client.environment("evt_environment_001", "2026-06-02T10:00:01Z", {
|
|
22
|
+
name: "production",
|
|
23
|
+
region: "global"
|
|
24
|
+
});
|
|
25
|
+
client.issue("evt_issue_001", "2026-06-02T10:00:02Z", {
|
|
26
|
+
title: "Checkout timeout",
|
|
27
|
+
level: "error",
|
|
28
|
+
message: "Request timed out after retry budget"
|
|
29
|
+
});
|
|
30
|
+
client.log("evt_log_001", "2026-06-02T10:00:03Z", {
|
|
31
|
+
message: "worker started",
|
|
32
|
+
level: "info",
|
|
33
|
+
logger: "job-runner"
|
|
34
|
+
});
|
|
35
|
+
client.span("evt_span_001", "2026-06-02T10:00:04Z", {
|
|
36
|
+
name: "GET /health",
|
|
37
|
+
traceId: "trace_001",
|
|
38
|
+
spanId: "span_001",
|
|
39
|
+
status: "ok",
|
|
40
|
+
durationMs: 12.5
|
|
41
|
+
});
|
|
42
|
+
client.action("evt_action_001", "2026-06-02T10:00:05Z", {
|
|
43
|
+
name: "deploy",
|
|
44
|
+
status: "success"
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
console.log(client.previewJson());
|
|
48
|
+
|
|
49
|
+
const transport = RecordingTransport.alwaysAccept();
|
|
50
|
+
const response = await client.shutdown(transport);
|
|
51
|
+
console.error(JSON.stringify({ ok: true, status: response.statusCode, attempts: response.attempts, events: 6 }));
|