@brokr/sdk 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/dist/auth.js +175 -0
- package/dist/auth.mjs +151 -0
- package/dist/brokr_runtime.py +333 -0
- package/dist/index.d.ts +17 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +568 -0
- package/dist/index.mjs +558 -0
- package/dist/management.js +92 -0
- package/dist/management.mjs +66 -0
- package/dist/react.js +264 -0
- package/dist/react.mjs +225 -0
- package/dist/runtime.js +512 -0
- package/dist/runtime.mjs +501 -0
- package/dist/src/auth.d.ts +70 -0
- package/dist/src/auth.d.ts.map +1 -0
- package/dist/src/management.d.ts +68 -0
- package/dist/src/management.d.ts.map +1 -0
- package/dist/src/react/auth.d.ts +50 -0
- package/dist/src/react/auth.d.ts.map +1 -0
- package/dist/src/runtime.d.ts +217 -0
- package/dist/src/runtime.d.ts.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/dist/types.d.ts +135 -0
- package/dist/types.d.ts.map +1 -0
- package/package.json +79 -0
package/dist/runtime.mjs
ADDED
|
@@ -0,0 +1,501 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
3
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
4
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
5
|
+
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
6
|
+
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
|
|
7
|
+
}) : x)(function(x) {
|
|
8
|
+
if (typeof require !== "undefined") return require.apply(this, arguments);
|
|
9
|
+
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
10
|
+
});
|
|
11
|
+
var __esm = (fn, res) => function __init() {
|
|
12
|
+
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
13
|
+
};
|
|
14
|
+
var __export = (target, all) => {
|
|
15
|
+
for (var name in all)
|
|
16
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
17
|
+
};
|
|
18
|
+
var __copyProps = (to, from, except, desc) => {
|
|
19
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
20
|
+
for (let key of __getOwnPropNames(from))
|
|
21
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
22
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
23
|
+
}
|
|
24
|
+
return to;
|
|
25
|
+
};
|
|
26
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
27
|
+
|
|
28
|
+
// src/auth.ts
|
|
29
|
+
var auth_exports = {};
|
|
30
|
+
__export(auth_exports, {
|
|
31
|
+
BrokrAuthClient: () => BrokrAuthClient,
|
|
32
|
+
authMiddleware: () => authMiddleware
|
|
33
|
+
});
|
|
34
|
+
function parseCookies(cookieHeader) {
|
|
35
|
+
const cookies = /* @__PURE__ */ new Map();
|
|
36
|
+
for (const pair of cookieHeader.split(";")) {
|
|
37
|
+
const eqIdx = pair.indexOf("=");
|
|
38
|
+
if (eqIdx === -1) continue;
|
|
39
|
+
const name = pair.slice(0, eqIdx).trim();
|
|
40
|
+
const value = pair.slice(eqIdx + 1).trim();
|
|
41
|
+
if (name) cookies.set(name, value);
|
|
42
|
+
}
|
|
43
|
+
return cookies;
|
|
44
|
+
}
|
|
45
|
+
function authMiddleware(options) {
|
|
46
|
+
const { protectedRoutes = [], publicOnlyRoutes = [] } = options;
|
|
47
|
+
return async function middleware(request) {
|
|
48
|
+
const url = new URL(request.url);
|
|
49
|
+
const pathname = url.pathname;
|
|
50
|
+
const isProtected = protectedRoutes.some((route) => pathname.startsWith(route));
|
|
51
|
+
const isPublicOnly = publicOnlyRoutes.some((route) => pathname.startsWith(route));
|
|
52
|
+
if (!isProtected && !isPublicOnly) return void 0;
|
|
53
|
+
const cookieHeader = request.headers.get("cookie") ?? "";
|
|
54
|
+
const cookies = parseCookies(cookieHeader);
|
|
55
|
+
const hasSession = cookies.has("better-auth.session_token");
|
|
56
|
+
if (isProtected && !hasSession) {
|
|
57
|
+
return Response.redirect(new URL("/sign-in", request.url).toString(), 302);
|
|
58
|
+
}
|
|
59
|
+
if (isPublicOnly && hasSession) {
|
|
60
|
+
return Response.redirect(new URL("/", request.url).toString(), 302);
|
|
61
|
+
}
|
|
62
|
+
return void 0;
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
var BrokrAuthClient;
|
|
66
|
+
var init_auth = __esm({
|
|
67
|
+
"src/auth.ts"() {
|
|
68
|
+
"use strict";
|
|
69
|
+
init_runtime();
|
|
70
|
+
BrokrAuthClient = class {
|
|
71
|
+
constructor(token, gatewayUrl, appUrl) {
|
|
72
|
+
this._token = token;
|
|
73
|
+
this._gatewayUrl = gatewayUrl;
|
|
74
|
+
this._appUrl = appUrl ?? (typeof process !== "undefined" ? process.env.BETTER_AUTH_URL : void 0);
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Get current user from an incoming request's cookies.
|
|
78
|
+
* Calls the local Better Auth API (runs inside your app).
|
|
79
|
+
*/
|
|
80
|
+
async currentUser(request) {
|
|
81
|
+
const session = await this.getSession(request);
|
|
82
|
+
return session?.user ?? null;
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Get the full session (user + metadata) from an incoming request.
|
|
86
|
+
* Calls the local Better Auth API.
|
|
87
|
+
*/
|
|
88
|
+
async getSession(request) {
|
|
89
|
+
const appUrl = this._appUrl;
|
|
90
|
+
if (!appUrl) {
|
|
91
|
+
throw new BrokrError(
|
|
92
|
+
"[brokr] BETTER_AUTH_URL is not set. Auth may not be provisioned.",
|
|
93
|
+
"AUTH_NOT_CONFIGURED",
|
|
94
|
+
"auth"
|
|
95
|
+
);
|
|
96
|
+
}
|
|
97
|
+
const cookieHeader = request.headers.get("cookie") ?? "";
|
|
98
|
+
if (!cookieHeader) return null;
|
|
99
|
+
const res = await fetch(`${appUrl}/api/auth/get-session`, {
|
|
100
|
+
method: "GET",
|
|
101
|
+
headers: { cookie: cookieHeader }
|
|
102
|
+
});
|
|
103
|
+
if (!res.ok) return null;
|
|
104
|
+
const data = await res.json();
|
|
105
|
+
if (!data?.user || !data?.session) return null;
|
|
106
|
+
return {
|
|
107
|
+
user: {
|
|
108
|
+
id: data.user.id,
|
|
109
|
+
email: data.user.email,
|
|
110
|
+
name: data.user.name ?? null,
|
|
111
|
+
avatarUrl: data.user.image ?? null,
|
|
112
|
+
emailVerified: data.user.emailVerified ? /* @__PURE__ */ new Date() : null
|
|
113
|
+
},
|
|
114
|
+
sessionId: data.session.id,
|
|
115
|
+
expiresAt: new Date(data.session.expiresAt)
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Generate an OAuth authorization URL.
|
|
120
|
+
*/
|
|
121
|
+
async getOAuthUrl(provider, options) {
|
|
122
|
+
const appUrl = this._appUrl;
|
|
123
|
+
if (!appUrl) {
|
|
124
|
+
throw new BrokrError("[brokr] BETTER_AUTH_URL is not set.", "AUTH_NOT_CONFIGURED", "auth");
|
|
125
|
+
}
|
|
126
|
+
const redirectTo = options?.redirectTo ?? "/";
|
|
127
|
+
if (!redirectTo.startsWith("/") || redirectTo.startsWith("//")) {
|
|
128
|
+
throw new BrokrError("[brokr] redirectTo must be a relative path (start with /)", "INVALID_REDIRECT", "auth");
|
|
129
|
+
}
|
|
130
|
+
const params = new URLSearchParams({ callbackURL: redirectTo });
|
|
131
|
+
return { redirectUrl: `${appUrl}/api/auth/sign-in/social?provider=${provider}&${params}` };
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Send a magic link email (requires email capability).
|
|
135
|
+
*/
|
|
136
|
+
async sendMagicLink(email, options) {
|
|
137
|
+
const appUrl = this._appUrl;
|
|
138
|
+
if (!appUrl) {
|
|
139
|
+
throw new BrokrError("[brokr] BETTER_AUTH_URL is not set.", "AUTH_NOT_CONFIGURED", "auth");
|
|
140
|
+
}
|
|
141
|
+
const res = await fetch(`${appUrl}/api/auth/magic-link/send`, {
|
|
142
|
+
method: "POST",
|
|
143
|
+
headers: { "Content-Type": "application/json" },
|
|
144
|
+
body: JSON.stringify({ email, callbackURL: options?.redirectTo ?? "/" })
|
|
145
|
+
});
|
|
146
|
+
if (!res.ok) {
|
|
147
|
+
const data = await res.json().catch(() => ({}));
|
|
148
|
+
throw new BrokrError(
|
|
149
|
+
data.message ?? `[brokr] Failed to send magic link (HTTP ${res.status})`,
|
|
150
|
+
"AUTH_MAGIC_LINK_FAILED",
|
|
151
|
+
"auth"
|
|
152
|
+
);
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
// src/runtime.ts
|
|
160
|
+
function resolveToken() {
|
|
161
|
+
return typeof process !== "undefined" ? process.env.BROKR_TOKEN : void 0;
|
|
162
|
+
}
|
|
163
|
+
function assertToken(token, capability) {
|
|
164
|
+
if (!token) {
|
|
165
|
+
let hint = "brokr env pull --stack <name>";
|
|
166
|
+
try {
|
|
167
|
+
if (typeof process !== "undefined") {
|
|
168
|
+
const fs = __require("fs");
|
|
169
|
+
const path = __require("path");
|
|
170
|
+
const brokrFile = path.join(process.cwd(), ".brokr");
|
|
171
|
+
if (fs.existsSync(brokrFile)) {
|
|
172
|
+
const data = JSON.parse(fs.readFileSync(brokrFile, "utf8"));
|
|
173
|
+
if (data?.stackName) hint = `brokr env pull --stack ${data.stackName}`;
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
} catch {
|
|
177
|
+
}
|
|
178
|
+
throw new BrokrAuthError(
|
|
179
|
+
`[brokr] BROKR_TOKEN is not set.
|
|
180
|
+
Run: ${hint}`,
|
|
181
|
+
"BROKR_TOKEN_MISSING"
|
|
182
|
+
);
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
async function gatewayFetch(gatewayUrl, token, path, body, capability) {
|
|
186
|
+
let res;
|
|
187
|
+
try {
|
|
188
|
+
res = await fetch(`${gatewayUrl}${path}`, {
|
|
189
|
+
method: "POST",
|
|
190
|
+
headers: { "Content-Type": "application/json", Authorization: `Bearer ${token}` },
|
|
191
|
+
body: JSON.stringify(body)
|
|
192
|
+
});
|
|
193
|
+
} catch (err) {
|
|
194
|
+
throw new BrokrNetworkError(
|
|
195
|
+
`[brokr] Could not reach Brokr gateway. Check your network.
|
|
196
|
+
${err instanceof Error ? err.message : String(err)}`,
|
|
197
|
+
capability
|
|
198
|
+
);
|
|
199
|
+
}
|
|
200
|
+
if (res.status === 429) {
|
|
201
|
+
const retryAfter = parseInt(res.headers.get("Retry-After") ?? "60", 10);
|
|
202
|
+
const data = await res.json().catch(() => ({}));
|
|
203
|
+
throw new BrokrRateLimitError(
|
|
204
|
+
data.error ?? `[brokr] Rate limited (retry after ${retryAfter}s)`,
|
|
205
|
+
retryAfter,
|
|
206
|
+
capability
|
|
207
|
+
);
|
|
208
|
+
}
|
|
209
|
+
if (res.status === 401) {
|
|
210
|
+
throw new BrokrAuthError("[brokr] Invalid or expired BROKR_TOKEN.", "BROKR_TOKEN_INVALID");
|
|
211
|
+
}
|
|
212
|
+
if (!res.ok) {
|
|
213
|
+
const data = await res.json().catch(() => ({}));
|
|
214
|
+
throw new BrokrError(
|
|
215
|
+
data.error ?? `[brokr] ${capability} request failed (HTTP ${res.status})`,
|
|
216
|
+
data.code ?? `${capability.toUpperCase()}_FAILED`,
|
|
217
|
+
capability
|
|
218
|
+
);
|
|
219
|
+
}
|
|
220
|
+
return res.json();
|
|
221
|
+
}
|
|
222
|
+
function createBrokr(options) {
|
|
223
|
+
return new BrokrRuntime(options);
|
|
224
|
+
}
|
|
225
|
+
var GATEWAY_URL, BrokrError, BrokrAuthError, BrokrRateLimitError, BrokrNetworkError, models, BrokrAIClient, BrokrStorageClient, BrokrEmailClient, BrokrRuntime;
|
|
226
|
+
var init_runtime = __esm({
|
|
227
|
+
"src/runtime.ts"() {
|
|
228
|
+
GATEWAY_URL = "https://api.brokr.sh";
|
|
229
|
+
BrokrError = class extends Error {
|
|
230
|
+
constructor(message, code, capability, retryable = false) {
|
|
231
|
+
super(message);
|
|
232
|
+
this.code = code;
|
|
233
|
+
this.capability = capability;
|
|
234
|
+
this.retryable = retryable;
|
|
235
|
+
this.name = "BrokrError";
|
|
236
|
+
}
|
|
237
|
+
};
|
|
238
|
+
BrokrAuthError = class extends BrokrError {
|
|
239
|
+
constructor(message, code) {
|
|
240
|
+
super(message, code, "auth", false);
|
|
241
|
+
this.name = "BrokrAuthError";
|
|
242
|
+
}
|
|
243
|
+
};
|
|
244
|
+
BrokrRateLimitError = class extends BrokrError {
|
|
245
|
+
constructor(message, retryAfter, capability) {
|
|
246
|
+
super(message, "RATE_LIMITED", capability, true);
|
|
247
|
+
this.retryAfter = retryAfter;
|
|
248
|
+
this.name = "BrokrRateLimitError";
|
|
249
|
+
}
|
|
250
|
+
};
|
|
251
|
+
BrokrNetworkError = class extends BrokrError {
|
|
252
|
+
constructor(message, capability) {
|
|
253
|
+
super(message, "NETWORK_ERROR", capability, true);
|
|
254
|
+
this.name = "BrokrNetworkError";
|
|
255
|
+
}
|
|
256
|
+
};
|
|
257
|
+
models = {
|
|
258
|
+
/** Cheapest and fastest model (Deepseek Chat). */
|
|
259
|
+
FAST: "deepseek-chat",
|
|
260
|
+
/** Most capable model. */
|
|
261
|
+
SMART: "claude-sonnet-4-20250514",
|
|
262
|
+
/** Default balanced model (Deepseek Chat). */
|
|
263
|
+
BALANCED: "deepseek-chat"
|
|
264
|
+
};
|
|
265
|
+
BrokrAIClient = class {
|
|
266
|
+
constructor(_token, _gatewayUrl) {
|
|
267
|
+
this._token = _token;
|
|
268
|
+
this._gatewayUrl = _gatewayUrl;
|
|
269
|
+
}
|
|
270
|
+
/**
|
|
271
|
+
* Send a chat completion request.
|
|
272
|
+
*
|
|
273
|
+
* @example
|
|
274
|
+
* ```typescript
|
|
275
|
+
* const reply = await brokr.ai.chat([
|
|
276
|
+
* { role: 'user', content: 'Explain quantum computing in one sentence.' }
|
|
277
|
+
* ]);
|
|
278
|
+
* console.log(reply.content);
|
|
279
|
+
* ```
|
|
280
|
+
*/
|
|
281
|
+
async chat(messages, options) {
|
|
282
|
+
assertToken(this._token, "ai");
|
|
283
|
+
const data = await gatewayFetch(this._gatewayUrl, this._token, "/v1/chat/completions", {
|
|
284
|
+
messages,
|
|
285
|
+
model: options?.model,
|
|
286
|
+
max_tokens: options?.maxTokens,
|
|
287
|
+
temperature: options?.temperature
|
|
288
|
+
}, "ai");
|
|
289
|
+
return {
|
|
290
|
+
content: data.choices?.[0]?.message?.content ?? "",
|
|
291
|
+
model: data.model ?? "",
|
|
292
|
+
usage: {
|
|
293
|
+
promptTokens: data.usage?.prompt_tokens ?? 0,
|
|
294
|
+
completionTokens: data.usage?.completion_tokens ?? 0
|
|
295
|
+
}
|
|
296
|
+
};
|
|
297
|
+
}
|
|
298
|
+
/**
|
|
299
|
+
* Stream a chat completion. Yields text strings directly.
|
|
300
|
+
*
|
|
301
|
+
* @example
|
|
302
|
+
* ```typescript
|
|
303
|
+
* for await (const text of brokr.ai.stream(messages)) {
|
|
304
|
+
* process.stdout.write(text);
|
|
305
|
+
* }
|
|
306
|
+
* ```
|
|
307
|
+
*/
|
|
308
|
+
async *stream(messages, options) {
|
|
309
|
+
assertToken(this._token, "ai");
|
|
310
|
+
let res;
|
|
311
|
+
try {
|
|
312
|
+
res = await fetch(`${this._gatewayUrl}/v1/chat/completions`, {
|
|
313
|
+
method: "POST",
|
|
314
|
+
headers: { "Content-Type": "application/json", Authorization: `Bearer ${this._token}` },
|
|
315
|
+
body: JSON.stringify({ messages, stream: true, model: options?.model, max_tokens: options?.maxTokens })
|
|
316
|
+
});
|
|
317
|
+
} catch (err) {
|
|
318
|
+
throw new BrokrNetworkError(
|
|
319
|
+
`[brokr] Could not reach Brokr gateway.
|
|
320
|
+
${err instanceof Error ? err.message : String(err)}`,
|
|
321
|
+
"ai"
|
|
322
|
+
);
|
|
323
|
+
}
|
|
324
|
+
if (res.status === 429) {
|
|
325
|
+
const retryAfter = parseInt(res.headers.get("Retry-After") ?? "60", 10);
|
|
326
|
+
throw new BrokrRateLimitError("[brokr] AI rate limited.", retryAfter, "ai");
|
|
327
|
+
}
|
|
328
|
+
if (res.status === 401) {
|
|
329
|
+
throw new BrokrAuthError("[brokr] Invalid or expired BROKR_TOKEN.", "BROKR_TOKEN_INVALID");
|
|
330
|
+
}
|
|
331
|
+
if (!res.ok || !res.body) {
|
|
332
|
+
throw new BrokrError(`[brokr] AI stream failed (HTTP ${res.status})`, "AI_STREAM_FAILED", "ai");
|
|
333
|
+
}
|
|
334
|
+
const reader = res.body.getReader();
|
|
335
|
+
const decoder = new TextDecoder();
|
|
336
|
+
let buffer = "";
|
|
337
|
+
while (true) {
|
|
338
|
+
const { done, value } = await reader.read();
|
|
339
|
+
if (done) break;
|
|
340
|
+
buffer += decoder.decode(value, { stream: true });
|
|
341
|
+
const lines = buffer.split("\n");
|
|
342
|
+
buffer = lines.pop() ?? "";
|
|
343
|
+
for (const line of lines) {
|
|
344
|
+
if (!line.startsWith("data: ")) continue;
|
|
345
|
+
const payload = line.slice(6).trim();
|
|
346
|
+
if (payload === "[DONE]") return;
|
|
347
|
+
try {
|
|
348
|
+
const parsed = JSON.parse(payload);
|
|
349
|
+
const delta = parsed.choices?.[0]?.delta?.content ?? "";
|
|
350
|
+
if (delta) yield delta;
|
|
351
|
+
} catch {
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
/**
|
|
357
|
+
* OpenAI-SDK compatible base URL.
|
|
358
|
+
*
|
|
359
|
+
* @example
|
|
360
|
+
* ```typescript
|
|
361
|
+
* const openai = new OpenAI({ baseURL: brokr.ai.baseURL, apiKey: brokr.ai.apiKey });
|
|
362
|
+
* ```
|
|
363
|
+
*/
|
|
364
|
+
get baseURL() {
|
|
365
|
+
return `${this._gatewayUrl}/v1`;
|
|
366
|
+
}
|
|
367
|
+
/** Use as `apiKey` with the official OpenAI SDK to route through Brokr's gateway. */
|
|
368
|
+
get apiKey() {
|
|
369
|
+
assertToken(this._token, "ai");
|
|
370
|
+
return this._token;
|
|
371
|
+
}
|
|
372
|
+
};
|
|
373
|
+
BrokrStorageClient = class {
|
|
374
|
+
constructor(_token, _gatewayUrl) {
|
|
375
|
+
this._token = _token;
|
|
376
|
+
this._gatewayUrl = _gatewayUrl;
|
|
377
|
+
}
|
|
378
|
+
/**
|
|
379
|
+
* Get a presigned upload URL for browser-direct or streaming uploads.
|
|
380
|
+
*
|
|
381
|
+
* @example
|
|
382
|
+
* ```typescript
|
|
383
|
+
* const { url, key } = await brokr.storage.getUploadUrl('avatar.png', 'image/png');
|
|
384
|
+
* await fetch(url, { method: 'PUT', body: file });
|
|
385
|
+
* ```
|
|
386
|
+
*/
|
|
387
|
+
async getUploadUrl(filename, contentType = "application/octet-stream") {
|
|
388
|
+
assertToken(this._token, "storage");
|
|
389
|
+
return gatewayFetch(
|
|
390
|
+
this._gatewayUrl,
|
|
391
|
+
this._token,
|
|
392
|
+
"/v1/storage/sign-upload",
|
|
393
|
+
{ filename, contentType },
|
|
394
|
+
"storage"
|
|
395
|
+
);
|
|
396
|
+
}
|
|
397
|
+
/**
|
|
398
|
+
* Upload data to R2. Returns the stable object key.
|
|
399
|
+
*
|
|
400
|
+
* @example
|
|
401
|
+
* ```typescript
|
|
402
|
+
* const { key } = await brokr.storage.upload(fileBuffer, 'photo.jpg', 'image/jpeg');
|
|
403
|
+
* ```
|
|
404
|
+
*/
|
|
405
|
+
async upload(data, filename, contentType = "application/octet-stream") {
|
|
406
|
+
const { url, key } = await this.getUploadUrl(filename, contentType);
|
|
407
|
+
const putRes = await fetch(url, {
|
|
408
|
+
method: "PUT",
|
|
409
|
+
headers: { "Content-Type": contentType },
|
|
410
|
+
body: data
|
|
411
|
+
});
|
|
412
|
+
if (!putRes.ok) {
|
|
413
|
+
throw new BrokrError(`[brokr] Upload failed (HTTP ${putRes.status})`, "STORAGE_UPLOAD_FAILED", "storage");
|
|
414
|
+
}
|
|
415
|
+
return { key };
|
|
416
|
+
}
|
|
417
|
+
/**
|
|
418
|
+
* Get a presigned download URL for a stored object.
|
|
419
|
+
*
|
|
420
|
+
* @example
|
|
421
|
+
* ```typescript
|
|
422
|
+
* const { url } = await brokr.storage.url('photos/avatar.jpg');
|
|
423
|
+
* // use url in <img src={url} /> or redirect
|
|
424
|
+
* ```
|
|
425
|
+
*/
|
|
426
|
+
async url(key, options) {
|
|
427
|
+
assertToken(this._token, "storage");
|
|
428
|
+
return gatewayFetch(
|
|
429
|
+
this._gatewayUrl,
|
|
430
|
+
this._token,
|
|
431
|
+
"/v1/storage/sign-download",
|
|
432
|
+
{ key, expiresIn: options?.expiresIn },
|
|
433
|
+
"storage"
|
|
434
|
+
);
|
|
435
|
+
}
|
|
436
|
+
/** @deprecated Use `url()` instead. */
|
|
437
|
+
async getUrl(key, options) {
|
|
438
|
+
return this.url(key, options);
|
|
439
|
+
}
|
|
440
|
+
};
|
|
441
|
+
BrokrEmailClient = class {
|
|
442
|
+
constructor(_token, _gatewayUrl) {
|
|
443
|
+
this._token = _token;
|
|
444
|
+
this._gatewayUrl = _gatewayUrl;
|
|
445
|
+
}
|
|
446
|
+
/**
|
|
447
|
+
* Send an email. The from address and API credentials are resolved server-side.
|
|
448
|
+
*
|
|
449
|
+
* @example
|
|
450
|
+
* ```typescript
|
|
451
|
+
* await brokr.email.send({
|
|
452
|
+
* to: 'user@example.com',
|
|
453
|
+
* subject: 'Welcome!',
|
|
454
|
+
* html: '<h1>Welcome to the app</h1>',
|
|
455
|
+
* });
|
|
456
|
+
* ```
|
|
457
|
+
*/
|
|
458
|
+
async send(params) {
|
|
459
|
+
assertToken(this._token, "email");
|
|
460
|
+
return gatewayFetch(
|
|
461
|
+
this._gatewayUrl,
|
|
462
|
+
this._token,
|
|
463
|
+
"/v1/email/send",
|
|
464
|
+
params,
|
|
465
|
+
"email"
|
|
466
|
+
);
|
|
467
|
+
}
|
|
468
|
+
};
|
|
469
|
+
BrokrRuntime = class {
|
|
470
|
+
constructor(options) {
|
|
471
|
+
this._token = options?.token ?? resolveToken();
|
|
472
|
+
this._gatewayUrl = options?.gatewayUrl ?? GATEWAY_URL;
|
|
473
|
+
this.ai = new BrokrAIClient(this._token, this._gatewayUrl);
|
|
474
|
+
this.storage = new BrokrStorageClient(this._token, this._gatewayUrl);
|
|
475
|
+
this.email = new BrokrEmailClient(this._token, this._gatewayUrl);
|
|
476
|
+
}
|
|
477
|
+
/** Auth client — lazily initialized to avoid pulling in auth deps when not needed. */
|
|
478
|
+
get auth() {
|
|
479
|
+
if (!this._auth) {
|
|
480
|
+
const { BrokrAuthClient: BrokrAuthClient2 } = (init_auth(), __toCommonJS(auth_exports));
|
|
481
|
+
this._auth = new BrokrAuthClient2(this._token, this._gatewayUrl);
|
|
482
|
+
}
|
|
483
|
+
return this._auth;
|
|
484
|
+
}
|
|
485
|
+
};
|
|
486
|
+
}
|
|
487
|
+
});
|
|
488
|
+
init_runtime();
|
|
489
|
+
export {
|
|
490
|
+
BrokrAIClient,
|
|
491
|
+
BrokrAuthError,
|
|
492
|
+
BrokrEmailClient,
|
|
493
|
+
BrokrError,
|
|
494
|
+
BrokrNetworkError,
|
|
495
|
+
BrokrRateLimitError,
|
|
496
|
+
BrokrRuntime,
|
|
497
|
+
BrokrStorageClient,
|
|
498
|
+
GATEWAY_URL,
|
|
499
|
+
createBrokr,
|
|
500
|
+
models
|
|
501
|
+
};
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Brokr Auth Client
|
|
3
|
+
*
|
|
4
|
+
* Server-side auth utilities for apps provisioned with `brokr add auth`.
|
|
5
|
+
* Wraps Better Auth's server-side API with Brokr's zero-config DX.
|
|
6
|
+
*
|
|
7
|
+
* Gateway verify: cross-service token verification via api.brokr.sh
|
|
8
|
+
* Local calls: session/user operations via the app's own Better Auth API
|
|
9
|
+
*/
|
|
10
|
+
export interface AuthUser {
|
|
11
|
+
id: string;
|
|
12
|
+
email: string;
|
|
13
|
+
name: string | null;
|
|
14
|
+
avatarUrl: string | null;
|
|
15
|
+
emailVerified: Date | null;
|
|
16
|
+
}
|
|
17
|
+
export interface AuthSession {
|
|
18
|
+
user: AuthUser;
|
|
19
|
+
sessionId: string;
|
|
20
|
+
expiresAt: Date;
|
|
21
|
+
}
|
|
22
|
+
export interface CreateUserInput {
|
|
23
|
+
email: string;
|
|
24
|
+
name?: string;
|
|
25
|
+
password?: string;
|
|
26
|
+
}
|
|
27
|
+
export interface UpdateUserInput {
|
|
28
|
+
name?: string;
|
|
29
|
+
avatarUrl?: string;
|
|
30
|
+
}
|
|
31
|
+
export interface OAuthUrlOptions {
|
|
32
|
+
redirectTo?: string;
|
|
33
|
+
}
|
|
34
|
+
export interface MagicLinkOptions {
|
|
35
|
+
redirectTo?: string;
|
|
36
|
+
}
|
|
37
|
+
export declare class BrokrAuthClient {
|
|
38
|
+
private readonly _token;
|
|
39
|
+
private readonly _gatewayUrl;
|
|
40
|
+
private readonly _appUrl;
|
|
41
|
+
constructor(token: string | undefined, gatewayUrl: string, appUrl?: string);
|
|
42
|
+
/**
|
|
43
|
+
* Get current user from an incoming request's cookies.
|
|
44
|
+
* Calls the local Better Auth API (runs inside your app).
|
|
45
|
+
*/
|
|
46
|
+
currentUser(request: Request): Promise<AuthUser | null>;
|
|
47
|
+
/**
|
|
48
|
+
* Get the full session (user + metadata) from an incoming request.
|
|
49
|
+
* Calls the local Better Auth API.
|
|
50
|
+
*/
|
|
51
|
+
getSession(request: Request): Promise<AuthSession | null>;
|
|
52
|
+
/**
|
|
53
|
+
* Generate an OAuth authorization URL.
|
|
54
|
+
*/
|
|
55
|
+
getOAuthUrl(provider: string, options?: OAuthUrlOptions): Promise<{
|
|
56
|
+
redirectUrl: string;
|
|
57
|
+
}>;
|
|
58
|
+
/**
|
|
59
|
+
* Send a magic link email (requires email capability).
|
|
60
|
+
*/
|
|
61
|
+
sendMagicLink(email: string, options?: MagicLinkOptions): Promise<void>;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Create auth middleware for Next.js route protection.
|
|
65
|
+
*/
|
|
66
|
+
export declare function authMiddleware(options: {
|
|
67
|
+
protectedRoutes?: string[];
|
|
68
|
+
publicOnlyRoutes?: string[];
|
|
69
|
+
}): (request: Request) => Promise<Response | undefined>;
|
|
70
|
+
//# sourceMappingURL=auth.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../src/auth.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAQH,MAAM,WAAW,QAAQ;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,aAAa,EAAE,IAAI,GAAG,IAAI,CAAC;CAC5B;AAED,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,QAAQ,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,IAAI,CAAC;CACjB;AAED,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,eAAe;IAC9B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,eAAe;IAC9B,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,gBAAgB;IAC/B,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAMD,qBAAa,eAAe;IAC1B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAqB;IAC5C,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAS;IACrC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAqB;gBAG3C,KAAK,EAAE,MAAM,GAAG,SAAS,EACzB,UAAU,EAAE,MAAM,EAClB,MAAM,CAAC,EAAE,MAAM;IAOjB;;;OAGG;IACG,WAAW,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC;IAK7D;;;OAGG;IACG,UAAU,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC;IAwC/D;;OAEG;IACG,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,eAAe,GAAG,OAAO,CAAC;QAAE,WAAW,EAAE,MAAM,CAAA;KAAE,CAAC;IAehG;;OAEG;IACG,aAAa,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC;CAqB9E;AAiBD;;GAEG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE;IACtC,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;IAC3B,gBAAgB,CAAC,EAAE,MAAM,EAAE,CAAC;CAC7B,IAGkC,SAAS,OAAO,KAAG,OAAO,CAAC,QAAQ,GAAG,SAAS,CAAC,CAuBlF"}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Brokr SDK - Management Client
|
|
3
|
+
*
|
|
4
|
+
* For CLI and provisioning tools that manage stacks and providers
|
|
5
|
+
* via the Brokr tRPC API.
|
|
6
|
+
*
|
|
7
|
+
* @packageDocumentation
|
|
8
|
+
*/
|
|
9
|
+
import type { CreateStackInput, StackResponse, AddProviderInput, ProviderResponse } from '../types';
|
|
10
|
+
/**
|
|
11
|
+
* Configuration options for the Brokr management client
|
|
12
|
+
*/
|
|
13
|
+
export interface BrokrConfig {
|
|
14
|
+
/** Base URL for the Brokr API */
|
|
15
|
+
apiUrl: string;
|
|
16
|
+
/** JWT access token for authentication */
|
|
17
|
+
accessToken: string;
|
|
18
|
+
/** Optional: Request timeout in milliseconds */
|
|
19
|
+
timeout?: number;
|
|
20
|
+
/** Optional: Custom headers */
|
|
21
|
+
headers?: Record<string, string>;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Brokr management client for stack and provider operations.
|
|
25
|
+
*/
|
|
26
|
+
export declare class BrokrClient {
|
|
27
|
+
private config;
|
|
28
|
+
constructor(config: BrokrConfig);
|
|
29
|
+
/** Create a new stack with default providers. */
|
|
30
|
+
create(input: CreateStackInput): Promise<StackResponse>;
|
|
31
|
+
/** List all stacks for the current user. */
|
|
32
|
+
listStacks(): Promise<StackResponse[]>;
|
|
33
|
+
/** Get a specific stack by ID. */
|
|
34
|
+
getStack(id: string): Promise<StackResponse>;
|
|
35
|
+
/** Update a stack. */
|
|
36
|
+
updateStack(id: string, input: Partial<CreateStackInput>): Promise<StackResponse>;
|
|
37
|
+
/** Delete a stack. */
|
|
38
|
+
deleteStack(id: string): Promise<{
|
|
39
|
+
success: boolean;
|
|
40
|
+
}>;
|
|
41
|
+
/** Add a provider to a stack. */
|
|
42
|
+
add(provider: string, input?: AddProviderInput): Promise<ProviderResponse>;
|
|
43
|
+
/** Refresh the access token. */
|
|
44
|
+
refreshToken(refreshToken: string): Promise<{
|
|
45
|
+
accessToken: string;
|
|
46
|
+
refreshToken: string;
|
|
47
|
+
}>;
|
|
48
|
+
/** Update the access token. */
|
|
49
|
+
setAccessToken(accessToken: string): void;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Factory function to create a Brokr management client.
|
|
53
|
+
*
|
|
54
|
+
* @example
|
|
55
|
+
* ```typescript
|
|
56
|
+
* import { createBrokrClient } from '@brokr/sdk';
|
|
57
|
+
*
|
|
58
|
+
* const client = createBrokrClient({
|
|
59
|
+
* apiUrl: 'https://brokr.sh',
|
|
60
|
+
* accessToken: process.env.BROKR_ACCESS_TOKEN!,
|
|
61
|
+
* });
|
|
62
|
+
*
|
|
63
|
+
* const stack = await client.create({ stack: 'web-app', name: 'my-app' });
|
|
64
|
+
* ```
|
|
65
|
+
*/
|
|
66
|
+
export default function createBrokrClient(config: BrokrConfig): BrokrClient;
|
|
67
|
+
export declare const create: typeof createBrokrClient;
|
|
68
|
+
//# sourceMappingURL=management.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"management.d.ts","sourceRoot":"","sources":["../../src/management.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EACV,gBAAgB,EAChB,aAAa,EACb,gBAAgB,EAChB,gBAAgB,EACjB,MAAM,UAAU,CAAC;AA4BlB;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,iCAAiC;IACjC,MAAM,EAAE,MAAM,CAAC;IACf,0CAA0C;IAC1C,WAAW,EAAE,MAAM,CAAC;IACpB,gDAAgD;IAChD,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,+BAA+B;IAC/B,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAClC;AAED;;GAEG;AACH,qBAAa,WAAW;IACtB,OAAO,CAAC,MAAM,CAAc;gBAEhB,MAAM,EAAE,WAAW;IAI/B,iDAAiD;IAC3C,MAAM,CAAC,KAAK,EAAE,gBAAgB,GAAG,OAAO,CAAC,aAAa,CAAC;IAI7D,4CAA4C;IACtC,UAAU,IAAI,OAAO,CAAC,aAAa,EAAE,CAAC;IAI5C,kCAAkC;IAC5B,QAAQ,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC;IAIlD,sBAAsB;IAChB,WAAW,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,CAAC,gBAAgB,CAAC,GAAG,OAAO,CAAC,aAAa,CAAC;IAIvF,sBAAsB;IAChB,WAAW,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,OAAO,EAAE,OAAO,CAAA;KAAE,CAAC;IAI5D,iCAAiC;IAC3B,GAAG,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,gBAAgB,GAAG,OAAO,CAAC,gBAAgB,CAAC;IAIhF,gCAAgC;IAC1B,YAAY,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,WAAW,EAAE,MAAM,CAAC;QAAC,YAAY,EAAE,MAAM,CAAA;KAAE,CAAC;IAIhG,+BAA+B;IAC/B,cAAc,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI;CAG1C;AAED;;;;;;;;;;;;;;GAcG;AACH,MAAM,CAAC,OAAO,UAAU,iBAAiB,CAAC,MAAM,EAAE,WAAW,GAAG,WAAW,CAE1E;AAED,eAAO,MAAM,MAAM,0BAAoB,CAAC"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Brokr Auth React Components + Hooks
|
|
3
|
+
*
|
|
4
|
+
* Wraps Better Auth's React client with Brokr's DX.
|
|
5
|
+
*
|
|
6
|
+
* @example
|
|
7
|
+
* import { BrokrAuth, useUser, useAuth, SignIn, SignUp, UserButton } from '@brokr/sdk/react'
|
|
8
|
+
*/
|
|
9
|
+
import React from 'react';
|
|
10
|
+
export interface AuthClientUser {
|
|
11
|
+
id: string;
|
|
12
|
+
email: string;
|
|
13
|
+
name: string | null;
|
|
14
|
+
avatarUrl: string | null;
|
|
15
|
+
emailVerified: boolean;
|
|
16
|
+
}
|
|
17
|
+
interface SignInRenderProps {
|
|
18
|
+
action: (formData: FormData) => Promise<void>;
|
|
19
|
+
error: string | null;
|
|
20
|
+
pending: boolean;
|
|
21
|
+
}
|
|
22
|
+
interface SignUpRenderProps {
|
|
23
|
+
action: (formData: FormData) => Promise<void>;
|
|
24
|
+
error: string | null;
|
|
25
|
+
pending: boolean;
|
|
26
|
+
}
|
|
27
|
+
export declare function BrokrAuth({ children }: {
|
|
28
|
+
children: React.ReactNode;
|
|
29
|
+
}): React.JSX.Element;
|
|
30
|
+
export declare function useUser(): {
|
|
31
|
+
user: AuthClientUser | null;
|
|
32
|
+
isLoaded: boolean;
|
|
33
|
+
};
|
|
34
|
+
export declare function useAuth(): {
|
|
35
|
+
signIn: (email: string, password: string) => Promise<void>;
|
|
36
|
+
signUp: (email: string, password: string, name?: string) => Promise<void>;
|
|
37
|
+
signOut: () => Promise<void>;
|
|
38
|
+
isSigningOut: boolean;
|
|
39
|
+
};
|
|
40
|
+
export declare function SignIn({ redirectTo, children, }: {
|
|
41
|
+
redirectTo?: string;
|
|
42
|
+
children?: (props: SignInRenderProps) => React.ReactNode;
|
|
43
|
+
}): React.JSX.Element;
|
|
44
|
+
export declare function SignUp({ redirectTo, children, }: {
|
|
45
|
+
redirectTo?: string;
|
|
46
|
+
children?: (props: SignUpRenderProps) => React.ReactNode;
|
|
47
|
+
}): React.JSX.Element;
|
|
48
|
+
export declare function UserButton(): React.JSX.Element | null;
|
|
49
|
+
export {};
|
|
50
|
+
//# sourceMappingURL=auth.d.ts.map
|