@nodaro/sdk 1.6.0 → 1.7.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,71 @@
1
+ 'use strict';
2
+
3
+ var ssr = require('@supabase/ssr');
4
+
5
+ // src/supabase-browser.ts
6
+ function legacyStorageKey(url) {
7
+ return `sb-${new URL(url).hostname.split(".")[0]}-auth-token`;
8
+ }
9
+ function domainApplies(hostname, cookieDomain) {
10
+ const bare = cookieDomain.replace(/^\./, "");
11
+ return hostname === bare || hostname.endsWith(`.${bare}`);
12
+ }
13
+ function migrateLegacySession(client, url) {
14
+ if (typeof localStorage === "undefined") return null;
15
+ const key = legacyStorageKey(url);
16
+ const raw = localStorage.getItem(key);
17
+ if (!raw) return null;
18
+ return (async () => {
19
+ try {
20
+ const parsed = JSON.parse(raw);
21
+ if (parsed.access_token && parsed.refresh_token) {
22
+ await client.auth.setSession({
23
+ access_token: parsed.access_token,
24
+ refresh_token: parsed.refresh_token
25
+ });
26
+ }
27
+ } catch {
28
+ } finally {
29
+ localStorage.removeItem(key);
30
+ }
31
+ })();
32
+ }
33
+ function createSharedSupabaseClient(opts) {
34
+ const hostname = typeof location !== "undefined" ? location.hostname : "";
35
+ const domain = opts.cookieDomain && domainApplies(hostname, opts.cookieDomain) ? opts.cookieDomain : void 0;
36
+ const client = ssr.createBrowserClient(opts.url, opts.anonKey, {
37
+ // Each app keeps its own module-level singleton; per-call instances keep
38
+ // tests deterministic.
39
+ isSingleton: false,
40
+ cookieOptions: {
41
+ ...domain ? { domain } : {},
42
+ path: "/",
43
+ sameSite: "lax",
44
+ secure: typeof location !== "undefined" && location.protocol === "https:",
45
+ // Long-lived cookie; real session validity is governed by refresh-token
46
+ // rotation, not cookie lifetime.
47
+ maxAge: 60 * 60 * 24 * 365
48
+ },
49
+ auth: {
50
+ flowType: "pkce",
51
+ detectSessionInUrl: true,
52
+ // Bypass Navigator Lock API: prevents AbortError from
53
+ // @supabase/auth-js/locks.ts during session synchronization; cross-tab
54
+ // coordination is non-critical for these apps.
55
+ lock: async (_name, _acquireTimeout, fn) => fn()
56
+ }
57
+ });
58
+ const migration = migrateLegacySession(client, opts.url);
59
+ if (migration) {
60
+ const orig = client.auth.getSession.bind(client.auth);
61
+ client.auth.getSession = async () => {
62
+ await migration;
63
+ return orig();
64
+ };
65
+ }
66
+ return client;
67
+ }
68
+
69
+ exports.createSharedSupabaseClient = createSharedSupabaseClient;
70
+ //# sourceMappingURL=supabase-browser.cjs.map
71
+ //# sourceMappingURL=supabase-browser.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/supabase-browser.ts"],"names":["createBrowserClient"],"mappings":"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","file":"supabase-browser.cjs","sourcesContent":["import { createBrowserClient } from \"@supabase/ssr\"\nimport type { SupabaseClient } from \"@supabase/supabase-js\"\n\n/**\n * Browser Supabase client with session storage in cookies instead of\n * localStorage, so several apps on sibling subdomains (e.g. app/studio/voice\n * on *.nodaro.ai) share one login: sign in on any of them, signed in on all;\n * sign out anywhere, signed out everywhere (supabase-js signOut defaults to\n * the global scope).\n */\nexport interface SharedSupabaseOptions {\n /** Supabase project URL (https://<ref>.supabase.co). */\n url: string\n anonKey: string\n /**\n * Cookie Domain for cross-subdomain sharing (e.g. \".nodaro.ai\"). Applied\n * only when the page's hostname is that domain or a subdomain of it; on any\n * other host (localhost, preview URLs) cookies stay host-only, which keeps\n * local dev on per-origin sessions.\n */\n cookieDomain?: string\n}\n\n/** supabase-js's default localStorage key: `sb-<project-ref>-auth-token`. */\nfunction legacyStorageKey(url: string): string {\n return `sb-${new URL(url).hostname.split(\".\")[0]}-auth-token`\n}\n\nfunction domainApplies(hostname: string, cookieDomain: string): boolean {\n const bare = cookieDomain.replace(/^\\./, \"\")\n return hostname === bare || hostname.endsWith(`.${bare}`)\n}\n\n/**\n * One-time adoption of a pre-cookie session this origin left in localStorage,\n * so already-signed-in users survive the storage switch. setSession persists\n * through the client's (cookie) storage; dead tokens reject and the user is\n * simply signed out. The legacy key is removed in every outcome.\n * Returns null when there is nothing to migrate.\n */\nfunction migrateLegacySession(\n client: SupabaseClient<any>,\n url: string\n): Promise<void> | null {\n if (typeof localStorage === \"undefined\") return null\n const key = legacyStorageKey(url)\n const raw = localStorage.getItem(key)\n if (!raw) return null\n return (async () => {\n try {\n const parsed = JSON.parse(raw) as {\n access_token?: string\n refresh_token?: string\n }\n if (parsed.access_token && parsed.refresh_token) {\n await client.auth.setSession({\n access_token: parsed.access_token,\n refresh_token: parsed.refresh_token,\n })\n }\n } catch {\n // Unparseable or dead legacy session — discard; the user logs in again.\n } finally {\n localStorage.removeItem(key)\n }\n })()\n}\n\nexport function createSharedSupabaseClient<Db = any>(\n opts: SharedSupabaseOptions\n): SupabaseClient<Db> {\n const hostname = typeof location !== \"undefined\" ? location.hostname : \"\"\n const domain =\n opts.cookieDomain && domainApplies(hostname, opts.cookieDomain)\n ? opts.cookieDomain\n : undefined\n\n const client = createBrowserClient<Db>(opts.url, opts.anonKey, {\n // Each app keeps its own module-level singleton; per-call instances keep\n // tests deterministic.\n isSingleton: false,\n cookieOptions: {\n ...(domain ? { domain } : {}),\n path: \"/\",\n sameSite: \"lax\",\n secure: typeof location !== \"undefined\" && location.protocol === \"https:\",\n // Long-lived cookie; real session validity is governed by refresh-token\n // rotation, not cookie lifetime.\n maxAge: 60 * 60 * 24 * 365,\n },\n auth: {\n flowType: \"pkce\",\n detectSessionInUrl: true,\n // Bypass Navigator Lock API: prevents AbortError from\n // @supabase/auth-js/locks.ts during session synchronization; cross-tab\n // coordination is non-critical for these apps.\n lock: async <R>(\n _name: string,\n _acquireTimeout: number,\n fn: () => Promise<R>\n ): Promise<R> => fn(),\n },\n })\n\n const migration = migrateLegacySession(client as SupabaseClient<any>, opts.url)\n if (migration) {\n // Gate reads on the one-time migration so the first getSession() after the\n // storage switch can't race it — keeps call sites unchanged in the apps.\n const orig = client.auth.getSession.bind(client.auth)\n client.auth.getSession = async () => {\n await migration\n return orig()\n }\n }\n\n return client\n}\n"]}
@@ -0,0 +1,24 @@
1
+ import { SupabaseClient } from '@supabase/supabase-js';
2
+
3
+ /**
4
+ * Browser Supabase client with session storage in cookies instead of
5
+ * localStorage, so several apps on sibling subdomains (e.g. app/studio/voice
6
+ * on *.nodaro.ai) share one login: sign in on any of them, signed in on all;
7
+ * sign out anywhere, signed out everywhere (supabase-js signOut defaults to
8
+ * the global scope).
9
+ */
10
+ interface SharedSupabaseOptions {
11
+ /** Supabase project URL (https://<ref>.supabase.co). */
12
+ url: string;
13
+ anonKey: string;
14
+ /**
15
+ * Cookie Domain for cross-subdomain sharing (e.g. ".nodaro.ai"). Applied
16
+ * only when the page's hostname is that domain or a subdomain of it; on any
17
+ * other host (localhost, preview URLs) cookies stay host-only, which keeps
18
+ * local dev on per-origin sessions.
19
+ */
20
+ cookieDomain?: string;
21
+ }
22
+ declare function createSharedSupabaseClient<Db = any>(opts: SharedSupabaseOptions): SupabaseClient<Db>;
23
+
24
+ export { type SharedSupabaseOptions, createSharedSupabaseClient };
@@ -0,0 +1,24 @@
1
+ import { SupabaseClient } from '@supabase/supabase-js';
2
+
3
+ /**
4
+ * Browser Supabase client with session storage in cookies instead of
5
+ * localStorage, so several apps on sibling subdomains (e.g. app/studio/voice
6
+ * on *.nodaro.ai) share one login: sign in on any of them, signed in on all;
7
+ * sign out anywhere, signed out everywhere (supabase-js signOut defaults to
8
+ * the global scope).
9
+ */
10
+ interface SharedSupabaseOptions {
11
+ /** Supabase project URL (https://<ref>.supabase.co). */
12
+ url: string;
13
+ anonKey: string;
14
+ /**
15
+ * Cookie Domain for cross-subdomain sharing (e.g. ".nodaro.ai"). Applied
16
+ * only when the page's hostname is that domain or a subdomain of it; on any
17
+ * other host (localhost, preview URLs) cookies stay host-only, which keeps
18
+ * local dev on per-origin sessions.
19
+ */
20
+ cookieDomain?: string;
21
+ }
22
+ declare function createSharedSupabaseClient<Db = any>(opts: SharedSupabaseOptions): SupabaseClient<Db>;
23
+
24
+ export { type SharedSupabaseOptions, createSharedSupabaseClient };
@@ -0,0 +1,69 @@
1
+ import { createBrowserClient } from '@supabase/ssr';
2
+
3
+ // src/supabase-browser.ts
4
+ function legacyStorageKey(url) {
5
+ return `sb-${new URL(url).hostname.split(".")[0]}-auth-token`;
6
+ }
7
+ function domainApplies(hostname, cookieDomain) {
8
+ const bare = cookieDomain.replace(/^\./, "");
9
+ return hostname === bare || hostname.endsWith(`.${bare}`);
10
+ }
11
+ function migrateLegacySession(client, url) {
12
+ if (typeof localStorage === "undefined") return null;
13
+ const key = legacyStorageKey(url);
14
+ const raw = localStorage.getItem(key);
15
+ if (!raw) return null;
16
+ return (async () => {
17
+ try {
18
+ const parsed = JSON.parse(raw);
19
+ if (parsed.access_token && parsed.refresh_token) {
20
+ await client.auth.setSession({
21
+ access_token: parsed.access_token,
22
+ refresh_token: parsed.refresh_token
23
+ });
24
+ }
25
+ } catch {
26
+ } finally {
27
+ localStorage.removeItem(key);
28
+ }
29
+ })();
30
+ }
31
+ function createSharedSupabaseClient(opts) {
32
+ const hostname = typeof location !== "undefined" ? location.hostname : "";
33
+ const domain = opts.cookieDomain && domainApplies(hostname, opts.cookieDomain) ? opts.cookieDomain : void 0;
34
+ const client = createBrowserClient(opts.url, opts.anonKey, {
35
+ // Each app keeps its own module-level singleton; per-call instances keep
36
+ // tests deterministic.
37
+ isSingleton: false,
38
+ cookieOptions: {
39
+ ...domain ? { domain } : {},
40
+ path: "/",
41
+ sameSite: "lax",
42
+ secure: typeof location !== "undefined" && location.protocol === "https:",
43
+ // Long-lived cookie; real session validity is governed by refresh-token
44
+ // rotation, not cookie lifetime.
45
+ maxAge: 60 * 60 * 24 * 365
46
+ },
47
+ auth: {
48
+ flowType: "pkce",
49
+ detectSessionInUrl: true,
50
+ // Bypass Navigator Lock API: prevents AbortError from
51
+ // @supabase/auth-js/locks.ts during session synchronization; cross-tab
52
+ // coordination is non-critical for these apps.
53
+ lock: async (_name, _acquireTimeout, fn) => fn()
54
+ }
55
+ });
56
+ const migration = migrateLegacySession(client, opts.url);
57
+ if (migration) {
58
+ const orig = client.auth.getSession.bind(client.auth);
59
+ client.auth.getSession = async () => {
60
+ await migration;
61
+ return orig();
62
+ };
63
+ }
64
+ return client;
65
+ }
66
+
67
+ export { createSharedSupabaseClient };
68
+ //# sourceMappingURL=supabase-browser.js.map
69
+ //# sourceMappingURL=supabase-browser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/supabase-browser.ts"],"names":[],"mappings":"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","file":"supabase-browser.js","sourcesContent":["import { createBrowserClient } from \"@supabase/ssr\"\nimport type { SupabaseClient } from \"@supabase/supabase-js\"\n\n/**\n * Browser Supabase client with session storage in cookies instead of\n * localStorage, so several apps on sibling subdomains (e.g. app/studio/voice\n * on *.nodaro.ai) share one login: sign in on any of them, signed in on all;\n * sign out anywhere, signed out everywhere (supabase-js signOut defaults to\n * the global scope).\n */\nexport interface SharedSupabaseOptions {\n /** Supabase project URL (https://<ref>.supabase.co). */\n url: string\n anonKey: string\n /**\n * Cookie Domain for cross-subdomain sharing (e.g. \".nodaro.ai\"). Applied\n * only when the page's hostname is that domain or a subdomain of it; on any\n * other host (localhost, preview URLs) cookies stay host-only, which keeps\n * local dev on per-origin sessions.\n */\n cookieDomain?: string\n}\n\n/** supabase-js's default localStorage key: `sb-<project-ref>-auth-token`. */\nfunction legacyStorageKey(url: string): string {\n return `sb-${new URL(url).hostname.split(\".\")[0]}-auth-token`\n}\n\nfunction domainApplies(hostname: string, cookieDomain: string): boolean {\n const bare = cookieDomain.replace(/^\\./, \"\")\n return hostname === bare || hostname.endsWith(`.${bare}`)\n}\n\n/**\n * One-time adoption of a pre-cookie session this origin left in localStorage,\n * so already-signed-in users survive the storage switch. setSession persists\n * through the client's (cookie) storage; dead tokens reject and the user is\n * simply signed out. The legacy key is removed in every outcome.\n * Returns null when there is nothing to migrate.\n */\nfunction migrateLegacySession(\n client: SupabaseClient<any>,\n url: string\n): Promise<void> | null {\n if (typeof localStorage === \"undefined\") return null\n const key = legacyStorageKey(url)\n const raw = localStorage.getItem(key)\n if (!raw) return null\n return (async () => {\n try {\n const parsed = JSON.parse(raw) as {\n access_token?: string\n refresh_token?: string\n }\n if (parsed.access_token && parsed.refresh_token) {\n await client.auth.setSession({\n access_token: parsed.access_token,\n refresh_token: parsed.refresh_token,\n })\n }\n } catch {\n // Unparseable or dead legacy session — discard; the user logs in again.\n } finally {\n localStorage.removeItem(key)\n }\n })()\n}\n\nexport function createSharedSupabaseClient<Db = any>(\n opts: SharedSupabaseOptions\n): SupabaseClient<Db> {\n const hostname = typeof location !== \"undefined\" ? location.hostname : \"\"\n const domain =\n opts.cookieDomain && domainApplies(hostname, opts.cookieDomain)\n ? opts.cookieDomain\n : undefined\n\n const client = createBrowserClient<Db>(opts.url, opts.anonKey, {\n // Each app keeps its own module-level singleton; per-call instances keep\n // tests deterministic.\n isSingleton: false,\n cookieOptions: {\n ...(domain ? { domain } : {}),\n path: \"/\",\n sameSite: \"lax\",\n secure: typeof location !== \"undefined\" && location.protocol === \"https:\",\n // Long-lived cookie; real session validity is governed by refresh-token\n // rotation, not cookie lifetime.\n maxAge: 60 * 60 * 24 * 365,\n },\n auth: {\n flowType: \"pkce\",\n detectSessionInUrl: true,\n // Bypass Navigator Lock API: prevents AbortError from\n // @supabase/auth-js/locks.ts during session synchronization; cross-tab\n // coordination is non-critical for these apps.\n lock: async <R>(\n _name: string,\n _acquireTimeout: number,\n fn: () => Promise<R>\n ): Promise<R> => fn(),\n },\n })\n\n const migration = migrateLegacySession(client as SupabaseClient<any>, opts.url)\n if (migration) {\n // Gate reads on the one-time migration so the first getSession() after the\n // storage switch can't race it — keeps call sites unchanged in the apps.\n const orig = client.auth.getSession.bind(client.auth)\n client.auth.getSession = async () => {\n await migration\n return orig()\n }\n }\n\n return client\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nodaro/sdk",
3
- "version": "1.6.0",
3
+ "version": "1.7.0",
4
4
  "description": "Typed REST client for the Nodaro API — workflows, jobs, executions, apps, characters, and more.",
