{"_id":"@advenahq/supabase-js","_rev":"1-1db081222a921af03f92e088a81ce5e0","name":"@advenahq/supabase-js","dist-tags":{"latest":"4.11.3"},"versions":{"4.11.2":{"name":"@advenahq/supabase-js","version":"4.11.2","keywords":["supabase","supabase-js","postgres","cache","caching"],"author":{"name":"Advena"},"license":"GPL-3.0-or-later","_id":"@advenahq/supabase-js@4.11.2","maintainers":[{"name":"bradleyhodges","email":"bradley.hodges@outlook.com"}],"homepage":"https://github.com/AdvenaHQ/supabase-js","bugs":{"url":"https://github.com/AdvenaHQ/supabase-js/issues"},"dist":{"shasum":"d3bb6b5423f84ebda162d44c8ea16f9f51c290d8","tarball":"https://registry.npmjs.org/@advenahq/supabase-js/-/supabase-js-4.11.2.tgz","fileCount":84,"integrity":"sha512-+7B1d4cIFt573VxefCbd8vV1AN+zAjvE+QRUvR4H/3XLeg31DBp8Yxe62tONB5WokoFt0woFoxTRo6Cqy/IEvw==","signatures":[{"sig":"MEYCIQCnolICJJ8QQFWz8MAt4sGdq1JrFF+x1MA9QJQfEY+SWQIhAJ4LpBxwGZ4gktVmlEEa9yr9gPzhNL8OKmTiApKAHTGp","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":354258},"main":"dist/main/index.js","types":"./dist/main/index.d.ts","module":"dist/module/index.js","exports":{".":{"import":"./dist/module/server/index.js","require":"./dist/main/server/index.js"},"./types":{"import":"./dist/module/types.js","require":"./dist/main/types.js"},"./client":{"import":"./dist/module/browser/index.js","require":"./dist/main/browser/index.js"},"./browser":{"import":"./dist/module/browser/index.js","require":"./dist/main/browser/index.js"}},"gitHead":"03c2335ab93a6a9d089a5edb2a73cc9e13893d3d","private":false,"scripts":{"build":"node scripts/build.js","clean":"git clean -xdf .cache .turbo node_modules -f","format":"biome check . --write --skip-errors --config-path ../../","bump-deps":"npx npm-check-updates --deep -u && pnpm up --latest --recursive && pnpm run format","typecheck":"tsc --noEmit --emitDeclarationOnly false"},"_npmUser":{"name":"bradleyhodges","email":"bradley.hodges@outlook.com"},"repository":{"url":"git+https://github.com/AdvenaHQ/supabase-js.git#main","type":"git"},"_npmVersion":"10.9.2","description":"A robust, high-performance, type-safe wrapper for Supabase with caching, extensible configuration, and more.","directories":{},"_nodeVersion":"23.5.0","dependencies":{"zod":"^3.24.1","next":"^15.1.2","chalk":"4.1.2","dayjs":"^1.11.13","ts-md5":"^1.3.1","ioredis":"^5.4.2","server-only":"^0.0.1","@supabase/ssr":"^0.5.2","@upstash/redis":"^1.34.3","@supabase/supabase-js":"^2.47.12","@supabase/postgrest-js":"^1.17.10"},"_hasShrinkwrap":false,"devDependencies":{"ora":"^8.1.1","tslib":"^2.8.1","esbuild":"^0.24.2","ts-node":"^10.9.2","inquirer":"^12.3.0","typescript":"^5.7.2","@types/node":"^22.10.2"},"_npmOperationalInternal":{"tmp":"tmp/supabase-js_4.11.2_1736401210404_0.8479633336910593","host":"s3://npm-registry-packages-npm-production"}},"4.11.3":{"name":"@advenahq/supabase-js","description":"A robust, high-performance, type-safe wrapper for Supabase with caching, extensible configuration, and more.","keywords":["supabase","supabase-js","postgres","cache","caching"],"private":false,"types":"./dist/main/index.d.ts","version":"4.11.3","main":"dist/main/index.js","module":"dist/module/index.js","scripts":{"build":"node scripts/build.js","bump-deps":"npx npm-check-updates --deep -u && pnpm up --latest --recursive && pnpm run format","format":"biome check . --write --skip-errors --config-path ../../","clean":"git clean -xdf .cache .turbo node_modules -f","typecheck":"tsc --noEmit --emitDeclarationOnly false","pub":"npm publish --access public"},"exports":{".":{"import":"./dist/module/server/index.js","require":"./dist/main/server/index.js"},"./browser":{"import":"./dist/module/browser/index.js","require":"./dist/main/browser/index.js"},"./client":{"import":"./dist/module/browser/index.js","require":"./dist/main/browser/index.js"},"./types":{"import":"./dist/module/types.js","require":"./dist/main/types.js"}},"repository":{"type":"git","url":"git+https://github.com/AdvenaHQ/supabase-js.git#main"},"bugs":{"url":"https://github.com/AdvenaHQ/supabase-js/issues"},"homepage":"https://github.com/AdvenaHQ/supabase-js","license":"GPL-3.0-or-later","author":{"name":"Advena"},"devDependencies":{"@types/node":"^22.10.2","esbuild":"^0.24.2","inquirer":"^12.3.0","ora":"^8.1.1","ts-node":"^10.9.2","tslib":"^2.8.1","typescript":"^5.7.2"},"dependencies":{"@supabase/postgrest-js":"^1.17.10","@supabase/ssr":"^0.5.2","@supabase/supabase-js":"^2.47.12","@upstash/redis":"^1.34.3","chalk":"4.1.2","dayjs":"^1.11.13","ioredis":"^5.4.2","next":"^15.1.2","server-only":"^0.0.1","ts-md5":"^1.3.1","zod":"^3.24.1"},"_id":"@advenahq/supabase-js@4.11.3","gitHead":"03c2335ab93a6a9d089a5edb2a73cc9e13893d3d","_nodeVersion":"23.5.0","_npmVersion":"10.9.2","dist":{"integrity":"sha512-bM9Dv36eI7YxW38c2+fUuyeYnZj7coH36Dx4jiTOMeUpE2nToyty4bRDbabHVPWq6gBI0k1nl72FSs/tEXgvfQ==","shasum":"0feaa4bda8eacf47a719fb243a3406549917b952","tarball":"https://registry.npmjs.org/@advenahq/supabase-js/-/supabase-js-4.11.3.tgz","fileCount":84,"unpackedSize":354354,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDuC4LiwDQTm1qQZgpVHpaX9c79DDGh4IFCIzxyKrNlkwIgZ7H+XDIrv8nVOOYpyseNzMCWvnQ8+3L1pQMAoDgKKMQ="}]},"_npmUser":{"name":"bradleyhodges","email":"bradley.hodges@outlook.com"},"directories":{},"maintainers":[{"name":"bradleyhodges","email":"bradley.hodges@outlook.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/supabase-js_4.11.3_1736401294108_0.15805158121396068"},"_hasShrinkwrap":false}},"time":{"created":"2025-01-09T05:40:09.969Z","modified":"2025-01-09T05:41:34.504Z","4.11.2":"2025-01-09T05:40:10.621Z","4.11.3":"2025-01-09T05:41:34.295Z"},"bugs":{"url":"https://github.com/AdvenaHQ/supabase-js/issues"},"author":{"name":"Advena"},"license":"GPL-3.0-or-later","homepage":"https://github.com/AdvenaHQ/supabase-js","keywords":["supabase","supabase-js","postgres","cache","caching"],"repository":{"type":"git","url":"git+https://github.com/AdvenaHQ/supabase-js.git#main"},"description":"A robust, high-performance, type-safe wrapper for Supabase with caching, extensible configuration, and more.","maintainers":[{"name":"bradleyhodges","email":"bradley.hodges@outlook.com"}],"readme":"# ⚡ @advenahq/supabase-js [![npm](https://img.shields.io/npm/v/@advenahq/supabase-js)](https://www.npmjs.com/package/@advenahq/supabase-js)\r\n\r\nThis package provides a high-performance, type-safe, reusable wrapper for utilising the Supabase client in Next.js projects in both server and browser contexts (SSR/SSG and client). The package is designed to be secure, efficient, and easy to use, and provides a simple way to interact with the Supabase client in a Next.js project.\r\n\r\n## 👏 Features\r\n- **Type-Safe**: Written in TypeScript and provides custom, type-safe extended interfaces for working with the Supabase client safely.\r\n- **Server-side Cache Support**: The package supports a number of cache providers, including [supacache](https://github.com/AdvenaHQ/supacache), [Upstash Redis](https://upstash.com/docs/redis/sdks/ts/overview), and vanilla redis servers (via [ioredis](https://github.com/redis/ioredis)), to dramatically improve performance for expensive and common queries.\r\n- **Full Supabase Client Support**: Provides full support for the Supabase client, including all methods and properties, such as Realtime, REST API, Storage, Auth, etc.\r\n- **Row Level Security (RLS) Support**: Both native and custom Row Level Security (RLS) patterns are supported by allowing you to pass custom JWTs at initialisation for use in the Authorization header (or utilise in-built roles).\r\n- **Service Role Support**: Painlessly create Supabase clients with your service role for server-side operations that require elevated permissions.\r\n- **Security-First Design**: The package is designed with security in mind and provides a safe and secure way to interact with your Supabase project. It automatically identifies risky behaviour and accounts for it, and scrubs sensitive configurations from the browser client at initialisation.\r\n\r\n## 📦 Installation\r\nTo install the package, run the following command:\r\n```bash\r\npnpm add @advenahq/supabase-js\r\n```\r\n\r\n## ⚙️ Configuring the Package\r\nThe package can be initialised and configured either inline (on-the-fly) or using a **shared configuration file (recommended)**.\r\n\r\nFor ease of use, it is recommended to set the following environment variables in your project's root:\r\n\r\n```bash\r\n# Retrieve these settings from your Supabase project's settings page (https://supabase.com/dashboard/project/_vnwgrcyvvigzihuvcutp_/settings/api)\r\n\r\n# The URL of the Supabase API\r\nUPV_SECRETS_SUPABASE_URL=https://<your-supabase-url>.supabase.co\r\n\r\n# Your Supabase project's secret/service_role JWT (API key)\r\nUPV_SECRETS_SUPABASE_SERVICEROLE_KEY=<your-supabase-service-role-key>\r\n\r\n# Your Supabase project's publishable/anon JWT (API key)\r\nUPV_SECRETS_SUPABASE_ANON_KEY=<your-supabase-anon-key>\r\n\r\n# Your Supabase project's JWT secret (for signing JWTs)\r\nUPV_SECRETS_SUPABASE_JWT_SECRET=<your-supabase-jwt-secret>\r\n```\r\n\r\nYou can configure the package (and client) by passing configuration options to the `useSupabase` hook. The following configuration options are available:\r\n\r\n```typescript\r\n{\r\n    /**\r\n     * Configures the provider for caching responses from the Supabase API.\r\n     */\r\n    cache?: {\r\n        /**\r\n         * The provider to use for caching responses from the Supabase API.\r\n         * \r\n         * Possible values:\r\n         * - `\"supacache\"`: Use a Supacache middleware service for intermediary caching.\r\n         * - `\"upstash-redis\"`: Use Upstash Redis for intermediary caching.\r\n         * - `\"redis\"`: Use Node Redis for intermediary caching.\r\n         *\r\n         * @default undefined (no intermediary caching)\r\n         */\r\n        provider: \"supacache\" | \"redis\" | \"upstash-redis\" | undefined;\r\n\r\n        /**\r\n         * Configuration options for the Supacache (middleware) cache provider.\r\n         *\r\n         * @see https://github.com/AdvenaHQ/supacache\r\n         */\r\n        supacache?: {\r\n            /**\r\n             * The URL of the Supacache middleware service.\r\n             */\r\n            url: string;\r\n\r\n            /**\r\n             * The cache service (auth) key for the Supacache middleware service. This is the\r\n             * `SUPACACHE_SERVICE_KEY` secret configured on the worker.\r\n             *\r\n             * @see https://github.com/AdvenaHQ/supacache?tab=readme-ov-file#middleware-worker-setup\r\n             */\r\n            serviceKey?: string | undefined;\r\n        };\r\n\r\n        /**\r\n         * Configuration options for the Upstash Redis cache provider.\r\n         */\r\n        upstash?: {\r\n            /**\r\n             * The URL of the Upstash Redis instance.\r\n             */\r\n            url: RedisConfigNodejs[\"url\"];\r\n\r\n            /**\r\n             * The token for the Upstash Redis instance.\r\n             */\r\n            token: RedisConfigNodejs[\"token\"];\r\n\r\n            /**\r\n             * The configuration options for the Upstash Redis client.\r\n             */\r\n            config?: RedisConfigNodejs;\r\n\r\n            /**\r\n             * The behavior options for the Upstash Redis cache provider.\r\n             */\r\n            behaviour?: {\r\n                /**\r\n                 * The time, in seconds, after which cached responses should expire and be dropped from the cache.\r\n                 *\r\n                 * @default 3600 (1 hour)\r\n                 */\r\n                expireSetAfter?: number | undefined;\r\n            };\r\n        } & RedisConfigNodejs;\r\n\r\n        /**\r\n         * Configuration options for the redis (ioredis) cache provider.\r\n         */\r\n        ioredis?: {\r\n            /**\r\n             * The Connection URL of the Redis instance.\r\n             */\r\n            url: string;\r\n        };\r\n    };\r\n\r\n    /**\r\n     * Configuration options for the Supabase client, passed to the Supabase client constructor.\r\n     *\r\n     * @link https://supabase.com/docs/reference/javascript/initializing\r\n     *\r\n     * @default undefined (use the default options):\r\n     *  - `config.db.schema` = \"public\"\r\n     */\r\n    config?: SupabaseClientServerOptionsType | undefined;\r\n\r\n    /**\r\n     * The database role to use when interacting with the Supabase API. This option has no effect if `auth.useToken` is set (as the JWT supplied to useToken will contain a \"role\" key).\r\n     *\r\n     * This option is useful when you need to use a specific role for server-side operations. Using \"service_role\" will cause the client to use the service role key.\r\n     *\r\n     * Possible values:\r\n     * - `\"anon\"`: Use the anonymous role.\r\n     * - `\"service_role\"`: Use the service role.\r\n     *\r\n     * @default \"anon\" (anonymous role)\r\n     */\r\n    role?: \"anon\" | \"service_role\" | undefined; // \"authenticated\"\r\n\r\n    /**\r\n     * The URL of the Supabase API.\r\n     *\r\n     * @default process.env.UPV_SECRETS_SUPABASE_URL\r\n     */\r\n    supabaseUrl: string;\r\n\r\n    /**\r\n     * Configures the authentication options for the Supabase client.\r\n     */\r\n    auth?: {\r\n        /**\r\n         * The JSON Web Token (JWT) to use for Row Level Security, used to construct the Authorization header. If configured, this option will override `role`, `keys.secret`, and `keys.publishable`.\r\n         *\r\n         * @remarks This is useful when you're using Supabase Auth and need custom claims for Row Level Security.\r\n         */\r\n        useToken?: string | undefined;\r\n\r\n        /**\r\n         * The secret key to use for signing JWTs.\r\n         *\r\n         * @remarks This is used for signing JWTs for use with Supabase Auth.\r\n         * @link https://supabase.com/dashboard/project/_/settings/api\r\n         */\r\n        jwtSecret?: string | undefined;\r\n\r\n        /**\r\n         * Configures the keys to use for authenticating requests to the Supabase API. This option has no effect if `useToken` is set.\r\n         */\r\n        keys?: {\r\n            /**\r\n             * Your Supabase installation's secret/service_role JWT (API key). This option has no effect if `auth.useToken` is set.\r\n             *\r\n             * @remarks This is used for server-side operations that require elevated permissions.\r\n             * @link https://supabase.com/dashboard/project/_/settings/api\r\n             *\r\n             * @default process.env.UPV_SECRETS_SUPABASE_SERVICEROLE_KEY\r\n             */\r\n            secret?: string | undefined;\r\n\r\n            /**\r\n             * Your Supabase installation's publishable/anon JWT (API key).\r\n             *\r\n             * @link https://supabase.com/dashboard/project/_/settings/api\r\n             *\r\n             * @default process.env.UPV_SECRETS_SUPABASE_ANON_KEY\r\n             */\r\n            publishable?: string | undefined;\r\n        };\r\n    };\r\n}\r\n```\r\n\r\n## Configuring the client\r\n\r\n### Shared Configuration\r\n\r\nA shared configuration file might look like this:\r\n\r\n```typescript\r\n// lib/supabase.ts\r\n\r\nimport { useSupabase as _useSupabase } from \"@advenahq/supabase-js\";\r\nimport type { UseSupabaseOptions } from \"@advenahq/supabase-js/types\";\r\n\r\nimport type { Database } from \"../path/to/database.types\"; // https://supabase.com/docs/reference/javascript/typescript-support\r\n\r\n/**\r\n * Asynchronously initializes and returns a Supabase client with the specified role and configuration.\r\n *\r\n * @param role - The role to use for the Supabase client, either \"service_role\" or \"anon\". Defaults to \"service_role\".\r\n * @param extendConfig - Optional configuration to extend the default Supabase options.\r\n * \r\n * @returns A promise that resolves to the initialized Supabase client.\r\n */\r\nexport const useSupabase = async (\r\n    role: \"service_role\" | \"anon\" = \"service_role\",\r\n    extendConfig?: Partial<UseSupabaseOptions> | undefined,\r\n) =>\r\n    await _useSupabase<Database>({\r\n        cache: {\r\n            provider: \"supacache\",\r\n            supacache: {\r\n                url: \"https://supacache.mycloudflareworker.workers.dev\",\r\n                serviceKey:\r\n                    \"your-service-key\",\r\n            },\r\n        },\r\n        role: \"anon\",\r\n        supabaseUrl: process.env.UPV_SECRETS_SUPABASE_URL as string, // Your project's Supabase URL\r\n        auth: {\r\n            keys: {\r\n                secret: process.env.UPV_SECRETS_SUPABASE_SERVICEROLE_KEY, // Your project's service_role (secret) key\r\n                publishable: process.env.UPV_SECRETS_SUPABASE_ANON_KEY, // Your project's anon (publishable) key\r\n            },\r\n        },\r\n    });\r\n```\r\n\r\nyou would then use the client as you normally would in your application:\r\n\r\n```tsx\r\n// app/page.ts\r\n\r\nimport { useSupabase } from \"@/lib/useSupabase\";\r\n\r\nexport default async function Page() {\r\n    // Use the Supabase client exported by the shared configuration\r\n    const supabase = await useSupabase();\r\n\r\n    // Fetch data from the users table\r\n    const { data, error } = await supabase\r\n        .from(\"users\")\r\n        .select(\"*\")\r\n        .eq(\"id\", 1)\r\n        .limit(1)\r\n        .single();\r\n\r\n    const { data, error } = await supabase\r\n        .from<Database.User>(\"users\")\r\n        .select(\"*\")\r\n        .eq(\"id\", 1)\r\n        .limit(1)\r\n        .single({ cacheTTL: 60 * 60 * 24 }); // Cache the response for 24 hours\r\n\r\n    ...\r\n}\r\n```\r\n\r\nor, even better, using the database types and custom cache ttl:\r\n\r\n```tsx\r\n// app/page.ts\r\n\r\nimport { useSupabase } from \"@/lib/useSupabase\";\r\n\r\nimport type { Tables } from \"../path/to/database.types\"; // https://supabase.com/docs/reference/javascript/typescript-support\r\n\r\nexport default async function Page() {\r\n    // Use the Supabase client exported by the shared configuration\r\n    const supabase = await useSupabase();\r\n\r\n    // Fetch data from the users table\r\n    const { data, error } = await supabase\r\n        .from(\"users\")\r\n        .cache(86400) // Cache the response for 24 hours (86400 seconds = 24 hours)\r\n        .select(\"*\")\r\n        .eq(\"id\", 1)\r\n        .limit(1)\r\n        .single<Tables<\"users\">>();\r\n\r\n    ...\r\n}\r\n```\r\n\r\n---\r\n\r\n### Inline configuration \r\nAlternatively, as mentioned, you can initialise and configure the package inline:\r\n\r\n```tsx\r\nimport { useSupabase } from \"@advenahq/supabase-js\";\r\n\r\nexport default async function Page() {\r\n    // Create a new Supabase client, configuring it inline\r\n    const supabase = await useSupabase({\r\n        role: \"anon\",\r\n        supabaseUrl: process.env.UPV_SECRETS_SUPABASE_URL as string,\r\n        auth: {\r\n            keys: {\r\n                secret: process.env.UPV_SECRETS_SUPABASE_SERVICEROLE_KEY,\r\n                publishable: process.env.UPV_SECRETS_SUPABASE_ANON_KEY,\r\n            },\r\n        },\r\n    });\r\n\r\n    ...\r\n}\r\n```\r\n\r\nIf environment variables are set, the package will automatically use them to configure the client. If not, you can pass the configuration options directly to the `useSupabase` hook. This means that you can simply:\r\n\r\n```tsx\r\nimport { useSupabase } from \"@advenahq/supabase-js\";\r\n\r\nexport default async function Page() {\r\n    // Create a new Supabase client, relying on environment variables for configuration\r\n    const supabase = await useSupabase();\r\n\r\n    ...\r\n}\r\n```\r\n\r\n## 🚗 Basic Usage\r\nUse the `useSupabase` hook to create a new Supabase client. The client can be used to interact with the Supabase API, including querying the database, using Realtime, and interacting with the Storage and Auth services.\r\n\r\nYou then use the created client as you would the standard Supabase client from the `@supabase/supabase-js` package. Comprehensive documentation is available on the [Supabase website](https://supabase.com/docs/reference/javascript/select).\r\n\r\n## 💼 Using Roles\r\nYou can optionally create a Supabase client with the Supabase service role. This is useful for server-side operations that require elevated permissions but should be done so with great caution as **the service role has full access to your database and bypasses all Row Level Security (RLS) policies**. By default, the client is created with the anonymous (anon) role.\r\n\r\n```tsx\r\n// lib/supabase.ts\r\n\r\nimport { useSupabase as _useSupabase } from \"@advenahq/supabase-js\";\r\n\r\nexport const useSupabase = async () =>\r\n    await _useSupabase({\r\n        role: \"service_role\", // Use the service role\r\n        ...\r\n    });\r\n```\r\n\r\n## 👋 Client (Browser) Usage\r\nThe client can also be used in the browser. This is useful for client-side operations that require authentication.\r\n```tsx\r\n// components/MyComponent.tsx\r\n\"use client\";\r\n\r\nimport { useSupabase } from '@advenahq/supabase-js/browser';\r\n\r\nfunction MyComponent() {\r\n    // Create a new Supabase browser client\r\n    const supabase = useSupabase();\r\n\r\n    // Use the client in the browser as you normally would\r\n    supabase\r\n        .channel('room1')\r\n        .on('postgres_changes', { event: '*', schema: 'public', table: 'countries' }, payload => {\r\n            console.log('Change received!', payload)\r\n        })\r\n        .subscribe();\r\n\r\n    ...\r\n}\r\n```\r\n\r\n## 🧸 Contributing\r\nContributions are welcome! Please open an issue or submit a pull request for any improvements or bug fixes.\r\n\r\n## ⚖️ License\r\nThis project is licensed under the GNU GPLv3 License. See the LICENSE file for details.\r\n\r\n![License Summary](license_summary.png)","readmeFilename":"README.md"}