@everscribe/components-core 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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Everscribe
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,157 @@
1
+ <p align="center">
2
+ <img src="https://raw.githubusercontent.com/everscribe/components/main/assets/everscribe.svg" alt="Everscribe" height="64" align="middle">
3
+ &nbsp;&nbsp;<b>+</b>&nbsp;&nbsp;
4
+ <img src="https://raw.githubusercontent.com/everscribe/components/main/assets/typescript.svg" alt="TypeScript" height="56" align="middle">
5
+ </p>
6
+
7
+ <p align="center">
8
+ <a href="https://www.npmjs.com/package/@everscribe/components-core"><img src="https://img.shields.io/npm/v/@everscribe/components-core.svg" alt="npm"></a>
9
+ <a href="https://github.com/everscribe/components/blob/main/LICENSE"><img src="https://img.shields.io/badge/license-MIT-blue.svg" alt="License: MIT"></a>
10
+ </p>
11
+
12
+ # @everscribe/components-core
13
+
14
+ Framework-agnostic core for [Everscribe](https://everscribe.io) embeddable audit-trail UI. The data layer behind [`@everscribe/components-react`](https://github.com/everscribe/components/tree/main/packages/react#readme) and [`@everscribe/components-element`](https://github.com/everscribe/components/tree/main/packages/element#readme): the API client, types, JWT parsing, diff renderer, and observable stores that drive the UI.
15
+
16
+ You usually don't install this directly - install the React or web-component package and you get this transitively. Reach for `core` when you want to **build your own UI** on top of Everscribe's data layer.
17
+
18
+ Part of [@everscribe/components](https://github.com/everscribe/components#readme). Token minting, the refresh chain, security, and rate limits are covered in the [web components guide](https://everscribe.io/docs/web-components/overview).
19
+
20
+ ## Install
21
+
22
+ ```bash
23
+ npm install @everscribe/components-core
24
+ ```
25
+
26
+ No peer dependencies; pure TypeScript, runs in browsers and Node 18+.
27
+
28
+ ## Stores
29
+
30
+ Two observable stores back the UI. Each manages its own lifecycle (initial fetch, polling, abort, dispose) and exposes a `getSnapshot` / `subscribe` interface compatible with React's `useSyncExternalStore` and any other framework's reactivity primitive.
31
+
32
+ ### `createEventsStore(config)`
33
+
34
+ Returns `EventsStore` - events list, pagination, polling, token refresh on 401.
35
+
36
+ ```ts
37
+ import { createEventsStore } from '@everscribe/components-core'
38
+
39
+ const store = createEventsStore({
40
+ apiBase: 'https://api.everscribe.io/v1/embed',
41
+ token,
42
+ pageSize: 25,
43
+ pollInterval: 5000,
44
+ // Same since/before/action/actor/actorType/targetType filters as the API:
45
+ action: 'user.invite',
46
+ })
47
+
48
+ const unsubscribe = store.subscribe(() => {
49
+ const { events, status, nextCursor, error } = store.getSnapshot()
50
+ render(events)
51
+ })
52
+
53
+ store.loadMore() // fetches the next page if cursor is set
54
+ store.refresh() // resets state and re-fetches from the top
55
+
56
+ // Always dispose to abort in-flight requests and stop the poll timer.
57
+ store.dispose()
58
+ unsubscribe()
59
+ ```
60
+
61
+ `pollInterval > 0` enables polling. Below `1000` ms is clamped with a `console.warn`. The poll loop pauses when `document.visibilityState === 'hidden'` and resumes on `visibilitychange`. Polling is also disabled whenever `before` is set - a closed-upper-bound time window can't admit newer events.
62
+
63
+ On a 401, the store calls `onTokenExpired` (if set) or fetches `tokenEndpoint`, swaps the token in-place, and retries the request. If both are absent the store transitions to `status: 'expired'`.
64
+
65
+ ### `createDistinctValuesStore(config)`
66
+
67
+ Returns `DistinctValuesStore` - fetches the three filter-dropdown source lists (`actions`, `actorTypes`, `targetTypes`) once per token. Failures are swallowed silently; an empty dropdown is strictly better UX than blocking the table render on a 500.
68
+
69
+ ```ts
70
+ import { createDistinctValuesStore } from '@everscribe/components-core'
71
+
72
+ const store = createDistinctValuesStore({ apiBase, token })
73
+ const unsubscribe = store.subscribe(() => {
74
+ const { actions, actorTypes, targetTypes } = store.getSnapshot()
75
+ render(actions, actorTypes, targetTypes)
76
+ })
77
+ store.dispose()
78
+ unsubscribe()
79
+ ```
80
+
81
+ ### `parseClaims(token)`
82
+
83
+ Decodes an embed JWT's payload into an `EmbedClaims` object. Returns `null` for null/undefined input or malformed tokens. No signature verification - the server enforces every read.
84
+
85
+ ```ts
86
+ import { parseClaims } from '@everscribe/components-core'
87
+
88
+ const claims = parseClaims(token)
89
+ if (claims?.columns) {
90
+ // Token scopes the column set - the picker should only show these.
91
+ }
92
+ ```
93
+
94
+ ## API client
95
+
96
+ Low-level fetch helpers if you want to skip the stores entirely. Each takes `{ apiBase, token, signal? }` plus its own params.
97
+
98
+ ```ts
99
+ import {
100
+ listEvents,
101
+ getEvent,
102
+ listDistinctActions,
103
+ listDistinctActorTypes,
104
+ listDistinctTargetTypes,
105
+ exportEvents,
106
+ fetchTokenViaOpts,
107
+ EmbedError,
108
+ } from '@everscribe/components-core'
109
+ ```
110
+
111
+ `EmbedError` is the typed error class thrown on non-2xx responses, with `kind` of `'unauthorized' | 'not_found' | 'rate_limited' | 'bad_request' | 'server' | 'network'` and an optional `retryAfterMs` parsed from the `Retry-After` header.
112
+
113
+ ## Diff
114
+
115
+ `renderDiff(change)` produces a side-by-side line diff of an event's `change` payload (`{ before, after }`). LCS-based, line-level, dependency-free. Mirrors the upstream Go implementation so client and server produce the same alignment.
116
+
117
+ ```ts
118
+ import { renderDiff, hasParseableDiff } from '@everscribe/components-core'
119
+
120
+ if (hasParseableDiff(event.change)) {
121
+ const { lines } = renderDiff(event.change)
122
+ // each line: { before, after, beforeKind, afterKind }
123
+ }
124
+ ```
125
+
126
+ ## Columns
127
+
128
+ ```ts
129
+ import { ALL_COLUMNS, COLUMN_LABELS } from '@everscribe/components-core'
130
+ ```
131
+
132
+ `ALL_COLUMNS` is the picker-visible default (`occurred_at`, `action`, `actor`, `target`, `tenant_id`, `result`). `COLUMN_LABELS` maps every known event field to a human label, including the columns not in the default set (`origin`, `metadata`, `change`, `idempotency_key`).
133
+
134
+ A token's `columns` claim, when set, overrides `ALL_COLUMNS` as the available column set.
135
+
136
+ ## Types
137
+
138
+ ```ts
139
+ import type {
140
+ Event,
141
+ EmbedClaims,
142
+ EventsStore,
143
+ EventsStoreConfig,
144
+ EventsStoreState,
145
+ EventsStatus,
146
+ DistinctValues,
147
+ DistinctValuesStore,
148
+ DistinctValuesStoreConfig,
149
+ ApiErrorKind,
150
+ ListEventsParams,
151
+ ExportFormat,
152
+ } from '@everscribe/components-core'
153
+ ```
154
+
155
+ ## License
156
+
157
+ MIT