5
5
  "type": "module",
6
6
  "license": "Apache-2.0",
@@ -19,6 +19,11 @@
19
19
  "types": "./dist/index.d.ts",
20
20
  "import": "./dist/index.js",
21
21
  "require": "./dist/index.cjs"
22
+ },
23
+ "./supabase": {
24
+ "types": "./dist/supabase-browser.d.ts",
25
+ "import": "./dist/supabase-browser.js",
26
+ "require": "./dist/supabase-browser.cjs"
22
27
  }
23
28
  },
24
29
  "files": [
@@ -36,8 +41,20 @@
36
41
  "test:watch": "vitest"
37
42
  },
38
43
  "dependencies": {
39
- "@nodaro/shared": "^1.9.0",
40
- "@nodaro/prompts": "^1.0.1"
44
+ "@nodaro/shared": "^1.13.0",
45
+ "@nodaro/prompts": "^1.2.1"
46
+ },
47
+ "peerDependencies": {
48
+ "@supabase/ssr": "^0.12.3",
49
+ "@supabase/supabase-js": "^2.110.5"
50
+ },
51
+ "peerDependenciesMeta": {
52
+ "@supabase/ssr": {
53
+ "optional": true
54
+ },
55
+ "@supabase/supabase-js": {
56
+ "optional": true
57
+ }
41
58
  },
42
59
  "devDependencies": {
43
60
  "@vitest/coverage-v8": "^4.1.2",