@bandeira-tech/b3nd-web 0.2.0 → 0.2.2

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.
@@ -6,7 +6,6 @@ interface AppsClientConfig {
6
6
  appServerUrl: string;
7
7
  apiBasePath: string;
8
8
  fetch?: typeof fetch;
9
- authToken?: string;
10
9
  }
11
10
  interface AppActionDef {
12
11
  action: string;
@@ -20,27 +19,34 @@ interface AppActionDef {
20
19
  plain?: string;
21
20
  };
22
21
  }
23
- interface AppRegistration {
24
- appKey: string;
25
- accountPrivateKeyPem: string;
26
- encryptionPublicKeyHex?: string;
27
- encryptionPrivateKeyPem?: string;
28
- allowedOrigins: string[];
29
- actions: AppActionDef[];
30
- }
22
+ type AuthenticatedMessage<T = unknown> = {
23
+ auth: Array<{
24
+ pubkey: string;
25
+ signature: string;
26
+ }>;
27
+ payload: T;
28
+ };
31
29
  declare class AppsClient {
32
30
  private base;
33
31
  private api;
34
32
  private f;
35
- private authToken?;
36
33
  constructor(cfg: AppsClientConfig);
37
- setAuthToken(token?: string): void;
38
34
  health(): Promise<unknown>;
39
- registerApp(reg: AppRegistration): Promise<{
35
+ updateOrigins(appKey: string, message: AuthenticatedMessage<{
36
+ allowedOrigins?: string[];
37
+ encryptionPublicKeyHex?: string | null;
38
+ }>): Promise<{
40
39
  success: boolean;
41
- error?: string;
42
40
  }>;
43
- updateSchema(appKey: string, actions: AppActionDef[]): Promise<{
41
+ updateGoogleClientId(appKey: string, message: AuthenticatedMessage<{
42
+ googleClientId: string | null;
43
+ }>): Promise<{
44
+ success: boolean;
45
+ }>;
46
+ updateSchema(appKey: string, message: AuthenticatedMessage<{
47
+ actions: AppActionDef[];
48
+ encryptionPublicKeyHex?: string | null;
49
+ }>): Promise<{
44
50
  success: boolean;
45
51
  error?: string;
46
52
  }>;
@@ -50,14 +56,17 @@ declare class AppsClient {
50
56
  appKey: string;
51
57
  allowedOrigins: string[];
52
58
  actions: AppActionDef[];
59
+ encryptionPublicKeyHex?: string | null;
53
60
  };
54
61
  }>;
55
- createSession(appKey: string, token: string): Promise<{
62
+ createSession(appKey: string, message: AuthenticatedMessage<{
63
+ session: string;
64
+ }>): Promise<{
56
65
  success: true;
57
66
  session: string;
58
67
  uri: string;
59
68
  }>;
60
- invokeAction(appKey: string, action: string, payload: string, origin?: string): Promise<{
69
+ invokeAction(appKey: string, action: string, signedMessage: AuthenticatedMessage<any>, origin?: string): Promise<{
61
70
  success: true;
62
71
  uri: string;
63
72
  record: {
@@ -76,4 +85,4 @@ declare class AppsClient {
76
85
  }>;
77
86
  }
78
87
 
79
- export { type AppActionDef, type AppRegistration, AppsClient, type AppsClientConfig };
88
+ export { type AppActionDef, AppsClient, type AppsClientConfig, type AuthenticatedMessage };
package/dist/apps/mod.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  AppsClient
3
- } from "../chunk-QHDBFVLU.js";
3
+ } from "../chunk-VAZUCGED.js";
4
4
  import "../chunk-MLKGABMK.js";
5
5
  export {
6
6
  AppsClient
@@ -1,10 +1,7 @@
1
1
  // wallet/client.ts
2
2
  var WalletClient = class {
3
- walletServerUrl;
4
- apiBasePath;
5
- fetchImpl;
6
- currentSession = null;
7
3
  constructor(config) {
4
+ this.currentSession = null;
8
5
  this.walletServerUrl = config.walletServerUrl.replace(/\/$/, "");
9
6
  if (!config.apiBasePath || typeof config.apiBasePath !== "string") {
10
7
  throw new Error("apiBasePath is required (e.g., '/api/v1')");
@@ -19,6 +16,16 @@ var WalletClient = class {
19
16
  this.fetchImpl = fetch;
20
17
  }
21
18
  }
19
+ buildUrl(path) {
20
+ const normalized = path.startsWith("/") ? path : `/${path}`;
21
+ return `${this.walletServerUrl}${this.apiBasePath}${normalized}`;
22
+ }
23
+ buildAppKeyUrl(path, appKey) {
24
+ if (!appKey || typeof appKey !== "string") {
25
+ throw new Error("appKey is required");
26
+ }
27
+ return `${this.buildUrl(path)}/${appKey}`;
28
+ }
22
29
  /**
23
30
  * Get the current authenticated session
24
31
  */
@@ -41,15 +48,13 @@ var WalletClient = class {
41
48
  * Get current username (if authenticated)
42
49
  */
43
50
  getUsername() {
44
- var _a;
45
- return ((_a = this.currentSession) == null ? void 0 : _a.username) || null;
51
+ return this.currentSession?.username || null;
46
52
  }
47
53
  /**
48
54
  * Get current JWT token (if authenticated)
49
55
  */
50
56
  getToken() {
51
- var _a;
52
- return ((_a = this.currentSession) == null ? void 0 : _a.token) || null;
57
+ return this.currentSession?.token || null;
53
58
  }
54
59
  /**
55
60
  * Clear current session (logout)
@@ -87,12 +92,12 @@ var WalletClient = class {
87
92
  * Change password for current user
88
93
  * Requires active authentication session
89
94
  */
90
- async changePassword(oldPassword, newPassword) {
95
+ async changePassword(appKey, oldPassword, newPassword) {
91
96
  if (!this.currentSession) {
92
97
  throw new Error("Not authenticated. Please login first.");
93
98
  }
94
99
  const response = await this.fetchImpl(
95
- `${this.walletServerUrl}${this.apiBasePath}/auth/change-password`,
100
+ this.buildAppKeyUrl("/auth/credentials/change-password", appKey),
96
101
  {
97
102
  method: "POST",
98
103
  headers: {
@@ -115,24 +120,30 @@ var WalletClient = class {
115
120
  * Does not require authentication
116
121
  */
117
122
  async requestPasswordReset(_username) {
118
- throw new Error("Use requestPasswordResetWithToken(token, username)");
123
+ throw new Error("Use requestPasswordResetWithToken(appKey, username)");
119
124
  }
120
125
  /**
121
126
  * Reset password using a reset token
122
127
  * Returns session data - call setSession() to activate it
123
128
  */
124
129
  async resetPassword(_username, _resetToken, _newPassword) {
125
- throw new Error("Use resetPasswordWithToken(token, username, resetToken, newPassword)");
130
+ throw new Error("Use resetPasswordWithToken(appKey, username, resetToken, newPassword)");
126
131
  }
127
132
  /**
128
133
  * Sign up with app token (scoped to an app)
129
134
  */
130
- async signupWithToken(token, credentials) {
131
- if (!token) throw new Error("token is required");
132
- const response = await this.fetchImpl(`${this.walletServerUrl}${this.apiBasePath}/auth/signup`, {
135
+ async signupWithToken(appKey, tokenOrCredentials, maybeCredentials) {
136
+ const credentials = typeof tokenOrCredentials === "string" ? maybeCredentials : tokenOrCredentials;
137
+ if (!credentials) throw new Error("credentials are required");
138
+ const response = await this.fetchImpl(this.buildAppKeyUrl("/auth/signup", appKey), {
133
139
  method: "POST",
134
140
  headers: { "Content-Type": "application/json" },
135
- body: JSON.stringify({ token, username: credentials.username, password: credentials.password })
141
+ body: JSON.stringify({
142
+ token: typeof tokenOrCredentials === "string" ? tokenOrCredentials : void 0,
143
+ type: "password",
144
+ username: credentials.username,
145
+ password: credentials.password
146
+ })
136
147
  });
137
148
  const data = await response.json();
138
149
  if (!response.ok || !data.success) {
@@ -143,13 +154,20 @@ var WalletClient = class {
143
154
  /**
144
155
  * Login with app token and session (scoped to an app)
145
156
  */
146
- async loginWithTokenSession(token, session, credentials) {
147
- if (!token) throw new Error("token is required");
148
- if (!session) throw new Error("session is required");
149
- const response = await this.fetchImpl(`${this.walletServerUrl}${this.apiBasePath}/auth/login`, {
157
+ async loginWithTokenSession(appKey, tokenOrSession, sessionOrCredentials, maybeCredentials) {
158
+ const session = typeof sessionOrCredentials === "string" && maybeCredentials ? sessionOrCredentials : tokenOrSession;
159
+ const credentials = maybeCredentials || sessionOrCredentials;
160
+ if (!session || typeof session !== "string") throw new Error("session is required");
161
+ const response = await this.fetchImpl(this.buildAppKeyUrl("/auth/login", appKey), {
150
162
  method: "POST",
151
163
  headers: { "Content-Type": "application/json" },
152
- body: JSON.stringify({ token, session, username: credentials.username, password: credentials.password })
164
+ body: JSON.stringify({
165
+ token: typeof tokenOrSession === "string" && maybeCredentials ? tokenOrSession : void 0,
166
+ session,
167
+ type: "password",
168
+ username: credentials.username,
169
+ password: credentials.password
170
+ })
153
171
  });
154
172
  const data = await response.json();
155
173
  if (!response.ok || !data.success) {
@@ -160,12 +178,12 @@ var WalletClient = class {
160
178
  /**
161
179
  * Request password reset scoped to app token
162
180
  */
163
- async requestPasswordResetWithToken(token, username) {
164
- if (!token) throw new Error("token is required");
165
- const response = await this.fetchImpl(`${this.walletServerUrl}${this.apiBasePath}/auth/request-password-reset`, {
181
+ async requestPasswordResetWithToken(appKey, tokenOrUsername, maybeUsername) {
182
+ const username = maybeUsername || tokenOrUsername;
183
+ const response = await this.fetchImpl(this.buildAppKeyUrl("/auth/credentials/request-password-reset", appKey), {
166
184
  method: "POST",
167
185
  headers: { "Content-Type": "application/json" },
168
- body: JSON.stringify({ token, username })
186
+ body: JSON.stringify({ username })
169
187
  });
170
188
  const data = await response.json();
171
189
  if (!response.ok || !data.success) {
@@ -174,14 +192,17 @@ var WalletClient = class {
174
192
  return { resetToken: data.resetToken, expiresIn: data.expiresIn };
175
193
  }
176
194
  /**
177
- * Reset password scoped to app token
195
+ * Reset password scoped to an app
178
196
  */
179
- async resetPasswordWithToken(token, username, resetToken, newPassword) {
180
- if (!token) throw new Error("token is required");
181
- const response = await this.fetchImpl(`${this.walletServerUrl}${this.apiBasePath}/auth/reset-password`, {
197
+ async resetPasswordWithToken(appKey, _tokenOrUsername, usernameOrReset, resetToken, newPassword) {
198
+ const username = usernameOrReset;
199
+ if (!resetToken || !newPassword) {
200
+ throw new Error("resetToken and newPassword are required");
201
+ }
202
+ const response = await this.fetchImpl(this.buildAppKeyUrl("/auth/credentials/reset-password", appKey), {
182
203
  method: "POST",
183
204
  headers: { "Content-Type": "application/json" },
184
- body: JSON.stringify({ token, username, resetToken, newPassword })
205
+ body: JSON.stringify({ username, resetToken, newPassword })
185
206
  });
186
207
  const data = await response.json();
187
208
  if (!response.ok || !data.success) {
@@ -193,12 +214,15 @@ var WalletClient = class {
193
214
  * Get public keys for the current authenticated user.
194
215
  * Requires an active authentication session.
195
216
  */
196
- async getPublicKeys() {
217
+ async getPublicKeys(appKey) {
197
218
  if (!this.currentSession) {
198
219
  throw new Error("Not authenticated. Please login first.");
199
220
  }
221
+ if (!appKey || typeof appKey !== "string") {
222
+ throw new Error("appKey is required");
223
+ }
200
224
  const response = await this.fetchImpl(
201
- `${this.walletServerUrl}${this.apiBasePath}/public-keys`,
225
+ this.buildAppKeyUrl("/auth/public-keys", appKey),
202
226
  {
203
227
  headers: {
204
228
  Authorization: `Bearer ${this.currentSession.token}`
@@ -247,8 +271,8 @@ var WalletClient = class {
247
271
  * Convenience method: Get current user's public keys
248
272
  * Requires active authentication session
249
273
  */
250
- async getMyPublicKeys() {
251
- return this.getPublicKeys();
274
+ async getMyPublicKeys(appKey) {
275
+ return this.getPublicKeys(appKey);
252
276
  }
253
277
  /**
254
278
  * Get server's public keys
@@ -270,6 +294,66 @@ var WalletClient = class {
270
294
  encryptionPublicKeyHex: data.encryptionPublicKeyHex
271
295
  };
272
296
  }
297
+ /**
298
+ * Sign up with Google OAuth (scoped to app token)
299
+ * Returns session data with Google profile info - call setSession() to activate it
300
+ *
301
+ * @param token - App token from app server
302
+ * @param googleIdToken - Google ID token from Google Sign-In
303
+ * @returns GoogleAuthSession with username, JWT token, and Google profile info
304
+ */
305
+ async signupWithGoogle(appKey, token, googleIdToken) {
306
+ if (!token) throw new Error("token is required");
307
+ if (!googleIdToken) throw new Error("googleIdToken is required");
308
+ const response = await this.fetchImpl(this.buildAppKeyUrl("/auth/signup", appKey), {
309
+ method: "POST",
310
+ headers: { "Content-Type": "application/json" },
311
+ body: JSON.stringify({ token, type: "google", googleIdToken })
312
+ });
313
+ const data = await response.json();
314
+ if (!response.ok || !data.success) {
315
+ throw new Error(data.error || `Google signup failed: ${response.statusText}`);
316
+ }
317
+ return {
318
+ username: data.username,
319
+ token: data.token,
320
+ expiresIn: data.expiresIn,
321
+ email: data.email,
322
+ name: data.name,
323
+ picture: data.picture
324
+ };
325
+ }
326
+ /**
327
+ * Login with Google OAuth (scoped to app token and session)
328
+ * Returns session data with Google profile info - call setSession() to activate it
329
+ *
330
+ * @param token - App token from app server
331
+ * @param session - Session key from app server
332
+ * @param googleIdToken - Google ID token from Google Sign-In
333
+ * @returns GoogleAuthSession with username, JWT token, and Google profile info
334
+ */
335
+ async loginWithGoogle(appKey, token, session, googleIdToken) {
336
+ if (!token) throw new Error("token is required");
337
+ if (!session) throw new Error("session is required");
338
+ if (!googleIdToken) throw new Error("googleIdToken is required");
339
+ const response = await this.fetchImpl(this.buildAppKeyUrl("/auth/login", appKey), {
340
+ method: "POST",
341
+ headers: { "Content-Type": "application/json" },
342
+ body: JSON.stringify({ token, session, type: "google", googleIdToken })
343
+ });
344
+ const data = await response.json();
345
+ if (!response.ok || !data.success) {
346
+ throw new Error(data.error || `Google login failed: ${response.statusText}`);
347
+ }
348
+ return {
349
+ username: data.username,
350
+ token: data.token,
351
+ expiresIn: data.expiresIn,
352
+ email: data.email,
353
+ name: data.name,
354
+ picture: data.picture
355
+ };
356
+ }
273
357
  };
274
358
 
275
359
  export {
@@ -1,8 +1,5 @@
1
1
  // clients/local-storage/mod.ts
2
2
  var LocalStorageClient = class {
3
- config;
4
- schema;
5
- storage;
6
3
  constructor(config) {
7
4
  this.config = {
8
5
  keyPrefix: config.keyPrefix || "b3nd:",
@@ -133,8 +130,8 @@ var LocalStorageClient = class {
133
130
  } else if (sortBy === "timestamp") {
134
131
  const aData = this.getStoredData(a.uri);
135
132
  const bData = this.getStoredData(b.uri);
136
- const aTs = (aData == null ? void 0 : aData.ts) || 0;
137
- const bTs = (bData == null ? void 0 : bData.ts) || 0;
133
+ const aTs = aData?.ts || 0;
134
+ const bTs = bData?.ts || 0;
138
135
  comparison = aTs - bTs;
139
136
  }
140
137
  return sortOrder === "asc" ? comparison : -comparison;