@palbase/backend 14.3.0 → 15.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/db/index.d.cts +2 -2
- package/dist/db/index.d.ts +2 -2
- package/dist/{endpoint-BG-JVUPL.d.cts → endpoint-BW8bn1y-.d.cts} +2 -8
- package/dist/{endpoint-BG-JVUPL.d.ts → endpoint-BW8bn1y-.d.ts} +2 -8
- package/dist/{index-QQ2byWrv.d.ts → index-B398u5B0.d.ts} +1 -1
- package/dist/{index-j3ZZS_VS.d.cts → index-DmkBkvP6.d.cts} +1 -1
- package/dist/index.cjs +40 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +22 -5
- package/dist/index.d.ts +22 -5
- package/dist/index.js +40 -1
- package/dist/index.js.map +1 -1
- package/dist/test/index.d.cts +1 -1
- package/dist/test/index.d.ts +1 -1
- package/docs/auth.md +37 -0
- package/docs/llms-full.txt +73 -3
- package/docs/services.md +36 -3
- package/package.json +1 -1
package/dist/test/index.d.cts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { D as DBClient, P as PBRequest, a as PalbaseModuleClients, L as Logger, C as CacheClient, U as User } from '../endpoint-
|
|
1
|
+
import { D as DBClient, P as PBRequest, a as PalbaseModuleClients, L as Logger, C as CacheClient, U as User } from '../endpoint-BW8bn1y-.cjs';
|
|
2
2
|
import 'zod';
|
|
3
3
|
|
|
4
4
|
/** Mock DB client with tracking and seed data support. */
|
package/dist/test/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { D as DBClient, P as PBRequest, a as PalbaseModuleClients, L as Logger, C as CacheClient, U as User } from '../endpoint-
|
|
1
|
+
import { D as DBClient, P as PBRequest, a as PalbaseModuleClients, L as Logger, C as CacheClient, U as User } from '../endpoint-BW8bn1y-.js';
|
|
2
2
|
import 'zod';
|
|
3
3
|
|
|
4
4
|
/** Mock DB client with tracking and seed data support. */
|
package/docs/auth.md
CHANGED
|
@@ -128,6 +128,43 @@ Or declare it on the route and let the runtime enforce it:
|
|
|
128
128
|
Unverified callers get `403 email_not_verified`. Use the route flag to fence a
|
|
129
129
|
whole controller, and the inline check when only part of a handler cares.
|
|
130
130
|
|
|
131
|
+
## Social sign-in and account linking
|
|
132
|
+
|
|
133
|
+
Signing in with Google or Apple is a client flow — the Web and iOS SDK docs
|
|
134
|
+
cover the redirect and code-exchange calls. The part your backend cares about
|
|
135
|
+
is which `user.id` comes out of it, because that id is what every row you wrote
|
|
136
|
+
is keyed on.
|
|
137
|
+
|
|
138
|
+
**One address, one account.** If someone signs up with `a@x.com` + password and
|
|
139
|
+
later signs in with Google on the same address, they land on the **same
|
|
140
|
+
`user.id`**, in the same session, with all their data. Palbase links the Google
|
|
141
|
+
identity onto the existing account instead of creating a second one. A second
|
|
142
|
+
account on the same address is not merely avoided — it is impossible: the email
|
|
143
|
+
is uniquely indexed.
|
|
144
|
+
|
|
145
|
+
The link happens only when the provider asserts the address is verified
|
|
146
|
+
(`email_verified`). If it does not, and the address already belongs to an
|
|
147
|
+
account, sign-in is refused with `409 email_already_registered` rather than
|
|
148
|
+
silently landing somewhere new.
|
|
149
|
+
|
|
150
|
+
**Linking into an unverified account clears its password.** An account whose
|
|
151
|
+
email was never verified could have been registered by anyone — including
|
|
152
|
+
someone who does not own the address. When a provider proves ownership and
|
|
153
|
+
links in, the untrusted password is removed and any session opened with it is
|
|
154
|
+
revoked. `@User()` still resolves to the same id, so your data keeps working;
|
|
155
|
+
the user simply no longer has a password until they set one.
|
|
156
|
+
|
|
157
|
+
**Going the other way** — a user who started with Google and now wants a
|
|
158
|
+
password — is the password *reset* flow, not `updatePassword`. There is no
|
|
159
|
+
current password to supply, so `updatePassword` fails; `resetPassword(email)`
|
|
160
|
+
followed by `confirmPasswordReset` sets the first one. Note that completing it
|
|
161
|
+
signs the user out everywhere.
|
|
162
|
+
|
|
163
|
+
To render the right form, ask the client SDK which credentials the account has
|
|
164
|
+
(`pb.auth.getSignInMethods()` in `@palbase/web`) — it reports whether a local
|
|
165
|
+
password exists and which providers are linked, so a Google-only user is never
|
|
166
|
+
shown a password field they cannot fill.
|
|
167
|
+
|
|
131
168
|
## Password reset and magic links
|
|
132
169
|
|
|
133
170
|
Both are client-driven and need no backend code: the client SDK calls the auth
|
package/docs/llms-full.txt
CHANGED
|
@@ -772,6 +772,43 @@ Or declare it on the route and let the runtime enforce it:
|
|
|
772
772
|
Unverified callers get `403 email_not_verified`. Use the route flag to fence a
|
|
773
773
|
whole controller, and the inline check when only part of a handler cares.
|
|
774
774
|
|
|
775
|
+
## Social sign-in and account linking
|
|
776
|
+
|
|
777
|
+
Signing in with Google or Apple is a client flow — the Web and iOS SDK docs
|
|
778
|
+
cover the redirect and code-exchange calls. The part your backend cares about
|
|
779
|
+
is which `user.id` comes out of it, because that id is what every row you wrote
|
|
780
|
+
is keyed on.
|
|
781
|
+
|
|
782
|
+
**One address, one account.** If someone signs up with `a@x.com` + password and
|
|
783
|
+
later signs in with Google on the same address, they land on the **same
|
|
784
|
+
`user.id`**, in the same session, with all their data. Palbase links the Google
|
|
785
|
+
identity onto the existing account instead of creating a second one. A second
|
|
786
|
+
account on the same address is not merely avoided — it is impossible: the email
|
|
787
|
+
is uniquely indexed.
|
|
788
|
+
|
|
789
|
+
The link happens only when the provider asserts the address is verified
|
|
790
|
+
(`email_verified`). If it does not, and the address already belongs to an
|
|
791
|
+
account, sign-in is refused with `409 email_already_registered` rather than
|
|
792
|
+
silently landing somewhere new.
|
|
793
|
+
|
|
794
|
+
**Linking into an unverified account clears its password.** An account whose
|
|
795
|
+
email was never verified could have been registered by anyone — including
|
|
796
|
+
someone who does not own the address. When a provider proves ownership and
|
|
797
|
+
links in, the untrusted password is removed and any session opened with it is
|
|
798
|
+
revoked. `@User()` still resolves to the same id, so your data keeps working;
|
|
799
|
+
the user simply no longer has a password until they set one.
|
|
800
|
+
|
|
801
|
+
**Going the other way** — a user who started with Google and now wants a
|
|
802
|
+
password — is the password *reset* flow, not `updatePassword`. There is no
|
|
803
|
+
current password to supply, so `updatePassword` fails; `resetPassword(email)`
|
|
804
|
+
followed by `confirmPasswordReset` sets the first one. Note that completing it
|
|
805
|
+
signs the user out everywhere.
|
|
806
|
+
|
|
807
|
+
To render the right form, ask the client SDK which credentials the account has
|
|
808
|
+
(`pb.auth.getSignInMethods()` in `@palbase/web`) — it reports whether a local
|
|
809
|
+
password exists and which providers are linked, so a Google-only user is never
|
|
810
|
+
shown a password field they cannot fill.
|
|
811
|
+
|
|
775
812
|
## Password reset and magic links
|
|
776
813
|
|
|
777
814
|
Both are client-driven and need no backend code: the client SDK calls the auth
|
|
@@ -1504,13 +1541,46 @@ const { data: doc } = await Documents.doc("rooms/abc").get();
|
|
|
1504
1541
|
|
|
1505
1542
|
## Notifications
|
|
1506
1543
|
|
|
1544
|
+
**No provider setup is required.** Every project starts with a managed sender, so
|
|
1545
|
+
email and SMS deliver on a brand-new project with no provider, no API key, and no
|
|
1546
|
+
`config/notifications.ts`. You configure your own provider only to send from your
|
|
1547
|
+
own domain — see [Config](./config.md).
|
|
1548
|
+
|
|
1507
1549
|
```ts
|
|
1508
1550
|
import { Notifications } from "@palbase/backend";
|
|
1509
|
-
|
|
1510
|
-
|
|
1511
|
-
await Notifications.
|
|
1551
|
+
|
|
1552
|
+
// Email — `to` takes one address or many.
|
|
1553
|
+
await Notifications.email.send({
|
|
1554
|
+
to: user.email,
|
|
1555
|
+
subject: "Your receipt",
|
|
1556
|
+
html: "<p>Thanks!</p>", // or `text`, or a server template:
|
|
1557
|
+
});
|
|
1558
|
+
await Notifications.email.send({
|
|
1559
|
+
to: user.email,
|
|
1560
|
+
templateSlug: "receipt", // defined in config/notifications.ts
|
|
1561
|
+
locale: "tr", // without this the extra locale rows are unreachable
|
|
1562
|
+
variables: { total: "₺240" },
|
|
1563
|
+
});
|
|
1564
|
+
|
|
1565
|
+
// Push — `to` is a device token, a list of them, or { topic }.
|
|
1566
|
+
await Notifications.push.send({
|
|
1567
|
+
to: { topic: "announcements" },
|
|
1568
|
+
title: "Deploy finished", // string, or a { "en": …, "tr": … } locale map
|
|
1569
|
+
body: "Your backend is live.",
|
|
1570
|
+
deep_link: "todoapp://deploys",
|
|
1571
|
+
});
|
|
1572
|
+
|
|
1573
|
+
// SMS — `body` and `templateSlug` are mutually exclusive.
|
|
1574
|
+
await Notifications.sms.send({ to: user.phone, body: "Your code is 123456" });
|
|
1512
1575
|
```
|
|
1513
1576
|
|
|
1577
|
+
A send that no provider can carry is rejected on the request itself with
|
|
1578
|
+
`provider_not_configured` — it is never accepted and then dropped, so a
|
|
1579
|
+
successful call means a real sender took the message.
|
|
1580
|
+
|
|
1581
|
+
`Notifications` also carries `verify` (phone OTP send/check), `inbox` (in-app
|
|
1582
|
+
messages), and `registerDevice` / `unregisterDevice` for push tokens.
|
|
1583
|
+
|
|
1514
1584
|
## Flags
|
|
1515
1585
|
|
|
1516
1586
|
```ts
|
package/docs/services.md
CHANGED
|
@@ -75,13 +75,46 @@ const { data: doc } = await Documents.doc("rooms/abc").get();
|
|
|
75
75
|
|
|
76
76
|
## Notifications
|
|
77
77
|
|
|
78
|
+
**No provider setup is required.** Every project starts with a managed sender, so
|
|
79
|
+
email and SMS deliver on a brand-new project with no provider, no API key, and no
|
|
80
|
+
`config/notifications.ts`. You configure your own provider only to send from your
|
|
81
|
+
own domain — see [Config](./config.md).
|
|
82
|
+
|
|
78
83
|
```ts
|
|
79
84
|
import { Notifications } from "@palbase/backend";
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
await Notifications.
|
|
85
|
+
|
|
86
|
+
// Email — `to` takes one address or many.
|
|
87
|
+
await Notifications.email.send({
|
|
88
|
+
to: user.email,
|
|
89
|
+
subject: "Your receipt",
|
|
90
|
+
html: "<p>Thanks!</p>", // or `text`, or a server template:
|
|
91
|
+
});
|
|
92
|
+
await Notifications.email.send({
|
|
93
|
+
to: user.email,
|
|
94
|
+
templateSlug: "receipt", // defined in config/notifications.ts
|
|
95
|
+
locale: "tr", // without this the extra locale rows are unreachable
|
|
96
|
+
variables: { total: "₺240" },
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
// Push — `to` is a device token, a list of them, or { topic }.
|
|
100
|
+
await Notifications.push.send({
|
|
101
|
+
to: { topic: "announcements" },
|
|
102
|
+
title: "Deploy finished", // string, or a { "en": …, "tr": … } locale map
|
|
103
|
+
body: "Your backend is live.",
|
|
104
|
+
deep_link: "todoapp://deploys",
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
// SMS — `body` and `templateSlug` are mutually exclusive.
|
|
108
|
+
await Notifications.sms.send({ to: user.phone, body: "Your code is 123456" });
|
|
83
109
|
```
|
|
84
110
|
|
|
111
|
+
A send that no provider can carry is rejected on the request itself with
|
|
112
|
+
`provider_not_configured` — it is never accepted and then dropped, so a
|
|
113
|
+
successful call means a real sender took the message.
|
|
114
|
+
|
|
115
|
+
`Notifications` also carries `verify` (phone OTP send/check), `inbox` (in-app
|
|
116
|
+
messages), and `registerDevice` / `unregisterDevice` for push tokens.
|
|
117
|
+
|
|
85
118
|
## Flags
|
|
86
119
|
|
|
87
120
|
```ts
|
package/package.json
CHANGED