@better-logger/core 0.6.0 โ 0.8.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 +248 -294
- package/dist/index.cjs +3 -3
- package/dist/index.d.cts +36 -23
- package/dist/index.d.ts +36 -23
- package/dist/index.js +3 -3
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,294 +1,248 @@
|
|
|
1
|
-
#
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
Execution flow debugger for modern apps. Zero deps. Works everywhere. <10KB.
|
|
6
|
-
|
|
7
|
-
```bash
|
|
8
|
-
npm install @better-logger/core
|
|
9
|
-
```
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
console.log('
|
|
17
|
-
console.log('
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
```
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
flow
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
-
|
|
158
|
-
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
```
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
})
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
---
|
|
251
|
-
|
|
252
|
-
## What's not included
|
|
253
|
-
|
|
254
|
-
- โ Log levels (debug, info, warn)
|
|
255
|
-
- โ Transports (file, HTTP, Elasticsearch)
|
|
256
|
-
- โ SaaS dashboards
|
|
257
|
-
- โ Auto-instrumentation
|
|
258
|
-
|
|
259
|
-
This is a developer debugging tool, not observability infrastructure.
|
|
260
|
-
|
|
261
|
-
---
|
|
262
|
-
|
|
263
|
-
## Roadmap
|
|
264
|
-
|
|
265
|
-
| Version | Focus |
|
|
266
|
-
|---------|-------|
|
|
267
|
-
| **V1** | Core flow debugger โ this release |
|
|
268
|
-
| **V2** | Custom renderers, `flow.run()` async helper, flow sampling |
|
|
269
|
-
| **V3** | Browser DevTools timeline panel |
|
|
270
|
-
| **V4+** | Python / Go / Rust ports, shared tracing schema |
|
|
271
|
-
|
|
272
|
-
---
|
|
273
|
-
|
|
274
|
-
## Organization
|
|
275
|
-
|
|
276
|
-
Published under the **@better-logger** org, owned by [0xmilord](https://github.com/0xmilord).
|
|
277
|
-
|
|
278
|
-
```bash
|
|
279
|
-
npm install @better-logger/core
|
|
280
|
-
```
|
|
281
|
-
|
|
282
|
-
All packages in this org share the same execution tracing schema.
|
|
283
|
-
|
|
284
|
-
---
|
|
285
|
-
|
|
286
|
-
## Test Coverage
|
|
287
|
-
|
|
288
|
-
**100%** across all metrics โ statements, branches, functions, lines.
|
|
289
|
-
|
|
290
|
-
[View detailed coverage report](./COVERAGE.md) | [Testing Strategy](./docs/TESTING-STRATEGY.md)
|
|
291
|
-
|
|
292
|
-
## License
|
|
293
|
-
|
|
294
|
-
MIT
|
|
1
|
+
# better-logger
|
|
2
|
+
|
|
3
|
+
**Track what your app *did*, not what it *said*.**
|
|
4
|
+
|
|
5
|
+
Execution flow debugger for modern apps. Zero deps. Works everywhere. <10KB.
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @better-logger/core
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Stop debugging like this:
|
|
12
|
+
|
|
13
|
+
```typescript
|
|
14
|
+
console.log('start')
|
|
15
|
+
console.log('user', user)
|
|
16
|
+
console.log('after db')
|
|
17
|
+
console.log('done')
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
And trying to mentally reconstruct what happened, in what order, and how long each thing took.
|
|
21
|
+
|
|
22
|
+
## Your app is not a list of messages. It's a flow.
|
|
23
|
+
|
|
24
|
+
```typescript
|
|
25
|
+
import { better } from '@better-logger/core'
|
|
26
|
+
|
|
27
|
+
// Replace console.log โ zero learning curve
|
|
28
|
+
better.log('User created', { email: 'test@example.com' })
|
|
29
|
+
better.log.warn('Slow query detected', { duration: 250 })
|
|
30
|
+
better.log.error('Payment failed', error)
|
|
31
|
+
|
|
32
|
+
// When you need structure
|
|
33
|
+
const flow = better.flow('user-onboarding', { tags: ['auth'] })
|
|
34
|
+
const step = flow.step('create-user', { email })
|
|
35
|
+
await createUser(email)
|
|
36
|
+
step.success()
|
|
37
|
+
flow.success()
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
**What you get:**
|
|
41
|
+
|
|
42
|
+
```
|
|
43
|
+
๐ [flow:user-onboarding] [auth] (tid: a1b2c3d4)
|
|
44
|
+
โ create-user
|
|
45
|
+
data: { email: "test@example.com" }
|
|
46
|
+
โ create-user (45ms)
|
|
47
|
+
๐ [flow:user-onboarding] success (45ms)
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
## Why this exists
|
|
51
|
+
|
|
52
|
+
Debugging today is broken:
|
|
53
|
+
|
|
54
|
+
| Problem | better-logger solution |
|
|
55
|
+
|---------|----------------------|
|
|
56
|
+
| `console.log` โ flat noise, no structure | Hierarchical flows with automatic timing |
|
|
57
|
+
| No automatic timing | Every step and flow tracks duration |
|
|
58
|
+
| No context propagation | `flow.setContext()` shares metadata across all steps |
|
|
59
|
+
| Async flows become impossible to follow | Deferred atomic rendering โ one output per flow |
|
|
60
|
+
| Need to learn new API | `better.log()` is `console.log()` โ just add `.log` |
|
|
61
|
+
|
|
62
|
+
## Quick Start
|
|
63
|
+
|
|
64
|
+
### 1. Drop-in replacement
|
|
65
|
+
|
|
66
|
+
Replace `console.log` with `better.log`:
|
|
67
|
+
|
|
68
|
+
```typescript
|
|
69
|
+
// Before
|
|
70
|
+
console.log('Server started on port 3000')
|
|
71
|
+
console.error('Database connection failed', error)
|
|
72
|
+
|
|
73
|
+
// After
|
|
74
|
+
import { better } from '@better-logger/core'
|
|
75
|
+
|
|
76
|
+
better.log('Server started on port 3000')
|
|
77
|
+
better.log.error('Database connection failed', error)
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
That's it. You now get structured, timed output for free.
|
|
81
|
+
|
|
82
|
+
### 2. When you need structure
|
|
83
|
+
|
|
84
|
+
For important operations, use explicit flows:
|
|
85
|
+
|
|
86
|
+
```typescript
|
|
87
|
+
const flow = better.flow('process-payment', { tags: ['billing'] })
|
|
88
|
+
flow.setContext({ orderId: 'ord-123', userId: 'user-456' })
|
|
89
|
+
|
|
90
|
+
const step = flow.step('charge-card', { amount: 99.99 })
|
|
91
|
+
const result = await paymentGateway.charge({ amount: 99.99 })
|
|
92
|
+
step.success(result)
|
|
93
|
+
|
|
94
|
+
flow.success()
|
|
95
|
+
better.log(`Payment processed: ${result.transactionId}`)
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
### 3. Async made easy
|
|
99
|
+
|
|
100
|
+
```typescript
|
|
101
|
+
const flow = better.flow('data-export')
|
|
102
|
+
|
|
103
|
+
const data = await flow.run('fetch-data', async () => {
|
|
104
|
+
return await db.users.find({})
|
|
105
|
+
})
|
|
106
|
+
|
|
107
|
+
const file = await flow.run('generate-file', async () => {
|
|
108
|
+
return await exportToCSV(data)
|
|
109
|
+
})
|
|
110
|
+
|
|
111
|
+
flow.success()
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
## API Reference
|
|
115
|
+
|
|
116
|
+
### `better.log()` โ The simple way
|
|
117
|
+
|
|
118
|
+
```typescript
|
|
119
|
+
better.log('message') // Simple message
|
|
120
|
+
better.log('message', data) // Message with data
|
|
121
|
+
better.log.info('message', data) // Info (same as log)
|
|
122
|
+
better.log.warn('message', data) // Warning (auto-tags flow)
|
|
123
|
+
better.log.error('message', error) // Error (fails flow)
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
### `better.flow()` โ The structured way
|
|
127
|
+
|
|
128
|
+
```typescript
|
|
129
|
+
const flow = better.flow('name', {
|
|
130
|
+
tags: ['tag1', 'tag2'], // Indexing labels
|
|
131
|
+
maxSteps: 100, // Safety limit
|
|
132
|
+
initialContext: { key: 'value' } // Shared metadata
|
|
133
|
+
})
|
|
134
|
+
|
|
135
|
+
flow.setContext({ userId: 'abc' }) // Add context
|
|
136
|
+
flow.getContext() // Get context copy
|
|
137
|
+
|
|
138
|
+
flow.step('step-name', data) // Create step
|
|
139
|
+
.success() // Mark success
|
|
140
|
+
.fail(error) // Mark failure
|
|
141
|
+
|
|
142
|
+
flow.success() // Complete flow
|
|
143
|
+
flow.fail(error) // Fail flow
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
### `better.flow.run()` โ Async helper
|
|
147
|
+
|
|
148
|
+
```typescript
|
|
149
|
+
const result = await flow.run('async-step', async () => {
|
|
150
|
+
return await fetchData() // Auto-completes step on success/fail
|
|
151
|
+
})
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
### Configuration
|
|
155
|
+
|
|
156
|
+
```typescript
|
|
157
|
+
better.log.setIdleTimeout(200) // Auto-complete timeout (ms)
|
|
158
|
+
better.log.setFlowName('my-app') // Default flow name
|
|
159
|
+
better.log.setDefaultTags(['app', 'v3']) // Tags on all flows
|
|
160
|
+
better.log.flush() // Force complete current flow
|
|
161
|
+
better.setEnabled(false) // Disable all logging
|
|
162
|
+
better.isEnabled() // Check if enabled
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
## Real-World Examples
|
|
166
|
+
|
|
167
|
+
We've included 10 comprehensive examples showing better-logger in real applications:
|
|
168
|
+
|
|
169
|
+
| Example | What it shows |
|
|
170
|
+
|---------|--------------|
|
|
171
|
+
| `01-express-rest-api.js` | Express middleware, CRUD endpoints, error handling |
|
|
172
|
+
| `02-background-job-processor.js` | Job queue, retry logic, nested flows |
|
|
173
|
+
| `03-authentication-flow.js` | Login, token refresh, password reset, security logging |
|
|
174
|
+
| `04-ecommerce-order-processing.js` | Multi-step checkout, inventory, payment, shipping |
|
|
175
|
+
| `05-cli-tool.js` | CLI commands, progress tracking, file processing |
|
|
176
|
+
| `06-api-integration-client.js` | HTTP client, retry logic, rate limiting, batch ops |
|
|
177
|
+
| `07-microservice-distributed-tracing.js` | Trace context, downstream calls, health checks |
|
|
178
|
+
| `08-testing-utilities.js` | Test runner, assertions, performance testing |
|
|
179
|
+
| `09-data-pipeline.js` | ETL pipelines, transforms, validation, aggregation |
|
|
180
|
+
| `10-full-application.js` | Complete Node.js app with all patterns combined |
|
|
181
|
+
|
|
182
|
+
## Features
|
|
183
|
+
|
|
184
|
+
### Zero Friction
|
|
185
|
+
- `better.log()` is a drop-in for `console.log()`
|
|
186
|
+
- No configuration needed โ import and use immediately
|
|
187
|
+
- Auto-flow management groups rapid calls together
|
|
188
|
+
- Idle timeout auto-completes flows (100ms default)
|
|
189
|
+
|
|
190
|
+
### Structured Output
|
|
191
|
+
- Hierarchical flows with visual nesting
|
|
192
|
+
- Automatic timing for every step and flow
|
|
193
|
+
- Context propagation across all steps
|
|
194
|
+
- Tags for filtering and grouping
|
|
195
|
+
- JSON export for downstream systems
|
|
196
|
+
|
|
197
|
+
### Production-Grade
|
|
198
|
+
- Zero dependencies โ nothing to break
|
|
199
|
+
- <10KB bundle โ won't bloat your app
|
|
200
|
+
- Works in Node.js 18+, browsers, Edge runtimes
|
|
201
|
+
- Full TypeScript support
|
|
202
|
+
- 100% test coverage
|
|
203
|
+
|
|
204
|
+
### Forgiving
|
|
205
|
+
- Call methods after completion โ silent no-ops
|
|
206
|
+
- Pass any data type โ handled gracefully
|
|
207
|
+
- Circular references โ won't crash
|
|
208
|
+
- Concurrent flows โ no interleaving
|
|
209
|
+
- Error anywhere โ won't break your app
|
|
210
|
+
|
|
211
|
+
## Migration from console.log
|
|
212
|
+
|
|
213
|
+
```typescript
|
|
214
|
+
// Before
|
|
215
|
+
console.log('User created:', user)
|
|
216
|
+
console.warn('Slow query', { duration: 250 })
|
|
217
|
+
console.error('Payment failed:', error)
|
|
218
|
+
|
|
219
|
+
// After (literally just add "better.")
|
|
220
|
+
import { better } from '@better-logger/core'
|
|
221
|
+
|
|
222
|
+
better.log('User created:', user)
|
|
223
|
+
better.log.warn('Slow query', { duration: 250 })
|
|
224
|
+
better.log.error('Payment failed:', error)
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
**Migration effort:** 10 minutes to replace all console.log. Hours to days to adopt flows strategically where they add value.
|
|
228
|
+
|
|
229
|
+
## What's NOT included
|
|
230
|
+
|
|
231
|
+
- โ Log levels (debug, info, warn, error) โ execution tracing โ log routing
|
|
232
|
+
- โ Transport layers (file, HTTP, Elasticsearch) โ zero-config philosophy
|
|
233
|
+
- โ SaaS dashboards โ we emit data, we don't host it
|
|
234
|
+
- โ Auto-instrumentation โ devs control what they trace
|
|
235
|
+
|
|
236
|
+
## Package Health
|
|
237
|
+
|
|
238
|
+
| Metric | Value |
|
|
239
|
+
|--------|-------|
|
|
240
|
+
| Bundle size | <10KB minified |
|
|
241
|
+
| Dependencies | 0 |
|
|
242
|
+
| Test coverage | 100% |
|
|
243
|
+
| TypeScript | Full support |
|
|
244
|
+
| Runtimes | Node 18+, Browser, Edge |
|
|
245
|
+
|
|
246
|
+
## License
|
|
247
|
+
|
|
248
|
+
MIT
|
package/dist/index.cjs
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
"use strict";var
|
|
2
|
-
`))):(
|
|
3
|
-
`)))}};var
|
|
1
|
+
"use strict";var I=Object.defineProperty;var ne=Object.getOwnPropertyDescriptor;var oe=Object.getOwnPropertyNames;var ie=Object.prototype.hasOwnProperty;var se=(e,r)=>{for(var t in r)I(e,t,{get:r[t],enumerable:!0})},ae=(e,r,t,n)=>{if(r&&typeof r=="object"||typeof r=="function")for(let i of oe(r))!ie.call(e,i)&&i!==t&&I(e,i,{get:()=>r[i],enumerable:!(n=ne(r,i))||n.enumerable});return e};var le=e=>ae(I({},"__esModule",{value:!0}),e);var ve={};se(ve,{NOOP_FLOW:()=>c,NOOP_STEP:()=>m,better:()=>d,createFlow:()=>k,getRenderer:()=>A,isEnabled:()=>x,normalizeError:()=>f,safeSerialize:()=>p,setClock:()=>j,setEnabled:()=>b,setIdGenerator:()=>Z,setRenderer:()=>G,subscribe:()=>H,toJSON:()=>J});module.exports=le(ve);function f(e){return e===void 0?{name:"Error",message:"Unknown error"}:e instanceof Error?{name:e.name,message:e.message,stack:e.stack}:typeof e=="string"?{name:"Error",message:e}:{name:"Error",message:String(e)}}var y=class{constructor(r,t){this._trace=r;this._clock=t;this._completed=!1}get isCompleted(){return this._completed}get trace(){return this._trace}success(){this._completed||(this._completed=!0,this._trace.end=this._clock.now(),this._trace.state="completed",this._trace.status="success")}fail(r){this._completed||(this._completed=!0,this._trace.end=this._clock.now(),this._trace.state="completed",this._trace.status="error",this._trace.error=f(r))}};var g=()=>{},m={success:g,fail:g},c={step:()=>m,child:()=>c,tag:g,tags:()=>[],setContext:g,getContext:()=>({}),success:g,fail:g,run:(e,r)=>{try{let t=r();return t instanceof Promise?t:Promise.resolve(t)}catch(t){return Promise.reject(t)}}};function U(e){let r=new WeakMap;function t(n){if(n===null||typeof n!="object")return n;if(n instanceof Date)return new Date(n.getTime());if(n instanceof RegExp)return new RegExp(n.source,n.flags);if(r.has(n))return r.get(n);if(Array.isArray(n)){let s=[];r.set(n,s);for(let o=0;o<n.length;o++)s.push(t(n[o]));return s}let i={};r.set(n,i);for(let s of Object.keys(n))i[s]=t(n[s]);return i}return t(e)}function R(e){if(e===null||typeof e!="object")return e;if(Object.freeze(e),Array.isArray(e))for(let r of e)R(r);else for(let r of Object.keys(e)){let t=e[r];t&&typeof t=="object"&&!Object.isFrozen(t)&&R(t)}return e}function z(e){let r=U(e);return R(r)}var O=new Set;function H(e){return O.add(e),()=>{O.delete(e)}}function ce(e){if(O.size!==0)for(let r of O)try{r(e)}catch{}}var C=class e{constructor(r,t,n,i,s){this._trace=r;this._clock=t;this._idGen=n;this._renderer=i;this._options=s;this._completed=!1;this._sequence=0}get isCompleted(){return this._completed}get trace(){return this._trace}step(r,t){if(this._completed)return m;let n=this._options.maxSteps;if(n!==void 0&&this._trace.steps.length>=n)return this._trace.meta===void 0?this._trace.meta={maxStepsExceeded:!0}:this._trace.meta.maxStepsExceeded=!0,m;let i={id:this._idGen.generate(),name:r,sequence:this._sequence++,state:"running",status:"pending",start:this._clock.now(),data:t,children:[]};return this._trace.steps.push(i),new y(i,this._clock)}child(r){if(this._completed)return c;if(this._options.enabled===!1)return c;let t={id:this._idGen.generate(),name:r,parentId:this._trace.id,state:"running",status:void 0,tags:[],start:this._clock.now(),context:{...this._trace.context},steps:[]};return new e(t,this._clock,this._idGen,this._renderer,{...this._options})}tag(r){this._completed||this._trace.tags.includes(r)||this._trace.tags.push(r)}tags(){return[...this._trace.tags]}setContext(r){this._completed||Object.assign(this._trace.context,r)}getContext(){return{...this._trace.context}}success(){this._finalize("success")}fail(r){this._trace.error=f(r),this._finalize("error")}run(r,t){if(this._completed)return Promise.resolve(t());let n=this.step(r);return Promise.resolve(t()).then(i=>(n.success(),i),i=>{throw n.fail(i),i})}_finalize(r){if(this._completed)return;this._completed=!0,this._trace.end=this._clock.now(),this._trace.state="completed",this._trace.status=r;let t=z(this._trace);ce(t),this._renderer.render(t)}};var h=class{generate(){return Math.random().toString(36).slice(2,10)}};var _=class{now(){return Date.now()}};function p(e,r){let t=r?.maxDepth??2,n=r?.maxLength??80,i=new WeakSet;function s(o,l){if(typeof o=="function")return`[Fn:${o.name||"?"}]`;if(typeof o=="symbol")return o.toString();if(l>t)return o&&typeof o=="object"?"[...]":o;if(o===null||typeof o!="object")return o;if(o instanceof Map)return`{Map(${o.size})}`;if(o instanceof Set)return`{Set(${o.size})}`;if(o instanceof Date)return o.toISOString();if(o instanceof RegExp)return o.toString();if(i.has(o))return"[Circular]";if(i.add(o),Array.isArray(o))return o.map(u=>s(u,l+1));let T={};for(let u of Object.keys(o)){let $=o[u];T[u]=s($,l+1)}return T}try{let o=JSON.stringify(s(e,0));return o&&o.length>n?o.slice(0,n)+"\u2026":o}catch{return"[Unserializable]"}}var de=()=>typeof process<"u"&&process.versions!==void 0&&process.versions.node!==void 0,ue=()=>typeof EdgeRuntime<"u",fe=()=>typeof caches<"u"&&"default"in caches,pe=()=>typeof window<"u"||typeof self<"u";function Y(){return de()?"node":ue()||fe()?"edge":pe()?"browser":"node"}var me="\x1B[0m",we="\x1B[32m",ge="\x1B[31m";var xe="\x1B[36m";var Fe="\x1B[2m";function he(){return!(Y()==="browser"||typeof process<"u"&&process.env?.NO_COLOR)}var _e=he();function v(e,r){return _e?`${r}${e}${me}`:e}function L(e){return v(e,we)}function E(e){return v(e,ge)}function K(e){return v(e,xe)}function P(e){return v(e,Fe)}function Q(e,r){if(r===void 0)return"\u2014";let t=Math.round(r-e);return t>=1e3?`${(t/1e3).toFixed(1)}s`:`${t}ms`}function V(e,r,t){let n=" ".repeat(r);t.push(`${n}${K("\u2192")} ${e.name}`),e.data!==void 0&&t.push(`${n} ${P("data:")} ${p(e.data,{maxLength:80})}`);let i=Q(e.start,e.end);e.status==="success"?t.push(`${n}${L("\u2713")} ${e.name} (${i})`):e.status==="error"?t.push(`${n}${E("\u2717")} ${e.name} (error: ${e.error?.message??"Unknown error"})`):t.push(`${n} ${e.name} (${i})`);for(let s of e.children)V(s,r+1,t)}var S=class{constructor(){this.name="console"}render(r){let t=[],n=r.tags.length>0?` [${r.tags.join(", ")}]`:"",i=r.status==="error"?"\u{1F525}":"\u{1F680}";t.push(`${i} [flow:${r.name}]${n} (${P("tid:")} ${r.id})`);for(let l of r.steps)V(l,1,t);let s=Q(r.start,r.end),o=r.meta?.maxStepsExceeded?` ${E("\u26A0\uFE0F maxSteps exceeded")}`:"";r.status==="error"?(t.push(`\u{1F3C1} [flow:${r.name}] ${E("failed")} (${s}, error: ${r.error?.message??"Unknown error"})${o}`),console.error(t.join(`
|
|
2
|
+
`))):(t.push(`\u{1F3C1} [flow:${r.name}] ${L("success")} (${s})${o}`),console.log(t.join(`
|
|
3
|
+
`)))}};var D=null;function G(e){D=e}function A(){return D}function X(e){return D??e}var B=new h,M=new _,Te=new S,W=!0;function b(e){W=e}function x(){return W}function Z(e){B=e}function j(e){M=e}function k(e,r){if(!W)return c;let t=r?.sample??1;if(t<1&&Math.random()>t)return c;if(r?.enabled===!1)return c;let n=X(Te),i={id:B.generate(),name:e,state:"running",tags:r?.tags??[],start:M.now(),context:r?.initialContext?{...r.initialContext}:{},steps:[]};return new C(i,M,B,n,r??{})}function ye(e){return e!==null&&typeof e=="object"&&("flow"in e||"tags"in e)}function Re(e,r,t){if(r.current&&t===void 0&&!r.current.completed)return r.current.flow;let n=t??e.flowName,i=k(n,{tags:[...e.defaultTags]});return r.current={flow:i,timer:null,lastError:null,completed:!1},i}function Oe(e,r){r.current&&(r.current.timer&&clearTimeout(r.current.timer),r.current.timer=setTimeout(()=>{ee(r)},e.idleTimeout))}function ee(e){!e.current||e.current.completed||(e.current.timer&&(clearTimeout(e.current.timer),e.current.timer=null),e.current.completed=!0,e.current.lastError?e.current.flow.fail(e.current.lastError):e.current.flow.success(),e.current=null)}function N(e,r,t,n,i,s){if(!x())return;let o,l;n===void 0?(o=void 0,l=void 0):ye(n)?i===void 0?(o=void 0,l=n):(o=void 0,l={...n,...i}):(o=n,l=i);let T=l?.flow,u=Re(e,r,T);if(l?.tags)for(let te of l.tags)u.tag(te);let $=s&&s!=="info"?`${t} [${s}]`:t,q=u.step($,o);s==="error"?(q.fail(o),r.current&&(r.current.lastError=o),u.tag("error")):(q.success(),s&&s!=="info"&&u.tag(s)),Oe(e,r)}var w={idleTimeout:100,flowName:"default",defaultTags:[]},F={current:null};function a(e,r,t){N(w,F,e,r,t)}a.info=(e,r,t)=>N(w,F,e,r,t,"info");a.warn=(e,r,t)=>N(w,F,e,r,t,"warn");a.error=(e,r,t)=>N(w,F,e,r,t,"error");a.setIdleTimeout=e=>{w.idleTimeout=e};a.setFlowName=e=>{w.flowName=e};a.setDefaultTags=e=>{w.defaultTags=e};a.activeFlow=()=>F.current?.flow??null;a.flush=()=>{ee(F)};var d=(e,r,t)=>{a(e,r,t)};d.log=a;d.flow=(e,r)=>k(e,r);d.setIdleTimeout=a.setIdleTimeout;d.setFlowName=a.setFlowName;d.setDefaultTags=a.setDefaultTags;d.activeFlow=a.activeFlow;d.flush=a.flush;d.setEnabled=b;d.isEnabled=x;function Ce(e){return typeof e=="object"&&e!==null&&"trace"in e&&typeof e.trace=="object"&&e.trace!==null}function J(e){let r=Ce(e)?e.trace:e;return JSON.stringify({version:1,flow:{id:r.id,name:r.name,...r.parentId!==void 0&&{parentId:r.parentId},state:r.state,...r.status!==void 0&&{status:r.status},tags:r.tags,start:r.start,...r.end!==void 0&&{end:r.end},...r.error!==void 0&&{error:r.error},context:r.context,steps:r.steps.map(re),...r.meta!==void 0&&{meta:r.meta}}},null,2)}function re(e){let r={id:e.id,name:e.name,sequence:e.sequence,state:e.state,status:e.status,start:e.start};if(e.end!==void 0&&(r.end=e.end),e.data!==void 0)try{r.data=JSON.parse(p(e.data))}catch{r.data="[Circular or unserializable]"}return e.error!==void 0&&(r.error=e.error),e.children.length>0&&(r.children=e.children.map(re)),r}0&&(module.exports={NOOP_FLOW,NOOP_STEP,better,createFlow,getRenderer,isEnabled,normalizeError,safeSerialize,setClock,setEnabled,setIdGenerator,setRenderer,subscribe,toJSON});
|
package/dist/index.d.cts
CHANGED
|
@@ -170,17 +170,16 @@ declare function setClock(clock: Clock): void;
|
|
|
170
170
|
declare function createFlow<Data = unknown>(name: string, options?: FlowOptions): FlowHandle<Data>;
|
|
171
171
|
|
|
172
172
|
/**
|
|
173
|
-
* V3: Zero-Friction
|
|
173
|
+
* V3: Zero-Friction better.log API
|
|
174
174
|
*
|
|
175
175
|
* Drop-in console.log replacement with auto-flow management.
|
|
176
176
|
*
|
|
177
177
|
* Usage:
|
|
178
|
-
* log('message')
|
|
179
|
-
* log('message', data)
|
|
180
|
-
* log('
|
|
181
|
-
* log('
|
|
182
|
-
*
|
|
183
|
-
* log.error('error', error)
|
|
178
|
+
* better.log('message')
|
|
179
|
+
* better.log('message', data)
|
|
180
|
+
* better.log.warn('warning', data)
|
|
181
|
+
* better.log.error('error', error)
|
|
182
|
+
* better.flow('explicit-flow', { tags: ['auth'] })
|
|
184
183
|
*/
|
|
185
184
|
|
|
186
185
|
/** Options for individual log calls */
|
|
@@ -190,22 +189,36 @@ interface LogCallOptions {
|
|
|
190
189
|
/** Additional tags for this step */
|
|
191
190
|
tags?: string[];
|
|
192
191
|
}
|
|
193
|
-
/**
|
|
194
|
-
interface
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
192
|
+
/** Options for creating an explicit flow via better.flow() */
|
|
193
|
+
interface BetterFlowOptions {
|
|
194
|
+
tags?: string[];
|
|
195
|
+
maxSteps?: number;
|
|
196
|
+
sample?: number;
|
|
197
|
+
initialContext?: Record<string, unknown>;
|
|
198
|
+
}
|
|
199
|
+
declare function logFn(message: string, dataOrOptions?: unknown, options?: LogCallOptions): void;
|
|
200
|
+
declare namespace logFn {
|
|
201
|
+
var info: (message: string, dataOrOptions?: unknown, options?: LogCallOptions) => void;
|
|
202
|
+
var warn: (message: string, dataOrOptions?: unknown, options?: LogCallOptions) => void;
|
|
203
|
+
var error: (message: string, dataOrOptions?: unknown, options?: LogCallOptions) => void;
|
|
204
|
+
var setIdleTimeout: (ms: number) => void;
|
|
205
|
+
var setFlowName: (name: string) => void;
|
|
206
|
+
var setDefaultTags: (tags: string[]) => void;
|
|
207
|
+
var activeFlow: () => FlowHandle | null;
|
|
208
|
+
var flush: () => void;
|
|
206
209
|
}
|
|
207
|
-
|
|
208
|
-
|
|
210
|
+
declare const betterBase: {
|
|
211
|
+
(message: string, dataOrOptions?: unknown, options?: LogCallOptions): void;
|
|
212
|
+
log: typeof logFn;
|
|
213
|
+
flow(name: string, options?: BetterFlowOptions): FlowHandle;
|
|
214
|
+
setIdleTimeout: (ms: number) => void;
|
|
215
|
+
setFlowName: (name: string) => void;
|
|
216
|
+
setDefaultTags: (tags: string[]) => void;
|
|
217
|
+
activeFlow: () => FlowHandle | null;
|
|
218
|
+
flush: () => void;
|
|
219
|
+
setEnabled: typeof setEnabled;
|
|
220
|
+
isEnabled: typeof isEnabled;
|
|
221
|
+
};
|
|
209
222
|
|
|
210
223
|
/** Contract for all renderer implementations */
|
|
211
224
|
interface FlowRenderer {
|
|
@@ -233,4 +246,4 @@ declare function toJSON(input: Readonly<FlowTrace> | {
|
|
|
233
246
|
trace: Readonly<FlowTrace>;
|
|
234
247
|
}): string;
|
|
235
248
|
|
|
236
|
-
export { type
|
|
249
|
+
export { type BetterFlowOptions, type Clock, type FlowListener, type FlowOptions, type FlowRenderer, type FlowState, type FlowStatus, type FlowTrace, type IdGenerator, type LogCallOptions, NOOP_FLOW, NOOP_STEP, type NoOpFlowHandle, type NoOpStepHandle, type NormalizedError, type SerializeOptions, type StepStatus, type StepTrace, betterBase as better, createFlow, getRenderer, isEnabled, normalizeError, safeSerialize, setClock, setEnabled, setIdGenerator, setRenderer, subscribe, toJSON };
|
package/dist/index.d.ts
CHANGED
|
@@ -170,17 +170,16 @@ declare function setClock(clock: Clock): void;
|
|
|
170
170
|
declare function createFlow<Data = unknown>(name: string, options?: FlowOptions): FlowHandle<Data>;
|
|
171
171
|
|
|
172
172
|
/**
|
|
173
|
-
* V3: Zero-Friction
|
|
173
|
+
* V3: Zero-Friction better.log API
|
|
174
174
|
*
|
|
175
175
|
* Drop-in console.log replacement with auto-flow management.
|
|
176
176
|
*
|
|
177
177
|
* Usage:
|
|
178
|
-
* log('message')
|
|
179
|
-
* log('message', data)
|
|
180
|
-
* log('
|
|
181
|
-
* log('
|
|
182
|
-
*
|
|
183
|
-
* log.error('error', error)
|
|
178
|
+
* better.log('message')
|
|
179
|
+
* better.log('message', data)
|
|
180
|
+
* better.log.warn('warning', data)
|
|
181
|
+
* better.log.error('error', error)
|
|
182
|
+
* better.flow('explicit-flow', { tags: ['auth'] })
|
|
184
183
|
*/
|
|
185
184
|
|
|
186
185
|
/** Options for individual log calls */
|
|
@@ -190,22 +189,36 @@ interface LogCallOptions {
|
|
|
190
189
|
/** Additional tags for this step */
|
|
191
190
|
tags?: string[];
|
|
192
191
|
}
|
|
193
|
-
/**
|
|
194
|
-
interface
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
192
|
+
/** Options for creating an explicit flow via better.flow() */
|
|
193
|
+
interface BetterFlowOptions {
|
|
194
|
+
tags?: string[];
|
|
195
|
+
maxSteps?: number;
|
|
196
|
+
sample?: number;
|
|
197
|
+
initialContext?: Record<string, unknown>;
|
|
198
|
+
}
|
|
199
|
+
declare function logFn(message: string, dataOrOptions?: unknown, options?: LogCallOptions): void;
|
|
200
|
+
declare namespace logFn {
|
|
201
|
+
var info: (message: string, dataOrOptions?: unknown, options?: LogCallOptions) => void;
|
|
202
|
+
var warn: (message: string, dataOrOptions?: unknown, options?: LogCallOptions) => void;
|
|
203
|
+
var error: (message: string, dataOrOptions?: unknown, options?: LogCallOptions) => void;
|
|
204
|
+
var setIdleTimeout: (ms: number) => void;
|
|
205
|
+
var setFlowName: (name: string) => void;
|
|
206
|
+
var setDefaultTags: (tags: string[]) => void;
|
|
207
|
+
var activeFlow: () => FlowHandle | null;
|
|
208
|
+
var flush: () => void;
|
|
206
209
|
}
|
|
207
|
-
|
|
208
|
-
|
|
210
|
+
declare const betterBase: {
|
|
211
|
+
(message: string, dataOrOptions?: unknown, options?: LogCallOptions): void;
|
|
212
|
+
log: typeof logFn;
|
|
213
|
+
flow(name: string, options?: BetterFlowOptions): FlowHandle;
|
|
214
|
+
setIdleTimeout: (ms: number) => void;
|
|
215
|
+
setFlowName: (name: string) => void;
|
|
216
|
+
setDefaultTags: (tags: string[]) => void;
|
|
217
|
+
activeFlow: () => FlowHandle | null;
|
|
218
|
+
flush: () => void;
|
|
219
|
+
setEnabled: typeof setEnabled;
|
|
220
|
+
isEnabled: typeof isEnabled;
|
|
221
|
+
};
|
|
209
222
|
|
|
210
223
|
/** Contract for all renderer implementations */
|
|
211
224
|
interface FlowRenderer {
|
|
@@ -233,4 +246,4 @@ declare function toJSON(input: Readonly<FlowTrace> | {
|
|
|
233
246
|
trace: Readonly<FlowTrace>;
|
|
234
247
|
}): string;
|
|
235
248
|
|
|
236
|
-
export { type
|
|
249
|
+
export { type BetterFlowOptions, type Clock, type FlowListener, type FlowOptions, type FlowRenderer, type FlowState, type FlowStatus, type FlowTrace, type IdGenerator, type LogCallOptions, NOOP_FLOW, NOOP_STEP, type NoOpFlowHandle, type NoOpStepHandle, type NormalizedError, type SerializeOptions, type StepStatus, type StepTrace, betterBase as better, createFlow, getRenderer, isEnabled, normalizeError, safeSerialize, setClock, setEnabled, setIdGenerator, setRenderer, subscribe, toJSON };
|
package/dist/index.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
function
|
|
2
|
-
`))):(
|
|
3
|
-
`)))}};var
|
|
1
|
+
function f(e){return e===void 0?{name:"Error",message:"Unknown error"}:e instanceof Error?{name:e.name,message:e.message,stack:e.stack}:typeof e=="string"?{name:"Error",message:e}:{name:"Error",message:String(e)}}var T=class{constructor(r,t){this._trace=r;this._clock=t;this._completed=!1}get isCompleted(){return this._completed}get trace(){return this._trace}success(){this._completed||(this._completed=!0,this._trace.end=this._clock.now(),this._trace.state="completed",this._trace.status="success")}fail(r){this._completed||(this._completed=!0,this._trace.end=this._clock.now(),this._trace.state="completed",this._trace.status="error",this._trace.error=f(r))}};var w=()=>{},g={success:w,fail:w},c={step:()=>g,child:()=>c,tag:w,tags:()=>[],setContext:w,getContext:()=>({}),success:w,fail:w,run:(e,r)=>{try{let t=r();return t instanceof Promise?t:Promise.resolve(t)}catch(t){return Promise.reject(t)}}};function B(e){let r=new WeakMap;function t(n){if(n===null||typeof n!="object")return n;if(n instanceof Date)return new Date(n.getTime());if(n instanceof RegExp)return new RegExp(n.source,n.flags);if(r.has(n))return r.get(n);if(Array.isArray(n)){let s=[];r.set(n,s);for(let o=0;o<n.length;o++)s.push(t(n[o]));return s}let i={};r.set(n,i);for(let s of Object.keys(n))i[s]=t(n[s]);return i}return t(e)}function y(e){if(e===null||typeof e!="object")return e;if(Object.freeze(e),Array.isArray(e))for(let r of e)y(r);else for(let r of Object.keys(e)){let t=e[r];t&&typeof t=="object"&&!Object.isFrozen(t)&&y(t)}return e}function $(e){let r=B(e);return y(r)}var R=new Set;function M(e){return R.add(e),()=>{R.delete(e)}}function ee(e){if(R.size!==0)for(let r of R)try{r(e)}catch{}}var O=class e{constructor(r,t,n,i,s){this._trace=r;this._clock=t;this._idGen=n;this._renderer=i;this._options=s;this._completed=!1;this._sequence=0}get isCompleted(){return this._completed}get trace(){return this._trace}step(r,t){if(this._completed)return g;let n=this._options.maxSteps;if(n!==void 0&&this._trace.steps.length>=n)return this._trace.meta===void 0?this._trace.meta={maxStepsExceeded:!0}:this._trace.meta.maxStepsExceeded=!0,g;let i={id:this._idGen.generate(),name:r,sequence:this._sequence++,state:"running",status:"pending",start:this._clock.now(),data:t,children:[]};return this._trace.steps.push(i),new T(i,this._clock)}child(r){if(this._completed)return c;if(this._options.enabled===!1)return c;let t={id:this._idGen.generate(),name:r,parentId:this._trace.id,state:"running",status:void 0,tags:[],start:this._clock.now(),context:{...this._trace.context},steps:[]};return new e(t,this._clock,this._idGen,this._renderer,{...this._options})}tag(r){this._completed||this._trace.tags.includes(r)||this._trace.tags.push(r)}tags(){return[...this._trace.tags]}setContext(r){this._completed||Object.assign(this._trace.context,r)}getContext(){return{...this._trace.context}}success(){this._finalize("success")}fail(r){this._trace.error=f(r),this._finalize("error")}run(r,t){if(this._completed)return Promise.resolve(t());let n=this.step(r);return Promise.resolve(t()).then(i=>(n.success(),i),i=>{throw n.fail(i),i})}_finalize(r){if(this._completed)return;this._completed=!0,this._trace.end=this._clock.now(),this._trace.state="completed",this._trace.status=r;let t=$(this._trace);ee(t),this._renderer.render(t)}};var F=class{generate(){return Math.random().toString(36).slice(2,10)}};var h=class{now(){return Date.now()}};function p(e,r){let t=r?.maxDepth??2,n=r?.maxLength??80,i=new WeakSet;function s(o,l){if(typeof o=="function")return`[Fn:${o.name||"?"}]`;if(typeof o=="symbol")return o.toString();if(l>t)return o&&typeof o=="object"?"[...]":o;if(o===null||typeof o!="object")return o;if(o instanceof Map)return`{Map(${o.size})}`;if(o instanceof Set)return`{Set(${o.size})}`;if(o instanceof Date)return o.toISOString();if(o instanceof RegExp)return o.toString();if(i.has(o))return"[Circular]";if(i.add(o),Array.isArray(o))return o.map(u=>s(u,l+1));let k={};for(let u of Object.keys(o)){let N=o[u];k[u]=s(N,l+1)}return k}try{let o=JSON.stringify(s(e,0));return o&&o.length>n?o.slice(0,n)+"\u2026":o}catch{return"[Unserializable]"}}var re=()=>typeof process<"u"&&process.versions!==void 0&&process.versions.node!==void 0,te=()=>typeof EdgeRuntime<"u",ne=()=>typeof caches<"u"&&"default"in caches,oe=()=>typeof window<"u"||typeof self<"u";function W(){return re()?"node":te()||ne()?"edge":oe()?"browser":"node"}var ie="\x1B[0m",se="\x1B[32m",ae="\x1B[31m";var le="\x1B[36m";var ce="\x1B[2m";function de(){return!(W()==="browser"||typeof process<"u"&&process.env?.NO_COLOR)}var ue=de();function C(e,r){return ue?`${r}${e}${ie}`:e}function I(e){return C(e,se)}function v(e){return C(e,ae)}function J(e){return C(e,le)}function z(e){return C(e,ce)}function q(e,r){if(r===void 0)return"\u2014";let t=Math.round(r-e);return t>=1e3?`${(t/1e3).toFixed(1)}s`:`${t}ms`}function U(e,r,t){let n=" ".repeat(r);t.push(`${n}${J("\u2192")} ${e.name}`),e.data!==void 0&&t.push(`${n} ${z("data:")} ${p(e.data,{maxLength:80})}`);let i=q(e.start,e.end);e.status==="success"?t.push(`${n}${I("\u2713")} ${e.name} (${i})`):e.status==="error"?t.push(`${n}${v("\u2717")} ${e.name} (error: ${e.error?.message??"Unknown error"})`):t.push(`${n} ${e.name} (${i})`);for(let s of e.children)U(s,r+1,t)}var _=class{constructor(){this.name="console"}render(r){let t=[],n=r.tags.length>0?` [${r.tags.join(", ")}]`:"",i=r.status==="error"?"\u{1F525}":"\u{1F680}";t.push(`${i} [flow:${r.name}]${n} (${z("tid:")} ${r.id})`);for(let l of r.steps)U(l,1,t);let s=q(r.start,r.end),o=r.meta?.maxStepsExceeded?` ${v("\u26A0\uFE0F maxSteps exceeded")}`:"";r.status==="error"?(t.push(`\u{1F3C1} [flow:${r.name}] ${v("failed")} (${s}, error: ${r.error?.message??"Unknown error"})${o}`),console.error(t.join(`
|
|
2
|
+
`))):(t.push(`\u{1F3C1} [flow:${r.name}] ${I("success")} (${s})${o}`),console.log(t.join(`
|
|
3
|
+
`)))}};var H=null;function Y(e){H=e}function K(){return H}function Q(e){return H??e}var L=new F,P=new h,me=new _,D=!0;function G(e){D=e}function S(){return D}function we(e){L=e}function ge(e){P=e}function E(e,r){if(!D)return c;let t=r?.sample??1;if(t<1&&Math.random()>t)return c;if(r?.enabled===!1)return c;let n=Q(me),i={id:L.generate(),name:e,state:"running",tags:r?.tags??[],start:P.now(),context:r?.initialContext?{...r.initialContext}:{},steps:[]};return new O(i,P,L,n,r??{})}function xe(e){return e!==null&&typeof e=="object"&&("flow"in e||"tags"in e)}function Fe(e,r,t){if(r.current&&t===void 0&&!r.current.completed)return r.current.flow;let n=t??e.flowName,i=E(n,{tags:[...e.defaultTags]});return r.current={flow:i,timer:null,lastError:null,completed:!1},i}function he(e,r){r.current&&(r.current.timer&&clearTimeout(r.current.timer),r.current.timer=setTimeout(()=>{V(r)},e.idleTimeout))}function V(e){!e.current||e.current.completed||(e.current.timer&&(clearTimeout(e.current.timer),e.current.timer=null),e.current.completed=!0,e.current.lastError?e.current.flow.fail(e.current.lastError):e.current.flow.success(),e.current=null)}function b(e,r,t,n,i,s){if(!S())return;let o,l;n===void 0?(o=void 0,l=void 0):xe(n)?i===void 0?(o=void 0,l=n):(o=void 0,l={...n,...i}):(o=n,l=i);let k=l?.flow,u=Fe(e,r,k);if(l?.tags)for(let j of l.tags)u.tag(j);let N=s&&s!=="info"?`${t} [${s}]`:t,A=u.step(N,o);s==="error"?(A.fail(o),r.current&&(r.current.lastError=o),u.tag("error")):(A.success(),s&&s!=="info"&&u.tag(s)),he(e,r)}var m={idleTimeout:100,flowName:"default",defaultTags:[]},x={current:null};function a(e,r,t){b(m,x,e,r,t)}a.info=(e,r,t)=>b(m,x,e,r,t,"info");a.warn=(e,r,t)=>b(m,x,e,r,t,"warn");a.error=(e,r,t)=>b(m,x,e,r,t,"error");a.setIdleTimeout=e=>{m.idleTimeout=e};a.setFlowName=e=>{m.flowName=e};a.setDefaultTags=e=>{m.defaultTags=e};a.activeFlow=()=>x.current?.flow??null;a.flush=()=>{V(x)};var d=(e,r,t)=>{a(e,r,t)};d.log=a;d.flow=(e,r)=>E(e,r);d.setIdleTimeout=a.setIdleTimeout;d.setFlowName=a.setFlowName;d.setDefaultTags=a.setDefaultTags;d.activeFlow=a.activeFlow;d.flush=a.flush;d.setEnabled=G;d.isEnabled=S;function _e(e){return typeof e=="object"&&e!==null&&"trace"in e&&typeof e.trace=="object"&&e.trace!==null}function X(e){let r=_e(e)?e.trace:e;return JSON.stringify({version:1,flow:{id:r.id,name:r.name,...r.parentId!==void 0&&{parentId:r.parentId},state:r.state,...r.status!==void 0&&{status:r.status},tags:r.tags,start:r.start,...r.end!==void 0&&{end:r.end},...r.error!==void 0&&{error:r.error},context:r.context,steps:r.steps.map(Z),...r.meta!==void 0&&{meta:r.meta}}},null,2)}function Z(e){let r={id:e.id,name:e.name,sequence:e.sequence,state:e.state,status:e.status,start:e.start};if(e.end!==void 0&&(r.end=e.end),e.data!==void 0)try{r.data=JSON.parse(p(e.data))}catch{r.data="[Circular or unserializable]"}return e.error!==void 0&&(r.error=e.error),e.children.length>0&&(r.children=e.children.map(Z)),r}export{c as NOOP_FLOW,g as NOOP_STEP,d as better,E as createFlow,K as getRenderer,S as isEnabled,f as normalizeError,p as safeSerialize,ge as setClock,G as setEnabled,we as setIdGenerator,Y as setRenderer,M as subscribe,X as toJSON};
|
package/package.json
CHANGED