cauthy-auth 0.35.1 → 0.36.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 CHANGED
@@ -63,6 +63,8 @@ const { invitation, acceptInvitation } = useAuth() // or with your
63
63
 
64
64
  The forms follow what the workspace turned on in Cauthy's dashboard: each provider's button carries its logo (`classNames.providerIcon` styles it), and a workspace that turned off the password or passkeys does not see them offered. `methods()` says so: `passwordSignIn`, `passkey`, `providers[].iconUrl`.
65
65
 
66
+ `<SignIn />` puts the quick ways in first: a passkey, each provider, then "Email me a sign-in link", which opens its own short step (the address typed so far, "Send me the link", "Back"). Then "or with your email", the address and password, and the primary "Sign in". Without the password, the address below the "or" asks for the sign-in link itself.
67
+
66
68
  And the person's account, in your application: name, password, second step, sessions.
67
69
 
68
70
  ```tsx
@@ -220,7 +222,7 @@ What Cauthy mails from these forms (a sign-in link, a new password, a confirmati
220
222
  <CauthyProvider locale={() => i18n.language}>
221
223
  ```
222
224
 
223
- `texts` changes any sentence. Its keys are stable: `email`, `password`, `name`, `code`, `signIn`, `signUp`, `continueWith`, `orWithEmail`, `forgotPassword`, `noAccount`, `createAccount`, `company`, `iAccept`, `and`, `termsOfService`, `privacyPolicy`, `haveAccount`, `sendLink`, `linkSent`, `codeHelp`, `codeHelpPhone`, `codeHelpEmail`, `sendEmailAgain`, `sendCodeSms`, `sendCodeWhatsapp`, `codeSent`, `pushSend`, `pushPick`, `pushWaiting`, `phone`, `phoneHelp`, `phoneOn`, `phoneOff`, `addPhone`, `removePhone`, `bySms`, `byWhatsapp`, `channel`, `verify`, `checkEmail`, `backToSignIn`, `emailMeALink`, `usePasskey`, `codeFromMail`, `signInLinkSent`, `newPassword`, `savePassword`, `passwordChanged`, `confirming`, `loading`, `emailConfirmed`, `invitedTo`, `invitedToOrganization`, `invitedAs`, `choosePassword`, `acceptInvite`, `openingInvitation`, `invitationInvalid`, `profile`, `save`, `saved`, `currentPassword`, `changePassword`, `passwordChangedHere`, `secondStep`, `secondStepOn`, `secondStepOff`, `turnOn`, `turnOff`, `addToApp`, `openInApp`, `recoveryCodes`, `newRecoveryCodes`, `keepCodes`, `passkeys`, `managePasskeys`, `passkeysHelp`, `noPasskeys`, `passkeyName`, `addPasskey` (unused), `addPasskeyDevice`, `addSecurityKey`, `passkeyKinds`, `removePasskey`, `passkeyAdded`, `passkeyUnnamed`, `sessions`, `signOutEverywhere`, `agents`, `agentsHelp`, `disconnect`, `anAgent`, `unknownDevice`, `emailAddress`, `newEmail`, `changeEmail`, `emailSent`, `linkedAccounts`, `noLinkedAccounts`, `linkWith`, `unlink`, `linked`, `ssoOnly`, `members`, `membersHidden`, `organizationMissing`, `memberYou`, `memberInvited`, `memberManager`, `memberRole`, `memberAdd`, `memberAdded`, `memberRemove`, `memberRemoveConfirm`, `memberLeave`, `memberLeaveConfirm`, `memberInviteAgain`, `memberInvitationSent`, `organization`, `organizationRename`, `organizationRenamed`, `organizationArchive`, `organizationArchiveConfirm`, `organizationArchived`, `organizationDelete`, `organizationDeleteConfirm`, `organizationDeleted`, `yes`, `cancel`, `termsChanged`, `termsChangedHelp`, `acceptTerms`, and `errors` by error code. Built in: English and Spanish (`locale`). The dashboard can start the look from your stylesheet (shadcn/ui and Tailwind, Stackmyth, or variables of your own); `npx cauthy-auth theme --css src/app/globals.css` reads it the same way from a terminal.
225
+ `texts` changes any sentence. Its keys are stable: `email`, `password`, `name`, `code`, `signIn`, `signUp`, `continueWith`, `orWithEmail`, `forgotPassword`, `noAccount`, `createAccount`, `company`, `iAccept`, `and`, `termsOfService`, `privacyPolicy`, `haveAccount`, `sendLink`, `linkSent`, `codeHelp`, `codeHelpPhone`, `codeHelpEmail`, `sendEmailAgain`, `sendCodeSms`, `sendCodeWhatsapp`, `codeSent`, `pushSend`, `pushPick`, `pushWaiting`, `phone`, `phoneHelp`, `phoneOn`, `phoneOff`, `addPhone`, `removePhone`, `bySms`, `byWhatsapp`, `channel`, `verify`, `checkEmail`, `backToSignIn`, `emailMeALink`, `linkHelp`, `sendMeTheLink`, `back`, `usePasskey`, `codeFromMail`, `signInLinkSent`, `newPassword`, `savePassword`, `passwordChanged`, `confirming`, `loading`, `emailConfirmed`, `invitedTo`, `invitedToOrganization`, `invitedAs`, `choosePassword`, `acceptInvite`, `openingInvitation`, `invitationInvalid`, `profile`, `save`, `saved`, `currentPassword`, `changePassword`, `passwordChangedHere`, `secondStep`, `secondStepOn`, `secondStepOff`, `turnOn`, `turnOff`, `addToApp`, `openInApp`, `recoveryCodes`, `newRecoveryCodes`, `keepCodes`, `passkeys`, `managePasskeys`, `passkeysHelp`, `noPasskeys`, `passkeyName`, `addPasskey` (unused), `addPasskeyDevice`, `addSecurityKey`, `passkeyKinds`, `removePasskey`, `passkeyAdded`, `passkeyUnnamed`, `sessions`, `signOutEverywhere`, `agents`, `agentsHelp`, `disconnect`, `anAgent`, `unknownDevice`, `emailAddress`, `newEmail`, `changeEmail`, `emailSent`, `linkedAccounts`, `noLinkedAccounts`, `linkWith`, `unlink`, `linked`, `ssoOnly`, `members`, `membersHidden`, `organizationMissing`, `memberYou`, `memberInvited`, `memberManager`, `memberRole`, `memberAdd`, `memberAdded`, `memberRemove`, `memberRemoveConfirm`, `memberLeave`, `memberLeaveConfirm`, `memberInviteAgain`, `memberInvitationSent`, `organization`, `organizationRename`, `organizationRenamed`, `organizationArchive`, `organizationArchiveConfirm`, `organizationArchived`, `organizationDelete`, `organizationDeleteConfirm`, `organizationDeleted`, `yes`, `cancel`, `termsChanged`, `termsChangedHelp`, `acceptTerms`, and `errors` by error code. Built in: English and Spanish (`locale`). The dashboard can start the look from your stylesheet (shadcn/ui and Tailwind, Stackmyth, or variables of your own); `npx cauthy-auth theme --css src/app/globals.css` reads it the same way from a terminal.
224
226
 
