hotpipe 0.1.0 → 0.10.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 +3 -0
- package/dist/client/connection.d.ts +79 -9
- package/dist/client/connection.d.ts.map +1 -1
- package/dist/client/connection.js +191 -39
- package/dist/client/connection.js.map +1 -1
- package/dist/client/index.d.ts +23 -19
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +80 -68
- package/dist/client/index.js.map +1 -1
- package/dist/constants.d.ts +8 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/constants.js +8 -0
- package/dist/constants.js.map +1 -0
- package/dist/server/index.d.ts +114 -33
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/index.js +196 -56
- package/dist/server/index.js.map +1 -1
- package/dist/server/parse-secret.d.ts +5 -0
- package/dist/server/parse-secret.d.ts.map +1 -0
- package/dist/server/parse-secret.js +8 -0
- package/dist/server/parse-secret.js.map +1 -0
- package/dist/version.d.ts +2 -0
- package/dist/version.d.ts.map +1 -0
- package/dist/version.js +2 -0
- package/dist/version.js.map +1 -0
- package/package.json +6 -6
package/dist/server/index.js
CHANGED
|
@@ -1,103 +1,243 @@
|
|
|
1
1
|
import { SignJWT } from 'jose';
|
|
2
|
-
|
|
2
|
+
import { DEFAULT_TOKEN_EXPIRY_SECONDS } from '../constants';
|
|
3
|
+
import { SDK_VERSION } from '../version';
|
|
4
|
+
import { parseSecret } from './parse-secret';
|
|
5
|
+
const DEFAULT_API_URL = 'https://api.hotpipe.dev';
|
|
3
6
|
/**
|
|
4
|
-
*
|
|
7
|
+
* Derives a publish-specific auth token from the shared secret via HMAC.
|
|
8
|
+
* This ensures the raw secret is never sent over the wire as a Bearer token.
|
|
9
|
+
*/
|
|
10
|
+
async function derivePublishToken(apiKey) {
|
|
11
|
+
const encoder = new TextEncoder();
|
|
12
|
+
const key = await crypto.subtle.importKey('raw', encoder.encode(apiKey), { name: 'HMAC', hash: 'SHA-256' }, false, ['sign']);
|
|
13
|
+
const signature = await crypto.subtle.sign('HMAC', key, encoder.encode('hotpipe-publish-v1'));
|
|
14
|
+
return Array.from(new Uint8Array(signature))
|
|
15
|
+
.map((b) => b.toString(16).padStart(2, '0'))
|
|
16
|
+
.join('');
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Creates a typed server-side publisher for emitting events to the hotpipe API
|
|
5
20
|
* from API routes, server actions, webhooks, cron jobs, etc.
|
|
6
21
|
*
|
|
7
22
|
* ```ts
|
|
8
|
-
* const realtime =
|
|
9
|
-
*
|
|
23
|
+
* const realtime = createPipePublisher({
|
|
24
|
+
* secret: process.env.HOTPIPE_SECRET!,
|
|
10
25
|
* events: realtimeEvents,
|
|
11
26
|
* });
|
|
12
27
|
*
|
|
13
|
-
*
|
|
28
|
+
* const teamChat = realtime.pipe('team-chat');
|
|
29
|
+
* await teamChat.publish('message.created', { ... });
|
|
14
30
|
* ```
|
|
15
31
|
*/
|
|
16
|
-
export function
|
|
17
|
-
const
|
|
18
|
-
const
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
32
|
+
export function createPipePublisher(config) {
|
|
33
|
+
const { projectId, apiKey } = parseSecret(config.secret);
|
|
34
|
+
const apiUrl = config.apiUrl ?? DEFAULT_API_URL;
|
|
35
|
+
let cachedHeaders = null;
|
|
36
|
+
async function getHeaders() {
|
|
37
|
+
if (!cachedHeaders) {
|
|
38
|
+
const publishToken = await derivePublishToken(apiKey);
|
|
39
|
+
cachedHeaders = {
|
|
40
|
+
'Content-Type': 'application/json',
|
|
41
|
+
Authorization: `Bearer ${publishToken}`,
|
|
42
|
+
'X-Hotpipe-SDK': SDK_VERSION,
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
return cachedHeaders;
|
|
46
|
+
}
|
|
47
|
+
async function publishToApi(pipe, event, data, options) {
|
|
48
|
+
const schema = config.events[event];
|
|
49
|
+
if (schema) {
|
|
50
|
+
schema.parse(data);
|
|
51
|
+
}
|
|
52
|
+
const body = { projectId, pipe, event, data };
|
|
53
|
+
if (options?.sender) {
|
|
54
|
+
body.sender = options.sender;
|
|
55
|
+
}
|
|
56
|
+
const res = await fetch(`${apiUrl}/publish`, {
|
|
57
|
+
method: 'POST',
|
|
58
|
+
headers: await getHeaders(),
|
|
59
|
+
body: JSON.stringify(body),
|
|
60
|
+
});
|
|
61
|
+
if (!res.ok) {
|
|
62
|
+
throw new Error(`hotpipe publish failed: ${res.status} ${await res.text()}`);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
22
65
|
return {
|
|
23
66
|
/**
|
|
24
|
-
*
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
const res = await fetch(`${brokerUrl}/publish`, {
|
|
32
|
-
method: 'POST',
|
|
33
|
-
headers,
|
|
34
|
-
body: JSON.stringify({ channel, event, data }),
|
|
35
|
-
});
|
|
36
|
-
if (!res.ok) {
|
|
37
|
-
throw new Error(`hotpipe publish failed: ${res.status} ${await res.text()}`);
|
|
38
|
-
}
|
|
39
|
-
},
|
|
40
|
-
/**
|
|
41
|
-
* Publish multiple events in a single HTTP request.
|
|
67
|
+
* Get a reference to a pipe. Returns a `{ publish }` object with
|
|
68
|
+
* the same signature as the client-side `usePipe` publish function.
|
|
69
|
+
*
|
|
70
|
+
* ```ts
|
|
71
|
+
* const teamChat = realtime.pipe('team-chat');
|
|
72
|
+
* await teamChat.publish('message.created', { ... });
|
|
73
|
+
* ```
|
|
42
74
|
*/
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
}
|
|
49
|
-
if (!res.ok) {
|
|
50
|
-
throw new Error(`hotpipe batch publish failed: ${res.status} ${await res.text()}`);
|
|
51
|
-
}
|
|
75
|
+
pipe(pipe) {
|
|
76
|
+
return {
|
|
77
|
+
async publish(event, data, options) {
|
|
78
|
+
return publishToApi(pipe, event, data, options);
|
|
79
|
+
},
|
|
80
|
+
};
|
|
52
81
|
},
|
|
53
82
|
};
|
|
54
83
|
}
|
|
55
84
|
/**
|
|
56
|
-
* Creates a Next.js-compatible route handler for
|
|
57
|
-
*
|
|
58
|
-
*
|
|
85
|
+
* Creates a Next.js-compatible catch-all route handler for hotpipe.
|
|
86
|
+
* Mount this at `app/api/realtime/[...all]/route.ts` and the SDK
|
|
87
|
+
* handles the rest.
|
|
59
88
|
*
|
|
60
89
|
* ```ts
|
|
61
|
-
* // app/api/realtime/
|
|
62
|
-
* export const POST =
|
|
63
|
-
* secret: process.env.
|
|
90
|
+
* // app/api/realtime/[...all]/route.ts
|
|
91
|
+
* export const { POST } = createPipeHandler({
|
|
92
|
+
* secret: process.env.HOTPIPE_SECRET!,
|
|
64
93
|
* authorize: async (req) => {
|
|
65
|
-
* const session = await
|
|
94
|
+
* const { session } = await getAuth(req);
|
|
66
95
|
* if (!session) return null;
|
|
67
96
|
* return {
|
|
68
|
-
* userId: session.
|
|
69
|
-
*
|
|
70
|
-
*
|
|
71
|
-
* [`user-${session.
|
|
97
|
+
* userId: session.userId,
|
|
98
|
+
* pipes: {
|
|
99
|
+
* global: { subscribe: true, publish: true },
|
|
100
|
+
* [`user-${session.userId}`]: { subscribe: true },
|
|
72
101
|
* },
|
|
73
102
|
* };
|
|
74
103
|
* },
|
|
75
104
|
* });
|
|
76
105
|
* ```
|
|
77
106
|
*/
|
|
78
|
-
export function
|
|
79
|
-
const
|
|
80
|
-
const
|
|
81
|
-
|
|
107
|
+
export function createPipeHandler(handlerConfig) {
|
|
108
|
+
const { projectId, apiKey } = parseSecret(handlerConfig.secret);
|
|
109
|
+
const encodedApiKey = new TextEncoder().encode(apiKey);
|
|
110
|
+
const expiry = handlerConfig.tokenExpiry || DEFAULT_TOKEN_EXPIRY_SECONDS;
|
|
111
|
+
async function handleAuth(req) {
|
|
82
112
|
try {
|
|
83
113
|
const result = await handlerConfig.authorize(req);
|
|
84
114
|
if (!result) {
|
|
85
115
|
return Response.json({ error: 'Unauthorized' }, { status: 401 });
|
|
86
116
|
}
|
|
117
|
+
// Transform { subscribe?: boolean, publish?: boolean } to string arrays
|
|
118
|
+
// for the API wire format
|
|
119
|
+
const permissions = {};
|
|
120
|
+
for (const [pipe, perms] of Object.entries(result.pipes)) {
|
|
121
|
+
const arr = [];
|
|
122
|
+
if (perms.subscribe)
|
|
123
|
+
arr.push('subscribe');
|
|
124
|
+
if (perms.publish)
|
|
125
|
+
arr.push('publish');
|
|
126
|
+
permissions[pipe] = arr;
|
|
127
|
+
}
|
|
87
128
|
const token = await new SignJWT({
|
|
88
|
-
|
|
89
|
-
|
|
129
|
+
projectId,
|
|
130
|
+
pipes: Object.keys(result.pipes),
|
|
131
|
+
permissions,
|
|
90
132
|
})
|
|
91
133
|
.setSubject(result.userId)
|
|
92
134
|
.setIssuedAt()
|
|
93
135
|
.setExpirationTime(`${expiry}s`)
|
|
94
136
|
.setProtectedHeader({ alg: 'HS256' })
|
|
95
|
-
.sign(
|
|
137
|
+
.sign(encodedApiKey);
|
|
96
138
|
return Response.json({ token });
|
|
97
139
|
}
|
|
98
140
|
catch {
|
|
99
141
|
return Response.json({ error: 'Internal error' }, { status: 500 });
|
|
100
142
|
}
|
|
143
|
+
}
|
|
144
|
+
async function handler(req) {
|
|
145
|
+
const url = new URL(req.url);
|
|
146
|
+
if (url.pathname.endsWith('/auth')) {
|
|
147
|
+
return handleAuth(req);
|
|
148
|
+
}
|
|
149
|
+
return Response.json({ error: 'Not found' }, { status: 404 });
|
|
150
|
+
}
|
|
151
|
+
return { POST: handler };
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* Creates a server-side admin client for revoking pipe access.
|
|
155
|
+
*
|
|
156
|
+
* ```ts
|
|
157
|
+
* const pipeAdmin = createPipeAdmin({
|
|
158
|
+
* secret: process.env.HOTPIPE_SECRET!,
|
|
159
|
+
* });
|
|
160
|
+
*
|
|
161
|
+
* await pipeAdmin.revoke('user-123', 'room-xyz');
|
|
162
|
+
* await pipeAdmin.revokeAll('user-123');
|
|
163
|
+
* ```
|
|
164
|
+
*/
|
|
165
|
+
export function createPipeAdmin(config) {
|
|
166
|
+
const { projectId, apiKey } = parseSecret(config.secret);
|
|
167
|
+
const apiUrl = config.apiUrl ?? DEFAULT_API_URL;
|
|
168
|
+
let cachedHeaders = null;
|
|
169
|
+
async function getHeaders() {
|
|
170
|
+
if (!cachedHeaders) {
|
|
171
|
+
const publishToken = await derivePublishToken(apiKey);
|
|
172
|
+
cachedHeaders = {
|
|
173
|
+
'Content-Type': 'application/json',
|
|
174
|
+
Authorization: `Bearer ${publishToken}`,
|
|
175
|
+
'X-Hotpipe-SDK': SDK_VERSION,
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
return cachedHeaders;
|
|
179
|
+
}
|
|
180
|
+
async function postRevoke(body) {
|
|
181
|
+
const res = await fetch(`${apiUrl}/revoke`, {
|
|
182
|
+
method: 'POST',
|
|
183
|
+
headers: await getHeaders(),
|
|
184
|
+
body: JSON.stringify({ projectId, ...body }),
|
|
185
|
+
});
|
|
186
|
+
if (!res.ok) {
|
|
187
|
+
throw new Error(`hotpipe revoke failed: ${res.status} ${await res.text()}`);
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
async function postBatchRevoke(body) {
|
|
191
|
+
const res = await fetch(`${apiUrl}/revoke/batch`, {
|
|
192
|
+
method: 'POST',
|
|
193
|
+
headers: await getHeaders(),
|
|
194
|
+
body: JSON.stringify({ projectId, ...body }),
|
|
195
|
+
});
|
|
196
|
+
if (!res.ok) {
|
|
197
|
+
throw new Error(`hotpipe batch revoke failed: ${res.status} ${await res.text()}`);
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
return {
|
|
201
|
+
/**
|
|
202
|
+
* Revoke access to one or more pipes for a user.
|
|
203
|
+
*
|
|
204
|
+
* ```ts
|
|
205
|
+
* await pipeAdmin.revoke('user-123', 'room-xyz');
|
|
206
|
+
* await pipeAdmin.revoke('user-123', ['room-xyz', 'room-abc']);
|
|
207
|
+
* ```
|
|
208
|
+
*/
|
|
209
|
+
async revoke(userId, pipe, options) {
|
|
210
|
+
if (Array.isArray(pipe)) {
|
|
211
|
+
const revocations = pipe.map((p) => ({ userId, pipe: p }));
|
|
212
|
+
await postBatchRevoke({ revocations, ttl: options?.ttl });
|
|
213
|
+
}
|
|
214
|
+
else {
|
|
215
|
+
await postRevoke({ userId, pipe, ttl: options?.ttl });
|
|
216
|
+
}
|
|
217
|
+
},
|
|
218
|
+
/**
|
|
219
|
+
* Revoke all pipe access for a user (e.g., account suspension).
|
|
220
|
+
*
|
|
221
|
+
* ```ts
|
|
222
|
+
* await pipeAdmin.revokeAll('user-123');
|
|
223
|
+
* ```
|
|
224
|
+
*/
|
|
225
|
+
async revokeAll(userId, options) {
|
|
226
|
+
await postRevoke({ userId, allPipes: true, ttl: options?.ttl });
|
|
227
|
+
},
|
|
228
|
+
/**
|
|
229
|
+
* Batch-revoke access for multiple user/pipe combinations.
|
|
230
|
+
*
|
|
231
|
+
* ```ts
|
|
232
|
+
* await pipeAdmin.revokeBatch([
|
|
233
|
+
* { userId: 'user-123', pipe: 'room-xyz' },
|
|
234
|
+
* { userId: 'user-456', pipe: 'room-xyz' },
|
|
235
|
+
* ]);
|
|
236
|
+
* ```
|
|
237
|
+
*/
|
|
238
|
+
async revokeBatch(revocations, options) {
|
|
239
|
+
await postBatchRevoke({ revocations, ttl: options?.ttl });
|
|
240
|
+
},
|
|
101
241
|
};
|
|
102
242
|
}
|
|
103
243
|
//# sourceMappingURL=index.js.map
|
package/dist/server/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/server/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/server/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parse-secret.d.ts","sourceRoot":"","sources":["../../src/server/parse-secret.ts"],"names":[],"mappings":"AAAA,wBAAgB,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAMjF"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export function parseSecret(secret) {
|
|
2
|
+
const match = secret.match(/^hp_([a-zA-Z0-9]{8})_([a-zA-Z0-9]{32})$/);
|
|
3
|
+
if (!match || !match[1]) {
|
|
4
|
+
throw new Error('Invalid hotpipe secret format. Expected: hp_<id>_<key>');
|
|
5
|
+
}
|
|
6
|
+
return { projectId: match[1], apiKey: secret };
|
|
7
|
+
}
|
|
8
|
+
//# sourceMappingURL=parse-secret.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parse-secret.js","sourceRoot":"","sources":["../../src/server/parse-secret.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,WAAW,CAAC,MAAc;IACxC,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,yCAAyC,CAAC,CAAC;IACtE,IAAI,CAAC,KAAK,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;QACxB,MAAM,IAAI,KAAK,CAAC,wDAAwD,CAAC,CAAC;IAC5E,CAAC;IACD,OAAO,EAAE,SAAS,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC;AACjD,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"version.d.ts","sourceRoot":"","sources":["../src/version.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,WAAW,WAAW,CAAC"}
|
package/dist/version.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"version.js","sourceRoot":"","sources":["../src/version.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,WAAW,GAAG,QAAQ,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "hotpipe",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "Type-safe real-time
|
|
3
|
+
"version": "0.10.0",
|
|
4
|
+
"description": "Type-safe real-time events for React and Next.js",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"keywords": [
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
"react",
|
|
11
11
|
"hooks",
|
|
12
12
|
"pubsub",
|
|
13
|
-
"
|
|
13
|
+
"events",
|
|
14
14
|
"nextjs",
|
|
15
15
|
"type-safe",
|
|
16
16
|
"zod"
|
|
@@ -40,7 +40,7 @@
|
|
|
40
40
|
"reset": "npm run clean && rm -rf node_modules"
|
|
41
41
|
},
|
|
42
42
|
"dependencies": {
|
|
43
|
-
"jose": "^
|
|
43
|
+
"jose": "^6.1.3"
|
|
44
44
|
},
|
|
45
45
|
"peerDependencies": {
|
|
46
46
|
"react": ">=18",
|
|
@@ -48,7 +48,7 @@
|
|
|
48
48
|
},
|
|
49
49
|
"devDependencies": {
|
|
50
50
|
"@pepper/tsconfig": "1.0.0",
|
|
51
|
-
"@types/react": ">=
|
|
52
|
-
"typescript": "^5.
|
|
51
|
+
"@types/react": ">=19",
|
|
52
|
+
"typescript": "^5.9.3"
|
|
53
53
|
}
|
|
54
54
|
}
|