@dreamshive/better-auth-tauri 0.1.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.
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Refetch the session when the network comes back online. Useful after
3
+ * suspend/resume or a flaky wifi transition — otherwise the session
4
+ * store would keep showing the cached pre-disconnect state until some
5
+ * other request tries (and fails) to reach the server.
6
+ *
7
+ * Uses the browser's standard `online` event, which the Tauri WebView
8
+ * exposes the same way Chrome/Safari do. No Tauri plugin needed — the
9
+ * OS-level network state flows through the webview's navigator.
10
+ *
11
+ * Returns an unlisten function.
12
+ */
13
+ export function setupTauriOnlineManager(store) {
14
+ if (typeof window === "undefined") {
15
+ return () => { };
16
+ }
17
+ const handleOnline = () => {
18
+ store.notify("$sessionSignal");
19
+ };
20
+ window.addEventListener("online", handleOnline);
21
+ return () => {
22
+ window.removeEventListener("online", handleOnline);
23
+ };
24
+ }
25
+ //# sourceMappingURL=online-manager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"online-manager.js","sourceRoot":"","sources":["../src/online-manager.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,uBAAuB,CAAC,KAAkB;IACxD,IAAI,OAAO,MAAM,KAAK,WAAW,EAAE,CAAC;QAClC,OAAO,GAAG,EAAE,GAAE,CAAC,CAAC;IAClB,CAAC;IAED,MAAM,YAAY,GAAG,GAAG,EAAE;QACxB,KAAK,CAAC,MAAM,CAAC,gBAAgB,CAAC,CAAC;IACjC,CAAC,CAAC;IAEF,MAAM,CAAC,gBAAgB,CAAC,QAAQ,EAAE,YAAY,CAAC,CAAC;IAEhD,OAAO,GAAG,EAAE;QACV,MAAM,CAAC,mBAAmB,CAAC,QAAQ,EAAE,YAAY,CAAC,CAAC;IACrD,CAAC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,46 @@
1
+ import * as z from "zod";
2
+ /**
3
+ * Server-side proxy that plants the OAuth CSRF state cookie in the system
4
+ * browser's cookie jar *before* redirecting to the provider's authorization
5
+ * URL. Without this, Better Auth's callback state-vs-cookie check fails in
6
+ * the Tauri flow because the state cookie was set on the `/sign-in/social`
7
+ * response inside the Tauri webview — a different cookie jar from the one
8
+ * the system browser uses for the actual OAuth dance.
9
+ *
10
+ * Two modes, matching the Expo plugin:
11
+ *
12
+ * 1. `oauthState` query param present → plant it as a plain `oauth_state`
13
+ * cookie (10 min TTL). Used when the client already has a stored state
14
+ * it wants re-seeded before starting the flow.
15
+ *
16
+ * 2. `oauthState` absent → extract the `state` query param from the
17
+ * authorization URL and plant it as a signed `state` cookie (5 min
18
+ * TTL). This is the common path for a fresh OAuth sign-in.
19
+ *
20
+ * Endpoint is hidden from the Better Auth route docs — it's an internal
21
+ * detail of the Tauri plugin flow.
22
+ */
23
+ export declare const tauriAuthorizationProxy: import("better-call").StrictEndpoint<"/tauri-authorization-proxy", {
24
+ method: "GET";
25
+ query: z.ZodObject<{
26
+ authorizationURL: z.ZodString;
27
+ oauthState: z.ZodOptional<z.ZodString>;
28
+ }, z.core.$strip>;
29
+ metadata: {
30
+ readonly scope: "server";
31
+ };
32
+ }, {
33
+ status: ("OK" | "CREATED" | "ACCEPTED" | "NO_CONTENT" | "MULTIPLE_CHOICES" | "MOVED_PERMANENTLY" | "FOUND" | "SEE_OTHER" | "NOT_MODIFIED" | "TEMPORARY_REDIRECT" | "BAD_REQUEST" | "UNAUTHORIZED" | "PAYMENT_REQUIRED" | "FORBIDDEN" | "NOT_FOUND" | "METHOD_NOT_ALLOWED" | "NOT_ACCEPTABLE" | "PROXY_AUTHENTICATION_REQUIRED" | "REQUEST_TIMEOUT" | "CONFLICT" | "GONE" | "LENGTH_REQUIRED" | "PRECONDITION_FAILED" | "PAYLOAD_TOO_LARGE" | "URI_TOO_LONG" | "UNSUPPORTED_MEDIA_TYPE" | "RANGE_NOT_SATISFIABLE" | "EXPECTATION_FAILED" | "I'M_A_TEAPOT" | "MISDIRECTED_REQUEST" | "UNPROCESSABLE_ENTITY" | "LOCKED" | "FAILED_DEPENDENCY" | "TOO_EARLY" | "UPGRADE_REQUIRED" | "PRECONDITION_REQUIRED" | "TOO_MANY_REQUESTS" | "REQUEST_HEADER_FIELDS_TOO_LARGE" | "UNAVAILABLE_FOR_LEGAL_REASONS" | "INTERNAL_SERVER_ERROR" | "NOT_IMPLEMENTED" | "BAD_GATEWAY" | "SERVICE_UNAVAILABLE" | "GATEWAY_TIMEOUT" | "HTTP_VERSION_NOT_SUPPORTED" | "VARIANT_ALSO_NEGOTIATES" | "INSUFFICIENT_STORAGE" | "LOOP_DETECTED" | "NOT_EXTENDED" | "NETWORK_AUTHENTICATION_REQUIRED") | import("better-call").Status;
34
+ body: ({
35
+ message?: string;
36
+ code?: string;
37
+ cause?: unknown;
38
+ } & Record<string, any>) | undefined;
39
+ headers: HeadersInit;
40
+ statusCode: number;
41
+ name: string;
42
+ message: string;
43
+ stack?: string;
44
+ cause?: unknown;
45
+ }>;
46
+ //# sourceMappingURL=routes.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"routes.d.ts","sourceRoot":"","sources":["../src/routes.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,CAAC,MAAM,KAAK,CAAC;AAEzB;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,eAAO,MAAM,uBAAuB;;;;;;;;;;;;eA0C8G,CAAC;YAAkB,CAAC;aAAmB,CAAC;;;;;;;;EADzL,CAAC"}
package/dist/routes.js ADDED
@@ -0,0 +1,51 @@
1
+ import { APIError, createAuthEndpoint } from "better-auth/api";
2
+ import { HIDE_METADATA } from "better-auth";
3
+ import * as z from "zod";
4
+ /**
5
+ * Server-side proxy that plants the OAuth CSRF state cookie in the system
6
+ * browser's cookie jar *before* redirecting to the provider's authorization
7
+ * URL. Without this, Better Auth's callback state-vs-cookie check fails in
8
+ * the Tauri flow because the state cookie was set on the `/sign-in/social`
9
+ * response inside the Tauri webview — a different cookie jar from the one
10
+ * the system browser uses for the actual OAuth dance.
11
+ *
12
+ * Two modes, matching the Expo plugin:
13
+ *
14
+ * 1. `oauthState` query param present → plant it as a plain `oauth_state`
15
+ * cookie (10 min TTL). Used when the client already has a stored state
16
+ * it wants re-seeded before starting the flow.
17
+ *
18
+ * 2. `oauthState` absent → extract the `state` query param from the
19
+ * authorization URL and plant it as a signed `state` cookie (5 min
20
+ * TTL). This is the common path for a fresh OAuth sign-in.
21
+ *
22
+ * Endpoint is hidden from the Better Auth route docs — it's an internal
23
+ * detail of the Tauri plugin flow.
24
+ */
25
+ export const tauriAuthorizationProxy = createAuthEndpoint("/tauri-authorization-proxy", {
26
+ method: "GET",
27
+ query: z.object({
28
+ authorizationURL: z.string(),
29
+ oauthState: z.string().optional(),
30
+ }),
31
+ metadata: HIDE_METADATA,
32
+ }, async (ctx) => {
33
+ const { oauthState, authorizationURL } = ctx.query;
34
+ if (oauthState) {
35
+ const oauthStateCookie = ctx.context.createAuthCookie("oauth_state", {
36
+ maxAge: 600,
37
+ });
38
+ ctx.setCookie(oauthStateCookie.name, oauthState, oauthStateCookie.attributes);
39
+ return ctx.redirect(authorizationURL);
40
+ }
41
+ const state = new URL(authorizationURL).searchParams.get("state");
42
+ if (!state) {
43
+ throw new APIError("BAD_REQUEST", {
44
+ message: "authorizationURL is missing required `state` query parameter",
45
+ });
46
+ }
47
+ const stateCookie = ctx.context.createAuthCookie("state", { maxAge: 300 });
48
+ await ctx.setSignedCookie(stateCookie.name, state, ctx.context.secret, stateCookie.attributes);
49
+ return ctx.redirect(authorizationURL);
50
+ });
51
+ //# sourceMappingURL=routes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"routes.js","sourceRoot":"","sources":["../src/routes.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAC/D,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,KAAK,CAAC,MAAM,KAAK,CAAC;AAEzB;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAAG,kBAAkB,CACvD,4BAA4B,EAC5B;IACE,MAAM,EAAE,KAAK;IACb,KAAK,EAAE,CAAC,CAAC,MAAM,CAAC;QACd,gBAAgB,EAAE,CAAC,CAAC,MAAM,EAAE;QAC5B,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;KAClC,CAAC;IACF,QAAQ,EAAE,aAAa;CACxB,EACD,KAAK,EAAE,GAAG,EAAE,EAAE;IACZ,MAAM,EAAE,UAAU,EAAE,gBAAgB,EAAE,GAAG,GAAG,CAAC,KAAK,CAAC;IAEnD,IAAI,UAAU,EAAE,CAAC;QACf,MAAM,gBAAgB,GAAG,GAAG,CAAC,OAAO,CAAC,gBAAgB,CAAC,aAAa,EAAE;YACnE,MAAM,EAAE,GAAG;SACZ,CAAC,CAAC;QACH,GAAG,CAAC,SAAS,CACX,gBAAgB,CAAC,IAAI,EACrB,UAAU,EACV,gBAAgB,CAAC,UAAU,CAC5B,CAAC;QACF,OAAO,GAAG,CAAC,QAAQ,CAAC,gBAAgB,CAAC,CAAC;IACxC,CAAC;IAED,MAAM,KAAK,GAAG,IAAI,GAAG,CAAC,gBAAgB,CAAC,CAAC,YAAY,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;IAClE,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,MAAM,IAAI,QAAQ,CAAC,aAAa,EAAE;YAChC,OAAO,EAAE,8DAA8D;SACxE,CAAC,CAAC;IACL,CAAC;IAED,MAAM,WAAW,GAAG,GAAG,CAAC,OAAO,CAAC,gBAAgB,CAAC,OAAO,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC;IAC3E,MAAM,GAAG,CAAC,eAAe,CACvB,WAAW,CAAC,IAAI,EAChB,KAAK,EACL,GAAG,CAAC,OAAO,CAAC,MAAM,EAClB,WAAW,CAAC,UAAU,CACvB,CAAC;IACF,OAAO,GAAG,CAAC,QAAQ,CAAC,gBAAgB,CAAC,CAAC;AACxC,CAAC,CACF,CAAC"}
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Detects whether the current runtime is a Tauri webview.
3
+ * During `vite dev` / `nuxt dev` in a normal browser, the Tauri IPC
4
+ * globals are absent — the client plugin should no-op its desktop
5
+ * branches in that case so the same code works in both environments.
6
+ */
7
+ export declare function isTauriRuntime(): boolean;
8
+ /**
9
+ * Build a deep-link URL from a scheme + path.
10
+ * `createSchemeURL("/auth/callback", "sokudo")` → `"sokudo://auth/callback"`
11
+ */
12
+ export declare function createSchemeURL(path: string, scheme: string): string;
13
+ /**
14
+ * Origin equivalent for a custom scheme, e.g. `sokudo://`.
15
+ * Used for the `tauri-origin` header so the server can validate the request
16
+ * came from a trusted Tauri app build.
17
+ */
18
+ export declare function getOrigin(scheme: string): string;
19
+ /** Forgiving JSON.parse that never throws. */
20
+ export declare function safeJSONParse<T = unknown>(input: string | null | undefined): T | null;
21
+ //# sourceMappingURL=utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,wBAAgB,cAAc,IAAI,OAAO,CAOxC;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAGpE;AAED;;;;GAIG;AACH,wBAAgB,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAEhD;AAED,8CAA8C;AAC9C,wBAAgB,aAAa,CAAC,CAAC,GAAG,OAAO,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,CAAC,GAAG,IAAI,CAOrF"}
package/dist/utils.js ADDED
@@ -0,0 +1,41 @@
1
+ /**
2
+ * Detects whether the current runtime is a Tauri webview.
3
+ * During `vite dev` / `nuxt dev` in a normal browser, the Tauri IPC
4
+ * globals are absent — the client plugin should no-op its desktop
5
+ * branches in that case so the same code works in both environments.
6
+ */
7
+ export function isTauriRuntime() {
8
+ if (typeof window === "undefined")
9
+ return false;
10
+ return ("__TAURI_INTERNALS__" in window ||
11
+ "__TAURI__" in window ||
12
+ "__TAURI_METADATA__" in window);
13
+ }
14
+ /**
15
+ * Build a deep-link URL from a scheme + path.
16
+ * `createSchemeURL("/auth/callback", "sokudo")` → `"sokudo://auth/callback"`
17
+ */
18
+ export function createSchemeURL(path, scheme) {
19
+ const normalized = path.startsWith("/") ? path.slice(1) : path;
20
+ return `${scheme}://${normalized}`;
21
+ }
22
+ /**
23
+ * Origin equivalent for a custom scheme, e.g. `sokudo://`.
24
+ * Used for the `tauri-origin` header so the server can validate the request
25
+ * came from a trusted Tauri app build.
26
+ */
27
+ export function getOrigin(scheme) {
28
+ return `${scheme}://`;
29
+ }
30
+ /** Forgiving JSON.parse that never throws. */
31
+ export function safeJSONParse(input) {
32
+ if (!input)
33
+ return null;
34
+ try {
35
+ return JSON.parse(input);
36
+ }
37
+ catch {
38
+ return null;
39
+ }
40
+ }
41
+ //# sourceMappingURL=utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.js","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,MAAM,UAAU,cAAc;IAC5B,IAAI,OAAO,MAAM,KAAK,WAAW;QAAE,OAAO,KAAK,CAAC;IAChD,OAAO,CACL,qBAAqB,IAAI,MAAM;QAC/B,WAAW,IAAI,MAAM;QACrB,oBAAoB,IAAI,MAAM,CAC/B,CAAC;AACJ,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,eAAe,CAAC,IAAY,EAAE,MAAc;IAC1D,MAAM,UAAU,GAAG,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IAC/D,OAAO,GAAG,MAAM,MAAM,UAAU,EAAE,CAAC;AACrC,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,SAAS,CAAC,MAAc;IACtC,OAAO,GAAG,MAAM,KAAK,CAAC;AACxB,CAAC;AAED,8CAA8C;AAC9C,MAAM,UAAU,aAAa,CAAc,KAAgC;IACzE,IAAI,CAAC,KAAK;QAAE,OAAO,IAAI,CAAC;IACxB,IAAI,CAAC;QACH,OAAO,IAAI,CAAC,KAAK,CAAC,KAAK,CAAM,CAAC;IAChC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare const PACKAGE_VERSION = "0.1.0";
2
+ //# sourceMappingURL=version.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"version.d.ts","sourceRoot":"","sources":["../src/version.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,eAAe,UAAU,CAAC"}
@@ -0,0 +1,2 @@
1
+ export const PACKAGE_VERSION = "0.1.0";
2
+ //# sourceMappingURL=version.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"version.js","sourceRoot":"","sources":["../src/version.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,eAAe,GAAG,OAAO,CAAC"}
package/package.json ADDED
@@ -0,0 +1,81 @@
1
+ {
2
+ "name": "@dreamshive/better-auth-tauri",
3
+ "version": "0.1.0",
4
+ "description": "Better Auth plugin for Tauri desktop apps — handles OAuth via the system browser with deep-link callbacks, cookie bridging via URL, and secure token storage hooks.",
5
+ "license": "MIT",
6
+ "author": "Rully Ardiansyah",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "git+https://github.com/DreamsHive/better-auth-tauri.git"
10
+ },
11
+ "homepage": "https://github.com/DreamsHive/better-auth-tauri#readme",
12
+ "bugs": {
13
+ "url": "https://github.com/DreamsHive/better-auth-tauri/issues"
14
+ },
15
+ "type": "module",
16
+ "sideEffects": false,
17
+ "keywords": [
18
+ "better-auth",
19
+ "tauri",
20
+ "oauth",
21
+ "auth",
22
+ "desktop",
23
+ "deep-link"
24
+ ],
25
+ "exports": {
26
+ ".": {
27
+ "types": "./dist/index.d.ts",
28
+ "import": "./dist/index.js",
29
+ "default": "./dist/index.js"
30
+ },
31
+ "./client": {
32
+ "types": "./dist/client.d.ts",
33
+ "import": "./dist/client.js",
34
+ "default": "./dist/client.js"
35
+ }
36
+ },
37
+ "main": "./dist/index.js",
38
+ "types": "./dist/index.d.ts",
39
+ "files": [
40
+ "dist",
41
+ "src",
42
+ "README.md",
43
+ "LICENSE"
44
+ ],
45
+ "scripts": {
46
+ "build": "tsc -p tsconfig.build.json",
47
+ "dev": "tsc -p tsconfig.build.json --watch",
48
+ "typecheck": "tsc --noEmit",
49
+ "test": "vitest run",
50
+ "test:watch": "vitest",
51
+ "clean": "rm -rf dist",
52
+ "prepublishOnly": "bun run clean && bun run build && bun run typecheck && bun run test"
53
+ },
54
+ "dependencies": {
55
+ "zod": "^3.24.0 || ^4.0.0"
56
+ },
57
+ "peerDependencies": {
58
+ "@tauri-apps/plugin-deep-link": "^2.0.0",
59
+ "@tauri-apps/plugin-shell": "^2.0.0",
60
+ "better-auth": "^1.6.0"
61
+ },
62
+ "peerDependenciesMeta": {
63
+ "@tauri-apps/plugin-deep-link": {
64
+ "optional": true
65
+ },
66
+ "@tauri-apps/plugin-shell": {
67
+ "optional": true
68
+ }
69
+ },
70
+ "devDependencies": {
71
+ "@tauri-apps/plugin-deep-link": "^2.0.0",
72
+ "@tauri-apps/plugin-shell": "^2.0.0",
73
+ "@types/node": "^20.0.0",
74
+ "better-auth": "^1.6.5",
75
+ "typescript": "^5.7.0",
76
+ "vitest": "^2.1.0"
77
+ },
78
+ "publishConfig": {
79
+ "access": "public"
80
+ }
81
+ }