225
227
  Connect your application to Cauthy in one step, from Cauthy's dashboard ("Connect a System") or from a terminal. In the application's folder, `init` reads its framework (Next.js, TanStack Start, React Router or Remix, SvelteKit, Vite + React, Express, Hono, Fastify), makes the client, writes every variable to its env file, `CAUTHY_SECRET` included, and lays down the route and a sign-in page, never over a file that is there:
226
228
 
package/dist/react.d.mts CHANGED
@@ -1190,6 +1190,10 @@ interface AuthTexts {
1190
1190
  checkEmail: string;
1191
1191
  backToSignIn: string;
1192
1192
  emailMeALink: string;
1193
+ /** The sign-in link's own step: what it does, its send button, the way back. */
1194
+ linkHelp: string;
1195
+ sendMeTheLink: string;
1196
+ back: string;
1193
1197
  usePasskey: string;
1194
1198
  codeFromMail: string;
1195
1199
  signInLinkSent: string;
package/dist/react.d.ts CHANGED
@@ -1190,6 +1190,10 @@ interface AuthTexts {
1190
1190
  checkEmail: string;
1191
1191
  backToSignIn: string;
1192
1192
  emailMeALink: string;
1193
+ /** The sign-in link's own step: what it does, its send button, the way back. */
1194
+ linkHelp: string;
1195
+ sendMeTheLink: string;
1196
+ back: string;
1193
1197
  usePasskey: string;
1194
1198
  codeFromMail: string;
1195
1199
  signInLinkSent: string;
package/dist/react.js CHANGED
@@ -816,6 +816,9 @@ var TEXTS = {
816
816
  checkEmail: "Almost there: open the link we sent to confirm your address \u2014 it signs you in.",
817
817
  backToSignIn: "Back to sign in",
818
818
  emailMeALink: "Email me a sign-in link",
819
+ linkHelp: "We will email you a link that signs you in, no password needed.",
820
+ sendMeTheLink: "Send me the link",
821
+ back: "Back",
819
822
  usePasskey: "Sign in with a passkey",
820
823
  codeFromMail: "Reading it on another device? Enter the code from the email.",
821
824
  signInLinkSent: "If that address has an account, a link to sign in is on its way.",
@@ -997,6 +1000,9 @@ var TEXTS = {
997
1000
  checkEmail: "Casi listo: abre el enlace que te enviamos para confirmar tu correo; te deja adentro.",
998
1001
  backToSignIn: "Volver a entrar",
999
1002
  emailMeALink: "Env\xEDame un enlace para entrar",
1003
+ linkHelp: "Te enviamos un enlace al correo que te deja entrar, sin contrase\xF1a.",
1004
+ sendMeTheLink: "Env\xEDame el enlace",
1005
+ back: "Volver",
1000
1006
  usePasskey: "Entrar con una llave de acceso",
1001
1007
  codeFromMail: "\xBFLo est\xE1s leyendo en otro dispositivo? Escribe el c\xF3digo que trae el correo.",
1002
1008
  signInLinkSent: "Si ese correo tiene una cuenta, ya va en camino un enlace para entrar.",
@@ -1692,9 +1698,14 @@ function SignIn(props) {
1692
1698
  f.setError(null);
1693
1699
  return toCompany();
1694
1700
  }
1701
+ if (step === "link") {
1702
+ if (company?.enforced) return toCompany();
1703
+ if (f.check(checkEmail(email))) return sendLink();
1704
+ return;
1705
+ }
1695
1706
  if (step === "password" && !passwordOn) {
1696
1707
  if (company) return toCompany();
1697
- if (methods?.magicLink) return sendLink();
1708
+ if (methods?.magicLink && f.check(checkEmail(email))) return sendLink();
1698
1709
  return;
1699
1710
  }
1700
1711
  if (step === "password" && !f.check(checkEmail(email), checkPassword(password))) return;
@@ -1735,6 +1746,11 @@ function SignIn(props) {
1735
1746
  if (!r.ok) return f.setError(r.error);
1736
1747
  setStep("sent");
1737
1748
  };
1749
+ const openLink = () => {
1750
+ autofill.current?.abort();
1751
+ f.setError(null);
1752
+ setStep("link");
1753
+ };
1738
1754
  const general = f.error && !f.error.field ? f.error : null;
1739
1755
  const asksEmail = offers.email;
1740
1756
  if (step === "opening") return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Wrap, { f, as: "div", slot: "form", root: f.root, busy: true });
@@ -1748,11 +1764,27 @@ function SignIn(props) {
1748
1764
  ] });
1749
1765
  }
