@synqauth/plugin-magic-link 0.0.0-stage → 0.2.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Aerosol
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,24 @@
1
- # Temporary Holding Version
1
+ # @synqauth/plugin-magic-link
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ A Synq plugin for email codes and magic links from your own UI.
4
+
5
+ Synq is customer identity for businesses: an OpenID Connect issuer for each of your brands, with Solana wallet, social, email and passkey sign-in. The documentation is at [docs.synq.build](https://docs.synq.build).
6
+
7
+ This package is at 0.x and hasn't been published yet: its API can change in any release until Synq's first customer depends on it.
8
+
9
+ ## Usage
10
+
11
+ Start an emailed code or magic link from your own UI: the person types their address on your page, and the brand's hosted page sends the email and takes the code or link. You bring no email transport.
12
+
13
+ To take the code on your own page instead, with no trip to the hosted page, use own-UI sign-in: `useSignIn().emailCode` or `<SignInForm>` from `@synqauth/react`.
14
+
15
+ ```tsx
16
+ import { magicLinkPlugin } from '@synqauth/plugin-magic-link'
17
+
18
+ const { signInUrl } = magicLinkPlugin().actions(request)
19
+ location.assign(signInUrl({ email: 'ada@example.com', returnTo: '/account' }))
20
+ ```
21
+
22
+ ## License
23
+
24
+ MIT
@@ -0,0 +1,29 @@
1
+ //#region src/index.d.ts
2
+ /** The plugin's id: its actions are under it in `usePlugin` and the mount's plugin list. */
3
+ export declare const MAGIC_LINK_PLUGIN_ID = "magic-link";
4
+ /** Calls the app's route mount, from its own page: what @synqauth/react and @synqauth/nextjs/client hand a plugin. */
5
+ export type MountRequest = (path: string, init?: RequestInit) => Promise<Response>;
6
+ /** What the magic-link plugin does from the page: where to send the person to get a code or link by email. */
7
+ export interface MagicLinkActions {
8
+ /**
9
+ * Where to send someone to sign in with an emailed code or link: the
10
+ * brand's page at its email step, with `email` filled in when given.
11
+ */
12
+ signInUrl: (options?: {
13
+ email?: string;
14
+ returnTo?: string;
15
+ }) => string;
16
+ }
17
+ /** The magic-link plugin, in `SynqClientPlugin`'s shape: for `<SynqProvider plugins>` or `@synqauth/nextjs/client`. */
18
+ export interface MagicLinkPlugin {
19
+ readonly id: typeof MAGIC_LINK_PLUGIN_ID;
20
+ actions: (request: MountRequest) => MagicLinkActions;
21
+ }
22
+ /** What `magicLinkPlugin()` takes. */
23
+ export interface MagicLinkPluginOptions {
24
+ /** The route mount's path, as the app's `synqAuth()` has it: `/api/auth` by default. */
25
+ basePath?: string;
26
+ }
27
+ /** The magic-link plugin: the brand's email step, with the person's address filled in. */
28
+ export declare function magicLinkPlugin(options?: MagicLinkPluginOptions): MagicLinkPlugin;
29
+ //#endregion
package/dist/index.js ADDED
@@ -0,0 +1,24 @@
1
+ //#region src/index.ts
2
+ /** The plugin's id: its actions are under it in `usePlugin` and the mount's plugin list. */
3
+ const MAGIC_LINK_PLUGIN_ID = "magic-link";
4
+ /** A plausible address: something before and after one @, no spaces. The issuer checks it properly. */
5
+ const EMAIL = /^[^\s@]+@[^\s@]+$/;
6
+ /** The magic-link plugin: the brand's email step, with the person's address filled in. */
7
+ function magicLinkPlugin(options = {}) {
8
+ const base = `/${(options.basePath ?? "/api/auth").replace(/^\/+|\/+$/g, "")}`;
9
+ return {
10
+ id: MAGIC_LINK_PLUGIN_ID,
11
+ actions: () => ({ signInUrl: ({ email, returnTo } = {}) => {
12
+ const query = new URLSearchParams({ method: "email" });
13
+ const address = email?.trim();
14
+ if (address) {
15
+ if (address.length > 254 || !EMAIL.test(address)) throw new TypeError(`Not an email address: ${address}`);
16
+ query.set("login_hint", address);
17
+ }
18
+ if (returnTo) query.set("returnTo", returnTo);
19
+ return `${base}/sign-in?${query.toString()}`;
20
+ } })
21
+ };
22
+ }
23
+ //#endregion
24
+ export { MAGIC_LINK_PLUGIN_ID, magicLinkPlugin };
package/package.json CHANGED
@@ -1,6 +1,38 @@
1
1
  {
2
2
  "name": "@synqauth/plugin-magic-link",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
3
+ "version": "0.2.0",
4
+ "description": "A Synq plugin that sends people from your own UI to the hosted page's emailed code or magic link.",
5
+ "license": "MIT",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "git+https://github.com/aerosol-build/synq.git",
9
+ "directory": "packages/plugin-magic-link"
10
+ },
11
+ "type": "module",
12
+ "sideEffects": false,
13
+ "engines": {
14
+ "node": ">=22"
15
+ },
16
+ "exports": {
17
+ ".": {
18
+ "types": "./dist/index.d.ts",
19
+ "default": "./dist/index.js"
20
+ },
21
+ "./package.json": "./package.json"
22
+ },
23
+ "files": [
24
+ "dist"
25
+ ],
26
+ "publishConfig": {
27
+ "access": "public"
28
+ },
29
+ "devDependencies": {
30
+ "vitest": "5.0.2"
31
+ },
32
+ "scripts": {
33
+ "build": "tsdown",
34
+ "lint": "eslint .",
35
+ "typecheck": "tsc",
36
+ "test": "vitest run"
37
+ }
6
38
  }