@baasix/sdk 0.1.18 → 0.1.20
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 +147 -4
- package/dist/index.cjs +190 -8
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +38 -3
- package/dist/index.d.ts +38 -3
- package/dist/index.js +190 -9
- package/dist/index.js.map +1 -1
- package/dist/modules/auth.cjs +140 -3
- package/dist/modules/auth.cjs.map +1 -1
- package/dist/modules/auth.d.cts +104 -4
- package/dist/modules/auth.d.ts +104 -4
- package/dist/modules/auth.js +140 -4
- package/dist/modules/auth.js.map +1 -1
- package/package.json +3 -2
package/README.md
CHANGED
|
@@ -9,7 +9,7 @@ Official JavaScript/TypeScript SDK for [Baasix](https://www.baasix.com) Backend-
|
|
|
9
9
|
## Features
|
|
10
10
|
|
|
11
11
|
- 🌐 **Universal** - Works in browsers, Node.js, and React Native
|
|
12
|
-
- 🔐 **Flexible Auth** - JWT tokens, HTTP-only cookies, OAuth (Google,
|
|
12
|
+
- 🔐 **Flexible Auth** - JWT tokens, HTTP-only cookies, 35+ OAuth providers (Google, GitHub, Discord, Microsoft, Slack, and more), passkeys (WebAuthn), and 2FA (TOTP + backup codes)
|
|
13
13
|
- 💾 **Customizable Storage** - LocalStorage, AsyncStorage, or custom adapters
|
|
14
14
|
- 📝 **Type-Safe** - Full TypeScript support with generics
|
|
15
15
|
- 🔄 **Auto Token Refresh** - Seamless token management
|
|
@@ -23,6 +23,7 @@ Official JavaScript/TypeScript SDK for [Baasix](https://www.baasix.com) Backend-
|
|
|
23
23
|
- 🔔 **Notifications** - User notification system with realtime delivery
|
|
24
24
|
- 🗃️ **Migrations** - Database schema migration management
|
|
25
25
|
- 🔃 **Sort/Reorder** - Drag-and-drop style item reordering
|
|
26
|
+
- 🧩 **App Builder** - Create and manage pages & blocks via the items API
|
|
26
27
|
|
|
27
28
|
## Installation
|
|
28
29
|
|
|
@@ -416,6 +417,65 @@ const results = await baasix.items('orders').aggregate({
|
|
|
416
417
|
});
|
|
417
418
|
```
|
|
418
419
|
|
|
420
|
+
## App Builder (Pages & Blocks)
|
|
421
|
+
|
|
422
|
+
The Baasix [App Builder](https://baasix.dev/docs/guides/app-builder) lets admins compose internal
|
|
423
|
+
tools from 27 data-bound block types (tables, wizard forms, kanban, charts, tabs, modals, reports,
|
|
424
|
+
and more) with cross-block reactivity on a 12-column grid. Pages and blocks are stored in the
|
|
425
|
+
`baasix_Page` and `baasix_Block` system collections, so you manage them with the **same `items()`
|
|
426
|
+
API** — no special client. Block `config` is validated server-side on every create and update.
|
|
427
|
+
|
|
428
|
+
```typescript
|
|
429
|
+
// Create a page
|
|
430
|
+
const page = await baasix.items('baasix_Page').create({
|
|
431
|
+
name: 'Operations',
|
|
432
|
+
slug: 'operations', // unique per tenant; used in /pages/?slug=operations
|
|
433
|
+
icon: 'gauge',
|
|
434
|
+
});
|
|
435
|
+
|
|
436
|
+
// Add a table block bound to the orders collection
|
|
437
|
+
await baasix.items('baasix_Block').create({
|
|
438
|
+
page_Id: page.id,
|
|
439
|
+
type: 'table',
|
|
440
|
+
collection: 'orders',
|
|
441
|
+
position: { row: 0, col: 0, span: 8 }, // 12-column grid: row, col, span
|
|
442
|
+
config: {
|
|
443
|
+
columns: [{ field: 'id' }, { field: 'customer' }, { field: 'total' }],
|
|
444
|
+
filter: { status: { eq: 'open' } },
|
|
445
|
+
sort: 'createdAt:desc',
|
|
446
|
+
actions: { create: true, edit: true, view: true },
|
|
447
|
+
},
|
|
448
|
+
});
|
|
449
|
+
|
|
450
|
+
// Add a status chart beside it
|
|
451
|
+
await baasix.items('baasix_Block').create({
|
|
452
|
+
page_Id: page.id,
|
|
453
|
+
type: 'chart',
|
|
454
|
+
collection: 'orders',
|
|
455
|
+
position: { row: 0, col: 8, span: 4 },
|
|
456
|
+
config: {
|
|
457
|
+
chartType: 'doughnut',
|
|
458
|
+
aggregate: { count: { function: 'count', field: 'id' } },
|
|
459
|
+
groupBy: ['status'],
|
|
460
|
+
},
|
|
461
|
+
});
|
|
462
|
+
|
|
463
|
+
// List all blocks on a page
|
|
464
|
+
const blocks = await baasix.items('baasix_Block')
|
|
465
|
+
.filter({ page_Id: { eq: page.id } })
|
|
466
|
+
.get();
|
|
467
|
+
```
|
|
468
|
+
|
|
469
|
+
> **Block types (27):** data — `table`, `form`, `details`, `kanban`, `calendar`, `chart`, `cardlist`,
|
|
470
|
+
> `map` (Leaflet or Google Maps), `geochart`, `media`, `feed`, `timeline`, `progress`, `repeater`,
|
|
471
|
+
> `report`, `filter`; layout — `tabs`, `container`, `modal`, `divider` (children carry
|
|
472
|
+
> `parentBlock_Id` + `slot`); content & input — `markdown`, `richtext`, `buttons`, `input`,
|
|
473
|
+
> `iframe`, `upload`, `code`.
|
|
474
|
+
> Filters in any block config use the same filter DSL as the items API, plus the runtime
|
|
475
|
+
> placeholders `"$param.<name>"`, `"$selection.<blockId>.<field>"` and `"$input.<name>"` for
|
|
476
|
+
> master-detail wiring. See the
|
|
477
|
+
> [App Builder guide](https://baasix.dev/docs/guides/app-builder) for the full config reference.
|
|
478
|
+
|
|
419
479
|
## Filter Operators
|
|
420
480
|
|
|
421
481
|
Baasix supports 50+ filter operators:
|
|
@@ -1181,24 +1241,107 @@ baasix.realtime.disconnect();
|
|
|
1181
1241
|
|
|
1182
1242
|
## OAuth / Social Login
|
|
1183
1243
|
|
|
1244
|
+
35 social providers are supported via the `SOCIAL_PROVIDERS` constant — `google`, `github`, `discord`, `microsoft`, `slack`, `apple`, `facebook`, `gitlab`, `linkedin`, `twitter`, … 35 total. `getOAuthUrl`'s `provider` option is typed as `OAuthProvider`, the union of all 35 ids — import `SOCIAL_PROVIDERS` if you need the list at runtime (e.g. to render login buttons).
|
|
1245
|
+
|
|
1246
|
+
End-to-end browser flow: `getOAuthUrl()` builds the provider redirect URL → the browser navigates there and completes the provider's login → the provider redirects back to your app's callback page with a `token` (or `error`) query param → your callback page calls `handleOAuthCallback(token)` to finish signing in.
|
|
1247
|
+
|
|
1184
1248
|
```typescript
|
|
1185
|
-
|
|
1249
|
+
import { SOCIAL_PROVIDERS, type OAuthProvider } from '@baasix/sdk';
|
|
1250
|
+
|
|
1251
|
+
// SOCIAL_PROVIDERS: readonly array of all 35 provider ids, e.g. for rendering buttons
|
|
1252
|
+
SOCIAL_PROVIDERS.forEach((provider) => renderSocialButton(provider));
|
|
1253
|
+
|
|
1254
|
+
// 1. Redirect to the OAuth provider
|
|
1186
1255
|
const url = baasix.auth.getOAuthUrl({
|
|
1187
|
-
provider: '
|
|
1256
|
+
provider: 'github', // OAuthProvider — one of SOCIAL_PROVIDERS (35 total)
|
|
1188
1257
|
redirectUrl: 'https://myapp.com/auth/callback',
|
|
1189
1258
|
});
|
|
1190
1259
|
window.location.href = url;
|
|
1191
1260
|
|
|
1192
|
-
//
|
|
1261
|
+
// 2. Provider redirects back to your callback page with ?token=... (or ?error=...)
|
|
1262
|
+
// In your callback page:
|
|
1193
1263
|
const params = new URLSearchParams(window.location.search);
|
|
1194
1264
|
const token = params.get('token');
|
|
1265
|
+
const error = params.get('error');
|
|
1195
1266
|
|
|
1196
1267
|
if (token) {
|
|
1197
1268
|
const { user } = await baasix.auth.handleOAuthCallback(token);
|
|
1198
1269
|
console.log('Logged in as:', user.email);
|
|
1270
|
+
} else if (error) {
|
|
1271
|
+
console.error('OAuth sign-in failed:', error);
|
|
1272
|
+
}
|
|
1273
|
+
```
|
|
1274
|
+
|
|
1275
|
+
## Auth Method Discovery
|
|
1276
|
+
|
|
1277
|
+
Ask the server which login methods are actually enabled (registration, email/password, magic link, passkey, 2FA, and the list of configured social providers) so your login UI only shows what's available. The result is cached per client instance — pass `force: true` to bypass the cache.
|
|
1278
|
+
|
|
1279
|
+
```typescript
|
|
1280
|
+
const methods = await baasix.auth.getAuthMethods();
|
|
1281
|
+
// {
|
|
1282
|
+
// registration: true,
|
|
1283
|
+
// emailPassword: true,
|
|
1284
|
+
// magicLink: false,
|
|
1285
|
+
// passkey: true,
|
|
1286
|
+
// twoFactor: true,
|
|
1287
|
+
// socialProviders: ['google', 'github', 'discord'],
|
|
1288
|
+
// }
|
|
1289
|
+
|
|
1290
|
+
if (methods.socialProviders.includes('google')) {
|
|
1291
|
+
// show "Sign in with Google"
|
|
1292
|
+
}
|
|
1293
|
+
if (methods.passkey) {
|
|
1294
|
+
// show "Sign in with a passkey"
|
|
1199
1295
|
}
|
|
1200
1296
|
```
|
|
1201
1297
|
|
|
1298
|
+
## Two-Factor Authentication
|
|
1299
|
+
|
|
1300
|
+
TOTP-based 2FA (SHA1, 6-digit codes, 30s window) with 10 single-use backup codes. 2FA gates **password login only** — social, magic-link, and passkey sign-ins bypass the 2FA challenge (they're already a possession/federated factor). Enabling 2FA requires the account to already have a password credential.
|
|
1301
|
+
|
|
1302
|
+
```typescript
|
|
1303
|
+
// Enable 2FA (while logged in) — returns a secret, otpauth:// URL (render as a QR code), and backup codes
|
|
1304
|
+
const setup = await baasix.auth.twoFactor.enable();
|
|
1305
|
+
// { secret, otpauthUrl, backupCodes: [10 codes] }
|
|
1306
|
+
|
|
1307
|
+
// Confirm setup with a code from the authenticator app
|
|
1308
|
+
await baasix.auth.twoFactor.verifySetup('123456');
|
|
1309
|
+
// { enabled: true }
|
|
1310
|
+
|
|
1311
|
+
// Disable 2FA (requires the account password)
|
|
1312
|
+
await baasix.auth.twoFactor.disable('currentPassword');
|
|
1313
|
+
// { disabled: true }
|
|
1314
|
+
|
|
1315
|
+
// Login flow with 2FA enabled
|
|
1316
|
+
const result = await baasix.auth.login({ email, password });
|
|
1317
|
+
|
|
1318
|
+
if ('twoFactorRequired' in result && result.twoFactorRequired) {
|
|
1319
|
+
// Prompt for a TOTP code or an unused backup code
|
|
1320
|
+
const { user, token } = await baasix.auth.twoFactor.verify(result.twoFactorToken, '123456');
|
|
1321
|
+
} else {
|
|
1322
|
+
// Logged in directly — 2FA not enabled for this account
|
|
1323
|
+
const { user, token } = result;
|
|
1324
|
+
}
|
|
1325
|
+
```
|
|
1326
|
+
|
|
1327
|
+
## Passkeys
|
|
1328
|
+
|
|
1329
|
+
WebAuthn-based, usernameless passkey sign-in with per-user credential management. **Browser-only** — `baasix.auth.passkey.*` methods dynamically import `@simplewebauthn/browser` and throw a `BaasixError` when called outside a browser (e.g. Node.js or React Native).
|
|
1330
|
+
|
|
1331
|
+
```typescript
|
|
1332
|
+
// Register a passkey for the currently logged-in user
|
|
1333
|
+
await baasix.auth.passkey.register('MacBook Touch ID'); // name is optional
|
|
1334
|
+
|
|
1335
|
+
// Authenticate with a passkey (no prior login required)
|
|
1336
|
+
const { user, token } = await baasix.auth.passkey.authenticate();
|
|
1337
|
+
|
|
1338
|
+
// List the current user's registered passkeys (no key material returned)
|
|
1339
|
+
const passkeys = await baasix.auth.passkey.list();
|
|
1340
|
+
|
|
1341
|
+
// Remove one of your own passkeys
|
|
1342
|
+
await baasix.auth.passkey.remove(passkeys[0].id);
|
|
1343
|
+
```
|
|
1344
|
+
|
|
1202
1345
|
## Invitation System (Multi-tenant)
|
|
1203
1346
|
|
|
1204
1347
|
```typescript
|
package/dist/index.cjs
CHANGED
|
@@ -192,7 +192,7 @@ var HttpClient = class {
|
|
|
192
192
|
} catch {
|
|
193
193
|
}
|
|
194
194
|
const message = errorData.error?.message || errorData.message || response.statusText || "Request failed";
|
|
195
|
-
const code = errorData.error?.code;
|
|
195
|
+
const code = errorData.error?.code ?? errorData.code;
|
|
196
196
|
const details = errorData.details;
|
|
197
197
|
return new BaasixError(message, response.status, code, details);
|
|
198
198
|
}
|
|
@@ -476,17 +476,123 @@ var MemoryStorageAdapter = class {
|
|
|
476
476
|
};
|
|
477
477
|
|
|
478
478
|
// src/modules/auth.ts
|
|
479
|
+
var SOCIAL_PROVIDERS = ["apple", "atlassian", "cognito", "discord", "dropbox", "facebook", "figma", "github", "gitlab", "google", "huggingface", "kakao", "kick", "line", "linear", "linkedin", "microsoft", "naver", "notion", "paybin", "paypal", "polar", "railway", "reddit", "roblox", "salesforce", "slack", "spotify", "tiktok", "twitch", "twitter", "vercel", "vk", "wechat", "zoom"];
|
|
479
480
|
var AuthModule = class {
|
|
480
481
|
client;
|
|
481
482
|
storage;
|
|
482
483
|
authMode;
|
|
483
484
|
onAuthStateChange;
|
|
484
485
|
currentUser = null;
|
|
486
|
+
authMethodsCache = null;
|
|
487
|
+
/**
|
|
488
|
+
* Two-factor authentication (TOTP) helpers.
|
|
489
|
+
*
|
|
490
|
+
* @example
|
|
491
|
+
* ```typescript
|
|
492
|
+
* const result = await baasix.auth.login({ email, password });
|
|
493
|
+
* if ("twoFactorRequired" in result && result.twoFactorRequired) {
|
|
494
|
+
* const { user, token } = await baasix.auth.twoFactor.verify(result.twoFactorToken, code);
|
|
495
|
+
* }
|
|
496
|
+
* ```
|
|
497
|
+
*/
|
|
498
|
+
twoFactor;
|
|
499
|
+
/**
|
|
500
|
+
* Passkey (WebAuthn) registration and authentication helpers.
|
|
501
|
+
* Browser-only: throws a `BaasixError` when called outside a browser
|
|
502
|
+
* environment (no `window`/`PublicKeyCredential`).
|
|
503
|
+
*
|
|
504
|
+
* @example
|
|
505
|
+
* ```typescript
|
|
506
|
+
* // Register a passkey for the currently logged-in user
|
|
507
|
+
* await baasix.auth.passkey.register("My Laptop");
|
|
508
|
+
*
|
|
509
|
+
* // Authenticate with a passkey (no prior login required)
|
|
510
|
+
* const { user, token } = await baasix.auth.passkey.authenticate();
|
|
511
|
+
*
|
|
512
|
+
* // List and remove registered passkeys
|
|
513
|
+
* const passkeys = await baasix.auth.passkey.list();
|
|
514
|
+
* await baasix.auth.passkey.remove(passkeys[0].id);
|
|
515
|
+
* ```
|
|
516
|
+
*/
|
|
517
|
+
passkey = {
|
|
518
|
+
register: async (name) => {
|
|
519
|
+
this.assertBrowser();
|
|
520
|
+
const { startRegistration } = await import('@simplewebauthn/browser');
|
|
521
|
+
const options = await this.client.post("/auth/passkey/register/options", {});
|
|
522
|
+
const attestation = await startRegistration({ optionsJSON: options });
|
|
523
|
+
await this.client.post("/auth/passkey/register/verify", {
|
|
524
|
+
response: attestation,
|
|
525
|
+
name: name || null
|
|
526
|
+
});
|
|
527
|
+
return { verified: true };
|
|
528
|
+
},
|
|
529
|
+
authenticate: async (opts) => {
|
|
530
|
+
this.assertBrowser();
|
|
531
|
+
const { startAuthentication } = await import('@simplewebauthn/browser');
|
|
532
|
+
const { options, challengeId } = await this.client.post(
|
|
533
|
+
"/auth/passkey/authenticate/options",
|
|
534
|
+
{},
|
|
535
|
+
{ skipAuth: true }
|
|
536
|
+
);
|
|
537
|
+
const assertion = await startAuthentication({ optionsJSON: options });
|
|
538
|
+
const response = await this.client.post(
|
|
539
|
+
"/auth/passkey/authenticate/verify",
|
|
540
|
+
{ challengeId, response: assertion, authMode: opts?.authMode },
|
|
541
|
+
{ skipAuth: true }
|
|
542
|
+
);
|
|
543
|
+
await this.storeTokens(response);
|
|
544
|
+
this.emitAuthStateChange("SIGNED_IN", response.user);
|
|
545
|
+
return response;
|
|
546
|
+
},
|
|
547
|
+
list: async () => (await this.client.get("/auth/passkey")).passkeys,
|
|
548
|
+
remove: async (id) => {
|
|
549
|
+
await this.client.delete(`/auth/passkey/${encodeURIComponent(id)}`);
|
|
550
|
+
}
|
|
551
|
+
};
|
|
485
552
|
constructor(config) {
|
|
486
553
|
this.client = config.client;
|
|
487
554
|
this.storage = config.storage;
|
|
488
555
|
this.authMode = config.authMode;
|
|
489
556
|
this.onAuthStateChange = config.onAuthStateChange;
|
|
557
|
+
this.twoFactor = {
|
|
558
|
+
verify: async (twoFactorToken, code, opts) => {
|
|
559
|
+
const response = await this.client.post(
|
|
560
|
+
"/auth/2fa/verify",
|
|
561
|
+
{
|
|
562
|
+
twoFactorToken,
|
|
563
|
+
code,
|
|
564
|
+
authMode: opts?.authMode,
|
|
565
|
+
authType: opts?.authType
|
|
566
|
+
},
|
|
567
|
+
{ skipAuth: true }
|
|
568
|
+
);
|
|
569
|
+
await this.storeTokens(response);
|
|
570
|
+
this.emitAuthStateChange("SIGNED_IN", response.user);
|
|
571
|
+
return response;
|
|
572
|
+
},
|
|
573
|
+
enable: () => {
|
|
574
|
+
return this.client.post("/auth/2fa/enable");
|
|
575
|
+
},
|
|
576
|
+
verifySetup: (code) => {
|
|
577
|
+
return this.client.post("/auth/2fa/verify-setup", {
|
|
578
|
+
code
|
|
579
|
+
});
|
|
580
|
+
},
|
|
581
|
+
disable: (password) => {
|
|
582
|
+
return this.client.post("/auth/2fa/disable", {
|
|
583
|
+
password
|
|
584
|
+
});
|
|
585
|
+
}
|
|
586
|
+
};
|
|
587
|
+
}
|
|
588
|
+
/**
|
|
589
|
+
* Assert that we're running in a browser environment with WebAuthn support.
|
|
590
|
+
* Throws a `BaasixError` otherwise.
|
|
591
|
+
*/
|
|
592
|
+
assertBrowser() {
|
|
593
|
+
if (typeof window === "undefined" || !window.PublicKeyCredential) {
|
|
594
|
+
throw new BaasixError("Passkeys are only available in a browser", 400);
|
|
595
|
+
}
|
|
490
596
|
}
|
|
491
597
|
/**
|
|
492
598
|
* Emit an authentication state change event
|
|
@@ -583,9 +689,39 @@ var AuthModule = class {
|
|
|
583
689
|
},
|
|
584
690
|
{ skipAuth: true }
|
|
585
691
|
);
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
692
|
+
if ("twoFactorRequired" in response && response.twoFactorRequired) {
|
|
693
|
+
return response;
|
|
694
|
+
}
|
|
695
|
+
const authResponse = response;
|
|
696
|
+
await this.storeTokens(authResponse);
|
|
697
|
+
this.emitAuthStateChange("SIGNED_IN", authResponse.user);
|
|
698
|
+
return authResponse;
|
|
699
|
+
}
|
|
700
|
+
/**
|
|
701
|
+
* Discover which authentication methods are enabled for this project
|
|
702
|
+
* (registration, email/password, magic link, passkey, 2FA, and the list
|
|
703
|
+
* of configured social/OAuth providers). Result is cached per instance;
|
|
704
|
+
* pass `force: true` to bypass the cache and refetch.
|
|
705
|
+
*
|
|
706
|
+
* @example
|
|
707
|
+
* ```typescript
|
|
708
|
+
* const methods = await baasix.auth.getAuthMethods();
|
|
709
|
+
* if (methods.socialProviders.includes("google")) {
|
|
710
|
+
* // show "Sign in with Google"
|
|
711
|
+
* }
|
|
712
|
+
* ```
|
|
713
|
+
*/
|
|
714
|
+
async getAuthMethods(force = false) {
|
|
715
|
+
if (this.authMethodsCache && !force) {
|
|
716
|
+
return this.authMethodsCache;
|
|
717
|
+
}
|
|
718
|
+
const response = await this.client.get(
|
|
719
|
+
"/",
|
|
720
|
+
{ skipAuth: true }
|
|
721
|
+
);
|
|
722
|
+
const authMethods = response?.project?.auth;
|
|
723
|
+
this.authMethodsCache = authMethods;
|
|
724
|
+
return authMethods;
|
|
589
725
|
}
|
|
590
726
|
/**
|
|
591
727
|
* Logout the current user
|
|
@@ -2406,6 +2542,42 @@ var NotificationsModule = class {
|
|
|
2406
2542
|
);
|
|
2407
2543
|
return { count: response.count };
|
|
2408
2544
|
}
|
|
2545
|
+
/**
|
|
2546
|
+
* Mark notifications as unseen (unread)
|
|
2547
|
+
*
|
|
2548
|
+
* @example
|
|
2549
|
+
* ```typescript
|
|
2550
|
+
* // Mark specific notifications as unseen
|
|
2551
|
+
* await baasix.notifications.markAsUnseen(['id1', 'id2']);
|
|
2552
|
+
*
|
|
2553
|
+
* // Mark all notifications as unseen
|
|
2554
|
+
* await baasix.notifications.markAsUnseen();
|
|
2555
|
+
* ```
|
|
2556
|
+
*/
|
|
2557
|
+
async markAsUnseen(notificationIds) {
|
|
2558
|
+
const response = await this.client.post(
|
|
2559
|
+
"/notifications/mark-unseen",
|
|
2560
|
+
{ notificationIds }
|
|
2561
|
+
);
|
|
2562
|
+
return { count: response.count };
|
|
2563
|
+
}
|
|
2564
|
+
/**
|
|
2565
|
+
* Get the per-type notification link templates configured in settings
|
|
2566
|
+
* (`metadata.notificationLinks`). Templates may contain `{{field}}`
|
|
2567
|
+
* placeholders resolved from the notification (including `data.*` paths).
|
|
2568
|
+
*
|
|
2569
|
+
* @example
|
|
2570
|
+
* ```typescript
|
|
2571
|
+
* const links = await baasix.notifications.getLinks();
|
|
2572
|
+
* // { task_assigned: '/pages/?slug=tasks&id={{data.taskId}}' }
|
|
2573
|
+
* ```
|
|
2574
|
+
*/
|
|
2575
|
+
async getLinks() {
|
|
2576
|
+
const response = await this.client.get(
|
|
2577
|
+
"/notifications/links"
|
|
2578
|
+
);
|
|
2579
|
+
return response.data ?? {};
|
|
2580
|
+
}
|
|
2409
2581
|
/**
|
|
2410
2582
|
* Delete notifications for the current user
|
|
2411
2583
|
*
|
|
@@ -2712,10 +2884,11 @@ var SettingsModule = class {
|
|
|
2712
2884
|
* });
|
|
2713
2885
|
* ```
|
|
2714
2886
|
*/
|
|
2715
|
-
async update(settings) {
|
|
2887
|
+
async update(settings, options) {
|
|
2716
2888
|
const response = await this.client.patch(
|
|
2717
2889
|
"/settings",
|
|
2718
|
-
settings
|
|
2890
|
+
settings,
|
|
2891
|
+
options?.tenantId !== void 0 && options?.tenantId !== null ? { params: { tenant_id: options.tenantId } } : void 0
|
|
2719
2892
|
);
|
|
2720
2893
|
return response.data;
|
|
2721
2894
|
}
|
|
@@ -4721,15 +4894,23 @@ var ServerModule = class {
|
|
|
4721
4894
|
/**
|
|
4722
4895
|
* Get server information including project settings
|
|
4723
4896
|
*
|
|
4897
|
+
* @param tenantId - Optional tenant ID to fetch tenant-merged project settings
|
|
4898
|
+
*
|
|
4724
4899
|
* @example
|
|
4725
4900
|
* ```typescript
|
|
4726
4901
|
* const info = await baasix.server.info();
|
|
4727
4902
|
* console.log('Project:', info.project?.name);
|
|
4728
4903
|
* console.log('Version:', info.version);
|
|
4904
|
+
*
|
|
4905
|
+
* // Tenant-aware: settings merged for the given tenant
|
|
4906
|
+
* const tenantInfo = await baasix.server.info("tenant-uuid");
|
|
4729
4907
|
* ```
|
|
4730
4908
|
*/
|
|
4731
|
-
async info() {
|
|
4732
|
-
return this.client.get(
|
|
4909
|
+
async info(tenantId) {
|
|
4910
|
+
return this.client.get(
|
|
4911
|
+
"/",
|
|
4912
|
+
tenantId ? { params: { tenant_id: tenantId } } : void 0
|
|
4913
|
+
);
|
|
4733
4914
|
}
|
|
4734
4915
|
/**
|
|
4735
4916
|
* Check server health
|
|
@@ -5060,6 +5241,7 @@ exports.RealtimeChannel = RealtimeChannel;
|
|
|
5060
5241
|
exports.RealtimeModule = RealtimeModule;
|
|
5061
5242
|
exports.ReportsModule = ReportsModule;
|
|
5062
5243
|
exports.RolesModule = RolesModule;
|
|
5244
|
+
exports.SOCIAL_PROVIDERS = SOCIAL_PROVIDERS;
|
|
5063
5245
|
exports.STORAGE_KEYS = STORAGE_KEYS;
|
|
5064
5246
|
exports.SchemasModule = SchemasModule;
|
|
5065
5247
|
exports.SettingsModule = SettingsModule;
|