1750
1766
  if (step === "code") return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SecondStepForm, { f, auth });
1767
+ if (step === "link") {
1768
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Wrap, { f, as: "form", slot: "form", root: f.root, onSubmit: submit, noValidate: true, children: [
1769
+ general && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Say, { f, tone: "danger", children: f.say(general) }),
1770
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Note, { f, children: f.t.linkHelp }),
1771
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Field, { f, name: "email", type: "email", label: f.t.email, value: email, autoComplete: "username", required: true, onChange: setEmail }),
1772
+ challenge.node,
1773
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "submit", variant: "primary", loading: f.loading("link"), disabled: f.busy, className: f.cx("button"), children: f.t.sendMeTheLink }),
1774
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "button", variant: "secondary", disabled: f.busy, className: f.cx("providerButton"), onClick: () => {
1775
+ f.setError(null);
1776
+ setStep("password");
1777
+ }, children: f.t.back })
1778
+ ] });
1779
+ }
1780
+ const quickLink = methods?.magicLink === true && passwordOn;
1781
+ const quick = offers.passkey || (methods?.providers.length ?? 0) > 0 || quickLink;
1751
1782
  return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Wrap, { f, as: "form", slot: "form", root: f.root, onSubmit: submit, noValidate: true, children: [
1752
1783
  general && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Say, { f, tone: "danger", children: f.say(general) }),
1753
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ProviderButtons, { f, providers: methods?.providers ?? [], onPick: (id) => auth.signIn.social(id, { returnTo: props.returnTo }) }),
1754
1784
  offers.passkey && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "button", variant: "secondary", loading: f.loading("passkey"), disabled: f.busy, className: f.cx("providerButton"), onClick: () => void usePasskey(), children: f.t.usePasskey }),
