@productcraft/social 0.7.1 → 1.0.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 +58 -27
- package/dist/index.d.cts +715 -709
- package/dist/index.d.ts +715 -709
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -14,8 +14,8 @@ Social's surface splits two ways — both reach the same data but differ in auth
|
|
|
14
14
|
|
|
15
15
|
| Caller | URL prefix | Auth | What you do |
|
|
16
16
|
|---|---|---|---|
|
|
17
|
-
| **PlatformUser admin** | `/v1/workspaces/{
|
|
18
|
-
| **Customer backend** | `/v1/communities/{
|
|
17
|
+
| **PlatformUser admin** | `/v1/workspaces/{workspace_id}/...` | cookie or PAK | Create communities, run moderation, read analytics. |
|
|
18
|
+
| **Customer backend** | `/v1/communities/{community_id}/...` | PAK + `X-Acting-As: <actor_id>` header | Day-to-day reads/writes on behalf of an EndUser. |
|
|
19
19
|
|
|
20
20
|
The customer backend acts on behalf of one of its EndUsers via the `X-Acting-As` header — the SDK passes whatever you put in headers straight through, so a per-request wrapper that injects the acting actor id is idiomatic.
|
|
21
21
|
|
|
@@ -24,14 +24,13 @@ The customer backend acts on behalf of one of its EndUsers via the `X-Acting-As`
|
|
|
24
24
|
```ts
|
|
25
25
|
import { Social } from "@productcraft/social";
|
|
26
26
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
});
|
|
27
|
+
// Reads PRODUCTCRAFT_API_KEY from the environment
|
|
28
|
+
const social = new Social();
|
|
30
29
|
|
|
31
30
|
const { data, error } = await social.client.POST(
|
|
32
|
-
"/v1/workspaces/{
|
|
31
|
+
"/v1/workspaces/{workspace_id}/communities",
|
|
33
32
|
{
|
|
34
|
-
params: { path: {
|
|
33
|
+
params: { path: { workspace_id: "<workspace-uuid>" } },
|
|
35
34
|
body: { display_name: "Founders Club", slug: "founders" },
|
|
36
35
|
},
|
|
37
36
|
);
|
|
@@ -43,10 +42,10 @@ const { data, error } = await social.client.POST(
|
|
|
43
42
|
const actor_id = "<actor-uuid>"; // the EndUser's Social actor id
|
|
44
43
|
|
|
45
44
|
const { data, error } = await social.client.POST(
|
|
46
|
-
"/v1/communities/{
|
|
45
|
+
"/v1/communities/{community_id}/posts",
|
|
47
46
|
{
|
|
48
47
|
params: {
|
|
49
|
-
path: {
|
|
48
|
+
path: { community_id: "<community-uuid>" },
|
|
50
49
|
header: { "X-Acting-As": actor_id },
|
|
51
50
|
},
|
|
52
51
|
body: {
|
|
@@ -63,10 +62,42 @@ const { data, error } = await social.client.POST(
|
|
|
63
62
|
|
|
64
63
|
Social's wire is snake_case both at the DTO level and in TS types — there's no name translation layer for this surface. Use snake_case keys in `body` to match what the API actually accepts.
|
|
65
64
|
|
|
65
|
+
## Migrating from 0.x to 1.0
|
|
66
|
+
|
|
67
|
+
1.0 renames every **path parameter** to snake_case, to match the rest of the ProductCraft APIs: `{communityId}` is now `{community_id}`, `{actorId}` is `{actor_id}`, `{srcActorId}` is `{src_actor_id}`, and so on. Request URLs are unchanged, so nothing breaks at runtime; the change is in the TypeScript path keys and in `params.path`:
|
|
68
|
+
|
|
69
|
+
```ts
|
|
70
|
+
// 0.x
|
|
71
|
+
await social.client.GET("/v1/communities/{communityId}/posts/{postId}", {
|
|
72
|
+
params: { path: { communityId, postId } },
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
// 1.0
|
|
76
|
+
await social.client.GET("/v1/communities/{community_id}/posts/{post_id}", {
|
|
77
|
+
params: { path: { community_id: communityId, post_id: postId } },
|
|
78
|
+
});
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
Where a route names a target actor next to the acting `actor_id`, the target got its own name: `posts/{post_id}/tags/{tagged_actor_id}/approve`, `actors/{tagged_actor_id}/tagged`, `actors/{owner_actor_id}/highlights`, `lists/{list_id}/members/{member_actor_id}`, `conversations/{conversation_id}/members/{member_actor_id}`. A search-and-replace of the placeholders plus the `path` keys is the whole migration. Post `attributes` now read back with the keys exactly as you stored them (`imageUrl` stays `imageUrl`); before, the API returned them snake_cased.
|
|
82
|
+
|
|
83
|
+
## Credentials from the environment
|
|
84
|
+
|
|
85
|
+
Server-side, omit `auth` and the client reads your workspace key from the environment:
|
|
86
|
+
|
|
87
|
+
```bash
|
|
88
|
+
# .env
|
|
89
|
+
PRODUCTCRAFT_API_KEY=pcft_live_...
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
- An explicit `auth` always wins over the environment.
|
|
93
|
+
- Hosts are never read from the environment. Override them in code with `baseUrl`.
|
|
94
|
+
- This is a server-only fallback. Never put a key in `NEXT_PUBLIC_*` or any other variable a bundler inlines into browser code.
|
|
95
|
+
|
|
66
96
|
## Configuration
|
|
67
97
|
|
|
68
98
|
```ts
|
|
69
99
|
new Social({
|
|
100
|
+
// Omit to use PRODUCTCRAFT_API_KEY from the environment
|
|
70
101
|
auth: { type: "apiKey", key: "pcft_live_..." }
|
|
71
102
|
| { type: "bearer", token: "eyJ..." }
|
|
72
103
|
| { type: "cookie", value: "auth_token=..." },
|
|
@@ -82,20 +113,20 @@ new Social({
|
|
|
82
113
|
```ts
|
|
83
114
|
// Create a post
|
|
84
115
|
await social.client.POST(
|
|
85
|
-
"/v1/communities/{
|
|
86
|
-
{ params: { path: { communityId } }, body: { text: "..." } },
|
|
116
|
+
"/v1/communities/{community_id}/posts",
|
|
117
|
+
{ params: { path: { community_id: communityId } }, body: { text: "..." } },
|
|
87
118
|
);
|
|
88
119
|
|
|
89
120
|
// Get the actor's ranked home feed
|
|
90
121
|
await social.client.GET(
|
|
91
|
-
"/v1/communities/{
|
|
92
|
-
{ params: { path: { communityId, actorId } } },
|
|
122
|
+
"/v1/communities/{community_id}/actors/{actor_id}/feed",
|
|
123
|
+
{ params: { path: { community_id: communityId, actor_id: actorId } } },
|
|
93
124
|
);
|
|
94
125
|
|
|
95
126
|
// Discover (community-wide ranked feed, not personalised to follows)
|
|
96
127
|
await social.client.GET(
|
|
97
|
-
"/v1/communities/{
|
|
98
|
-
{ params: { path: { communityId } } },
|
|
128
|
+
"/v1/communities/{community_id}/discover-feed",
|
|
129
|
+
{ params: { path: { community_id: communityId } } },
|
|
99
130
|
);
|
|
100
131
|
|
|
101
132
|
// React / unreact / bookmark / quote / repost — same shape, different paths
|
|
@@ -106,13 +137,13 @@ await social.client.GET(
|
|
|
106
137
|
```ts
|
|
107
138
|
// Post a story (24h TTL)
|
|
108
139
|
await social.client.POST(
|
|
109
|
-
"/v1/communities/{
|
|
140
|
+
"/v1/communities/{community_id}/stories",
|
|
110
141
|
{ params: { ... }, body: { media_url: "...", visibility: "close_friends" } },
|
|
111
142
|
);
|
|
112
143
|
|
|
113
144
|
// Story tray (the bubble row at the top of the home screen)
|
|
114
145
|
await social.client.GET(
|
|
115
|
-
"/v1/communities/{
|
|
146
|
+
"/v1/communities/{community_id}/actors/{actor_id}/story-tray",
|
|
116
147
|
{ ... },
|
|
117
148
|
);
|
|
118
149
|
```
|
|
@@ -122,12 +153,12 @@ await social.client.GET(
|
|
|
122
153
|
```ts
|
|
123
154
|
// Follow / unfollow
|
|
124
155
|
await social.client.PUT(
|
|
125
|
-
"/v1/communities/{
|
|
156
|
+
"/v1/communities/{community_id}/follows/{src_actor_id}/{dst_actor_id}",
|
|
126
157
|
{ ... },
|
|
127
158
|
);
|
|
128
159
|
|
|
129
160
|
// Block / mute / restrict — same shape, different paths
|
|
130
|
-
// Close friends, hashtag follows, muted terms — all under /actors/{
|
|
161
|
+
// Close friends, hashtag follows, muted terms — all under /actors/{actor_id}/...
|
|
131
162
|
```
|
|
132
163
|
|
|
133
164
|
### Notifications
|
|
@@ -135,19 +166,19 @@ await social.client.PUT(
|
|
|
135
166
|
```ts
|
|
136
167
|
// List
|
|
137
168
|
await social.client.GET(
|
|
138
|
-
"/v1/communities/{
|
|
169
|
+
"/v1/communities/{community_id}/actors/{actor_id}/notifications",
|
|
139
170
|
{ ... },
|
|
140
171
|
);
|
|
141
172
|
|
|
142
173
|
// Unread count for the bell badge
|
|
143
174
|
await social.client.GET(
|
|
144
|
-
"/v1/communities/{
|
|
175
|
+
"/v1/communities/{community_id}/actors/{actor_id}/notifications/unread-count",
|
|
145
176
|
{ ... },
|
|
146
177
|
);
|
|
147
178
|
|
|
148
179
|
// Mark all read
|
|
149
180
|
await social.client.POST(
|
|
150
|
-
"/v1/communities/{
|
|
181
|
+
"/v1/communities/{community_id}/actors/{actor_id}/notifications/read-all",
|
|
151
182
|
{ ... },
|
|
152
183
|
);
|
|
153
184
|
```
|
|
@@ -157,13 +188,13 @@ await social.client.POST(
|
|
|
157
188
|
```ts
|
|
158
189
|
// Start / open a conversation
|
|
159
190
|
await social.client.POST(
|
|
160
|
-
"/v1/communities/{
|
|
191
|
+
"/v1/communities/{community_id}/conversations",
|
|
161
192
|
{ params: { ... }, body: { members: ["act_a", "act_b"] } },
|
|
162
193
|
);
|
|
163
194
|
|
|
164
195
|
// Send a message
|
|
165
196
|
await social.client.POST(
|
|
166
|
-
"/v1/communities/{
|
|
197
|
+
"/v1/communities/{community_id}/conversations/{conversation_id}/messages",
|
|
167
198
|
{ ... },
|
|
168
199
|
);
|
|
169
200
|
```
|
|
@@ -173,19 +204,19 @@ await social.client.POST(
|
|
|
173
204
|
```ts
|
|
174
205
|
// List flags
|
|
175
206
|
await social.client.GET(
|
|
176
|
-
"/v1/workspaces/{
|
|
207
|
+
"/v1/workspaces/{workspace_id}/communities/{community_id}/moderation/flags",
|
|
177
208
|
{ ... },
|
|
178
209
|
);
|
|
179
210
|
|
|
180
211
|
// Act on a flag (resolve / dismiss / take action on the target)
|
|
181
212
|
await social.client.POST(
|
|
182
|
-
"/v1/workspaces/{
|
|
213
|
+
"/v1/workspaces/{workspace_id}/communities/{community_id}/moderation/flags/{flag_id}/actions",
|
|
183
214
|
{ params: { ... }, body: { action: "remove_content", note: "..." } },
|
|
184
215
|
);
|
|
185
216
|
|
|
186
217
|
// Shadow-ban an actor
|
|
187
218
|
await social.client.PUT(
|
|
188
|
-
"/v1/workspaces/{
|
|
219
|
+
"/v1/workspaces/{workspace_id}/communities/{community_id}/moderation/actors/{actor_id}/shadow-ban",
|
|
189
220
|
{ ... },
|
|
190
221
|
);
|
|
191
222
|
```
|