@lovelaces-io/storyteller 0.1.0 → 0.2.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 CHANGED
@@ -1,8 +1,42 @@
1
1
  # Storyteller
2
2
 
3
+ [![npm](https://img.shields.io/npm/v/@lovelaces-io/storyteller)](https://www.npmjs.com/package/@lovelaces-io/storyteller)
4
+ [![license](https://img.shields.io/npm/l/@lovelaces-io/storyteller)](LICENSE)
5
+ [![zero deps](https://img.shields.io/badge/dependencies-0-brightgreen)](package.json)
6
+
3
7
  Lightweight TypeScript logging library that treats logs as **stories** — grouped notes emitted as a single structured event.
4
8
 
5
- Zero dependencies. ~24 kB packed. TypeScript-first.
9
+ Zero dependencies. TypeScript-first. One record per story.
10
+
11
+ ## Why Storyteller?
12
+
13
+ **Before:** 47 scattered `console.log` lines. Something broke. Good luck figuring out what happened.
14
+
15
+ ```
16
+ [14:30:00] User clicked checkout
17
+ [14:30:00] Validating cart...
18
+ [14:30:01] Cart valid
19
+ [14:30:01] Charging card...
20
+ [14:30:03] ERROR: gateway timeout
21
+ [14:30:03] Retrying...
22
+ [14:30:04] Charge succeeded
23
+ ```
24
+
25
+ **After:** One story. One record. The whole picture.
26
+
27
+ ```json
28
+ {
29
+ "level": "Warning",
30
+ "title": "Payment retry succeeded",
31
+ "durationMs": 4000,
32
+ "notes": [
33
+ { "timestamp": "14:30:00", "note": "User clicked checkout" },
34
+ { "timestamp": "14:30:01", "note": "Cart validated", "what": { "items": 3 } },
35
+ { "timestamp": "14:30:03", "note": "Card declined", "error": { "message": "gateway timeout" } },
36
+ { "timestamp": "14:30:04", "note": "Retry succeeded" }
37
+ ]
38
+ }
39
+ ```
6
40
 
7
41
  ## Install
8
42
 
@@ -10,44 +44,41 @@ Zero dependencies. ~24 kB packed. TypeScript-first.
10
44
  npm install @lovelaces-io/storyteller
11
45
  ```
12
46
 
13
- ## Usage
47
+ ## Quick Start
14
48
 
15
49
  ```ts
16
50
  import { Storyteller } from "@lovelaces-io/storyteller";
17
51
 
18
52
  const story = new Storyteller({
19
- origin: { where: { app: "checkout", page: "Payment" } },
20
- });
21
-
22
- // Collect notes as things happen
23
- story.note("User submitted payment", {
24
- who: { id: "user:413" },
25
- what: { amount: 49.99, currency: "USD" },
53
+ origin: { who: "checkout-service", where: { app: "web" } },
26
54
  });
27
55
 
28
- story.note("Charging card", {
29
- what: "stripe:charge",
30
- where: { service: "payments" },
31
- });
32
-
33
- // Tell the story when it's done
56
+ story.note("User submitted payment", { what: { amount: 49.99 } });
57
+ story.note("Charging card", { where: "stripe" });
34
58
  story.tell("Payment completed");
35
59
  ```
36
60
 
37
- Notes are bundled into one structured event, delivered to your audiences, and cleared for the next story.
61
+ Notes are collected, sorted chronologically, and emitted as one structured event to your audiences.
62
+
63
+ ## Two Output Modes
64
+
65
+ | Mode | What it is | Use it for |
66
+ |------|-----------|------------|
67
+ | **Story** (JSON) | Clean serializable record | DB storage, monitoring, audit logs |
68
+ | **Report** (text) | Colorized human-readable output | Console, log files, debugging |
69
+
70
+ `JSON.stringify(event)` gives you the story record. `formatStory(event)` gives you the report.
38
71
 
39
72
  ## Three Levels
40
73
 
41
74
  ```ts
42
- story.tell("Payment completed"); // success
43
- story.warn("Payment slow but succeeded"); // something was off
75
+ story.tell("Payment completed"); // all good
76
+ story.warn("Payment slow but succeeded"); // heads up
44
77
  story.oops("Payment failed", new Error()); // something broke
45
78
  ```
46
79
 
47
80
  ## Context on Every Note
48
81
 
49
- Every note can carry `who`, `what`, `where`, and `error`:
50
-
51
82
  ```ts
52
83
  story.note("Write failed", {
53
84
  who: { id: "user:99" },
@@ -57,83 +88,51 @@ story.note("Write failed", {
57
88
  });
58
89
  ```
59
90
 
60
- ## Audiences
91
+ ## Audiences — Who Hears Your Stories
61
92
 
62
- Stories are delivered to **audiences**. Console is included by default. Add your own:
93
+ Stories are delivered to **audiences**. Console is included by default.
63
94
 
64
95
  ```ts
65
96
  import { dbAudience } from "@lovelaces-io/storyteller";
66
97
 
67
- // Persist warn and oops events to your database
98
+ // Store warn and oops events in your database
68
99
  story.audience.add(
69
100
  dbAudience(async (event) => await db.insert("logs", event))
70
101
  );
71
102
 
72
- // Target specific audiences per story
103
+ // Target specific audiences
73
104
  story.oops("Critical failure", error).to("console", "db");
74
105
  ```
75
106
 
76
- ## Summaries
77
-
78
- Generate a formatted summary without emitting:
79
-
80
- ```ts
81
- const summary = story.summarize({
82
- title: "Dashboard status",
83
- level: "tell",
84
- verbosity: "full",
85
- });
86
-
87
- console.log(summary.text);
88
- ```
89
-
90
- ```
91
- Story: Dashboard status
92
- Level: tell
93
- Time: Mar 22, 2026, 3:42:18 PM (12ms)
94
- Origin: checkout / Payment
95
- Notes:
96
- 3:42:18 PM — User submitted payment
97
- 3:42:18 PM — Charging card
98
- ```
107
+ ## Quick Reference
108
+
109
+ | Method | Returns | Description |
110
+ |--------|---------|-------------|
111
+ | `note(text, context?)` | `this` | Add a timestamped note with optional who/what/where/error |
112
+ | `tell(title)` | `{ to }` | Tell a success story |
113
+ | `warn(title)` | `{ to }` | Tell a cautionary story |
114
+ | `oops(title, error?)` | `{ to }` | Tell an error story |
115
+ | `reset()` | `this` | Clear notes without telling a story |
116
+ | `summarize(options?)` | `FormattedReport` | Preview current notes as a formatted report |
117
+ | `audience.add(member)` | `this` | Register an audience |
118
+ | `audience.remove(name)` | `this` | Unregister an audience |
119
+ | `audience.has(name)` | `boolean` | Check if an audience is listening |
120
+ | `audience.names()` | `string[]` | List who's listening |
99
121
 
100
122
  ## Shared Instance
101
123
 
102
- Use `useStoryteller()` for cross-component logging into the same story:
103
-
104
124
  ```ts
105
125
  import { useStoryteller } from "@lovelaces-io/storyteller";
106
126
 
107
- // Same instance everywhere
108
- const story = useStoryteller({ origin: { where: { app: "admin" } } });
109
- ```
110
-
111
- ## Structured Output
112
-
113
- Every story is a typed, serializable JSON object — designed for humans and machines:
114
-
115
- ```json
116
- {
117
- "timestamp": "2026-03-22T14:15:03.421Z",
118
- "level": "oops",
119
- "title": "Payment failed",
120
- "origin": { "where": { "app": "checkout", "page": "Payment" } },
121
- "notes": [
122
- {
123
- "timestamp": "2026-03-22T14:15:02.218Z",
124
- "note": "User submitted payment",
125
- "who": { "id": "user:413" }
126
- }
127
- ],
128
- "error": { "name": "Error", "message": "gateway timeout" }
129
- }
127
+ const story = useStoryteller({ origin: { who: "worker" } });
130
128
  ```
131
129
 
132
130
  ## Docs
133
131
 
134
132
  - [API Reference](docs/API.md) — full signatures and examples
135
- - [How It Works](docs/HOW-IT-WORKS.md) — narrative guide with real-world scenarios
133
+ - [How It Works](docs/HOW-IT-WORKS.md) — narrative guide
136
134
  - [Changelog](CHANGELOG.md)
135
+ - [For AI Agents](AGENTS.md) — guidance for AI coding assistants
137
136
 
138
137
  ## License
139
138