1755
- asksEmail && ((methods?.providers.length ?? 0) > 0 || offers.passkey) && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Or, { f, children: f.t.orWithEmail }),
1785
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ProviderButtons, { f, providers: methods?.providers ?? [], onPick: (id) => auth.signIn.social(id, { returnTo: props.returnTo }) }),
1786
+ quickLink && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "button", variant: "secondary", disabled: f.busy, className: f.cx("providerButton"), onClick: openLink, children: f.t.emailMeALink }),
1787
+ asksEmail && quick && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Or, { f, children: f.t.orWithEmail }),
1756
1788
  asksEmail && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Field, { f, name: "email", type: "email", label: f.t.email, value: email, autoComplete: methods?.passkeyHere ? "username webauthn" : "username", required: true, onChange: setEmail }),
1757
1789
  company && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(f.Button, { type: "button", variant: company.enforced ? "primary" : "secondary", loading: f.loading("sso"), disabled: f.busy, className: f.cx(company.enforced ? "button" : "providerButton"), onClick: toCompany, children: [
1758
1790
  f.t.continueWith,
@@ -1778,8 +1810,10 @@ function SignIn(props) {
1778
1810
  challenge.node,
1779
1811
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "submit", variant: "primary", loading: f.loading(), disabled: f.busy, className: f.cx("button"), children: f.t.signIn })
1780
1812
  ] }),
1781
- !company?.enforced && !passwordOn && methods?.magicLink && challenge.node,
1782
- methods?.magicLink && !company?.enforced && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "button", variant: "secondary", loading: f.loading("link"), disabled: f.busy, className: f.cx("providerButton"), onClick: () => void sendLink(), children: f.t.emailMeALink }),
1813
+ !company?.enforced && !passwordOn && methods?.magicLink && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
1814
+ challenge.node,
1815
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "submit", variant: "primary", loading: f.loading("link"), disabled: f.busy, className: f.cx("button"), children: f.t.sendMeTheLink })
1816
+ ] }),
1783
1817
  methods?.signUp !== false && props.links?.signUp && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Note, { f, footer: true, children: [
1784
1818
  f.t.noAccount,
1785
1819
  " ",