@sansavision/yousaid 0.0.0-stage → 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/CHANGELOG.md +13 -0
- package/LICENSE +6 -0
- package/README.md +152 -2
- package/dist/index.d.ts +532 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +383 -0
- package/dist/proof-strings.d.ts +39 -0
- package/dist/proof-strings.d.ts.map +1 -0
- package/dist/proof-strings.js +56 -0
- package/dist/proof-upload.d.ts +96 -0
- package/dist/proof-upload.d.ts.map +1 -0
- package/dist/proof-upload.js +174 -0
- package/dist/proof.d.ts +356 -0
- package/dist/proof.d.ts.map +1 -0
- package/dist/proof.js +278 -0
- package/dist/realtime.d.ts +113 -0
- package/dist/realtime.d.ts.map +1 -0
- package/dist/realtime.js +246 -0
- package/package.json +37 -4
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to `@sansavision/yousaid` are recorded here. The project
|
|
4
|
+
follows semantic versioning for the stable surface listed in README.md.
|
|
5
|
+
|
|
6
|
+
## 0.2.0
|
|
7
|
+
|
|
8
|
+
First npm release.
|
|
9
|
+
|
|
10
|
+
- Ships compiled ES2022 JavaScript with TypeScript declarations and declaration maps.
|
|
11
|
+
- Stable: `YouSaidClient` (`sendSignal`, `verifyInstallation`, `listInbox`, `markInboxRead`, `streamInbox`, `confirmRelease`, `mergeAnonymousHistory`), `collectDiagnostics`, `anonymousVisitorId`, `SIGNAL_ATTACHMENT_LIMITS`, `YOUSAID_SDK_VERSION` and the signal, inbox and diagnostics types.
|
|
12
|
+
- New: `SignalInput.context.apphelm` (`AppHelmSignalContext`) carries AppHelm workspace, product, user and session ids so YouSaid can link a conversation back to AppHelm.
|
|
13
|
+
- Experimental (tagged `@experimental`): Rooms, agents, approvals, moderation, proof rendering, beacons and uploads, realtime, `createSseParser` and map helpers.
|
package/LICENSE
ADDED
package/README.md
CHANGED
|
@@ -1,3 +1,153 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @sansavision/yousaid
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
The framework-free YouSaid client. Send customer signals from your product, show
|
|
4
|
+
the end user their private inbox of replies, and ask whether a release fixed
|
|
5
|
+
their problem. Works in any modern browser and in Node 20 or later.
|
|
6
|
+
|
|
7
|
+
```sh
|
|
8
|
+
npm install @sansavision/yousaid @sansavision/yousaid-server
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
`@sansavision/yousaid-server` runs on your server only. It signs the end user's
|
|
12
|
+
identity so the browser never holds your product signing secret.
|
|
13
|
+
|
|
14
|
+
## 1. Mint an identity token on your server
|
|
15
|
+
|
|
16
|
+
```ts
|
|
17
|
+
import { createYouSaidIdentityToken } from "@sansavision/yousaid-server";
|
|
18
|
+
|
|
19
|
+
// GET /api/yousaid-token, behind your own session check.
|
|
20
|
+
export async function GET(request: Request) {
|
|
21
|
+
const user = await currentUser(request);
|
|
22
|
+
const token = await createYouSaidIdentityToken(
|
|
23
|
+
{ sub: user.id, org_id: "org_...", product_id: "prd_...", email: user.email, name: user.name },
|
|
24
|
+
process.env.YOUSAID_SIGNING_SECRET!,
|
|
25
|
+
{ keyId: process.env.YOUSAID_KEY_ID! },
|
|
26
|
+
);
|
|
27
|
+
return new Response(token, { headers: { "cache-control": "no-store" } });
|
|
28
|
+
}
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## 2. Create the client
|
|
32
|
+
|
|
33
|
+
```ts
|
|
34
|
+
import { YouSaidClient } from "@sansavision/yousaid";
|
|
35
|
+
|
|
36
|
+
const client = new YouSaidClient({
|
|
37
|
+
// Prefer a function: every state-changing request consumes the token's nonce.
|
|
38
|
+
token: () => fetch("/api/yousaid-token").then((response) => response.text()),
|
|
39
|
+
});
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
| Option | Meaning |
|
|
43
|
+
| --- | --- |
|
|
44
|
+
| `token` | A signed identity token, or a sync or async function that returns a fresh one. Required. |
|
|
45
|
+
| `endpoint` | The signals URL. Defaults to `https://yousaid.dev/api/signals`. Every other call uses the origin of this URL. |
|
|
46
|
+
| `fetch` | A custom `fetch`, for tests or runtimes without a global one. |
|
|
47
|
+
|
|
48
|
+
## 3. Send a signal
|
|
49
|
+
|
|
50
|
+
```ts
|
|
51
|
+
const receipt = await client.sendSignal({
|
|
52
|
+
kind: "bug", // support, bug, feature, ux or review
|
|
53
|
+
title: "PDF export freezes",
|
|
54
|
+
body: "The export hangs at 90 percent on long pages.",
|
|
55
|
+
context: { route: "/export", appVersion: "4.2.0" },
|
|
56
|
+
});
|
|
57
|
+
// receipt: { signalId, threadId, state: "acknowledged", receipt, inboxUrl, replayed }
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
Retries are safe: pass your own `idempotencyKey` (one is generated otherwise) and a
|
|
61
|
+
replay answers `replayed: true` with the original ids.
|
|
62
|
+
|
|
63
|
+
Attachments and diagnostics are optional:
|
|
64
|
+
|
|
65
|
+
```ts
|
|
66
|
+
import { collectDiagnostics, SIGNAL_ATTACHMENT_LIMITS } from "@sansavision/yousaid";
|
|
67
|
+
|
|
68
|
+
await client.sendSignal({
|
|
69
|
+
title: "Checkout button does nothing",
|
|
70
|
+
body: "Clicking Pay shows no error.",
|
|
71
|
+
attachments: files.slice(0, SIGNAL_ATTACHMENT_LIMITS.maxFiles),
|
|
72
|
+
// Only after the end user saw and agreed to what is shared. Query strings are never included.
|
|
73
|
+
diagnostics: collectDiagnostics({ consent: true, appVersion: "4.2.0" }),
|
|
74
|
+
});
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
### AppHelm context
|
|
78
|
+
|
|
79
|
+
If your product also reports to AppHelm, attach the AppHelm ids so your team
|
|
80
|
+
gets an "Open in AppHelm" link on the conversation:
|
|
81
|
+
|
|
82
|
+
```ts
|
|
83
|
+
await client.sendSignal({
|
|
84
|
+
title: "Sync stopped",
|
|
85
|
+
body: "Nothing synced since this morning.",
|
|
86
|
+
context: {
|
|
87
|
+
apphelm: {
|
|
88
|
+
workspaceId: "ws_123", // required, ^[A-Za-z0-9_-]{1,100}$
|
|
89
|
+
productId: "prod_9", // optional, ^[A-Za-z0-9_-]{1,100}$
|
|
90
|
+
externalUserId: "user-42", // optional, ^[A-Za-z0-9._:@+-]{1,200}$
|
|
91
|
+
distinctHash: "9f86d081884c7d65", // optional lowercase hex, 16 to 128 characters
|
|
92
|
+
sessionHash: "2c26b46b68ffc68f", // optional lowercase hex, 16 to 128 characters
|
|
93
|
+
},
|
|
94
|
+
},
|
|
95
|
+
});
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
Send ids and hashes only, never emails or names. Unknown keys or an invalid value
|
|
99
|
+
drop the whole `apphelm` object; the signal itself is always accepted. YouSaid adds
|
|
100
|
+
the person link (it needs `externalUserId` or `distinctHash`) and the session link
|
|
101
|
+
(it needs `sessionHash`) only when `workspaceId` matches the AppHelm workspace an
|
|
102
|
+
owner or admin connected in YouSaid.
|
|
103
|
+
|
|
104
|
+
## 4. Inbox
|
|
105
|
+
|
|
106
|
+
```ts
|
|
107
|
+
const page = await client.listInbox({ limit: 20 }); // { unread, items, nextCursor }
|
|
108
|
+
await client.markInboxRead(page.items.map((item) => item.id)); // or markInboxRead() for all
|
|
109
|
+
|
|
110
|
+
const stop = new AbortController();
|
|
111
|
+
void client.streamInbox((event) => {
|
|
112
|
+
if (event.type === "item") console.log("New reply", event.item.subject, event.unread);
|
|
113
|
+
}, stop.signal);
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
## 5. Release receipts
|
|
117
|
+
|
|
118
|
+
When you ship a fix, YouSaid asks the people who reported the problem whether it
|
|
119
|
+
works now. Record their answer:
|
|
120
|
+
|
|
121
|
+
```ts
|
|
122
|
+
await client.confirmRelease("rel_...", "resolved");
|
|
123
|
+
await client.confirmRelease("rel_...", "still_broken", "Still freezes on Safari.");
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
`still_broken` opens a follow-up signal for your team.
|
|
127
|
+
|
|
128
|
+
## More
|
|
129
|
+
|
|
130
|
+
- `client.verifyInstallation()` checks the signed identity and records SDK health for onboarding.
|
|
131
|
+
- `anonymousVisitorId()` and `client.mergeAnonymousHistory()` join anonymous hosted-form history to the signed user after sign-in.
|
|
132
|
+
- `YOUSAID_SDK_VERSION` is the version of this package.
|
|
133
|
+
|
|
134
|
+
## Stability
|
|
135
|
+
|
|
136
|
+
Version 0.2.0 marks this surface as **stable**. It follows semantic versioning:
|
|
137
|
+
|
|
138
|
+
- `YouSaidClient` with its constructor options (`token` string or async callback, `endpoint`, `fetch`) and the methods `sendSignal`, `verifyInstallation`, `listInbox`, `markInboxRead`, `streamInbox`, `confirmRelease` and `mergeAnonymousHistory`
|
|
139
|
+
- `collectDiagnostics`, `anonymousVisitorId`, `SIGNAL_ATTACHMENT_LIMITS`, `YOUSAID_SDK_VERSION`
|
|
140
|
+
- the types `SignalInput` (including `context.apphelm`), `SignalReceipt`, `SignalKind`, `InboxItem`, `InboxPage`, `InboxEvent`, `DiagnosticsCapsule`, `YouSaidClientOptions` and `AppHelmSignalContext`
|
|
141
|
+
|
|
142
|
+
Everything else is **experimental** and tagged `@experimental` in the type
|
|
143
|
+
declarations: Rooms methods and types, agents, approvals, moderation, `proof()`
|
|
144
|
+
and the proof render, beacon and upload helpers, `RoomRealtimeClient`,
|
|
145
|
+
`createSseParser` and the map helpers. Experimental APIs can change in any
|
|
146
|
+
minor release.
|
|
147
|
+
|
|
148
|
+
## Licence
|
|
149
|
+
|
|
150
|
+
`UNLICENSED`. All rights reserved, Sansa Group AB. Licence terms are pending
|
|
151
|
+
owner and legal review; see LICENSE.
|
|
152
|
+
|
|
153
|
+
Documentation: https://yousaid.dev/docs/sdk
|