diff --git a/.gitattributes b/.gitattributes
index a9a88850fc9dcd51bad9b12db4de48141aa19783..20164a4feccdcc0ae640ac782fa3ef464e342fe6 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -36,3 +36,4 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
node_modules/@esbuild/win32-x64/esbuild.exe filter=lfs diff=lfs merge=lfs -text
node_modules/@rollup/rollup-win32-x64-gnu/rollup.win32-x64-gnu.node filter=lfs diff=lfs merge=lfs -text
node_modules/@rollup/rollup-win32-x64-msvc/rollup.win32-x64-msvc.node filter=lfs diff=lfs merge=lfs -text
+node_modules/@tailwindcss/oxide-win32-x64-msvc/tailwindcss-oxide.win32-x64-msvc.node filter=lfs diff=lfs merge=lfs -text
diff --git a/node_modules/@supabase/realtime-js/LICENSE b/node_modules/@supabase/realtime-js/LICENSE
new file mode 100644
index 0000000000000000000000000000000000000000..ddeba6a00ae5ec536d5429e040bc73ef2c6a07d6
--- /dev/null
+++ b/node_modules/@supabase/realtime-js/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2020 Supabase
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/node_modules/@supabase/realtime-js/README.md b/node_modules/@supabase/realtime-js/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..f2e3d9835c8d140f0d93b1d586abe6272bd1d774
--- /dev/null
+++ b/node_modules/@supabase/realtime-js/README.md
@@ -0,0 +1,447 @@
+
+
+
+
+
+
+
+
+
+
+
Supabase Realtime JS SDK
+
+ Send ephemeral messages with Broadcast , track and synchronize state with Presence , and listen to database changes with Postgres Change Data Capture (CDC) .
+
+
+ Guides
+ ·
+ Reference Docs
+ ·
+ Multiplayer Demo
+
+
+
+
+
+[](https://github.com/supabase/supabase-js/actions?query=branch%3Amaster)
+[](https://www.npmjs.com/package/@supabase/realtime-js)
+[](#license)
+[](https://pkg.pr.new/~/supabase/realtime-js)
+
+
+
+# Overview
+
+This SDK enables you to use the following Supabase Realtime's features:
+
+- **Broadcast**: send ephemeral messages from client to clients with minimal latency. Use cases include sharing cursor positions between users.
+- **Presence**: track and synchronize shared state across clients with the help of CRDTs. Use cases include tracking which users are currently viewing a specific webpage.
+- **Postgres Change Data Capture (CDC)**: listen for changes in your PostgreSQL database and send them to clients.
+
+# Usage
+
+## Installing the Package
+
+```bash
+npm install @supabase/realtime-js
+```
+
+## Creating a Channel
+
+```js
+import { RealtimeClient } from '@supabase/realtime-js'
+
+const client = new RealtimeClient(REALTIME_URL, {
+ params: {
+ apikey: API_KEY,
+ },
+})
+
+const channel = client.channel('test-channel', {})
+
+channel.subscribe((status, err) => {
+ if (status === 'SUBSCRIBED') {
+ console.log('Connected!')
+ }
+
+ if (status === 'CHANNEL_ERROR') {
+ console.log(`There was an error subscribing to channel: ${err.message}`)
+ }
+
+ if (status === 'TIMED_OUT') {
+ console.log('Realtime server did not respond in time.')
+ }
+
+ if (status === 'CLOSED') {
+ console.log('Realtime channel was unexpectedly closed.')
+ }
+})
+```
+
+### Notes:
+
+- `REALTIME_URL` is `'ws://localhost:4000/socket'` when developing locally and `'wss://.supabase.co/realtime/v1'` when connecting to your Supabase project.
+- `API_KEY` is a JWT whose claims must contain `exp` and `role` (existing database role).
+- Channel name can be any `string`.
+- Setting `private` to `true` means that the client will use RLS to determine if the user can connect or not to a given channel.
+
+## Broadcast
+
+Your client can send and receive messages based on the `event`.
+
+```js
+// Setup...
+
+const channel = client.channel('broadcast-test', { broadcast: { ack: false, self: false } })
+
+channel.on('broadcast', { event: 'some-event' }, (payload) => console.log(payload))
+
+channel.subscribe(async (status) => {
+ if (status === 'SUBSCRIBED') {
+ // Send message to other clients listening to 'broadcast-test' channel
+ await channel.send({
+ type: 'broadcast',
+ event: 'some-event',
+ payload: { hello: 'world' },
+ })
+ }
+})
+```
+
+### Notes:
+
+- Setting `ack` to `true` means that the `channel.send` promise will resolve once server replies with acknowledgment that it received the broadcast message request.
+- Setting `self` to `true` means that the client will receive the broadcast message it sent out.
+
+### Broadcast Replay
+
+Broadcast Replay enables **private** channels to access messages that were sent earlier. Only messages published via [Broadcast From the Database](https://supabase.com/docs/guides/realtime/broadcast#trigger-broadcast-messages-from-your-database) are available for replay.
+
+You can configure replay with the following options:
+
+- **`since`** (Required): The epoch timestamp in milliseconds, specifying the earliest point from which messages should be retrieved.
+- **`limit`** (Optional): The number of messages to return. This must be a positive integer, with a maximum value of 25.
+
+Example:
+
+```typescript
+const twelveHours = 12 * 60 * 60 * 1000
+const twelveHoursAgo = Date.now() - twelveHours
+
+const config = { private: true, broadcast: { replay: { since: twelveHoursAgo, limit: 10 } } }
+
+supabase
+ .channel('main:room', { config })
+ .on('broadcast', { event: 'my_event' }, (payload) => {
+ if (payload?.meta?.replayed) {
+ console.log('This message was sent earlier:', payload)
+ } else {
+ console.log('This is a new message', payload)
+ }
+ // ...
+ })
+ .subscribe()
+```
+
+## Presence
+
+Your client can track and sync state that's stored in the channel.
+
+```js
+// Setup...
+
+const channel = client.channel('presence-test', {
+ config: {
+ presence: {
+ key: '',
+ },
+ },
+})
+
+channel.on('presence', { event: 'sync' }, () => {
+ console.log('Online users: ', channel.presenceState())
+})
+
+channel.on('presence', { event: 'join' }, ({ newPresences }) => {
+ console.log('New users have joined: ', newPresences)
+})
+
+channel.on('presence', { event: 'leave' }, ({ leftPresences }) => {
+ console.log('Users have left: ', leftPresences)
+})
+
+channel.subscribe(async (status) => {
+ if (status === 'SUBSCRIBED') {
+ const status = await channel.track({ user_id: 1 })
+ console.log(status)
+ }
+})
+```
+
+> `config.presence.enabled` (set automatically if you add an `.on('presence', ...)` listener)
+> controls whether _this_ client receives presence state and updates from other clients —
+> without it, `presenceState()` stays empty for you. It does not affect whether other clients
+> see you: calling `track()` always makes you visible to subscribers that do have presence
+> enabled. On RLS-protected channels, receiving presence updates additionally requires the
+> `presence.read` policy to authorize this client.
+
+## Postgres CDC
+
+Receive database changes on the client.
+
+```js
+// Setup...
+
+const channel = client.channel('db-changes')
+
+channel.on('postgres_changes', { event: '*', schema: 'public' }, (payload) => {
+ console.log('All changes in public schema: ', payload)
+})
+
+channel.on(
+ 'postgres_changes',
+ { event: 'INSERT', schema: 'public', table: 'messages' },
+ (payload) => {
+ console.log('All inserts in messages table: ', payload)
+ }
+)
+
+channel.on(
+ 'postgres_changes',
+ { event: 'UPDATE', schema: 'public', table: 'users', filter: 'username=eq.Realtime' },
+ (payload) => {
+ console.log('All updates on users table when username is Realtime: ', payload)
+ }
+)
+
+channel.subscribe(async (status) => {
+ if (status === 'SUBSCRIBED') {
+ console.log('Ready to receive database changes!')
+ }
+})
+```
+
+### Filters
+
+The `filter` option accepts **either** a raw string **or** a
+`postgresChangesFilter()` builder — both produce the exact same wire format, so
+you can mix and match and existing string filters keep working unchanged:
+
+```js
+// Raw string — always supported, fully backward compatible
+{ event: 'UPDATE', schema: 'public', table: 'users', filter: 'id=eq.1' }
+
+// Builder — type-checked, ergonomic; the SDK serializes it for you
+{ event: 'UPDATE', schema: 'public', table: 'users', filter: postgresChangesFilter().eq('id', 1) }
+```
+
+A filter is a `column=operator.value` expression evaluated server-side. The
+following operators are supported:
+
+| Operator | String form | Builder | Meaning |
+| --------------------- | ---------------------------- | -------------------------------------- | --------------------------------- |
+| `eq` | `id=eq.1` | `.eq('id', 1)` | equal |
+| `neq` | `id=neq.1` | `.neq('id', 1)` | not equal |
+| `lt` `lte` `gt` `gte` | `age=gte.18` | `.gte('age', 18)` | comparison |
+| `in` | `status=in.(active,pending)` | `.in('status', ['active', 'pending'])` | in list |
+| `like` `ilike` | `title=like.%foo%` | `.like('title', '%foo%')` | pattern match (case in/sensitive) |
+| `is` | `deleted_at=is.null` | `.is('deleted_at', null)` | `IS null/true/false/unknown` |
+| `match` `imatch` | `title=match.^foo` | `.match('title', '^foo')` | POSIX regex match (`~` / `~*`) |
+| `isdistinct` | `value=isdistinct.1` | `.isDistinct('value', 1)` | NULL-safe inequality |
+
+**Negation** — prefix any operator with `not.` (string) or use
+`.not(column, operator, value)` (builder):
+
+```js
+// String
+{ event: '*', schema: 'public', table: 'posts', filter: 'status=not.in.(draft,archived)' }
+
+// Builder
+{
+ event: '*',
+ schema: 'public',
+ table: 'posts',
+ filter: postgresChangesFilter().not('status', 'in', ['draft', 'archived']),
+}
+```
+
+**AND composition** — multiple conditions are combined with commas and applied
+as an `AND`. With the builder you just chain calls:
+
+```js
+// String
+{ event: 'UPDATE', schema: 'public', table: 'orders', filter: 'amount=gt.100,status=in.(open,pending)' }
+
+// Builder — equivalent, chained
+{
+ event: 'UPDATE',
+ schema: 'public',
+ table: 'orders',
+ filter: postgresChangesFilter().gt('amount', 100).in('status', ['open', 'pending']),
+}
+```
+
+#### Building filters with `postgresChangesFilter()`
+
+The builder (modeled on the `postgrest-js` filter methods) is the recommended,
+type-checked way to compose filters — but it is entirely optional; raw strings
+remain fully supported.
+
+```js
+import { postgresChangesFilter } from '@supabase/realtime-js'
+
+channel.on(
+ 'postgres_changes',
+ {
+ event: 'UPDATE',
+ schema: 'public',
+ table: 'orders',
+ // → 'amount=gt.100,status=not.in.(draft,archived)'
+ filter: postgresChangesFilter().gt('amount', 100).not('status', 'in', ['draft', 'archived']),
+ },
+ (payload) => console.log(payload)
+)
+```
+
+The builder exposes `eq`, `neq`, `gt`, `gte`, `lt`, `lte`, `in`, `like`,
+`ilike`, `match`, `imatch`, `is`, `isDistinct` and `not`. Call `.build()` if you
+need the raw string yourself (e.g. to log it or store it).
+
+**Values are sent verbatim** — the server has no quoting/escaping, so spaces and
+quotes are preserved as-is. The server separates conditions by commas outside
+parentheses, so a literal comma in a scalar value can't be expressed (commas
+inside `in.(…)` are fine); the builder throws on such values rather than
+silently producing a broken filter.
+
+> **Note for PostgREST users:** Realtime evaluates filters server-side over a
+> single table's WAL — there is no resource embedding (`!inner`, embedded
+> filters) and no `or()` grouping. Use `%` (not `*`) for `like`/`ilike`
+> wildcards, since filters travel in the WebSocket payload rather than a URL.
+
+### Selecting columns
+
+Use `select` to receive only a subset of columns instead of the full row. This
+reduces payload size (helpful for large `bytea`/`jsonb` columns). The selected
+columns must be selectable by the subscribing role:
+
+```js
+channel.on(
+ 'postgres_changes',
+ { event: '*', schema: 'public', table: 'users', select: ['id', 'first_name'] },
+ (payload) => {
+ // payload.new only contains { id, first_name }
+ console.log(payload)
+ }
+)
+```
+
+## Get All Channels
+
+You can see all the channels that your client has instantiatied.
+
+```js
+// Setup...
+
+client.getChannels()
+```
+
+## Cleanup
+
+It is highly recommended that you clean up your channels after you're done with them.
+
+- Remove a single channel
+
+```js
+// Setup...
+
+const channel = client.channel('some-channel-to-remove')
+
+channel.unsubscribe()
+client.removeChannel(channel)
+```
+
+- Remove all channels and close the connection
+
+```js
+// Setup...
+
+client.removeAllChannels()
+client.disconnect()
+```
+
+## Development
+
+This package is part of the [Supabase JavaScript monorepo](https://github.com/supabase/supabase-js). To work on this package:
+
+### Building
+
+```bash
+# Complete build (from monorepo root)
+pnpm nx build realtime-js
+
+# Build with watch mode for development
+pnpm nx build realtime-js --watch
+
+# Individual build targets
+pnpm nx build:main realtime-js # CommonJS build (dist/main/)
+pnpm nx build:module realtime-js # ES Modules build (dist/module/)
+
+# Other useful commands
+pnpm nx clean realtime-js # Clean build artifacts
+pnpm nx lint realtime-js # Run ESLint
+pnpm nx typecheck realtime-js # TypeScript type checking
+```
+
+#### Build Outputs
+
+- **CommonJS (`dist/main/`)** - For Node.js environments
+- **ES Modules (`dist/module/`)** - For modern bundlers (Webpack, Vite, Rollup)
+- **TypeScript definitions (`dist/module/index.d.ts`)** - Type definitions for TypeScript projects
+
+Note: Unlike some other packages, realtime-js doesn't include a UMD build since it's primarily used in Node.js or bundled applications.
+
+#### Validating Package Exports
+
+```bash
+# Check if package exports are correctly configured
+pnpm nx check-exports realtime-js
+```
+
+This command uses ["Are the types wrong?"](https://github.com/arethetypeswrong/arethetypeswrong.github.io) to verify that the package exports work correctly in different environments. Run this before publishing to ensure your package can be imported correctly by all consumers.
+
+### Testing
+
+**No Docker or Supabase instance required!** The realtime-js tests use mocked WebSocket connections, so they're completely self-contained.
+
+```bash
+# Run unit tests (from monorepo root)
+pnpm nx test realtime-js
+
+# Run tests with coverage report
+pnpm nx test:coverage realtime-js
+
+# Run tests in watch mode during development
+pnpm nx test:watch realtime-js
+```
+
+#### Test Scripts Explained
+
+- **test** - Runs all unit tests once using Vitest
+- **test:coverage** - Runs tests and generates coverage report with terminal output
+- **test:watch** - Runs tests in interactive watch mode for development
+
+The tests mock WebSocket connections using `mock-socket`, so you can run them anytime without any external dependencies.
+
+### Contributing
+
+We welcome contributions! Please see our [Contributing Guide](../../../CONTRIBUTING.md) for details on how to get started.
+
+For major changes or if you're unsure about something, please open an issue first to discuss your proposed changes.
+
+## Credits
+
+This repo draws heavily from [phoenix-js](https://github.com/phoenixframework/phoenix/tree/master/assets/js/phoenix).
+
+## License
+
+MIT.
diff --git a/node_modules/@supabase/realtime-js/dist/module/RealtimePresence.d.ts b/node_modules/@supabase/realtime-js/dist/module/RealtimePresence.d.ts
new file mode 100644
index 0000000000000000000000000000000000000000..1e1121cd15183ae324d1a5480483c5d364620a66
--- /dev/null
+++ b/node_modules/@supabase/realtime-js/dist/module/RealtimePresence.d.ts
@@ -0,0 +1,62 @@
+import type RealtimeChannel from './RealtimeChannel';
+export type Presence = {
+ presence_ref: string;
+} & T;
+export type RealtimePresenceState = {
+ [key: string]: Presence[];
+};
+export type RealtimePresenceJoinPayload = {
+ event: `${REALTIME_PRESENCE_LISTEN_EVENTS.JOIN}`;
+ key: string;
+ currentPresences: Presence[];
+ newPresences: Presence[];
+};
+export type RealtimePresenceLeavePayload = {
+ event: `${REALTIME_PRESENCE_LISTEN_EVENTS.LEAVE}`;
+ key: string;
+ currentPresences: Presence[];
+ leftPresences: Presence[];
+};
+export declare enum REALTIME_PRESENCE_LISTEN_EVENTS {
+ SYNC = "sync",
+ JOIN = "join",
+ LEAVE = "leave"
+}
+export type RealtimePresenceOptions = {
+ events?: {
+ state: string;
+ diff: string;
+ };
+};
+export default class RealtimePresence {
+ channel: RealtimeChannel;
+ get state(): RealtimePresenceState;
+ private presenceAdapter;
+ /**
+ * Creates a Presence helper that keeps the local presence state in sync with the server.
+ *
+ * @param channel - The realtime channel to bind to.
+ * @param opts - Optional custom event names, e.g. `{ events: { state: 'state', diff: 'diff' } }`.
+ *
+ * @category Realtime
+ *
+ * @example Example for a presence channel
+ * ```ts
+ * const presence = new RealtimePresence(channel)
+ *
+ * channel.on('presence', ({ event, key }) => {
+ * console.log(`Presence ${event} on ${key}`)
+ * })
+ * ```
+ */
+ constructor(channel: RealtimeChannel, opts?: RealtimePresenceOptions);
+}
+//# sourceMappingURL=RealtimePresence.d.ts.map
\ No newline at end of file
diff --git a/node_modules/@supabase/realtime-js/dist/module/RealtimePresence.d.ts.map b/node_modules/@supabase/realtime-js/dist/module/RealtimePresence.d.ts.map
new file mode 100644
index 0000000000000000000000000000000000000000..166fa89a293032036e67d6abda873478a1dead3d
--- /dev/null
+++ b/node_modules/@supabase/realtime-js/dist/module/RealtimePresence.d.ts.map
@@ -0,0 +1 @@
+{"version":3,"file":"RealtimePresence.d.ts","sourceRoot":"","sources":["../../src/RealtimePresence.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,eAAe,MAAM,mBAAmB,CAAA;AAGpD,MAAM,MAAM,QAAQ,CAAC,CAAC,SAAS;IAAE,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAA;CAAE,GAAG,EAAE,IAAI;IAC5D,YAAY,EAAE,MAAM,CAAA;CACrB,GAAG,CAAC,CAAA;AAEL,MAAM,MAAM,qBAAqB,CAAC,CAAC,SAAS;IAAE,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAA;CAAE,GAAG,EAAE,IAAI;IACzE,CAAC,GAAG,EAAE,MAAM,GAAG,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAA;CAC7B,CAAA;AAED,MAAM,MAAM,2BAA2B,CAAC,CAAC,SAAS;IAAE,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAA;CAAE,IAAI;IAC1E,KAAK,EAAE,GAAG,+BAA+B,CAAC,IAAI,EAAE,CAAA;IAChD,GAAG,EAAE,MAAM,CAAA;IACX,gBAAgB,EAAE,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAA;IAC/B,YAAY,EAAE,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAA;CAC5B,CAAA;AAED,MAAM,MAAM,4BAA4B,CAAC,CAAC,SAAS;IAAE,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAA;CAAE,IAAI;IAC3E,KAAK,EAAE,GAAG,+BAA+B,CAAC,KAAK,EAAE,CAAA;IACjD,GAAG,EAAE,MAAM,CAAA;IACX,gBAAgB,EAAE,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAA;IAC/B,aAAa,EAAE,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAA;CAC7B,CAAA;AAED,oBAAY,+BAA+B;IACzC,IAAI,SAAS;IACb,IAAI,SAAS;IACb,KAAK,UAAU;CAChB;AAED,MAAM,MAAM,uBAAuB,GAAG;IACpC,MAAM,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAA;CACzC,CAAA;AAED,MAAM,CAAC,OAAO,OAAO,gBAAgB;IAyB1B,OAAO,EAAE,eAAe;IAxBjC,IAAI,KAAK,0BAER;IAED,OAAO,CAAC,eAAe,CAAiB;IAExC;;;;;;;;;;;;;;;;OAgBG;gBAEM,OAAO,EAAE,eAAe,EAC/B,IAAI,CAAC,EAAE,uBAAuB;CAIjC"}
\ No newline at end of file
diff --git a/node_modules/@supabase/realtime-js/dist/module/RealtimePresence.js b/node_modules/@supabase/realtime-js/dist/module/RealtimePresence.js
new file mode 100644
index 0000000000000000000000000000000000000000..7ce1f5e80cab55aa392b2ac8383878b1785b1950
--- /dev/null
+++ b/node_modules/@supabase/realtime-js/dist/module/RealtimePresence.js
@@ -0,0 +1,38 @@
+/*
+ This file draws heavily from https://github.com/phoenixframework/phoenix/blob/d344ec0a732ab4ee204215b31de69cf4be72e3bf/assets/js/phoenix/presence.js
+ License: https://github.com/phoenixframework/phoenix/blob/d344ec0a732ab4ee204215b31de69cf4be72e3bf/LICENSE.md
+*/
+import PresenceAdapter from './phoenix/presenceAdapter';
+export var REALTIME_PRESENCE_LISTEN_EVENTS;
+(function (REALTIME_PRESENCE_LISTEN_EVENTS) {
+ REALTIME_PRESENCE_LISTEN_EVENTS["SYNC"] = "sync";
+ REALTIME_PRESENCE_LISTEN_EVENTS["JOIN"] = "join";
+ REALTIME_PRESENCE_LISTEN_EVENTS["LEAVE"] = "leave";
+})(REALTIME_PRESENCE_LISTEN_EVENTS || (REALTIME_PRESENCE_LISTEN_EVENTS = {}));
+export default class RealtimePresence {
+ get state() {
+ return this.presenceAdapter.state;
+ }
+ /**
+ * Creates a Presence helper that keeps the local presence state in sync with the server.
+ *
+ * @param channel - The realtime channel to bind to.
+ * @param opts - Optional custom event names, e.g. `{ events: { state: 'state', diff: 'diff' } }`.
+ *
+ * @category Realtime
+ *
+ * @example Example for a presence channel
+ * ```ts
+ * const presence = new RealtimePresence(channel)
+ *
+ * channel.on('presence', ({ event, key }) => {
+ * console.log(`Presence ${event} on ${key}`)
+ * })
+ * ```
+ */
+ constructor(channel, opts) {
+ this.channel = channel;
+ this.presenceAdapter = new PresenceAdapter(this.channel.channelAdapter, opts);
+ }
+}
+//# sourceMappingURL=RealtimePresence.js.map
\ No newline at end of file
diff --git a/node_modules/@supabase/realtime-js/dist/module/RealtimePresence.js.map b/node_modules/@supabase/realtime-js/dist/module/RealtimePresence.js.map
new file mode 100644
index 0000000000000000000000000000000000000000..3aa22598d8af07c6bc724083408372d580ca266f
--- /dev/null
+++ b/node_modules/@supabase/realtime-js/dist/module/RealtimePresence.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"RealtimePresence.js","sourceRoot":"","sources":["../../src/RealtimePresence.ts"],"names":[],"mappings":"AAAA;;;EAGE;AAGF,OAAO,eAAe,MAAM,2BAA2B,CAAA;AAwBvD,MAAM,CAAN,IAAY,+BAIX;AAJD,WAAY,+BAA+B;IACzC,gDAAa,CAAA;IACb,gDAAa,CAAA;IACb,kDAAe,CAAA;AACjB,CAAC,EAJW,+BAA+B,KAA/B,+BAA+B,QAI1C;AAMD,MAAM,CAAC,OAAO,OAAO,gBAAgB;IACnC,IAAI,KAAK;QACP,OAAO,IAAI,CAAC,eAAe,CAAC,KAAK,CAAA;IACnC,CAAC;IAID;;;;;;;;;;;;;;;;OAgBG;IACH,YACS,OAAwB,EAC/B,IAA8B;QADvB,YAAO,GAAP,OAAO,CAAiB;QAG/B,IAAI,CAAC,eAAe,GAAG,IAAI,eAAe,CAAC,IAAI,CAAC,OAAO,CAAC,cAAc,EAAE,IAAI,CAAC,CAAA;IAC/E,CAAC;CACF"}
\ No newline at end of file
diff --git a/node_modules/@supabase/realtime-js/dist/tsconfig.module.tsbuildinfo b/node_modules/@supabase/realtime-js/dist/tsconfig.module.tsbuildinfo
new file mode 100644
index 0000000000000000000000000000000000000000..f3c5d70ae5c5c77fd560a84d6a9479ea8c1a6c5f
--- /dev/null
+++ b/node_modules/@supabase/realtime-js/dist/tsconfig.module.tsbuildinfo
@@ -0,0 +1 @@
+{"fileNames":["../../../../node_modules/.pnpm/typescript@5.8.3/node_modules/typescript/lib/lib.es5.d.ts","../../../../node_modules/.pnpm/typescript@5.8.3/node_modules/typescript/lib/lib.es2015.d.ts","../../../../node_modules/.pnpm/typescript@5.8.3/node_modules/typescript/lib/lib.es2016.d.ts","../../../../node_modules/.pnpm/typescript@5.8.3/node_modules/typescript/lib/lib.es2017.d.ts","../../../../node_modules/.pnpm/typescript@5.8.3/node_modules/typescript/lib/lib.es2018.d.ts","../../../../node_modules/.pnpm/typescript@5.8.3/node_modules/typescript/lib/lib.es2019.d.ts","../../../../node_modules/.pnpm/typescript@5.8.3/node_modules/typescript/lib/lib.es2020.d.ts","../../../../node_modules/.pnpm/typescript@5.8.3/node_modules/typescript/lib/lib.es2021.d.ts","../../../../node_modules/.pnpm/typescript@5.8.3/node_modules/typescript/lib/lib.es2022.d.ts","../../../../node_modules/.pnpm/typescript@5.8.3/node_modules/typescript/lib/lib.dom.d.ts","../../../../node_modules/.pnpm/typescript@5.8.3/node_modules/typescript/lib/lib.es2015.core.d.ts","../../../../node_modules/.pnpm/typescript@5.8.3/node_modules/typescript/lib/lib.es2015.collection.d.ts","../../../../node_modules/.pnpm/typescript@5.8.3/node_modules/typescript/lib/lib.es2015.generator.d.ts","../../../../node_modules/.pnpm/typescript@5.8.3/node_modules/typescript/lib/lib.es2015.iterable.d.ts","../../../../node_modules/.pnpm/typescript@5.8.3/node_modules/typescript/lib/lib.es2015.promise.d.ts","../../../../node_modules/.pnpm/typescript@5.8.3/node_modules/typescript/lib/lib.es2015.proxy.d.ts","../../../../node_modules/.pnpm/typescript@5.8.3/node_modules/typescript/lib/lib.es2015.reflect.d.ts","../../../../node_modules/.pnpm/typescript@5.8.3/node_modules/typescript/lib/lib.es2015.symbol.d.ts","../../../../node_modules/.pnpm/typescript@5.8.3/node_modules/typescript/lib/lib.es2015.symbol.wellknown.d.ts","../../../../node_modules/.pnpm/typescript@5.8.3/node_modules/typescript/lib/lib.es2016.array.include.d.ts","../../../../node_modules/.pnpm/typescript@5.8.3/node_modules/typescript/lib/lib.es2016.intl.d.ts","../../../../node_modules/.pnpm/typescript@5.8.3/node_modules/typescript/lib/lib.es2017.arraybuffer.d.ts","../../../../node_modules/.pnpm/typescript@5.8.3/node_modules/typescript/lib/lib.es2017.date.d.ts","../../../../node_modules/.pnpm/typescript@5.8.3/node_modules/typescript/lib/lib.es2017.object.d.ts","../../../../node_modules/.pnpm/typescript@5.8.3/node_modules/typescript/lib/lib.es2017.sharedmemory.d.ts","../../../../node_modules/.pnpm/typescript@5.8.3/node_modules/typescript/lib/lib.es2017.string.d.ts","../../../../node_modules/.pnpm/typescript@5.8.3/node_modules/typescript/lib/lib.es2017.intl.d.ts","../../../../node_modules/.pnpm/typescript@5.8.3/node_modules/typescript/lib/lib.es2017.typedarrays.d.ts","../../../../node_modules/.pnpm/typescript@5.8.3/node_modules/typescript/lib/lib.es2018.asyncgenerator.d.ts","../../../../node_modules/.pnpm/typescript@5.8.3/node_modules/typescript/lib/lib.es2018.asynciterable.d.ts","../../../../node_modules/.pnpm/typescript@5.8.3/node_modules/typescript/lib/lib.es2018.intl.d.ts","../../../../node_modules/.pnpm/typescript@5.8.3/node_modules/typescript/lib/lib.es2018.promise.d.ts","../../../../node_modules/.pnpm/typescript@5.8.3/node_modules/typescript/lib/lib.es2018.regexp.d.ts","../../../../node_modules/.pnpm/typescript@5.8.3/node_modules/typescript/lib/lib.es2019.array.d.ts","../../../../node_modules/.pnpm/typescript@5.8.3/node_modules/typescript/lib/lib.es2019.object.d.ts","../../../../node_modules/.pnpm/typescript@5.8.3/node_modules/typescript/lib/lib.es2019.string.d.ts","../../../../node_modules/.pnpm/typescript@5.8.3/node_modules/typescript/lib/lib.es2019.symbol.d.ts","../../../../node_modules/.pnpm/typescript@5.8.3/node_modules/typescript/lib/lib.es2019.intl.d.ts","../../../../node_modules/.pnpm/typescript@5.8.3/node_modules/typescript/lib/lib.es2020.bigint.d.ts","../../../../node_modules/.pnpm/typescript@5.8.3/node_modules/typescript/lib/lib.es2020.date.d.ts","../../../../node_modules/.pnpm/typescript@5.8.3/node_modules/typescript/lib/lib.es2020.promise.d.ts","../../../../node_modules/.pnpm/typescript@5.8.3/node_modules/typescript/lib/lib.es2020.sharedmemory.d.ts","../../../../node_modules/.pnpm/typescript@5.8.3/node_modules/typescript/lib/lib.es2020.string.d.ts","../../../../node_modules/.pnpm/typescript@5.8.3/node_modules/typescript/lib/lib.es2020.symbol.wellknown.d.ts","../../../../node_modules/.pnpm/typescript@5.8.3/node_modules/typescript/lib/lib.es2020.intl.d.ts","../../../../node_modules/.pnpm/typescript@5.8.3/node_modules/typescript/lib/lib.es2020.number.d.ts","../../../../node_modules/.pnpm/typescript@5.8.3/node_modules/typescript/lib/lib.es2021.promise.d.ts","../../../../node_modules/.pnpm/typescript@5.8.3/node_modules/typescript/lib/lib.es2021.string.d.ts","../../../../node_modules/.pnpm/typescript@5.8.3/node_modules/typescript/lib/lib.es2021.weakref.d.ts","../../../../node_modules/.pnpm/typescript@5.8.3/node_modules/typescript/lib/lib.es2021.intl.d.ts","../../../../node_modules/.pnpm/typescript@5.8.3/node_modules/typescript/lib/lib.es2022.array.d.ts","../../../../node_modules/.pnpm/typescript@5.8.3/node_modules/typescript/lib/lib.es2022.error.d.ts","../../../../node_modules/.pnpm/typescript@5.8.3/node_modules/typescript/lib/lib.es2022.intl.d.ts","../../../../node_modules/.pnpm/typescript@5.8.3/node_modules/typescript/lib/lib.es2022.object.d.ts","../../../../node_modules/.pnpm/typescript@5.8.3/node_modules/typescript/lib/lib.es2022.string.d.ts","../../../../node_modules/.pnpm/typescript@5.8.3/node_modules/typescript/lib/lib.es2022.regexp.d.ts","../../../../node_modules/.pnpm/typescript@5.8.3/node_modules/typescript/lib/lib.decorators.d.ts","../../../../node_modules/.pnpm/typescript@5.8.3/node_modules/typescript/lib/lib.decorators.legacy.d.ts","../../../../node_modules/.pnpm/tslib@2.8.1/node_modules/tslib/tslib.d.ts","../src/lib/version.ts","../../../../node_modules/.pnpm/@supabase+phoenix@0.4.5/node_modules/@supabase/phoenix/priv/static/types/constants.d.ts","../../../../node_modules/.pnpm/@supabase+phoenix@0.4.5/node_modules/@supabase/phoenix/priv/static/types/longpoll.d.ts","../../../../node_modules/.pnpm/@supabase+phoenix@0.4.5/node_modules/@supabase/phoenix/priv/static/types/types.d.ts","../../../../node_modules/.pnpm/@supabase+phoenix@0.4.5/node_modules/@supabase/phoenix/priv/static/types/timer.d.ts","../../../../node_modules/.pnpm/@supabase+phoenix@0.4.5/node_modules/@supabase/phoenix/priv/static/types/socket.d.ts","../../../../node_modules/.pnpm/@supabase+phoenix@0.4.5/node_modules/@supabase/phoenix/priv/static/types/push.d.ts","../../../../node_modules/.pnpm/@supabase+phoenix@0.4.5/node_modules/@supabase/phoenix/priv/static/types/channel.d.ts","../../../../node_modules/.pnpm/@supabase+phoenix@0.4.5/node_modules/@supabase/phoenix/priv/static/types/presence.d.ts","../../../../node_modules/.pnpm/@supabase+phoenix@0.4.5/node_modules/@supabase/phoenix/priv/static/types/serializer.d.ts","../../../../node_modules/.pnpm/@supabase+phoenix@0.4.5/node_modules/@supabase/phoenix/priv/static/types/index.d.ts","../src/phoenix/types.ts","../src/lib/constants.ts","../src/lib/websocket-factory.ts","../src/lib/serializer.ts","../src/lib/transformers.ts","../src/phoenix/socketAdapter.ts","../src/RealtimeClient.ts","../src/phoenix/channelAdapter.ts","../src/phoenix/presenceAdapter.ts","../src/RealtimePresence.ts","../src/lib/normalizeChannelError.ts","../src/RealtimePostgresFilterBuilder.ts","../src/RealtimeChannel.ts","../src/index.ts","../../../../node_modules/.pnpm/@types+node@20.19.9/node_modules/@types/node/compatibility/disposable.d.ts","../../../../node_modules/.pnpm/@types+node@20.19.9/node_modules/@types/node/compatibility/indexable.d.ts","../../../../node_modules/.pnpm/@types+node@20.19.9/node_modules/@types/node/compatibility/iterators.d.ts","../../../../node_modules/.pnpm/@types+node@20.19.9/node_modules/@types/node/compatibility/index.d.ts","../../../../node_modules/.pnpm/@types+node@20.19.9/node_modules/@types/node/globals.typedarray.d.ts","../../../../node_modules/.pnpm/@types+node@20.19.9/node_modules/@types/node/buffer.buffer.d.ts","../../../../node_modules/.pnpm/buffer@5.7.1/node_modules/buffer/index.d.ts","../../../../node_modules/.pnpm/undici-types@6.21.0/node_modules/undici-types/header.d.ts","../../../../node_modules/.pnpm/undici-types@6.21.0/node_modules/undici-types/readable.d.ts","../../../../node_modules/.pnpm/undici-types@6.21.0/node_modules/undici-types/file.d.ts","../../../../node_modules/.pnpm/undici-types@6.21.0/node_modules/undici-types/fetch.d.ts","../../../../node_modules/.pnpm/undici-types@6.21.0/node_modules/undici-types/formdata.d.ts","../../../../node_modules/.pnpm/undici-types@6.21.0/node_modules/undici-types/connector.d.ts","../../../../node_modules/.pnpm/undici-types@6.21.0/node_modules/undici-types/client.d.ts","../../../../node_modules/.pnpm/undici-types@6.21.0/node_modules/undici-types/errors.d.ts","../../../../node_modules/.pnpm/undici-types@6.21.0/node_modules/undici-types/dispatcher.d.ts","../../../../node_modules/.pnpm/undici-types@6.21.0/node_modules/undici-types/global-dispatcher.d.ts","../../../../node_modules/.pnpm/undici-types@6.21.0/node_modules/undici-types/global-origin.d.ts","../../../../node_modules/.pnpm/undici-types@6.21.0/node_modules/undici-types/pool-stats.d.ts","../../../../node_modules/.pnpm/undici-types@6.21.0/node_modules/undici-types/pool.d.ts","../../../../node_modules/.pnpm/undici-types@6.21.0/node_modules/undici-types/handlers.d.ts","../../../../node_modules/.pnpm/undici-types@6.21.0/node_modules/undici-types/balanced-pool.d.ts","../../../../node_modules/.pnpm/undici-types@6.21.0/node_modules/undici-types/agent.d.ts","../../../../node_modules/.pnpm/undici-types@6.21.0/node_modules/undici-types/mock-interceptor.d.ts","../../../../node_modules/.pnpm/undici-types@6.21.0/node_modules/undici-types/mock-agent.d.ts","../../../../node_modules/.pnpm/undici-types@6.21.0/node_modules/undici-types/mock-client.d.ts","../../../../node_modules/.pnpm/undici-types@6.21.0/node_modules/undici-types/mock-pool.d.ts","../../../../node_modules/.pnpm/undici-types@6.21.0/node_modules/undici-types/mock-errors.d.ts","../../../../node_modules/.pnpm/undici-types@6.21.0/node_modules/undici-types/proxy-agent.d.ts","../../../../node_modules/.pnpm/undici-types@6.21.0/node_modules/undici-types/env-http-proxy-agent.d.ts","../../../../node_modules/.pnpm/undici-types@6.21.0/node_modules/undici-types/retry-handler.d.ts","../../../../node_modules/.pnpm/undici-types@6.21.0/node_modules/undici-types/retry-agent.d.ts","../../../../node_modules/.pnpm/undici-types@6.21.0/node_modules/undici-types/api.d.ts","../../../../node_modules/.pnpm/undici-types@6.21.0/node_modules/undici-types/interceptors.d.ts","../../../../node_modules/.pnpm/undici-types@6.21.0/node_modules/undici-types/util.d.ts","../../../../node_modules/.pnpm/undici-types@6.21.0/node_modules/undici-types/cookies.d.ts","../../../../node_modules/.pnpm/undici-types@6.21.0/node_modules/undici-types/patch.d.ts","../../../../node_modules/.pnpm/undici-types@6.21.0/node_modules/undici-types/websocket.d.ts","../../../../node_modules/.pnpm/undici-types@6.21.0/node_modules/undici-types/eventsource.d.ts","../../../../node_modules/.pnpm/undici-types@6.21.0/node_modules/undici-types/filereader.d.ts","../../../../node_modules/.pnpm/undici-types@6.21.0/node_modules/undici-types/diagnostics-channel.d.ts","../../../../node_modules/.pnpm/undici-types@6.21.0/node_modules/undici-types/content-type.d.ts","../../../../node_modules/.pnpm/undici-types@6.21.0/node_modules/undici-types/cache.d.ts","../../../../node_modules/.pnpm/undici-types@6.21.0/node_modules/undici-types/index.d.ts","../../../../node_modules/.pnpm/@types+node@20.19.9/node_modules/@types/node/globals.d.ts","../../../../node_modules/.pnpm/@types+node@20.19.9/node_modules/@types/node/assert.d.ts","../../../../node_modules/.pnpm/@types+node@20.19.9/node_modules/@types/node/assert/strict.d.ts","../../../../node_modules/.pnpm/@types+node@20.19.9/node_modules/@types/node/async_hooks.d.ts","../../../../node_modules/.pnpm/@types+node@20.19.9/node_modules/@types/node/buffer.d.ts","../../../../node_modules/.pnpm/@types+node@20.19.9/node_modules/@types/node/child_process.d.ts","../../../../node_modules/.pnpm/@types+node@20.19.9/node_modules/@types/node/cluster.d.ts","../../../../node_modules/.pnpm/@types+node@20.19.9/node_modules/@types/node/console.d.ts","../../../../node_modules/.pnpm/@types+node@20.19.9/node_modules/@types/node/constants.d.ts","../../../../node_modules/.pnpm/@types+node@20.19.9/node_modules/@types/node/crypto.d.ts","../../../../node_modules/.pnpm/@types+node@20.19.9/node_modules/@types/node/dgram.d.ts","../../../../node_modules/.pnpm/@types+node@20.19.9/node_modules/@types/node/diagnostics_channel.d.ts","../../../../node_modules/.pnpm/@types+node@20.19.9/node_modules/@types/node/dns.d.ts","../../../../node_modules/.pnpm/@types+node@20.19.9/node_modules/@types/node/dns/promises.d.ts","../../../../node_modules/.pnpm/@types+node@20.19.9/node_modules/@types/node/domain.d.ts","../../../../node_modules/.pnpm/@types+node@20.19.9/node_modules/@types/node/dom-events.d.ts","../../../../node_modules/.pnpm/@types+node@20.19.9/node_modules/@types/node/events.d.ts","../../../../node_modules/.pnpm/@types+node@20.19.9/node_modules/@types/node/fs.d.ts","../../../../node_modules/.pnpm/@types+node@20.19.9/node_modules/@types/node/fs/promises.d.ts","../../../../node_modules/.pnpm/@types+node@20.19.9/node_modules/@types/node/http.d.ts","../../../../node_modules/.pnpm/@types+node@20.19.9/node_modules/@types/node/http2.d.ts","../../../../node_modules/.pnpm/@types+node@20.19.9/node_modules/@types/node/https.d.ts","../../../../node_modules/.pnpm/@types+node@20.19.9/node_modules/@types/node/inspector.d.ts","../../../../node_modules/.pnpm/@types+node@20.19.9/node_modules/@types/node/module.d.ts","../../../../node_modules/.pnpm/@types+node@20.19.9/node_modules/@types/node/net.d.ts","../../../../node_modules/.pnpm/@types+node@20.19.9/node_modules/@types/node/os.d.ts","../../../../node_modules/.pnpm/@types+node@20.19.9/node_modules/@types/node/path.d.ts","../../../../node_modules/.pnpm/@types+node@20.19.9/node_modules/@types/node/perf_hooks.d.ts","../../../../node_modules/.pnpm/@types+node@20.19.9/node_modules/@types/node/process.d.ts","../../../../node_modules/.pnpm/@types+node@20.19.9/node_modules/@types/node/punycode.d.ts","../../../../node_modules/.pnpm/@types+node@20.19.9/node_modules/@types/node/querystring.d.ts","../../../../node_modules/.pnpm/@types+node@20.19.9/node_modules/@types/node/readline.d.ts","../../../../node_modules/.pnpm/@types+node@20.19.9/node_modules/@types/node/readline/promises.d.ts","../../../../node_modules/.pnpm/@types+node@20.19.9/node_modules/@types/node/repl.d.ts","../../../../node_modules/.pnpm/@types+node@20.19.9/node_modules/@types/node/sea.d.ts","../../../../node_modules/.pnpm/@types+node@20.19.9/node_modules/@types/node/stream.d.ts","../../../../node_modules/.pnpm/@types+node@20.19.9/node_modules/@types/node/stream/promises.d.ts","../../../../node_modules/.pnpm/@types+node@20.19.9/node_modules/@types/node/stream/consumers.d.ts","../../../../node_modules/.pnpm/@types+node@20.19.9/node_modules/@types/node/stream/web.d.ts","../../../../node_modules/.pnpm/@types+node@20.19.9/node_modules/@types/node/string_decoder.d.ts","../../../../node_modules/.pnpm/@types+node@20.19.9/node_modules/@types/node/test.d.ts","../../../../node_modules/.pnpm/@types+node@20.19.9/node_modules/@types/node/timers.d.ts","../../../../node_modules/.pnpm/@types+node@20.19.9/node_modules/@types/node/timers/promises.d.ts","../../../../node_modules/.pnpm/@types+node@20.19.9/node_modules/@types/node/tls.d.ts","../../../../node_modules/.pnpm/@types+node@20.19.9/node_modules/@types/node/trace_events.d.ts","../../../../node_modules/.pnpm/@types+node@20.19.9/node_modules/@types/node/tty.d.ts","../../../../node_modules/.pnpm/@types+node@20.19.9/node_modules/@types/node/url.d.ts","../../../../node_modules/.pnpm/@types+node@20.19.9/node_modules/@types/node/util.d.ts","../../../../node_modules/.pnpm/@types+node@20.19.9/node_modules/@types/node/v8.d.ts","../../../../node_modules/.pnpm/@types+node@20.19.9/node_modules/@types/node/vm.d.ts","../../../../node_modules/.pnpm/@types+node@20.19.9/node_modules/@types/node/wasi.d.ts","../../../../node_modules/.pnpm/@types+node@20.19.9/node_modules/@types/node/worker_threads.d.ts","../../../../node_modules/.pnpm/@types+node@20.19.9/node_modules/@types/node/zlib.d.ts","../../../../node_modules/.pnpm/@types+node@20.19.9/node_modules/@types/node/index.d.ts","../../../../node_modules/.pnpm/@types+jsonwebtoken@8.5.9/node_modules/@types/jsonwebtoken/index.d.ts"],"fileIdsList":[[63,64,65,66,90,133],[90,133],[62,63,64,65,66,67,68,69,90,133],[63,67,90,133],[63,90,133],[62,63,64,67,90,133],[61,62,90,133],[90,133,182],[90,130,133],[90,132,133],[133],[90,133,138,167],[90,133,134,139,145,146,153,164,175],[90,133,134,135,145,153],[85,86,87,90,133],[90,133,136,176],[90,133,137,138,146,154],[90,133,138,164,172],[90,133,139,141,145,153],[90,132,133,140],[90,133,141,142],[90,133,143,145],[90,132,133,145],[90,133,145,146,147,164,175],[90,133,145,146,147,160,164,167],[90,128,133],[90,133,141,145,148,153,164,175],[90,133,145,146,148,149,153,164,172,175],[90,133,148,150,164,172,175],[88,89,90,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181],[90,133,145,151],[90,133,152,175,180],[90,133,141,145,153,164],[90,133,154],[90,133,155],[90,132,133,156],[90,130,131,132,133,134,135,136,137,138,139,140,141,142,143,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181],[90,133,158],[90,133,159],[90,133,145,160,161],[90,133,160,162,176,178],[90,133,145,164,165,167],[90,133,166,167],[90,133,164,165],[90,133,167],[90,133,168],[90,130,133,164,169],[90,133,145,170,171],[90,133,170,171],[90,133,138,153,164,172],[90,133,173],[90,133,153,174],[90,133,148,159,175],[90,133,138,176],[90,133,164,177],[90,133,152,178],[90,133,179],[90,133,145,147,156,164,167,175,178,180],[90,133,164,181],[90,100,104,133,175],[90,100,133,164,175],[90,95,133],[90,97,100,133,172,175],[90,133,153,172],[90,95,133,182],[90,97,100,133,153,175],[90,92,93,96,99,133,145,164,175],[90,100,107,133],[90,92,98,133],[90,100,121,122,133],[90,96,100,133,167,175,182],[90,121,133,182],[90,94,95,133,182],[90,100,133],[90,94,95,96,97,98,99,100,101,102,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,122,123,124,125,126,127,133],[90,100,115,133],[90,100,107,108,133],[90,98,100,108,109,133],[90,99,133],[90,92,95,100,133],[90,100,104,108,109,133],[90,104,133],[90,98,100,103,133,175],[90,92,97,100,107,133],[90,133,164],[90,95,100,121,133,180,182],[59,71,72,75,77,78,80,81,82,90,133],[59,71,72,73,74,75,76,83,90,133],[59,90,133],[59,79,83,90,133],[59,73,77,80,83,90,133],[59,60,71,90,133],[59,70,71,72,76,83,90,133],[59,70,71,78,80,90,133],[59,70,71,72,77,90,133],[59,70,90,133]],"fileInfos":[{"version":"69684132aeb9b5642cbcd9e22dff7818ff0ee1aa831728af0ecf97d3364d5546","affectsGlobalScope":true,"impliedFormat":1},{"version":"45b7ab580deca34ae9729e97c13cfd999df04416a79116c3bfb483804f85ded4","impliedFormat":1},{"version":"3facaf05f0c5fc569c5649dd359892c98a85557e3e0c847964caeb67076f4d75","impliedFormat":1},{"version":"e44bb8bbac7f10ecc786703fe0a6a4b952189f908707980ba8f3c8975a760962","impliedFormat":1},{"version":"5e1c4c362065a6b95ff952c0eab010f04dcd2c3494e813b493ecfd4fcb9fc0d8","impliedFormat":1},{"version":"68d73b4a11549f9c0b7d352d10e91e5dca8faa3322bfb77b661839c42b1ddec7","impliedFormat":1},{"version":"5efce4fc3c29ea84e8928f97adec086e3dc876365e0982cc8479a07954a3efd4","impliedFormat":1},{"version":"feecb1be483ed332fad555aff858affd90a48ab19ba7272ee084704eb7167569","impliedFormat":1},{"version":"ee7bad0c15b58988daa84371e0b89d313b762ab83cb5b31b8a2d1162e8eb41c2","impliedFormat":1},{"version":"092c2bfe125ce69dbb1223c85d68d4d2397d7d8411867b5cc03cec902c233763","affectsGlobalScope":true,"impliedFormat":1},{"version":"c57796738e7f83dbc4b8e65132f11a377649c00dd3eee333f672b8f0a6bea671","affectsGlobalScope":true,"impliedFormat":1},{"version":"dc2df20b1bcdc8c2d34af4926e2c3ab15ffe1160a63e58b7e09833f616efff44","affectsGlobalScope":true,"impliedFormat":1},{"version":"515d0b7b9bea2e31ea4ec968e9edd2c39d3eebf4a2d5cbd04e88639819ae3b71","affectsGlobalScope":true,"impliedFormat":1},{"version":"0559b1f683ac7505ae451f9a96ce4c3c92bdc71411651ca6ddb0e88baaaad6a3","affectsGlobalScope":true,"impliedFormat":1},{"version":"0dc1e7ceda9b8b9b455c3a2d67b0412feab00bd2f66656cd8850e8831b08b537","affectsGlobalScope":true,"impliedFormat":1},{"version":"ce691fb9e5c64efb9547083e4a34091bcbe5bdb41027e310ebba8f7d96a98671","affectsGlobalScope":true,"impliedFormat":1},{"version":"8d697a2a929a5fcb38b7a65594020fcef05ec1630804a33748829c5ff53640d0","affectsGlobalScope":true,"impliedFormat":1},{"version":"4ff2a353abf8a80ee399af572debb8faab2d33ad38c4b4474cff7f26e7653b8d","affectsGlobalScope":true,"impliedFormat":1},{"version":"936e80ad36a2ee83fc3caf008e7c4c5afe45b3cf3d5c24408f039c1d47bdc1df","affectsGlobalScope":true,"impliedFormat":1},{"version":"d15bea3d62cbbdb9797079416b8ac375ae99162a7fba5de2c6c505446486ac0a","affectsGlobalScope":true,"impliedFormat":1},{"version":"68d18b664c9d32a7336a70235958b8997ebc1c3b8505f4f1ae2b7e7753b87618","affectsGlobalScope":true,"impliedFormat":1},{"version":"eb3d66c8327153d8fa7dd03f9c58d351107fe824c79e9b56b462935176cdf12a","affectsGlobalScope":true,"impliedFormat":1},{"version":"38f0219c9e23c915ef9790ab1d680440d95419ad264816fa15009a8851e79119","affectsGlobalScope":true,"impliedFormat":1},{"version":"69ab18c3b76cd9b1be3d188eaf8bba06112ebbe2f47f6c322b5105a6fbc45a2e","affectsGlobalScope":true,"impliedFormat":1},{"version":"fef8cfad2e2dc5f5b3d97a6f4f2e92848eb1b88e897bb7318cef0e2820bceaab","affectsGlobalScope":true,"impliedFormat":1},{"version":"2f11ff796926e0832f9ae148008138ad583bd181899ab7dd768a2666700b1893","affectsGlobalScope":true,"impliedFormat":1},{"version":"4de680d5bb41c17f7f68e0419412ca23c98d5749dcaaea1896172f06435891fc","affectsGlobalScope":true,"impliedFormat":1},{"version":"954296b30da6d508a104a3a0b5d96b76495c709785c1d11610908e63481ee667","affectsGlobalScope":true,"impliedFormat":1},{"version":"ac9538681b19688c8eae65811b329d3744af679e0bdfa5d842d0e32524c73e1c","affectsGlobalScope":true,"impliedFormat":1},{"version":"0a969edff4bd52585473d24995c5ef223f6652d6ef46193309b3921d65dd4376","affectsGlobalScope":true,"impliedFormat":1},{"version":"9e9fbd7030c440b33d021da145d3232984c8bb7916f277e8ffd3dc2e3eae2bdb","affectsGlobalScope":true,"impliedFormat":1},{"version":"811ec78f7fefcabbda4bfa93b3eb67d9ae166ef95f9bff989d964061cbf81a0c","affectsGlobalScope":true,"impliedFormat":1},{"version":"717937616a17072082152a2ef351cb51f98802fb4b2fdabd32399843875974ca","affectsGlobalScope":true,"impliedFormat":1},{"version":"d7e7d9b7b50e5f22c915b525acc5a49a7a6584cf8f62d0569e557c5cfc4b2ac2","affectsGlobalScope":true,"impliedFormat":1},{"version":"71c37f4c9543f31dfced6c7840e068c5a5aacb7b89111a4364b1d5276b852557","affectsGlobalScope":true,"impliedFormat":1},{"version":"576711e016cf4f1804676043e6a0a5414252560eb57de9faceee34d79798c850","affectsGlobalScope":true,"impliedFormat":1},{"version":"89c1b1281ba7b8a96efc676b11b264de7a8374c5ea1e6617f11880a13fc56dc6","affectsGlobalScope":true,"impliedFormat":1},{"version":"74f7fa2d027d5b33eb0471c8e82a6c87216223181ec31247c357a3e8e2fddc5b","affectsGlobalScope":true,"impliedFormat":1},{"version":"d6d7ae4d1f1f3772e2a3cde568ed08991a8ae34a080ff1151af28b7f798e22ca","affectsGlobalScope":true,"impliedFormat":1},{"version":"063600664504610fe3e99b717a1223f8b1900087fab0b4cad1496a114744f8df","affectsGlobalScope":true,"impliedFormat":1},{"version":"934019d7e3c81950f9a8426d093458b65d5aff2c7c1511233c0fd5b941e608ab","affectsGlobalScope":true,"impliedFormat":1},{"version":"52ada8e0b6e0482b728070b7639ee42e83a9b1c22d205992756fe020fd9f4a47","affectsGlobalScope":true,"impliedFormat":1},{"version":"3bdefe1bfd4d6dee0e26f928f93ccc128f1b64d5d501ff4a8cf3c6371200e5e6","affectsGlobalScope":true,"impliedFormat":1},{"version":"59fb2c069260b4ba00b5643b907ef5d5341b167e7d1dbf58dfd895658bda2867","affectsGlobalScope":true,"impliedFormat":1},{"version":"639e512c0dfc3fad96a84caad71b8834d66329a1f28dc95e3946c9b58176c73a","affectsGlobalScope":true,"impliedFormat":1},{"version":"368af93f74c9c932edd84c58883e736c9e3d53cec1fe24c0b0ff451f529ceab1","affectsGlobalScope":true,"impliedFormat":1},{"version":"af3dd424cf267428f30ccfc376f47a2c0114546b55c44d8c0f1d57d841e28d74","affectsGlobalScope":true,"impliedFormat":1},{"version":"995c005ab91a498455ea8dfb63aa9f83fa2ea793c3d8aa344be4a1678d06d399","affectsGlobalScope":true,"impliedFormat":1},{"version":"959d36cddf5e7d572a65045b876f2956c973a586da58e5d26cde519184fd9b8a","affectsGlobalScope":true,"impliedFormat":1},{"version":"965f36eae237dd74e6cca203a43e9ca801ce38824ead814728a2807b1910117d","affectsGlobalScope":true,"impliedFormat":1},{"version":"3925a6c820dcb1a06506c90b1577db1fdbf7705d65b62b99dce4be75c637e26b","affectsGlobalScope":true,"impliedFormat":1},{"version":"0a3d63ef2b853447ec4f749d3f368ce642264246e02911fcb1590d8c161b8005","affectsGlobalScope":true,"impliedFormat":1},{"version":"b5ce7a470bc3628408429040c4e3a53a27755022a32fd05e2cb694e7015386c7","affectsGlobalScope":true,"impliedFormat":1},{"version":"8444af78980e3b20b49324f4a16ba35024fef3ee069a0eb67616ea6ca821c47a","affectsGlobalScope":true,"impliedFormat":1},{"version":"3287d9d085fbd618c3971944b65b4be57859f5415f495b33a6adc994edd2f004","affectsGlobalScope":true,"impliedFormat":1},{"version":"b4b67b1a91182421f5df999988c690f14d813b9850b40acd06ed44691f6727ad","affectsGlobalScope":true,"impliedFormat":1},{"version":"8e7f8264d0fb4c5339605a15daadb037bf238c10b654bb3eee14208f860a32ea","affectsGlobalScope":true,"impliedFormat":1},{"version":"782dec38049b92d4e85c1585fbea5474a219c6984a35b004963b00beb1aab538","affectsGlobalScope":true,"impliedFormat":1},{"version":"a6a5253138c5432c68a1510c70fe78a644fe2e632111ba778e1978010d6edfec","impliedFormat":1},{"version":"440cb49331c56cd592851f31d646721775359ba1eec5451c1a2b011840e14740","signature":"be0899822ae6a4989051302579dfb478226abcbb204ae2fff49ff68bb35ad362"},{"version":"1621da3c4da45c37b79d6d361f7de9f0ea40b171dd11ef1ef1bb026665965fc9","impliedFormat":1},{"version":"3878700a966f0201a3e2b9aea8b75cc65008741c359889314e7b0c56c0c07b56","impliedFormat":1},{"version":"f040575209f695a7616fba0045e6a0c88d19d77b246a0098caeb4c9384447d15","impliedFormat":1},{"version":"1fcc4bb6d083b31e1587711ab5a8b0467b52a125f9735467774285bc8cc127e6","impliedFormat":1},{"version":"2193f35e13aee12b162670006604b914edb47fa0e391f39a8fe94a5402b60139","impliedFormat":1},{"version":"0e085cc503ad1332728d56244e9f7a603404beca17c0c5b2d815ed29e0727d4b","impliedFormat":1},{"version":"deda38d3245acb0404dd845dae172547c895c99c442082f176071cbb40d092f3","impliedFormat":1},{"version":"89659dc89f3a21d2a29c898297c96d56ef49f25eee0ee54aace7bd00758b6334","impliedFormat":1},{"version":"df4e0cf0d4a4ea996065de24fb0f621f96321f048869fbf4ef58a55593084d16","impliedFormat":1},{"version":"e6f3d02d69394dae0771c088b3c0b982cf15b6a91678c59f1d5fbd7c5e6ad8f8","impliedFormat":1},{"version":"b8a1713ca8c673a77f367cb999fb99e38857a3a63773563f957ba7aa35773c64","signature":"ef182902b33ac9b9ad90c163b313722d2bc9d8c2cfefeb418b3205d70504a486"},{"version":"999422164f1c0a7e6752769e1895f37ddcc30ef38bb747a2f95c859dd14c99d7","signature":"24911a68c2bf41d4c1ef50f348c4a8ff5dce2c24fdbad4b3dfa6b13416586347"},{"version":"2ff46c35f9aa3a1b53d02da9fdb7dcacf993dc5d7b2b47e9d504b3aa0d78de0b","signature":"5a800cb44fd70e436adf02e020dea317b0026786910e4bbc7ca014208c894ffd"},{"version":"1f4bc648881142502012c47a20f58810bd05fbb77ce1bbc8ec375cdb3c48128e","signature":"2b6c6039f4d2f656904d66f82231488f4852f861d27147884895097f74e3e812"},{"version":"a7f36938ca5806a4dcf38b49552c99361173d8e71a50fe87576b3820163a26b8","signature":"963de0b3445cc4323b606aeb7f9ce711425700088c766aac88fbd5fffd4b5c5f"},{"version":"6533d0e6ba8c44aa52b5149c6e1c3ab4a2e30a9d335ace2bbd86f98efe8d0b15","signature":"f433c0d7201ac0aa6904dbd08e9ab5fa3edf986ffa839ba90153201775d30a46"},{"version":"45b389dd47cf9fad7d097bbbf6bdba054d324f160ac768046a75695213b23b2f","signature":"cc06f33fc3cf6fe668cb89ea339a94b9d4a34ac1a97f72b9c7cf8d461eaf3416"},{"version":"8d68260e686f4c39abfd4534611598dbf46e78effb8d3fb53f8aedf45c1f0195","signature":"648f8efc20f2b0f36b1e90235aae754e3570fc78aeac5fd870ea447f0664a3d7"},{"version":"ff8007a9dd6ce59acb658e3002a53bfb71adc96ad0f312df17cc92023b56f9fb","signature":"26e665c1d4e03ceb2ea99fad6492cf213acc650bf41939cd8388ba3b60900427"},{"version":"8f46c9fad693160b323821763473ad0694db52eb158276ea14bc0fcd6b709e67","signature":"95bdd836ed77c23e530fcd3a0823df8fd611035590dfd8d38ee164c56f2bd2c4"},{"version":"9d2514a52535fcc0b50cadddeaca991246cff67acd4f046dd2a9ced348333708","signature":"db8fefaee4e14c6b8dd507c69ceebee78422cb938374d30dfd1f21e84d6a75f1"},{"version":"b034df3bfd937ddf8b2cb2431c0444360682bbca7e46665cb1fb132289395816","signature":"f96537f0fcfd0379e3254479573ffebc8a67c13a2cd3144c744b032af33800b9"},{"version":"69c17ac55199aa7405f50dc5ade2e339f7dcc47af334f88a38f756b9d8de6779","signature":"c2d50e73c775fee10c2361880cd227f3497a67677536208cd0e8a5d5ab562a0d"},{"version":"261881658863312a66b3912ec63de3d2a8cfda57cc3f244d2ad7248b255a6bb4","signature":"435279e408da8dba444c8ba93bbefddcae9e99b33acfc9a7c3318583e8f4a745"},{"version":"70521b6ab0dcba37539e5303104f29b721bfb2940b2776da4cc818c07e1fefc1","affectsGlobalScope":true,"impliedFormat":1},{"version":"ab41ef1f2cdafb8df48be20cd969d875602483859dc194e9c97c8a576892c052","affectsGlobalScope":true,"impliedFormat":1},{"version":"d153a11543fd884b596587ccd97aebbeed950b26933ee000f94009f1ab142848","affectsGlobalScope":true,"impliedFormat":1},{"version":"21d819c173c0cf7cc3ce57c3276e77fd9a8a01d35a06ad87158781515c9a438a","impliedFormat":1},{"version":"a79e62f1e20467e11a904399b8b18b18c0c6eea6b50c1168bf215356d5bebfaf","affectsGlobalScope":true,"impliedFormat":1},{"version":"49a5a44f2e68241a1d2bd9ec894535797998841c09729e506a7cbfcaa40f2180","affectsGlobalScope":true,"impliedFormat":1},{"version":"8e9c23ba78aabc2e0a27033f18737a6df754067731e69dc5f52823957d60a4b6","impliedFormat":1},{"version":"5929864ce17fba74232584d90cb721a89b7ad277220627cc97054ba15a98ea8f","impliedFormat":1},{"version":"763fe0f42b3d79b440a9b6e51e9ba3f3f91352469c1e4b3b67bfa4ff6352f3f4","impliedFormat":1},{"version":"25c8056edf4314820382a5fdb4bb7816999acdcb929c8f75e3f39473b87e85bc","impliedFormat":1},{"version":"c464d66b20788266e5353b48dc4aa6bc0dc4a707276df1e7152ab0c9ae21fad8","impliedFormat":1},{"version":"78d0d27c130d35c60b5e5566c9f1e5be77caf39804636bc1a40133919a949f21","impliedFormat":1},{"version":"c6fd2c5a395f2432786c9cb8deb870b9b0e8ff7e22c029954fabdd692bff6195","impliedFormat":1},{"version":"1d6e127068ea8e104a912e42fc0a110e2aa5a66a356a917a163e8cf9a65e4a75","impliedFormat":1},{"version":"5ded6427296cdf3b9542de4471d2aa8d3983671d4cac0f4bf9c637208d1ced43","impliedFormat":1},{"version":"7f182617db458e98fc18dfb272d40aa2fff3a353c44a89b2c0ccb3937709bfb5","impliedFormat":1},{"version":"cadc8aced301244057c4e7e73fbcae534b0f5b12a37b150d80e5a45aa4bebcbd","impliedFormat":1},{"version":"385aab901643aa54e1c36f5ef3107913b10d1b5bb8cbcd933d4263b80a0d7f20","impliedFormat":1},{"version":"9670d44354bab9d9982eca21945686b5c24a3f893db73c0dae0fd74217a4c219","impliedFormat":1},{"version":"0b8a9268adaf4da35e7fa830c8981cfa22adbbe5b3f6f5ab91f6658899e657a7","impliedFormat":1},{"version":"11396ed8a44c02ab9798b7dca436009f866e8dae3c9c25e8c1fbc396880bf1bb","impliedFormat":1},{"version":"ba7bc87d01492633cb5a0e5da8a4a42a1c86270e7b3d2dea5d156828a84e4882","impliedFormat":1},{"version":"4893a895ea92c85345017a04ed427cbd6a1710453338df26881a6019432febdd","impliedFormat":1},{"version":"c21dc52e277bcfc75fac0436ccb75c204f9e1b3fa5e12729670910639f27343e","impliedFormat":1},{"version":"13f6f39e12b1518c6650bbb220c8985999020fe0f21d818e28f512b7771d00f9","impliedFormat":1},{"version":"9b5369969f6e7175740bf51223112ff209f94ba43ecd3bb09eefff9fd675624a","impliedFormat":1},{"version":"4fe9e626e7164748e8769bbf74b538e09607f07ed17c2f20af8d680ee49fc1da","impliedFormat":1},{"version":"24515859bc0b836719105bb6cc3d68255042a9f02a6022b3187948b204946bd2","impliedFormat":1},{"version":"ea0148f897b45a76544ae179784c95af1bd6721b8610af9ffa467a518a086a43","impliedFormat":1},{"version":"24c6a117721e606c9984335f71711877293a9651e44f59f3d21c1ea0856f9cc9","impliedFormat":1},{"version":"dd3273ead9fbde62a72949c97dbec2247ea08e0c6952e701a483d74ef92d6a17","impliedFormat":1},{"version":"405822be75ad3e4d162e07439bac80c6bcc6dbae1929e179cf467ec0b9ee4e2e","impliedFormat":1},{"version":"0db18c6e78ea846316c012478888f33c11ffadab9efd1cc8bcc12daded7a60b6","impliedFormat":1},{"version":"e61be3f894b41b7baa1fbd6a66893f2579bfad01d208b4ff61daef21493ef0a8","impliedFormat":1},{"version":"bd0532fd6556073727d28da0edfd1736417a3f9f394877b6d5ef6ad88fba1d1a","impliedFormat":1},{"version":"89167d696a849fce5ca508032aabfe901c0868f833a8625d5a9c6e861ef935d2","impliedFormat":1},{"version":"615ba88d0128ed16bf83ef8ccbb6aff05c3ee2db1cc0f89ab50a4939bfc1943f","impliedFormat":1},{"version":"a4d551dbf8746780194d550c88f26cf937caf8d56f102969a110cfaed4b06656","impliedFormat":1},{"version":"8bd86b8e8f6a6aa6c49b71e14c4ffe1211a0e97c80f08d2c8cc98838006e4b88","impliedFormat":1},{"version":"317e63deeb21ac07f3992f5b50cdca8338f10acd4fbb7257ebf56735bf52ab00","impliedFormat":1},{"version":"4732aec92b20fb28c5fe9ad99521fb59974289ed1e45aecb282616202184064f","impliedFormat":1},{"version":"2e85db9e6fd73cfa3d7f28e0ab6b55417ea18931423bd47b409a96e4a169e8e6","impliedFormat":1},{"version":"c46e079fe54c76f95c67fb89081b3e399da2c7d109e7dca8e4b58d83e332e605","impliedFormat":1},{"version":"bf67d53d168abc1298888693338cb82854bdb2e69ef83f8a0092093c2d562107","impliedFormat":1},{"version":"1ca84b44ad1d8e4576f24904d8b95dd23b94ea67e1575f89614ac90062fc67f4","affectsGlobalScope":true,"impliedFormat":1},{"version":"6d586db0a09a9495ebb5dece28f54df9684bfbd6e1f568426ca153126dac4a40","impliedFormat":1},{"version":"7394959e5a741b185456e1ef5d64599c36c60a323207450991e7a42e08911419","impliedFormat":1},{"version":"8c0bcd6c6b67b4b503c11e91a1fb91522ed585900eab2ab1f61bba7d7caa9d6f","impliedFormat":1},{"version":"567b7f607f400873151d7bc63a049514b53c3c00f5f56e9e95695d93b66a138e","affectsGlobalScope":true,"impliedFormat":1},{"version":"f3e58c4c18a031cbb17abec7a4ad0bd5ae9fc70c1f4ba1e7fb921ad87c504aca","impliedFormat":1},{"version":"84c1930e33d1bb12ad01bcbe11d656f9646bd21b2fb2afd96e8e10615a021aef","impliedFormat":1},{"version":"35ec8b6760fd7138bbf5809b84551e31028fb2ba7b6dc91d95d098bf212ca8b4","affectsGlobalScope":true,"impliedFormat":1},{"version":"5524481e56c48ff486f42926778c0a3cce1cc85dc46683b92b1271865bcf015a","impliedFormat":1},{"version":"4b87f767c7bc841511113c876a6b8bf1fd0cb0b718c888ad84478b372ec486b1","affectsGlobalScope":true,"impliedFormat":1},{"version":"8d04e3640dd9eb67f7f1e5bd3d0bf96c784666f7aefc8ac1537af6f2d38d4c29","impliedFormat":1},{"version":"9d19808c8c291a9010a6c788e8532a2da70f811adb431c97520803e0ec649991","impliedFormat":1},{"version":"2bf469abae4cc9c0f340d4e05d9d26e37f936f9c8ca8f007a6534f109dcc77e4","impliedFormat":1},{"version":"4aacb0dd020eeaef65426153686cc639a78ec2885dc72ad220be1d25f1a439df","impliedFormat":1},{"version":"f0bd7e6d931657b59605c44112eaf8b980ba7f957a5051ed21cb93d978cf2f45","impliedFormat":1},{"version":"71450bbc2d82821d24ca05699a533e72758964e9852062c53b30f31c36978ab8","affectsGlobalScope":true,"impliedFormat":1},{"version":"0ada07543808f3b967624645a8e1ccd446f8b01ade47842acf1328aec899fed0","affectsGlobalScope":true,"impliedFormat":1},{"version":"4c21aaa8257d7950a5b75a251d9075b6a371208fc948c9c8402f6690ef3b5b55","impliedFormat":1},{"version":"b5895e6353a5d708f55d8685c38a235c3a6d8138e374dee8ceb8ffde5aa8002a","impliedFormat":1},{"version":"54c4f21f578864961efc94e8f42bc893a53509e886370ec7dd602e0151b9266c","impliedFormat":1},{"version":"de735eca2c51dd8b860254e9fdb6d9ec19fe402dfe597c23090841ce3937cfc5","impliedFormat":1},{"version":"4ff41188773cbf465807dd2f7059c7494cbee5115608efc297383832a1150c43","impliedFormat":1},{"version":"5650cf3dace09e7c25d384e3e6b818b938f68f4e8de96f52d9c5a1b3db068e86","impliedFormat":1},{"version":"1354ca5c38bd3fd3836a68e0f7c9f91f172582ba30ab15bb8c075891b91502b7","affectsGlobalScope":true,"impliedFormat":1},{"version":"5155da3047ef977944d791a2188ff6e6c225f6975cc1910ab7bb6838ab84cede","impliedFormat":1},{"version":"93f437e1398a4f06a984f441f7fa7a9f0535c04399619b5c22e0b87bdee182cb","impliedFormat":1},{"version":"afbe24ab0d74694372baa632ecb28bb375be53f3be53f9b07ecd7fc994907de5","impliedFormat":1},{"version":"e16d218a30f6a6810b57f7e968124eaa08c7bb366133ea34bbf01e7cd6b8c0ad","affectsGlobalScope":true,"impliedFormat":1},{"version":"eb8692dea24c27821f77e397272d9ed2eda0b95e4a75beb0fdda31081d15a8ae","affectsGlobalScope":true,"impliedFormat":1},{"version":"9e043a1bc8fbf2a255bccf9bf27e0f1caf916c3b0518ea34aa72357c0afd42ec","impliedFormat":1},{"version":"b4f70ec656a11d570e1a9edce07d118cd58d9760239e2ece99306ee9dfe61d02","impliedFormat":1},{"version":"3bc2f1e2c95c04048212c569ed38e338873f6a8593930cf5a7ef24ffb38fc3b6","impliedFormat":1},{"version":"8145e07aad6da5f23f2fcd8c8e4c5c13fb26ee986a79d03b0829b8fce152d8b2","impliedFormat":1},{"version":"f9d9d753d430ed050dc1bf2667a1bab711ccbb1c1507183d794cc195a5b085cc","impliedFormat":1},{"version":"9eece5e586312581ccd106d4853e861aaaa1a39f8e3ea672b8c3847eedd12f6e","impliedFormat":1},{"version":"5b6844ad931dcc1d3aca53268f4bd671428421464b1286746027aede398094f2","impliedFormat":1},{"version":"37ba7b45141a45ce6e80e66f2a96c8a5ab1bcef0fc2d0f56bb58df96ec67e972","impliedFormat":1},{"version":"125d792ec6c0c0f657d758055c494301cc5fdb327d9d9d5960b3f129aff76093","impliedFormat":1},{"version":"0dbcebe2126d03936c70545e96a6e41007cf065be38a1ce4d32a39fcedefead4","affectsGlobalScope":true,"impliedFormat":1},{"version":"1851a3b4db78664f83901bb9cac9e45e03a37bb5933cc5bf37e10bb7e91ab4eb","impliedFormat":1},{"version":"461e54289e6287e8494a0178ba18182acce51a02bca8dea219149bf2cf96f105","impliedFormat":1},{"version":"12ed4559eba17cd977aa0db658d25c4047067444b51acfdcbf38470630642b23","affectsGlobalScope":true,"impliedFormat":1},{"version":"f3ffabc95802521e1e4bcba4c88d8615176dc6e09111d920c7a213bdda6e1d65","impliedFormat":1},{"version":"e31e51c55800014d926e3f74208af49cb7352803619855c89296074d1ecbb524","impliedFormat":1},{"version":"ae56f65caf3be91108707bd8dfbccc2a57a91feb5daabf7165a06a945545ed26","impliedFormat":1},{"version":"a136d5de521da20f31631a0a96bf712370779d1c05b7015d7019a9b2a0446ca9","impliedFormat":1},{"version":"dfb96ba5177b68003deec9e773c47257da5c4c8a74053d8956389d832df72002","affectsGlobalScope":true,"impliedFormat":1},{"version":"92d3070580cf72b4bb80959b7f16ede9a3f39e6f4ef2ac87cfa4561844fdc69f","affectsGlobalScope":true,"impliedFormat":1},{"version":"d3dffd70e6375b872f0b4e152de4ae682d762c61a24881ecc5eb9f04c5caf76f","impliedFormat":1},{"version":"613deebaec53731ff6b74fe1a89f094b708033db6396b601df3e6d5ab0ec0a47","impliedFormat":1},{"version":"d91a7d8b5655c42986f1bdfe2105c4408f472831c8f20cf11a8c3345b6b56c8c","impliedFormat":1},{"version":"e56eb632f0281c9f8210eb8c86cc4839a427a4ffffcfd2a5e40b956050b3e042","affectsGlobalScope":true,"impliedFormat":1},{"version":"e8a979b8af001c9fc2e774e7809d233c8ca955a28756f52ee5dee88ccb0611d2","impliedFormat":1},{"version":"cac793cc47c29e26e4ac3601dcb00b4435ebed26203485790e44f2ad8b6ad847","impliedFormat":1},{"version":"bb4ed283cfb3db7ec1d4bb79c37f5e96d39b340f1f4de995c4b0b836c8d5fa05","impliedFormat":1}],"root":[60,[71,84]],"options":{"composite":true,"declaration":true,"declarationMap":true,"esModuleInterop":true,"importHelpers":true,"module":6,"noEmitOnError":true,"noFallthroughCasesInSwitch":true,"outDir":"./module","rootDir":"../src","skipLibCheck":true,"sourceMap":true,"strict":true,"stripInternal":true,"target":4},"referencedMap":[[67,1],[61,2],[70,3],[62,2],[68,4],[66,4],[69,5],[65,6],[64,2],[63,7],[183,8],[130,9],[131,9],[132,10],[90,11],[133,12],[134,13],[135,14],[85,2],[88,15],[86,2],[87,2],[136,16],[137,17],[138,18],[139,19],[140,20],[141,21],[142,21],[144,2],[143,22],[145,23],[146,24],[147,25],[129,26],[89,2],[148,27],[149,28],[150,29],[182,30],[151,31],[152,32],[153,33],[154,34],[155,35],[156,36],[157,37],[158,38],[159,39],[160,40],[161,40],[162,41],[163,2],[164,42],[166,43],[165,44],[167,45],[168,46],[169,47],[170,48],[171,49],[172,50],[173,51],[174,52],[175,53],[176,54],[177,55],[178,56],[179,57],[180,58],[181,59],[91,2],[59,2],[57,2],[58,2],[10,2],[12,2],[11,2],[2,2],[13,2],[14,2],[15,2],[16,2],[17,2],[18,2],[19,2],[20,2],[3,2],[21,2],[22,2],[4,2],[23,2],[27,2],[24,2],[25,2],[26,2],[28,2],[29,2],[30,2],[5,2],[31,2],[32,2],[33,2],[34,2],[6,2],[38,2],[35,2],[36,2],[37,2],[39,2],[7,2],[40,2],[45,2],[46,2],[41,2],[42,2],[43,2],[44,2],[8,2],[50,2],[47,2],[48,2],[49,2],[51,2],[9,2],[52,2],[53,2],[54,2],[56,2],[55,2],[1,2],[107,60],[117,61],[106,60],[127,62],[98,63],[97,64],[126,8],[120,65],[125,66],[100,67],[114,68],[99,69],[123,70],[95,71],[94,8],[124,72],[96,73],[101,74],[102,2],[105,74],[92,2],[128,75],[118,76],[109,77],[110,78],[112,79],[108,80],[111,81],[121,8],[103,82],[104,83],[113,84],[93,85],[116,76],[115,74],[119,2],[122,86],[83,87],[77,88],[82,89],[80,90],[84,91],[72,92],[81,89],[74,89],[75,89],[60,89],[73,89],[78,93],[79,94],[76,95],[71,96]],"latestChangedDtsFile":"./module/index.d.ts","version":"5.8.3"}
\ No newline at end of file
diff --git a/node_modules/@supabase/realtime-js/dist/tsconfig.tsbuildinfo b/node_modules/@supabase/realtime-js/dist/tsconfig.tsbuildinfo
new file mode 100644
index 0000000000000000000000000000000000000000..62d9f95973a60a53d6703f5ce11c179ae69af14e
--- /dev/null
+++ b/node_modules/@supabase/realtime-js/dist/tsconfig.tsbuildinfo
@@ -0,0 +1 @@
+{"fileNames":["../../../../node_modules/.pnpm/typescript@5.8.3/node_modules/typescript/lib/lib.es5.d.ts","../../../../node_modules/.pnpm/typescript@5.8.3/node_modules/typescript/lib/lib.es2015.d.ts","../../../../node_modules/.pnpm/typescript@5.8.3/node_modules/typescript/lib/lib.es2016.d.ts","../../../../node_modules/.pnpm/typescript@5.8.3/node_modules/typescript/lib/lib.es2017.d.ts","../../../../node_modules/.pnpm/typescript@5.8.3/node_modules/typescript/lib/lib.es2018.d.ts","../../../../node_modules/.pnpm/typescript@5.8.3/node_modules/typescript/lib/lib.es2019.d.ts","../../../../node_modules/.pnpm/typescript@5.8.3/node_modules/typescript/lib/lib.es2020.d.ts","../../../../node_modules/.pnpm/typescript@5.8.3/node_modules/typescript/lib/lib.es2021.d.ts","../../../../node_modules/.pnpm/typescript@5.8.3/node_modules/typescript/lib/lib.es2022.d.ts","../../../../node_modules/.pnpm/typescript@5.8.3/node_modules/typescript/lib/lib.dom.d.ts","../../../../node_modules/.pnpm/typescript@5.8.3/node_modules/typescript/lib/lib.es2015.core.d.ts","../../../../node_modules/.pnpm/typescript@5.8.3/node_modules/typescript/lib/lib.es2015.collection.d.ts","../../../../node_modules/.pnpm/typescript@5.8.3/node_modules/typescript/lib/lib.es2015.generator.d.ts","../../../../node_modules/.pnpm/typescript@5.8.3/node_modules/typescript/lib/lib.es2015.iterable.d.ts","../../../../node_modules/.pnpm/typescript@5.8.3/node_modules/typescript/lib/lib.es2015.promise.d.ts","../../../../node_modules/.pnpm/typescript@5.8.3/node_modules/typescript/lib/lib.es2015.proxy.d.ts","../../../../node_modules/.pnpm/typescript@5.8.3/node_modules/typescript/lib/lib.es2015.reflect.d.ts","../../../../node_modules/.pnpm/typescript@5.8.3/node_modules/typescript/lib/lib.es2015.symbol.d.ts","../../../../node_modules/.pnpm/typescript@5.8.3/node_modules/typescript/lib/lib.es2015.symbol.wellknown.d.ts","../../../../node_modules/.pnpm/typescript@5.8.3/node_modules/typescript/lib/lib.es2016.array.include.d.ts","../../../../node_modules/.pnpm/typescript@5.8.3/node_modules/typescript/lib/lib.es2016.intl.d.ts","../../../../node_modules/.pnpm/typescript@5.8.3/node_modules/typescript/lib/lib.es2017.arraybuffer.d.ts","../../../../node_modules/.pnpm/typescript@5.8.3/node_modules/typescript/lib/lib.es2017.date.d.ts","../../../../node_modules/.pnpm/typescript@5.8.3/node_modules/typescript/lib/lib.es2017.object.d.ts","../../../../node_modules/.pnpm/typescript@5.8.3/node_modules/typescript/lib/lib.es2017.sharedmemory.d.ts","../../../../node_modules/.pnpm/typescript@5.8.3/node_modules/typescript/lib/lib.es2017.string.d.ts","../../../../node_modules/.pnpm/typescript@5.8.3/node_modules/typescript/lib/lib.es2017.intl.d.ts","../../../../node_modules/.pnpm/typescript@5.8.3/node_modules/typescript/lib/lib.es2017.typedarrays.d.ts","../../../../node_modules/.pnpm/typescript@5.8.3/node_modules/typescript/lib/lib.es2018.asyncgenerator.d.ts","../../../../node_modules/.pnpm/typescript@5.8.3/node_modules/typescript/lib/lib.es2018.asynciterable.d.ts","../../../../node_modules/.pnpm/typescript@5.8.3/node_modules/typescript/lib/lib.es2018.intl.d.ts","../../../../node_modules/.pnpm/typescript@5.8.3/node_modules/typescript/lib/lib.es2018.promise.d.ts","../../../../node_modules/.pnpm/typescript@5.8.3/node_modules/typescript/lib/lib.es2018.regexp.d.ts","../../../../node_modules/.pnpm/typescript@5.8.3/node_modules/typescript/lib/lib.es2019.array.d.ts","../../../../node_modules/.pnpm/typescript@5.8.3/node_modules/typescript/lib/lib.es2019.object.d.ts","../../../../node_modules/.pnpm/typescript@5.8.3/node_modules/typescript/lib/lib.es2019.string.d.ts","../../../../node_modules/.pnpm/typescript@5.8.3/node_modules/typescript/lib/lib.es2019.symbol.d.ts","../../../../node_modules/.pnpm/typescript@5.8.3/node_modules/typescript/lib/lib.es2019.intl.d.ts","../../../../node_modules/.pnpm/typescript@5.8.3/node_modules/typescript/lib/lib.es2020.bigint.d.ts","../../../../node_modules/.pnpm/typescript@5.8.3/node_modules/typescript/lib/lib.es2020.date.d.ts","../../../../node_modules/.pnpm/typescript@5.8.3/node_modules/typescript/lib/lib.es2020.promise.d.ts","../../../../node_modules/.pnpm/typescript@5.8.3/node_modules/typescript/lib/lib.es2020.sharedmemory.d.ts","../../../../node_modules/.pnpm/typescript@5.8.3/node_modules/typescript/lib/lib.es2020.string.d.ts","../../../../node_modules/.pnpm/typescript@5.8.3/node_modules/typescript/lib/lib.es2020.symbol.wellknown.d.ts","../../../../node_modules/.pnpm/typescript@5.8.3/node_modules/typescript/lib/lib.es2020.intl.d.ts","../../../../node_modules/.pnpm/typescript@5.8.3/node_modules/typescript/lib/lib.es2020.number.d.ts","../../../../node_modules/.pnpm/typescript@5.8.3/node_modules/typescript/lib/lib.es2021.promise.d.ts","../../../../node_modules/.pnpm/typescript@5.8.3/node_modules/typescript/lib/lib.es2021.string.d.ts","../../../../node_modules/.pnpm/typescript@5.8.3/node_modules/typescript/lib/lib.es2021.weakref.d.ts","../../../../node_modules/.pnpm/typescript@5.8.3/node_modules/typescript/lib/lib.es2021.intl.d.ts","../../../../node_modules/.pnpm/typescript@5.8.3/node_modules/typescript/lib/lib.es2022.array.d.ts","../../../../node_modules/.pnpm/typescript@5.8.3/node_modules/typescript/lib/lib.es2022.error.d.ts","../../../../node_modules/.pnpm/typescript@5.8.3/node_modules/typescript/lib/lib.es2022.intl.d.ts","../../../../node_modules/.pnpm/typescript@5.8.3/node_modules/typescript/lib/lib.es2022.object.d.ts","../../../../node_modules/.pnpm/typescript@5.8.3/node_modules/typescript/lib/lib.es2022.string.d.ts","../../../../node_modules/.pnpm/typescript@5.8.3/node_modules/typescript/lib/lib.es2022.regexp.d.ts","../../../../node_modules/.pnpm/typescript@5.8.3/node_modules/typescript/lib/lib.decorators.d.ts","../../../../node_modules/.pnpm/typescript@5.8.3/node_modules/typescript/lib/lib.decorators.legacy.d.ts","../../../../node_modules/.pnpm/tslib@2.8.1/node_modules/tslib/tslib.d.ts","../src/lib/version.ts","../../../../node_modules/.pnpm/@supabase+phoenix@0.4.5/node_modules/@supabase/phoenix/priv/static/types/constants.d.ts","../../../../node_modules/.pnpm/@supabase+phoenix@0.4.5/node_modules/@supabase/phoenix/priv/static/types/longpoll.d.ts","../../../../node_modules/.pnpm/@supabase+phoenix@0.4.5/node_modules/@supabase/phoenix/priv/static/types/types.d.ts","../../../../node_modules/.pnpm/@supabase+phoenix@0.4.5/node_modules/@supabase/phoenix/priv/static/types/timer.d.ts","../../../../node_modules/.pnpm/@supabase+phoenix@0.4.5/node_modules/@supabase/phoenix/priv/static/types/socket.d.ts","../../../../node_modules/.pnpm/@supabase+phoenix@0.4.5/node_modules/@supabase/phoenix/priv/static/types/push.d.ts","../../../../node_modules/.pnpm/@supabase+phoenix@0.4.5/node_modules/@supabase/phoenix/priv/static/types/channel.d.ts","../../../../node_modules/.pnpm/@supabase+phoenix@0.4.5/node_modules/@supabase/phoenix/priv/static/types/presence.d.ts","../../../../node_modules/.pnpm/@supabase+phoenix@0.4.5/node_modules/@supabase/phoenix/priv/static/types/serializer.d.ts","../../../../node_modules/.pnpm/@supabase+phoenix@0.4.5/node_modules/@supabase/phoenix/priv/static/types/index.d.ts","../src/phoenix/types.ts","../src/lib/constants.ts","../src/lib/websocket-factory.ts","../src/lib/serializer.ts","../src/lib/transformers.ts","../src/phoenix/socketAdapter.ts","../src/RealtimeClient.ts","../src/phoenix/channelAdapter.ts","../src/phoenix/presenceAdapter.ts","../src/RealtimePresence.ts","../src/lib/normalizeChannelError.ts","../src/RealtimePostgresFilterBuilder.ts","../src/RealtimeChannel.ts","../src/index.ts","../../../../node_modules/.pnpm/@types+node@20.19.9/node_modules/@types/node/compatibility/disposable.d.ts","../../../../node_modules/.pnpm/@types+node@20.19.9/node_modules/@types/node/compatibility/indexable.d.ts","../../../../node_modules/.pnpm/@types+node@20.19.9/node_modules/@types/node/compatibility/iterators.d.ts","../../../../node_modules/.pnpm/@types+node@20.19.9/node_modules/@types/node/compatibility/index.d.ts","../../../../node_modules/.pnpm/@types+node@20.19.9/node_modules/@types/node/globals.typedarray.d.ts","../../../../node_modules/.pnpm/@types+node@20.19.9/node_modules/@types/node/buffer.buffer.d.ts","../../../../node_modules/.pnpm/buffer@5.7.1/node_modules/buffer/index.d.ts","../../../../node_modules/.pnpm/undici-types@6.21.0/node_modules/undici-types/header.d.ts","../../../../node_modules/.pnpm/undici-types@6.21.0/node_modules/undici-types/readable.d.ts","../../../../node_modules/.pnpm/undici-types@6.21.0/node_modules/undici-types/file.d.ts","../../../../node_modules/.pnpm/undici-types@6.21.0/node_modules/undici-types/fetch.d.ts","../../../../node_modules/.pnpm/undici-types@6.21.0/node_modules/undici-types/formdata.d.ts","../../../../node_modules/.pnpm/undici-types@6.21.0/node_modules/undici-types/connector.d.ts","../../../../node_modules/.pnpm/undici-types@6.21.0/node_modules/undici-types/client.d.ts","../../../../node_modules/.pnpm/undici-types@6.21.0/node_modules/undici-types/errors.d.ts","../../../../node_modules/.pnpm/undici-types@6.21.0/node_modules/undici-types/dispatcher.d.ts","../../../../node_modules/.pnpm/undici-types@6.21.0/node_modules/undici-types/global-dispatcher.d.ts","../../../../node_modules/.pnpm/undici-types@6.21.0/node_modules/undici-types/global-origin.d.ts","../../../../node_modules/.pnpm/undici-types@6.21.0/node_modules/undici-types/pool-stats.d.ts","../../../../node_modules/.pnpm/undici-types@6.21.0/node_modules/undici-types/pool.d.ts","../../../../node_modules/.pnpm/undici-types@6.21.0/node_modules/undici-types/handlers.d.ts","../../../../node_modules/.pnpm/undici-types@6.21.0/node_modules/undici-types/balanced-pool.d.ts","../../../../node_modules/.pnpm/undici-types@6.21.0/node_modules/undici-types/agent.d.ts","../../../../node_modules/.pnpm/undici-types@6.21.0/node_modules/undici-types/mock-interceptor.d.ts","../../../../node_modules/.pnpm/undici-types@6.21.0/node_modules/undici-types/mock-agent.d.ts","../../../../node_modules/.pnpm/undici-types@6.21.0/node_modules/undici-types/mock-client.d.ts","../../../../node_modules/.pnpm/undici-types@6.21.0/node_modules/undici-types/mock-pool.d.ts","../../../../node_modules/.pnpm/undici-types@6.21.0/node_modules/undici-types/mock-errors.d.ts","../../../../node_modules/.pnpm/undici-types@6.21.0/node_modules/undici-types/proxy-agent.d.ts","../../../../node_modules/.pnpm/undici-types@6.21.0/node_modules/undici-types/env-http-proxy-agent.d.ts","../../../../node_modules/.pnpm/undici-types@6.21.0/node_modules/undici-types/retry-handler.d.ts","../../../../node_modules/.pnpm/undici-types@6.21.0/node_modules/undici-types/retry-agent.d.ts","../../../../node_modules/.pnpm/undici-types@6.21.0/node_modules/undici-types/api.d.ts","../../../../node_modules/.pnpm/undici-types@6.21.0/node_modules/undici-types/interceptors.d.ts","../../../../node_modules/.pnpm/undici-types@6.21.0/node_modules/undici-types/util.d.ts","../../../../node_modules/.pnpm/undici-types@6.21.0/node_modules/undici-types/cookies.d.ts","../../../../node_modules/.pnpm/undici-types@6.21.0/node_modules/undici-types/patch.d.ts","../../../../node_modules/.pnpm/undici-types@6.21.0/node_modules/undici-types/websocket.d.ts","../../../../node_modules/.pnpm/undici-types@6.21.0/node_modules/undici-types/eventsource.d.ts","../../../../node_modules/.pnpm/undici-types@6.21.0/node_modules/undici-types/filereader.d.ts","../../../../node_modules/.pnpm/undici-types@6.21.0/node_modules/undici-types/diagnostics-channel.d.ts","../../../../node_modules/.pnpm/undici-types@6.21.0/node_modules/undici-types/content-type.d.ts","../../../../node_modules/.pnpm/undici-types@6.21.0/node_modules/undici-types/cache.d.ts","../../../../node_modules/.pnpm/undici-types@6.21.0/node_modules/undici-types/index.d.ts","../../../../node_modules/.pnpm/@types+node@20.19.9/node_modules/@types/node/globals.d.ts","../../../../node_modules/.pnpm/@types+node@20.19.9/node_modules/@types/node/assert.d.ts","../../../../node_modules/.pnpm/@types+node@20.19.9/node_modules/@types/node/assert/strict.d.ts","../../../../node_modules/.pnpm/@types+node@20.19.9/node_modules/@types/node/async_hooks.d.ts","../../../../node_modules/.pnpm/@types+node@20.19.9/node_modules/@types/node/buffer.d.ts","../../../../node_modules/.pnpm/@types+node@20.19.9/node_modules/@types/node/child_process.d.ts","../../../../node_modules/.pnpm/@types+node@20.19.9/node_modules/@types/node/cluster.d.ts","../../../../node_modules/.pnpm/@types+node@20.19.9/node_modules/@types/node/console.d.ts","../../../../node_modules/.pnpm/@types+node@20.19.9/node_modules/@types/node/constants.d.ts","../../../../node_modules/.pnpm/@types+node@20.19.9/node_modules/@types/node/crypto.d.ts","../../../../node_modules/.pnpm/@types+node@20.19.9/node_modules/@types/node/dgram.d.ts","../../../../node_modules/.pnpm/@types+node@20.19.9/node_modules/@types/node/diagnostics_channel.d.ts","../../../../node_modules/.pnpm/@types+node@20.19.9/node_modules/@types/node/dns.d.ts","../../../../node_modules/.pnpm/@types+node@20.19.9/node_modules/@types/node/dns/promises.d.ts","../../../../node_modules/.pnpm/@types+node@20.19.9/node_modules/@types/node/domain.d.ts","../../../../node_modules/.pnpm/@types+node@20.19.9/node_modules/@types/node/dom-events.d.ts","../../../../node_modules/.pnpm/@types+node@20.19.9/node_modules/@types/node/events.d.ts","../../../../node_modules/.pnpm/@types+node@20.19.9/node_modules/@types/node/fs.d.ts","../../../../node_modules/.pnpm/@types+node@20.19.9/node_modules/@types/node/fs/promises.d.ts","../../../../node_modules/.pnpm/@types+node@20.19.9/node_modules/@types/node/http.d.ts","../../../../node_modules/.pnpm/@types+node@20.19.9/node_modules/@types/node/http2.d.ts","../../../../node_modules/.pnpm/@types+node@20.19.9/node_modules/@types/node/https.d.ts","../../../../node_modules/.pnpm/@types+node@20.19.9/node_modules/@types/node/inspector.d.ts","../../../../node_modules/.pnpm/@types+node@20.19.9/node_modules/@types/node/module.d.ts","../../../../node_modules/.pnpm/@types+node@20.19.9/node_modules/@types/node/net.d.ts","../../../../node_modules/.pnpm/@types+node@20.19.9/node_modules/@types/node/os.d.ts","../../../../node_modules/.pnpm/@types+node@20.19.9/node_modules/@types/node/path.d.ts","../../../../node_modules/.pnpm/@types+node@20.19.9/node_modules/@types/node/perf_hooks.d.ts","../../../../node_modules/.pnpm/@types+node@20.19.9/node_modules/@types/node/process.d.ts","../../../../node_modules/.pnpm/@types+node@20.19.9/node_modules/@types/node/punycode.d.ts","../../../../node_modules/.pnpm/@types+node@20.19.9/node_modules/@types/node/querystring.d.ts","../../../../node_modules/.pnpm/@types+node@20.19.9/node_modules/@types/node/readline.d.ts","../../../../node_modules/.pnpm/@types+node@20.19.9/node_modules/@types/node/readline/promises.d.ts","../../../../node_modules/.pnpm/@types+node@20.19.9/node_modules/@types/node/repl.d.ts","../../../../node_modules/.pnpm/@types+node@20.19.9/node_modules/@types/node/sea.d.ts","../../../../node_modules/.pnpm/@types+node@20.19.9/node_modules/@types/node/stream.d.ts","../../../../node_modules/.pnpm/@types+node@20.19.9/node_modules/@types/node/stream/promises.d.ts","../../../../node_modules/.pnpm/@types+node@20.19.9/node_modules/@types/node/stream/consumers.d.ts","../../../../node_modules/.pnpm/@types+node@20.19.9/node_modules/@types/node/stream/web.d.ts","../../../../node_modules/.pnpm/@types+node@20.19.9/node_modules/@types/node/string_decoder.d.ts","../../../../node_modules/.pnpm/@types+node@20.19.9/node_modules/@types/node/test.d.ts","../../../../node_modules/.pnpm/@types+node@20.19.9/node_modules/@types/node/timers.d.ts","../../../../node_modules/.pnpm/@types+node@20.19.9/node_modules/@types/node/timers/promises.d.ts","../../../../node_modules/.pnpm/@types+node@20.19.9/node_modules/@types/node/tls.d.ts","../../../../node_modules/.pnpm/@types+node@20.19.9/node_modules/@types/node/trace_events.d.ts","../../../../node_modules/.pnpm/@types+node@20.19.9/node_modules/@types/node/tty.d.ts","../../../../node_modules/.pnpm/@types+node@20.19.9/node_modules/@types/node/url.d.ts","../../../../node_modules/.pnpm/@types+node@20.19.9/node_modules/@types/node/util.d.ts","../../../../node_modules/.pnpm/@types+node@20.19.9/node_modules/@types/node/v8.d.ts","../../../../node_modules/.pnpm/@types+node@20.19.9/node_modules/@types/node/vm.d.ts","../../../../node_modules/.pnpm/@types+node@20.19.9/node_modules/@types/node/wasi.d.ts","../../../../node_modules/.pnpm/@types+node@20.19.9/node_modules/@types/node/worker_threads.d.ts","../../../../node_modules/.pnpm/@types+node@20.19.9/node_modules/@types/node/zlib.d.ts","../../../../node_modules/.pnpm/@types+node@20.19.9/node_modules/@types/node/index.d.ts","../../../../node_modules/.pnpm/@types+jsonwebtoken@8.5.9/node_modules/@types/jsonwebtoken/index.d.ts"],"fileIdsList":[[63,64,65,66,90,133],[90,133],[62,63,64,65,66,67,68,69,90,133],[63,67,90,133],[63,90,133],[62,63,64,67,90,133],[61,62,90,133],[90,133,182],[90,130,133],[90,132,133],[133],[90,133,138,167],[90,133,134,139,145,146,153,164,175],[90,133,134,135,145,153],[85,86,87,90,133],[90,133,136,176],[90,133,137,138,146,154],[90,133,138,164,172],[90,133,139,141,145,153],[90,132,133,140],[90,133,141,142],[90,133,143,145],[90,132,133,145],[90,133,145,146,147,164,175],[90,133,145,146,147,160,164,167],[90,128,133],[90,133,141,145,148,153,164,175],[90,133,145,146,148,149,153,164,172,175],[90,133,148,150,164,172,175],[88,89,90,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181],[90,133,145,151],[90,133,152,175,180],[90,133,141,145,153,164],[90,133,154],[90,133,155],[90,132,133,156],[90,130,131,132,133,134,135,136,137,138,139,140,141,142,143,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181],[90,133,158],[90,133,159],[90,133,145,160,161],[90,133,160,162,176,178],[90,133,145,164,165,167],[90,133,166,167],[90,133,164,165],[90,133,167],[90,133,168],[90,130,133,164,169],[90,133,145,170,171],[90,133,170,171],[90,133,138,153,164,172],[90,133,173],[90,133,153,174],[90,133,148,159,175],[90,133,138,176],[90,133,164,177],[90,133,152,178],[90,133,179],[90,133,145,147,156,164,167,175,178,180],[90,133,164,181],[90,100,104,133,175],[90,100,133,164,175],[90,95,133],[90,97,100,133,172,175],[90,133,153,172],[90,95,133,182],[90,97,100,133,153,175],[90,92,93,96,99,133,145,164,175],[90,100,107,133],[90,92,98,133],[90,100,121,122,133],[90,96,100,133,167,175,182],[90,121,133,182],[90,94,95,133,182],[90,100,133],[90,94,95,96,97,98,99,100,101,102,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,122,123,124,125,126,127,133],[90,100,115,133],[90,100,107,108,133],[90,98,100,108,109,133],[90,99,133],[90,92,95,100,133],[90,100,104,108,109,133],[90,104,133],[90,98,100,103,133,175],[90,92,97,100,107,133],[90,133,164],[90,95,100,121,133,180,182],[59,71,72,75,77,78,80,81,82,90,133],[59,71,72,73,74,75,76,83,90,133],[59,90,133],[59,79,83,90,133],[59,73,77,80,83,90,133],[59,60,71,90,133],[59,70,71,72,76,83,90,133],[59,70,71,78,80,90,133],[59,70,71,72,77,90,133],[59,70,90,133]],"fileInfos":[{"version":"69684132aeb9b5642cbcd9e22dff7818ff0ee1aa831728af0ecf97d3364d5546","affectsGlobalScope":true,"impliedFormat":1},{"version":"45b7ab580deca34ae9729e97c13cfd999df04416a79116c3bfb483804f85ded4","impliedFormat":1},{"version":"3facaf05f0c5fc569c5649dd359892c98a85557e3e0c847964caeb67076f4d75","impliedFormat":1},{"version":"e44bb8bbac7f10ecc786703fe0a6a4b952189f908707980ba8f3c8975a760962","impliedFormat":1},{"version":"5e1c4c362065a6b95ff952c0eab010f04dcd2c3494e813b493ecfd4fcb9fc0d8","impliedFormat":1},{"version":"68d73b4a11549f9c0b7d352d10e91e5dca8faa3322bfb77b661839c42b1ddec7","impliedFormat":1},{"version":"5efce4fc3c29ea84e8928f97adec086e3dc876365e0982cc8479a07954a3efd4","impliedFormat":1},{"version":"feecb1be483ed332fad555aff858affd90a48ab19ba7272ee084704eb7167569","impliedFormat":1},{"version":"ee7bad0c15b58988daa84371e0b89d313b762ab83cb5b31b8a2d1162e8eb41c2","impliedFormat":1},{"version":"092c2bfe125ce69dbb1223c85d68d4d2397d7d8411867b5cc03cec902c233763","affectsGlobalScope":true,"impliedFormat":1},{"version":"c57796738e7f83dbc4b8e65132f11a377649c00dd3eee333f672b8f0a6bea671","affectsGlobalScope":true,"impliedFormat":1},{"version":"dc2df20b1bcdc8c2d34af4926e2c3ab15ffe1160a63e58b7e09833f616efff44","affectsGlobalScope":true,"impliedFormat":1},{"version":"515d0b7b9bea2e31ea4ec968e9edd2c39d3eebf4a2d5cbd04e88639819ae3b71","affectsGlobalScope":true,"impliedFormat":1},{"version":"0559b1f683ac7505ae451f9a96ce4c3c92bdc71411651ca6ddb0e88baaaad6a3","affectsGlobalScope":true,"impliedFormat":1},{"version":"0dc1e7ceda9b8b9b455c3a2d67b0412feab00bd2f66656cd8850e8831b08b537","affectsGlobalScope":true,"impliedFormat":1},{"version":"ce691fb9e5c64efb9547083e4a34091bcbe5bdb41027e310ebba8f7d96a98671","affectsGlobalScope":true,"impliedFormat":1},{"version":"8d697a2a929a5fcb38b7a65594020fcef05ec1630804a33748829c5ff53640d0","affectsGlobalScope":true,"impliedFormat":1},{"version":"4ff2a353abf8a80ee399af572debb8faab2d33ad38c4b4474cff7f26e7653b8d","affectsGlobalScope":true,"impliedFormat":1},{"version":"936e80ad36a2ee83fc3caf008e7c4c5afe45b3cf3d5c24408f039c1d47bdc1df","affectsGlobalScope":true,"impliedFormat":1},{"version":"d15bea3d62cbbdb9797079416b8ac375ae99162a7fba5de2c6c505446486ac0a","affectsGlobalScope":true,"impliedFormat":1},{"version":"68d18b664c9d32a7336a70235958b8997ebc1c3b8505f4f1ae2b7e7753b87618","affectsGlobalScope":true,"impliedFormat":1},{"version":"eb3d66c8327153d8fa7dd03f9c58d351107fe824c79e9b56b462935176cdf12a","affectsGlobalScope":true,"impliedFormat":1},{"version":"38f0219c9e23c915ef9790ab1d680440d95419ad264816fa15009a8851e79119","affectsGlobalScope":true,"impliedFormat":1},{"version":"69ab18c3b76cd9b1be3d188eaf8bba06112ebbe2f47f6c322b5105a6fbc45a2e","affectsGlobalScope":true,"impliedFormat":1},{"version":"fef8cfad2e2dc5f5b3d97a6f4f2e92848eb1b88e897bb7318cef0e2820bceaab","affectsGlobalScope":true,"impliedFormat":1},{"version":"2f11ff796926e0832f9ae148008138ad583bd181899ab7dd768a2666700b1893","affectsGlobalScope":true,"impliedFormat":1},{"version":"4de680d5bb41c17f7f68e0419412ca23c98d5749dcaaea1896172f06435891fc","affectsGlobalScope":true,"impliedFormat":1},{"version":"954296b30da6d508a104a3a0b5d96b76495c709785c1d11610908e63481ee667","affectsGlobalScope":true,"impliedFormat":1},{"version":"ac9538681b19688c8eae65811b329d3744af679e0bdfa5d842d0e32524c73e1c","affectsGlobalScope":true,"impliedFormat":1},{"version":"0a969edff4bd52585473d24995c5ef223f6652d6ef46193309b3921d65dd4376","affectsGlobalScope":true,"impliedFormat":1},{"version":"9e9fbd7030c440b33d021da145d3232984c8bb7916f277e8ffd3dc2e3eae2bdb","affectsGlobalScope":true,"impliedFormat":1},{"version":"811ec78f7fefcabbda4bfa93b3eb67d9ae166ef95f9bff989d964061cbf81a0c","affectsGlobalScope":true,"impliedFormat":1},{"version":"717937616a17072082152a2ef351cb51f98802fb4b2fdabd32399843875974ca","affectsGlobalScope":true,"impliedFormat":1},{"version":"d7e7d9b7b50e5f22c915b525acc5a49a7a6584cf8f62d0569e557c5cfc4b2ac2","affectsGlobalScope":true,"impliedFormat":1},{"version":"71c37f4c9543f31dfced6c7840e068c5a5aacb7b89111a4364b1d5276b852557","affectsGlobalScope":true,"impliedFormat":1},{"version":"576711e016cf4f1804676043e6a0a5414252560eb57de9faceee34d79798c850","affectsGlobalScope":true,"impliedFormat":1},{"version":"89c1b1281ba7b8a96efc676b11b264de7a8374c5ea1e6617f11880a13fc56dc6","affectsGlobalScope":true,"impliedFormat":1},{"version":"74f7fa2d027d5b33eb0471c8e82a6c87216223181ec31247c357a3e8e2fddc5b","affectsGlobalScope":true,"impliedFormat":1},{"version":"d6d7ae4d1f1f3772e2a3cde568ed08991a8ae34a080ff1151af28b7f798e22ca","affectsGlobalScope":true,"impliedFormat":1},{"version":"063600664504610fe3e99b717a1223f8b1900087fab0b4cad1496a114744f8df","affectsGlobalScope":true,"impliedFormat":1},{"version":"934019d7e3c81950f9a8426d093458b65d5aff2c7c1511233c0fd5b941e608ab","affectsGlobalScope":true,"impliedFormat":1},{"version":"52ada8e0b6e0482b728070b7639ee42e83a9b1c22d205992756fe020fd9f4a47","affectsGlobalScope":true,"impliedFormat":1},{"version":"3bdefe1bfd4d6dee0e26f928f93ccc128f1b64d5d501ff4a8cf3c6371200e5e6","affectsGlobalScope":true,"impliedFormat":1},{"version":"59fb2c069260b4ba00b5643b907ef5d5341b167e7d1dbf58dfd895658bda2867","affectsGlobalScope":true,"impliedFormat":1},{"version":"639e512c0dfc3fad96a84caad71b8834d66329a1f28dc95e3946c9b58176c73a","affectsGlobalScope":true,"impliedFormat":1},{"version":"368af93f74c9c932edd84c58883e736c9e3d53cec1fe24c0b0ff451f529ceab1","affectsGlobalScope":true,"impliedFormat":1},{"version":"af3dd424cf267428f30ccfc376f47a2c0114546b55c44d8c0f1d57d841e28d74","affectsGlobalScope":true,"impliedFormat":1},{"version":"995c005ab91a498455ea8dfb63aa9f83fa2ea793c3d8aa344be4a1678d06d399","affectsGlobalScope":true,"impliedFormat":1},{"version":"959d36cddf5e7d572a65045b876f2956c973a586da58e5d26cde519184fd9b8a","affectsGlobalScope":true,"impliedFormat":1},{"version":"965f36eae237dd74e6cca203a43e9ca801ce38824ead814728a2807b1910117d","affectsGlobalScope":true,"impliedFormat":1},{"version":"3925a6c820dcb1a06506c90b1577db1fdbf7705d65b62b99dce4be75c637e26b","affectsGlobalScope":true,"impliedFormat":1},{"version":"0a3d63ef2b853447ec4f749d3f368ce642264246e02911fcb1590d8c161b8005","affectsGlobalScope":true,"impliedFormat":1},{"version":"b5ce7a470bc3628408429040c4e3a53a27755022a32fd05e2cb694e7015386c7","affectsGlobalScope":true,"impliedFormat":1},{"version":"8444af78980e3b20b49324f4a16ba35024fef3ee069a0eb67616ea6ca821c47a","affectsGlobalScope":true,"impliedFormat":1},{"version":"3287d9d085fbd618c3971944b65b4be57859f5415f495b33a6adc994edd2f004","affectsGlobalScope":true,"impliedFormat":1},{"version":"b4b67b1a91182421f5df999988c690f14d813b9850b40acd06ed44691f6727ad","affectsGlobalScope":true,"impliedFormat":1},{"version":"8e7f8264d0fb4c5339605a15daadb037bf238c10b654bb3eee14208f860a32ea","affectsGlobalScope":true,"impliedFormat":1},{"version":"782dec38049b92d4e85c1585fbea5474a219c6984a35b004963b00beb1aab538","affectsGlobalScope":true,"impliedFormat":1},{"version":"a6a5253138c5432c68a1510c70fe78a644fe2e632111ba778e1978010d6edfec","impliedFormat":1},{"version":"440cb49331c56cd592851f31d646721775359ba1eec5451c1a2b011840e14740","signature":"be0899822ae6a4989051302579dfb478226abcbb204ae2fff49ff68bb35ad362"},{"version":"1621da3c4da45c37b79d6d361f7de9f0ea40b171dd11ef1ef1bb026665965fc9","impliedFormat":1},{"version":"3878700a966f0201a3e2b9aea8b75cc65008741c359889314e7b0c56c0c07b56","impliedFormat":1},{"version":"f040575209f695a7616fba0045e6a0c88d19d77b246a0098caeb4c9384447d15","impliedFormat":1},{"version":"1fcc4bb6d083b31e1587711ab5a8b0467b52a125f9735467774285bc8cc127e6","impliedFormat":1},{"version":"2193f35e13aee12b162670006604b914edb47fa0e391f39a8fe94a5402b60139","impliedFormat":1},{"version":"0e085cc503ad1332728d56244e9f7a603404beca17c0c5b2d815ed29e0727d4b","impliedFormat":1},{"version":"deda38d3245acb0404dd845dae172547c895c99c442082f176071cbb40d092f3","impliedFormat":1},{"version":"89659dc89f3a21d2a29c898297c96d56ef49f25eee0ee54aace7bd00758b6334","impliedFormat":1},{"version":"df4e0cf0d4a4ea996065de24fb0f621f96321f048869fbf4ef58a55593084d16","impliedFormat":1},{"version":"e6f3d02d69394dae0771c088b3c0b982cf15b6a91678c59f1d5fbd7c5e6ad8f8","impliedFormat":1},{"version":"b8a1713ca8c673a77f367cb999fb99e38857a3a63773563f957ba7aa35773c64","signature":"ef182902b33ac9b9ad90c163b313722d2bc9d8c2cfefeb418b3205d70504a486"},{"version":"999422164f1c0a7e6752769e1895f37ddcc30ef38bb747a2f95c859dd14c99d7","signature":"24911a68c2bf41d4c1ef50f348c4a8ff5dce2c24fdbad4b3dfa6b13416586347"},{"version":"2ff46c35f9aa3a1b53d02da9fdb7dcacf993dc5d7b2b47e9d504b3aa0d78de0b","signature":"5a800cb44fd70e436adf02e020dea317b0026786910e4bbc7ca014208c894ffd"},{"version":"1f4bc648881142502012c47a20f58810bd05fbb77ce1bbc8ec375cdb3c48128e","signature":"2b6c6039f4d2f656904d66f82231488f4852f861d27147884895097f74e3e812"},{"version":"a7f36938ca5806a4dcf38b49552c99361173d8e71a50fe87576b3820163a26b8","signature":"963de0b3445cc4323b606aeb7f9ce711425700088c766aac88fbd5fffd4b5c5f"},{"version":"6533d0e6ba8c44aa52b5149c6e1c3ab4a2e30a9d335ace2bbd86f98efe8d0b15","signature":"f433c0d7201ac0aa6904dbd08e9ab5fa3edf986ffa839ba90153201775d30a46"},{"version":"45b389dd47cf9fad7d097bbbf6bdba054d324f160ac768046a75695213b23b2f","signature":"cc06f33fc3cf6fe668cb89ea339a94b9d4a34ac1a97f72b9c7cf8d461eaf3416"},{"version":"8d68260e686f4c39abfd4534611598dbf46e78effb8d3fb53f8aedf45c1f0195","signature":"648f8efc20f2b0f36b1e90235aae754e3570fc78aeac5fd870ea447f0664a3d7"},{"version":"ff8007a9dd6ce59acb658e3002a53bfb71adc96ad0f312df17cc92023b56f9fb","signature":"26e665c1d4e03ceb2ea99fad6492cf213acc650bf41939cd8388ba3b60900427"},{"version":"8f46c9fad693160b323821763473ad0694db52eb158276ea14bc0fcd6b709e67","signature":"95bdd836ed77c23e530fcd3a0823df8fd611035590dfd8d38ee164c56f2bd2c4"},{"version":"9d2514a52535fcc0b50cadddeaca991246cff67acd4f046dd2a9ced348333708","signature":"db8fefaee4e14c6b8dd507c69ceebee78422cb938374d30dfd1f21e84d6a75f1"},{"version":"b034df3bfd937ddf8b2cb2431c0444360682bbca7e46665cb1fb132289395816","signature":"f96537f0fcfd0379e3254479573ffebc8a67c13a2cd3144c744b032af33800b9"},{"version":"69c17ac55199aa7405f50dc5ade2e339f7dcc47af334f88a38f756b9d8de6779","signature":"c2d50e73c775fee10c2361880cd227f3497a67677536208cd0e8a5d5ab562a0d"},{"version":"261881658863312a66b3912ec63de3d2a8cfda57cc3f244d2ad7248b255a6bb4","signature":"435279e408da8dba444c8ba93bbefddcae9e99b33acfc9a7c3318583e8f4a745"},{"version":"70521b6ab0dcba37539e5303104f29b721bfb2940b2776da4cc818c07e1fefc1","affectsGlobalScope":true,"impliedFormat":1},{"version":"ab41ef1f2cdafb8df48be20cd969d875602483859dc194e9c97c8a576892c052","affectsGlobalScope":true,"impliedFormat":1},{"version":"d153a11543fd884b596587ccd97aebbeed950b26933ee000f94009f1ab142848","affectsGlobalScope":true,"impliedFormat":1},{"version":"21d819c173c0cf7cc3ce57c3276e77fd9a8a01d35a06ad87158781515c9a438a","impliedFormat":1},{"version":"a79e62f1e20467e11a904399b8b18b18c0c6eea6b50c1168bf215356d5bebfaf","affectsGlobalScope":true,"impliedFormat":1},{"version":"49a5a44f2e68241a1d2bd9ec894535797998841c09729e506a7cbfcaa40f2180","affectsGlobalScope":true,"impliedFormat":1},{"version":"8e9c23ba78aabc2e0a27033f18737a6df754067731e69dc5f52823957d60a4b6","impliedFormat":1},{"version":"5929864ce17fba74232584d90cb721a89b7ad277220627cc97054ba15a98ea8f","impliedFormat":1},{"version":"763fe0f42b3d79b440a9b6e51e9ba3f3f91352469c1e4b3b67bfa4ff6352f3f4","impliedFormat":1},{"version":"25c8056edf4314820382a5fdb4bb7816999acdcb929c8f75e3f39473b87e85bc","impliedFormat":1},{"version":"c464d66b20788266e5353b48dc4aa6bc0dc4a707276df1e7152ab0c9ae21fad8","impliedFormat":1},{"version":"78d0d27c130d35c60b5e5566c9f1e5be77caf39804636bc1a40133919a949f21","impliedFormat":1},{"version":"c6fd2c5a395f2432786c9cb8deb870b9b0e8ff7e22c029954fabdd692bff6195","impliedFormat":1},{"version":"1d6e127068ea8e104a912e42fc0a110e2aa5a66a356a917a163e8cf9a65e4a75","impliedFormat":1},{"version":"5ded6427296cdf3b9542de4471d2aa8d3983671d4cac0f4bf9c637208d1ced43","impliedFormat":1},{"version":"7f182617db458e98fc18dfb272d40aa2fff3a353c44a89b2c0ccb3937709bfb5","impliedFormat":1},{"version":"cadc8aced301244057c4e7e73fbcae534b0f5b12a37b150d80e5a45aa4bebcbd","impliedFormat":1},{"version":"385aab901643aa54e1c36f5ef3107913b10d1b5bb8cbcd933d4263b80a0d7f20","impliedFormat":1},{"version":"9670d44354bab9d9982eca21945686b5c24a3f893db73c0dae0fd74217a4c219","impliedFormat":1},{"version":"0b8a9268adaf4da35e7fa830c8981cfa22adbbe5b3f6f5ab91f6658899e657a7","impliedFormat":1},{"version":"11396ed8a44c02ab9798b7dca436009f866e8dae3c9c25e8c1fbc396880bf1bb","impliedFormat":1},{"version":"ba7bc87d01492633cb5a0e5da8a4a42a1c86270e7b3d2dea5d156828a84e4882","impliedFormat":1},{"version":"4893a895ea92c85345017a04ed427cbd6a1710453338df26881a6019432febdd","impliedFormat":1},{"version":"c21dc52e277bcfc75fac0436ccb75c204f9e1b3fa5e12729670910639f27343e","impliedFormat":1},{"version":"13f6f39e12b1518c6650bbb220c8985999020fe0f21d818e28f512b7771d00f9","impliedFormat":1},{"version":"9b5369969f6e7175740bf51223112ff209f94ba43ecd3bb09eefff9fd675624a","impliedFormat":1},{"version":"4fe9e626e7164748e8769bbf74b538e09607f07ed17c2f20af8d680ee49fc1da","impliedFormat":1},{"version":"24515859bc0b836719105bb6cc3d68255042a9f02a6022b3187948b204946bd2","impliedFormat":1},{"version":"ea0148f897b45a76544ae179784c95af1bd6721b8610af9ffa467a518a086a43","impliedFormat":1},{"version":"24c6a117721e606c9984335f71711877293a9651e44f59f3d21c1ea0856f9cc9","impliedFormat":1},{"version":"dd3273ead9fbde62a72949c97dbec2247ea08e0c6952e701a483d74ef92d6a17","impliedFormat":1},{"version":"405822be75ad3e4d162e07439bac80c6bcc6dbae1929e179cf467ec0b9ee4e2e","impliedFormat":1},{"version":"0db18c6e78ea846316c012478888f33c11ffadab9efd1cc8bcc12daded7a60b6","impliedFormat":1},{"version":"e61be3f894b41b7baa1fbd6a66893f2579bfad01d208b4ff61daef21493ef0a8","impliedFormat":1},{"version":"bd0532fd6556073727d28da0edfd1736417a3f9f394877b6d5ef6ad88fba1d1a","impliedFormat":1},{"version":"89167d696a849fce5ca508032aabfe901c0868f833a8625d5a9c6e861ef935d2","impliedFormat":1},{"version":"615ba88d0128ed16bf83ef8ccbb6aff05c3ee2db1cc0f89ab50a4939bfc1943f","impliedFormat":1},{"version":"a4d551dbf8746780194d550c88f26cf937caf8d56f102969a110cfaed4b06656","impliedFormat":1},{"version":"8bd86b8e8f6a6aa6c49b71e14c4ffe1211a0e97c80f08d2c8cc98838006e4b88","impliedFormat":1},{"version":"317e63deeb21ac07f3992f5b50cdca8338f10acd4fbb7257ebf56735bf52ab00","impliedFormat":1},{"version":"4732aec92b20fb28c5fe9ad99521fb59974289ed1e45aecb282616202184064f","impliedFormat":1},{"version":"2e85db9e6fd73cfa3d7f28e0ab6b55417ea18931423bd47b409a96e4a169e8e6","impliedFormat":1},{"version":"c46e079fe54c76f95c67fb89081b3e399da2c7d109e7dca8e4b58d83e332e605","impliedFormat":1},{"version":"bf67d53d168abc1298888693338cb82854bdb2e69ef83f8a0092093c2d562107","impliedFormat":1},{"version":"1ca84b44ad1d8e4576f24904d8b95dd23b94ea67e1575f89614ac90062fc67f4","affectsGlobalScope":true,"impliedFormat":1},{"version":"6d586db0a09a9495ebb5dece28f54df9684bfbd6e1f568426ca153126dac4a40","impliedFormat":1},{"version":"7394959e5a741b185456e1ef5d64599c36c60a323207450991e7a42e08911419","impliedFormat":1},{"version":"8c0bcd6c6b67b4b503c11e91a1fb91522ed585900eab2ab1f61bba7d7caa9d6f","impliedFormat":1},{"version":"567b7f607f400873151d7bc63a049514b53c3c00f5f56e9e95695d93b66a138e","affectsGlobalScope":true,"impliedFormat":1},{"version":"f3e58c4c18a031cbb17abec7a4ad0bd5ae9fc70c1f4ba1e7fb921ad87c504aca","impliedFormat":1},{"version":"84c1930e33d1bb12ad01bcbe11d656f9646bd21b2fb2afd96e8e10615a021aef","impliedFormat":1},{"version":"35ec8b6760fd7138bbf5809b84551e31028fb2ba7b6dc91d95d098bf212ca8b4","affectsGlobalScope":true,"impliedFormat":1},{"version":"5524481e56c48ff486f42926778c0a3cce1cc85dc46683b92b1271865bcf015a","impliedFormat":1},{"version":"4b87f767c7bc841511113c876a6b8bf1fd0cb0b718c888ad84478b372ec486b1","affectsGlobalScope":true,"impliedFormat":1},{"version":"8d04e3640dd9eb67f7f1e5bd3d0bf96c784666f7aefc8ac1537af6f2d38d4c29","impliedFormat":1},{"version":"9d19808c8c291a9010a6c788e8532a2da70f811adb431c97520803e0ec649991","impliedFormat":1},{"version":"2bf469abae4cc9c0f340d4e05d9d26e37f936f9c8ca8f007a6534f109dcc77e4","impliedFormat":1},{"version":"4aacb0dd020eeaef65426153686cc639a78ec2885dc72ad220be1d25f1a439df","impliedFormat":1},{"version":"f0bd7e6d931657b59605c44112eaf8b980ba7f957a5051ed21cb93d978cf2f45","impliedFormat":1},{"version":"71450bbc2d82821d24ca05699a533e72758964e9852062c53b30f31c36978ab8","affectsGlobalScope":true,"impliedFormat":1},{"version":"0ada07543808f3b967624645a8e1ccd446f8b01ade47842acf1328aec899fed0","affectsGlobalScope":true,"impliedFormat":1},{"version":"4c21aaa8257d7950a5b75a251d9075b6a371208fc948c9c8402f6690ef3b5b55","impliedFormat":1},{"version":"b5895e6353a5d708f55d8685c38a235c3a6d8138e374dee8ceb8ffde5aa8002a","impliedFormat":1},{"version":"54c4f21f578864961efc94e8f42bc893a53509e886370ec7dd602e0151b9266c","impliedFormat":1},{"version":"de735eca2c51dd8b860254e9fdb6d9ec19fe402dfe597c23090841ce3937cfc5","impliedFormat":1},{"version":"4ff41188773cbf465807dd2f7059c7494cbee5115608efc297383832a1150c43","impliedFormat":1},{"version":"5650cf3dace09e7c25d384e3e6b818b938f68f4e8de96f52d9c5a1b3db068e86","impliedFormat":1},{"version":"1354ca5c38bd3fd3836a68e0f7c9f91f172582ba30ab15bb8c075891b91502b7","affectsGlobalScope":true,"impliedFormat":1},{"version":"5155da3047ef977944d791a2188ff6e6c225f6975cc1910ab7bb6838ab84cede","impliedFormat":1},{"version":"93f437e1398a4f06a984f441f7fa7a9f0535c04399619b5c22e0b87bdee182cb","impliedFormat":1},{"version":"afbe24ab0d74694372baa632ecb28bb375be53f3be53f9b07ecd7fc994907de5","impliedFormat":1},{"version":"e16d218a30f6a6810b57f7e968124eaa08c7bb366133ea34bbf01e7cd6b8c0ad","affectsGlobalScope":true,"impliedFormat":1},{"version":"eb8692dea24c27821f77e397272d9ed2eda0b95e4a75beb0fdda31081d15a8ae","affectsGlobalScope":true,"impliedFormat":1},{"version":"9e043a1bc8fbf2a255bccf9bf27e0f1caf916c3b0518ea34aa72357c0afd42ec","impliedFormat":1},{"version":"b4f70ec656a11d570e1a9edce07d118cd58d9760239e2ece99306ee9dfe61d02","impliedFormat":1},{"version":"3bc2f1e2c95c04048212c569ed38e338873f6a8593930cf5a7ef24ffb38fc3b6","impliedFormat":1},{"version":"8145e07aad6da5f23f2fcd8c8e4c5c13fb26ee986a79d03b0829b8fce152d8b2","impliedFormat":1},{"version":"f9d9d753d430ed050dc1bf2667a1bab711ccbb1c1507183d794cc195a5b085cc","impliedFormat":1},{"version":"9eece5e586312581ccd106d4853e861aaaa1a39f8e3ea672b8c3847eedd12f6e","impliedFormat":1},{"version":"5b6844ad931dcc1d3aca53268f4bd671428421464b1286746027aede398094f2","impliedFormat":1},{"version":"37ba7b45141a45ce6e80e66f2a96c8a5ab1bcef0fc2d0f56bb58df96ec67e972","impliedFormat":1},{"version":"125d792ec6c0c0f657d758055c494301cc5fdb327d9d9d5960b3f129aff76093","impliedFormat":1},{"version":"0dbcebe2126d03936c70545e96a6e41007cf065be38a1ce4d32a39fcedefead4","affectsGlobalScope":true,"impliedFormat":1},{"version":"1851a3b4db78664f83901bb9cac9e45e03a37bb5933cc5bf37e10bb7e91ab4eb","impliedFormat":1},{"version":"461e54289e6287e8494a0178ba18182acce51a02bca8dea219149bf2cf96f105","impliedFormat":1},{"version":"12ed4559eba17cd977aa0db658d25c4047067444b51acfdcbf38470630642b23","affectsGlobalScope":true,"impliedFormat":1},{"version":"f3ffabc95802521e1e4bcba4c88d8615176dc6e09111d920c7a213bdda6e1d65","impliedFormat":1},{"version":"e31e51c55800014d926e3f74208af49cb7352803619855c89296074d1ecbb524","impliedFormat":1},{"version":"ae56f65caf3be91108707bd8dfbccc2a57a91feb5daabf7165a06a945545ed26","impliedFormat":1},{"version":"a136d5de521da20f31631a0a96bf712370779d1c05b7015d7019a9b2a0446ca9","impliedFormat":1},{"version":"dfb96ba5177b68003deec9e773c47257da5c4c8a74053d8956389d832df72002","affectsGlobalScope":true,"impliedFormat":1},{"version":"92d3070580cf72b4bb80959b7f16ede9a3f39e6f4ef2ac87cfa4561844fdc69f","affectsGlobalScope":true,"impliedFormat":1},{"version":"d3dffd70e6375b872f0b4e152de4ae682d762c61a24881ecc5eb9f04c5caf76f","impliedFormat":1},{"version":"613deebaec53731ff6b74fe1a89f094b708033db6396b601df3e6d5ab0ec0a47","impliedFormat":1},{"version":"d91a7d8b5655c42986f1bdfe2105c4408f472831c8f20cf11a8c3345b6b56c8c","impliedFormat":1},{"version":"e56eb632f0281c9f8210eb8c86cc4839a427a4ffffcfd2a5e40b956050b3e042","affectsGlobalScope":true,"impliedFormat":1},{"version":"e8a979b8af001c9fc2e774e7809d233c8ca955a28756f52ee5dee88ccb0611d2","impliedFormat":1},{"version":"cac793cc47c29e26e4ac3601dcb00b4435ebed26203485790e44f2ad8b6ad847","impliedFormat":1},{"version":"bb4ed283cfb3db7ec1d4bb79c37f5e96d39b340f1f4de995c4b0b836c8d5fa05","impliedFormat":1}],"root":[60,[71,84]],"options":{"composite":true,"declaration":true,"declarationMap":true,"esModuleInterop":true,"importHelpers":true,"module":1,"noEmitOnError":true,"noFallthroughCasesInSwitch":true,"outDir":"./main","rootDir":"../src","skipLibCheck":true,"sourceMap":true,"strict":true,"stripInternal":true,"target":4},"referencedMap":[[67,1],[61,2],[70,3],[62,2],[68,4],[66,4],[69,5],[65,6],[64,2],[63,7],[183,8],[130,9],[131,9],[132,10],[90,11],[133,12],[134,13],[135,14],[85,2],[88,15],[86,2],[87,2],[136,16],[137,17],[138,18],[139,19],[140,20],[141,21],[142,21],[144,2],[143,22],[145,23],[146,24],[147,25],[129,26],[89,2],[148,27],[149,28],[150,29],[182,30],[151,31],[152,32],[153,33],[154,34],[155,35],[156,36],[157,37],[158,38],[159,39],[160,40],[161,40],[162,41],[163,2],[164,42],[166,43],[165,44],[167,45],[168,46],[169,47],[170,48],[171,49],[172,50],[173,51],[174,52],[175,53],[176,54],[177,55],[178,56],[179,57],[180,58],[181,59],[91,2],[59,2],[57,2],[58,2],[10,2],[12,2],[11,2],[2,2],[13,2],[14,2],[15,2],[16,2],[17,2],[18,2],[19,2],[20,2],[3,2],[21,2],[22,2],[4,2],[23,2],[27,2],[24,2],[25,2],[26,2],[28,2],[29,2],[30,2],[5,2],[31,2],[32,2],[33,2],[34,2],[6,2],[38,2],[35,2],[36,2],[37,2],[39,2],[7,2],[40,2],[45,2],[46,2],[41,2],[42,2],[43,2],[44,2],[8,2],[50,2],[47,2],[48,2],[49,2],[51,2],[9,2],[52,2],[53,2],[54,2],[56,2],[55,2],[1,2],[107,60],[117,61],[106,60],[127,62],[98,63],[97,64],[126,8],[120,65],[125,66],[100,67],[114,68],[99,69],[123,70],[95,71],[94,8],[124,72],[96,73],[101,74],[102,2],[105,74],[92,2],[128,75],[118,76],[109,77],[110,78],[112,79],[108,80],[111,81],[121,8],[103,82],[104,83],[113,84],[93,85],[116,76],[115,74],[119,2],[122,86],[83,87],[77,88],[82,89],[80,90],[84,91],[72,92],[81,89],[74,89],[75,89],[60,89],[73,89],[78,93],[79,94],[76,95],[71,96]],"latestChangedDtsFile":"./main/index.d.ts","version":"5.8.3"}
\ No newline at end of file
diff --git a/node_modules/@supabase/realtime-js/migrations/README.md b/node_modules/@supabase/realtime-js/migrations/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..bfcf0c2b24c27a832052e0516f5b955fecaf3f67
--- /dev/null
+++ b/node_modules/@supabase/realtime-js/migrations/README.md
@@ -0,0 +1,25 @@
+# Migration notes for `@supabase/realtime-js`
+
+Each file in this directory describes one migration theme — what changed in `@supabase/realtime-js`, who is affected, and what callers need to do.
+
+Files are shipped with the npm package, so the migration notes you see here are pinned to the version of `@supabase/realtime-js` you have installed. Upgrading the package brings the relevant migration notes along with it.
+
+## How agents should use this directory
+
+When helping a developer upgrade `@supabase/realtime-js`:
+
+1. Read the migration files in `node_modules/@supabase/realtime-js/migrations/` for the version they have installed.
+2. Cross-reference against the version they are upgrading to.
+3. Apply the migration steps described in each relevant file.
+
+## How humans should use this directory
+
+Browse the files for the migration theme you care about. Each file is self-contained and explains its own scope, audience, and steps.
+
+## File naming
+
+One file per migration theme, named by topic rather than version (e.g. `.md`, kebab-case). A single version can ship multiple theme files; a single theme can span multiple versions. Each file documents its own `Since` / `Will require action by` version range internally.
+
+## Cross-cutting migration notes
+
+Migrations that span multiple Supabase packages (e.g. Node.js version drops, monorepo restructures) live in [`docs/MIGRATION.md`](../../../../docs/MIGRATION.md) at the repository root, not here. This directory is scoped to `@supabase/realtime-js` only.
diff --git a/node_modules/@supabase/realtime-js/migrations/httpsend-server-version.md b/node_modules/@supabase/realtime-js/migrations/httpsend-server-version.md
new file mode 100644
index 0000000000000000000000000000000000000000..5ce0ec58c0abc599d602fed9246209955c60e5d9
--- /dev/null
+++ b/node_modules/@supabase/realtime-js/migrations/httpsend-server-version.md
@@ -0,0 +1,88 @@
+# `httpSend()` server version requirement
+
+**Since:** v2.107.0
+**Applies to:** anyone calling `RealtimeChannel.httpSend()` (or `RealtimeChannel.broadcast()` configured to use HTTP)
+
+`httpSend()` sends broadcast events through a per-event REST endpoint:
+
+```
+POST /api/broadcast/:topic/events/:event
+```
+
+This endpoint was added in **Realtime server v2.97.0** ([supabase/realtime#1864](https://github.com/supabase/realtime/pull/1864)). It also enables binary broadcast payloads (`application/octet-stream`), which the older batch endpoint does not support.
+
+## What changed
+
+- `httpSend()` calls the new per-event endpoint and expects HTTP `202`.
+- On `404`, the client now rejects with a message that names the requirement and the escape hatches (see below) instead of returning the generic `Not Found` text from the server.
+- The original `RealtimeChannel.send()` (and its REST fallback) still target the older `POST /api/broadcast` batch endpoint and are unaffected.
+
+## Who is affected
+
+You are affected if **all** of the following are true:
+
+1. You upgraded `@supabase/realtime-js` (or `@supabase/supabase-js`) to **v2.107.0 or later**, **and**
+2. You call `httpSend()` (or `broadcast()` with `type: 'broadcast'` routed through HTTP), **and**
+3. Your Realtime server is **older than v2.97.0**.
+
+If you only use the WebSocket `send()` API, or your Realtime server is already on v2.97.0+, nothing changes for you.
+
+## How to verify the server version
+
+The Realtime server does not currently emit a version header, so the easiest checks are:
+
+- **Hosted Supabase:** version is rolled forward continuously and is on v2.97.0+.
+- **Local development with the Supabase CLI:** recent CLI versions bundle Realtime v2.97.0+. Update the CLI to the latest stable.
+- **Self-hosted:** check the `image:` tag of the Realtime container in your `docker-compose.yml`.
+
+## What to do
+
+### If you are on a recent Supabase CLI
+
+You should already be on a compatible Realtime version. If you still see the 404 error, update the CLI:
+
+```bash
+# macOS / Homebrew
+brew upgrade supabase/tap/supabase
+
+# npm
+npm install -g supabase
+
+# scoop / etc — see https://supabase.com/docs/guides/local-development
+```
+
+Then restart the local Supabase stack.
+
+### If you need to pin a specific Realtime version locally
+
+The CLI honors a per-project pin file. Create the file with the desired image tag:
+
+```bash
+mkdir -p supabase/.temp
+echo "v2.97.3" > supabase/.temp/realtime-version
+supabase stop && supabase start
+```
+
+(This is the same mechanism the `@supabase/supabase-js` test harness uses internally.)
+
+### If you self-host
+
+Bump the Realtime image in your deployment to `v2.97.3` or newer:
+
+```yaml
+services:
+ realtime:
+ image: supabase/realtime:v2.97.3
+```
+
+### If you cannot update the server right now
+
+Downgrade `@supabase/realtime-js` (and `@supabase/supabase-js`) back to **v2.106.x**, which only uses the older `POST /api/broadcast` batch endpoint:
+
+```bash
+npm install @supabase/supabase-js@2.106.2
+```
+
+## Why the message is more specific now
+
+Prior to this release, a 404 from the new endpoint surfaced as a plain `Not Found` error, which was hard to act on. The client now rejects with a message that points at this migration file and the escape hatches above.
diff --git a/node_modules/@supabase/realtime-js/package.json b/node_modules/@supabase/realtime-js/package.json
new file mode 100644
index 0000000000000000000000000000000000000000..d0ad2aa412fd5a5640ef6feddbc78344c8ef391b
--- /dev/null
+++ b/node_modules/@supabase/realtime-js/package.json
@@ -0,0 +1,63 @@
+{
+ "name": "@supabase/realtime-js",
+ "version": "2.112.3",
+ "description": "Listen to realtime updates to your PostgreSQL database",
+ "keywords": [
+ "realtime",
+ "phoenix",
+ "elixir",
+ "javascript",
+ "typescript",
+ "firebase",
+ "supabase"
+ ],
+ "homepage": "https://github.com/supabase/supabase-js/tree/master/packages/core/realtime-js",
+ "bugs": "https://github.com/supabase/supabase-js/issues",
+ "files": [
+ "dist",
+ "src",
+ "migrations",
+ "AGENTS.md"
+ ],
+ "main": "dist/main/index.js",
+ "module": "dist/module/index.js",
+ "types": "dist/module/index.d.ts",
+ "repository": {
+ "type": "git",
+ "url": "https://github.com/supabase/supabase-js.git",
+ "directory": "packages/core/realtime-js"
+ },
+ "author": "Supabase",
+ "license": "MIT",
+ "dependencies": {
+ "@supabase/phoenix": "0.4.5",
+ "tslib": "2.8.1"
+ },
+ "devDependencies": {
+ "@arethetypeswrong/cli": "^0.18.2",
+ "@types/jsonwebtoken": "^8.5.8",
+ "@vitest/coverage-v8": "^4.1.5",
+ "jsdom": "^26.0.0",
+ "jsonwebtoken": "^9.0.0",
+ "mock-socket": "^9.3.1",
+ "typedoc": "^0.27.9",
+ "typescript": "~5.8.3",
+ "vitest": "4.1.6",
+ "web-worker": "1.2.0"
+ },
+ "engines": {
+ "node": ">=22.0.0"
+ },
+ "scripts": {
+ "build": "npm run build:main && npm run build:module",
+ "build:main": "tsc -p tsconfig.json",
+ "build:module": "tsc -p tsconfig.module.json",
+ "test": "vitest run",
+ "test:watch": "vitest",
+ "test:coverage": "vitest run --coverage.enabled true --coverage.reporter=text",
+ "docs": "typedoc --options ../../../typedoc.base.mjs src/index.ts --out docs/v2",
+ "docs:json": "typedoc --options ../../../typedoc.base.mjs --json docs/v2/spec.json --excludeExternals src/index.ts",
+ "check-exports": "attw --pack .",
+ "test:ci": "vitest run --coverage"
+ }
+}
\ No newline at end of file
diff --git a/node_modules/@supabase/realtime-js/src/RealtimeChannel.ts b/node_modules/@supabase/realtime-js/src/RealtimeChannel.ts
new file mode 100644
index 0000000000000000000000000000000000000000..3ccf75137b868c6051f92b2d9450b23af8880682
--- /dev/null
+++ b/node_modules/@supabase/realtime-js/src/RealtimeChannel.ts
@@ -0,0 +1,1340 @@
+import { CHANNEL_EVENTS, CHANNEL_STATES } from './lib/constants'
+import type { ChannelState } from './lib/constants'
+import type RealtimeClient from './RealtimeClient'
+import RealtimePresence, { REALTIME_PRESENCE_LISTEN_EVENTS } from './RealtimePresence'
+import type {
+ RealtimePresenceJoinPayload,
+ RealtimePresenceLeavePayload,
+ RealtimePresenceState,
+} from './RealtimePresence'
+import * as Transformers from './lib/transformers'
+import { httpEndpointURL } from './lib/transformers'
+import { normalizeChannelError } from './lib/normalizeChannelError'
+import ChannelAdapter from './phoenix/channelAdapter'
+import { ChannelBindingCallback, ChannelOnErrorCallback } from './phoenix/types'
+import type { Timer } from './phoenix/types'
+import { RealtimePostgresFilterBuilder } from './RealtimePostgresFilterBuilder'
+import type { RealtimePostgresChangesFilterOperator } from './RealtimePostgresFilterBuilder'
+
+export type { RealtimePostgresChangesFilterOperator } from './RealtimePostgresFilterBuilder'
+export {
+ RealtimePostgresFilterBuilder,
+ postgresChangesFilter,
+} from './RealtimePostgresFilterBuilder'
+
+type ReplayOption = {
+ since: number
+ limit?: number
+}
+
+export type RealtimeChannelOptions = {
+ config: {
+ /**
+ * self option enables client to receive message it broadcast
+ * ack option instructs server to acknowledge that broadcast message was received
+ * replay option instructs server to replay broadcast messages
+ * replication_ready option instructs the server to emit a `system` event once the
+ * Postgres replication connection backing this channel is established and ready to
+ * stream changes. Listen for it with `channel.on('system', {}, (payload) => ...)`;
+ * the payload's `status` is `'ok'` (`message: 'Replication connection established'`)
+ * on success or `'error'` if the connection is not ready in time.
+ */
+ broadcast?: {
+ self?: boolean
+ ack?: boolean
+ replay?: ReplayOption
+ replication_ready?: boolean
+ }
+ /**
+ * key option is used to track presence payload across clients
+ *
+ * enabled controls whether this client receives presence state and updates from other
+ * clients — set it to true (or add an `.on('presence', ...)` listener, which enables it
+ * automatically) if you want to see who else is present. Without it, this client's
+ * `presenceState()` stays empty and no `presence` events fire for you, because the
+ * underlying presence state machine buffers incoming updates until it has received an
+ * initial snapshot, which is only requested when this flag is set.
+ *
+ * It does not gate the other direction: calling `track()` always makes this client
+ * visible to other subscribers that have presence enabled, regardless of this client's
+ * own `enabled` setting. On RLS-protected (private) channels, receiving presence updates
+ * additionally requires the `presence.read` policy to authorize this client.
+ */
+ presence?: { key?: string; enabled?: boolean }
+ /**
+ * defines if the channel is private or not and if RLS policies will be used to check data
+ */
+ private?: boolean
+ }
+}
+
+type RealtimeChangesPayloadBase = {
+ schema: string
+ table: string
+}
+
+type RealtimeBroadcastChangesPayloadBase = RealtimeChangesPayloadBase & {
+ id: string
+}
+
+export type RealtimeBroadcastInsertPayload =
+ RealtimeBroadcastChangesPayloadBase & {
+ operation: `${REALTIME_POSTGRES_CHANGES_LISTEN_EVENT.INSERT}`
+ record: T
+ old_record: null
+ }
+
+export type RealtimeBroadcastUpdatePayload =
+ RealtimeBroadcastChangesPayloadBase & {
+ operation: `${REALTIME_POSTGRES_CHANGES_LISTEN_EVENT.UPDATE}`
+ record: T
+ old_record: T
+ }
+
+export type RealtimeBroadcastDeletePayload =
+ RealtimeBroadcastChangesPayloadBase & {
+ operation: `${REALTIME_POSTGRES_CHANGES_LISTEN_EVENT.DELETE}`
+ record: null
+ old_record: T
+ }
+
+export type RealtimeBroadcastPayload =
+ | RealtimeBroadcastInsertPayload
+ | RealtimeBroadcastUpdatePayload
+ | RealtimeBroadcastDeletePayload
+
+type RealtimePostgresChangesPayloadBase = {
+ schema: string
+ table: string
+ commit_timestamp: string
+ errors: string[]
+}
+
+export type RealtimePostgresInsertPayload =
+ RealtimePostgresChangesPayloadBase & {
+ eventType: `${REALTIME_POSTGRES_CHANGES_LISTEN_EVENT.INSERT}`
+ new: T
+ old: {}
+ }
+
+export type RealtimePostgresUpdatePayload =
+ RealtimePostgresChangesPayloadBase & {
+ eventType: `${REALTIME_POSTGRES_CHANGES_LISTEN_EVENT.UPDATE}`
+ new: T
+ old: Partial
+ }
+
+export type RealtimePostgresDeletePayload =
+ RealtimePostgresChangesPayloadBase & {
+ eventType: `${REALTIME_POSTGRES_CHANGES_LISTEN_EVENT.DELETE}`
+ new: {}
+ old: Partial
+ }
+
+export type RealtimePostgresChangesPayload =
+ | RealtimePostgresInsertPayload
+ | RealtimePostgresUpdatePayload
+ | RealtimePostgresDeletePayload
+
+export type RealtimePostgresChangesFilter = {
+ /**
+ * The type of database change to listen to.
+ */
+ event: T
+ /**
+ * The database schema to listen to.
+ */
+ schema: string
+ /**
+ * The database table to listen to.
+ */
+ table?: string
+ /**
+ * Receive database changes only when the filter is matched.
+ *
+ * A filter is a `column=operator.value` expression, e.g. `id=eq.1` or
+ * `title=like.%foo%`. See {@link RealtimePostgresChangesFilterOperator} for
+ * the available operators.
+ *
+ * Multiple filters can be combined with commas; they are applied as an `AND`
+ * condition: `filter: 'id=gt.0,id=lt.100'`.
+ *
+ * Any operator can be negated with the `not.` prefix: `filter: 'status=not.in.(draft,archived)'`.
+ *
+ * The server splits conditions on commas outside quotes/parentheses. To
+ * include a reserved character (`,`, `(`, `)`) in a value, wrap it in double
+ * quotes PostgREST-style: `name=eq."a,b"`. The {@link RealtimePostgresFilterBuilder}
+ * does this quoting for you.
+ *
+ * Instead of a raw string you can pass a {@link RealtimePostgresFilterBuilder}
+ * (via `postgresChangesFilter()`) for a type-checked, ergonomic way to compose filters; the
+ * SDK serializes it to a string automatically.
+ */
+ filter?: string | RealtimePostgresFilterBuilder
+ /**
+ * Restrict the change payload to a subset of columns instead of receiving the
+ * full row. Reduces payload size (helpful for large `bytea`/`jsonb` columns)
+ * and the data transferred per event.
+ *
+ * The listed columns must be selectable by the subscribing role.
+ *
+ * @example
+ * channel.on('postgres_changes', {
+ * event: '*',
+ * schema: 'public',
+ * table: 'users',
+ * select: ['id', 'first_name'],
+ * }, (payload) => {
+ * // payload.new only contains { id, first_name }
+ * })
+ */
+ select?: string[]
+}
+
+export type RealtimeChannelSendResponse = 'ok' | 'timed out' | 'error' | (string & {})
+
+/**
+ * Payload of a `system` event emitted by the server.
+ *
+ * Most notably, when a channel is created with `config.broadcast.replication_ready: true`,
+ * the server sends one of these once the Postgres replication connection is ready
+ * (`status: 'ok'`) or fails to become ready in time (`status: 'error'`).
+ */
+export type RealtimeSystemPayload = {
+ /** The extension that produced the message, e.g. `'system'` or `'postgres_changes'`. */
+ extension: 'system' | 'postgres_changes' | (string & {})
+ /** `'ok'` on success, `'error'` on failure. */
+ status: 'ok' | 'error' | (string & {})
+ /** Human-readable description, e.g. `'Replication connection established'`. */
+ message: string
+ /** The channel (sub)topic the message refers to. */
+ channel: string
+}
+
+export enum REALTIME_POSTGRES_CHANGES_LISTEN_EVENT {
+ ALL = '*',
+ INSERT = 'INSERT',
+ UPDATE = 'UPDATE',
+ DELETE = 'DELETE',
+}
+
+export enum REALTIME_LISTEN_TYPES {
+ BROADCAST = 'broadcast',
+ PRESENCE = 'presence',
+ POSTGRES_CHANGES = 'postgres_changes',
+ SYSTEM = 'system',
+}
+
+export enum REALTIME_SUBSCRIBE_STATES {
+ SUBSCRIBED = 'SUBSCRIBED',
+ TIMED_OUT = 'TIMED_OUT',
+ CLOSED = 'CLOSED',
+ CHANNEL_ERROR = 'CHANNEL_ERROR',
+}
+
+export const REALTIME_CHANNEL_STATES = CHANNEL_STATES
+
+type PostgresChangesFilters = {
+ postgres_changes: {
+ id: string
+ event: string
+ schema?: string
+ table?: string
+ filter?: string
+ select?: string[]
+ }[]
+}
+
+/**
+ * The `postgres_changes` filter fields that determine whether the server collapses two
+ * subscriptions into one. `filter` is always the serialized string form by the time it is compared.
+ */
+type PostgresChangesFilterShape = {
+ event?: string
+ schema?: string
+ table?: string
+ filter?: string
+ select?: string[]
+}
+
+type Binding = {
+ type: string
+ filter: { [key: string]: any }
+ callback: ChannelBindingCallback
+ ref: number
+ id?: string
+}
+
+/** A channel is the basic building block of Realtime
+ * and narrows the scope of data flow to subscribed clients.
+ * You can think of a channel as a chatroom where participants are able to see who's online
+ * and send and receive messages.
+ */
+export default class RealtimeChannel {
+ bindings: Record = {}
+ subTopic: string
+ broadcastEndpointURL: string
+ private: boolean
+ presence: RealtimePresence
+ /** @internal */
+ channelAdapter: ChannelAdapter
+
+ get state() {
+ return this.channelAdapter.state
+ }
+
+ set state(state: ChannelState) {
+ this.channelAdapter.state = state
+ }
+
+ get joinedOnce() {
+ return this.channelAdapter.joinedOnce
+ }
+
+ get timeout() {
+ return this.socket.timeout
+ }
+
+ get joinPush() {
+ return this.channelAdapter.joinPush
+ }
+
+ get rejoinTimer(): Timer {
+ return this.channelAdapter.rejoinTimer
+ }
+
+ /**
+ * Creates a channel that can broadcast messages, sync presence, and listen to Postgres changes.
+ *
+ * The topic determines which realtime stream you are subscribing to. Config options let you
+ * enable acknowledgement for broadcasts, presence tracking, or private channels.
+ *
+ * @category Realtime
+ *
+ * @example Using supabase-js (recommended)
+ * ```ts
+ * import { createClient } from '@supabase/supabase-js'
+ *
+ * const supabase = createClient('https://xyzcompany.supabase.co', 'your-publishable-key')
+ * const channel = supabase.channel('room1')
+ * channel
+ * .on('broadcast', { event: 'cursor-pos' }, (payload) => console.log(payload))
+ * .subscribe()
+ * ```
+ *
+ * @example Standalone import for bundle-sensitive environments
+ * ```ts
+ * import RealtimeClient from '@supabase/realtime-js'
+ *
+ * const client = new RealtimeClient('https://xyzcompany.supabase.co/realtime/v1', {
+ * params: { apikey: 'your-publishable-key' },
+ * })
+ * const channel = new RealtimeChannel('realtime:public:messages', { config: {} }, client)
+ * ```
+ */
+ constructor(
+ /** Topic name can be any string. */
+ public topic: string,
+ public params: RealtimeChannelOptions = { config: {} },
+ public socket: RealtimeClient
+ ) {
+ this.subTopic = topic.replace(/^realtime:/i, '')
+ this.params.config = {
+ ...{
+ broadcast: { ack: false, self: false },
+ presence: { key: '', enabled: false },
+ private: false,
+ },
+ ...params.config,
+ }
+
+ this.channelAdapter = new ChannelAdapter(this.socket.socketAdapter, topic, this.params)
+ this.presence = new RealtimePresence(this)
+
+ this._onClose(() => {
+ this.socket._remove(this)
+ })
+
+ this._updateFilterTransform()
+
+ this.broadcastEndpointURL = httpEndpointURL(this.socket.socketAdapter.endPointURL())
+ this.private = this.params.config.private || false
+
+ if (!this.private && this.params.config?.broadcast?.replay) {
+ throw new Error(
+ `tried to use replay on public channel '${this.topic}'. It must be a private channel.`
+ )
+ }
+ }
+
+ /**
+ * Subscribe registers your client with the server.
+ *
+ * The optional `callback` receives a `status` and, on failure, an `err` argument.
+ * Log the full `err` so its `cause`, `name`, and any structured fields aren't hidden
+ * behind `err.message`.
+ *
+ * @category Realtime
+ *
+ * @example Handling errors
+ * ```js
+ * supabase.channel('room1').subscribe((status, err) => {
+ * if (status === 'CHANNEL_ERROR' || status === 'TIMED_OUT') {
+ * // Log the full error: its `cause` often holds the underlying reason.
+ * console.error(status, err)
+ * }
+ * })
+ * ```
+ */
+ subscribe(
+ callback?: (status: REALTIME_SUBSCRIBE_STATES, err?: Error) => void,
+ timeout = this.timeout
+ ): RealtimeChannel {
+ if (!this.socket.isConnected()) {
+ this.socket.connect()
+ }
+ if (this.channelAdapter.isClosed()) {
+ const {
+ config: { broadcast, presence, private: isPrivate },
+ } = this.params
+
+ const postgres_changes = this.bindings.postgres_changes?.map((r) => r.filter) ?? []
+
+ const presence_enabled =
+ (!!this.bindings[REALTIME_LISTEN_TYPES.PRESENCE] &&
+ this.bindings[REALTIME_LISTEN_TYPES.PRESENCE].length > 0) ||
+ this.params.config.presence?.enabled === true
+ const accessTokenPayload: { access_token?: string } = {}
+ const config = {
+ broadcast,
+ presence: { ...presence, enabled: presence_enabled },
+ postgres_changes,
+ private: isPrivate,
+ }
+
+ if (this.socket.accessTokenValue) {
+ accessTokenPayload.access_token = this.socket.accessTokenValue
+ }
+
+ this._onError((reason: unknown) => {
+ callback?.(REALTIME_SUBSCRIBE_STATES.CHANNEL_ERROR, normalizeChannelError(reason))
+ })
+
+ this._onClose(() => callback?.(REALTIME_SUBSCRIBE_STATES.CLOSED))
+
+ this.updateJoinPayload({ ...{ config }, ...accessTokenPayload })
+
+ this._updateFilterMessage()
+
+ this.channelAdapter
+ .subscribe(timeout)
+ .receive('ok', async ({ postgres_changes }: PostgresChangesFilters) => {
+ // Only refresh auth if using callback-based tokens
+ if (!this.socket._isManualToken()) {
+ this.socket.setAuth()
+ }
+ if (postgres_changes === undefined) {
+ callback?.(REALTIME_SUBSCRIBE_STATES.SUBSCRIBED)
+ return
+ }
+
+ this._updatePostgresBindings(postgres_changes, callback)
+ })
+ .receive('error', (error: { [key: string]: any }) => {
+ this.state = CHANNEL_STATES.errored
+ const message = Object.values(error).join(', ') || 'error'
+ callback?.(REALTIME_SUBSCRIBE_STATES.CHANNEL_ERROR, new Error(message, { cause: error }))
+ })
+ .receive('timeout', () => {
+ callback?.(REALTIME_SUBSCRIBE_STATES.TIMED_OUT)
+ })
+ }
+ return this
+ }
+
+ private _updatePostgresBindings(
+ postgres_changes: PostgresChangesFilters['postgres_changes'],
+ callback?: (status: REALTIME_SUBSCRIBE_STATES, err?: Error) => void
+ ) {
+ const clientPostgresBindings = this.bindings.postgres_changes
+ const bindingsLen = clientPostgresBindings?.length ?? 0
+ const newPostgresBindings = []
+
+ for (let i = 0; i < bindingsLen; i++) {
+ const clientPostgresBinding = clientPostgresBindings[i]
+ const {
+ filter: { event, schema, table, filter },
+ } = clientPostgresBinding
+ const serverPostgresFilter = postgres_changes && postgres_changes[i]
+
+ if (
+ serverPostgresFilter &&
+ serverPostgresFilter.event === event &&
+ RealtimeChannel.isFilterValueEqual(serverPostgresFilter.schema, schema) &&
+ RealtimeChannel.isFilterValueEqual(serverPostgresFilter.table, table) &&
+ RealtimeChannel.isFilterValueEqual(serverPostgresFilter.filter, filter)
+ ) {
+ newPostgresBindings.push({
+ ...clientPostgresBinding,
+ id: serverPostgresFilter.id,
+ })
+ } else {
+ this.unsubscribe()
+ this.state = CHANNEL_STATES.errored
+
+ callback?.(
+ REALTIME_SUBSCRIBE_STATES.CHANNEL_ERROR,
+ new Error('mismatch between server and client bindings for postgres changes')
+ )
+ return
+ }
+ }
+
+ this.bindings.postgres_changes = newPostgresBindings
+
+ if (this.state != CHANNEL_STATES.errored && callback) {
+ callback(REALTIME_SUBSCRIBE_STATES.SUBSCRIBED)
+ }
+ }
+
+ /**
+ * Returns the current presence state for this channel.
+ *
+ * The shape is a map keyed by presence key (for example a user id) where each entry contains the
+ * tracked metadata for that user.
+ *
+ * @category Realtime
+ */
+ presenceState(): RealtimePresenceState {
+ return this.presence.state as RealtimePresenceState
+ }
+
+ /**
+ * Sends the supplied payload to the presence tracker so other subscribers can see that this
+ * client is online. Use `untrack` to stop broadcasting presence for the same key.
+ *
+ * Tracking makes this client visible to other subscribers immediately, regardless of this
+ * channel's `config.presence.enabled` setting or whether it has a `presence` listener — that
+ * flag only affects whether *this* client receives presence updates from others (and, on
+ * RLS-protected channels, whether it's authorized to do so).
+ *
+ * @category Realtime
+ */
+ async track(
+ payload: { [key: string]: any },
+ opts: { [key: string]: any } = {}
+ ): Promise {
+ return await this.send(
+ {
+ type: 'presence',
+ event: 'track',
+ payload,
+ },
+ opts
+ )
+ }
+
+ /**
+ * Removes the current presence state for this client.
+ *
+ * @category Realtime
+ */
+ async untrack(opts: { [key: string]: any } = {}): Promise {
+ return await this.send(
+ {
+ type: 'presence',
+ event: 'untrack',
+ },
+ opts
+ )
+ }
+
+ /**
+ * Listen for presence events on this channel — when peers join, leave, or
+ * sync presence state.
+ */
+ on(
+ type: `${REALTIME_LISTEN_TYPES.PRESENCE}`,
+ filter: { event: `${REALTIME_PRESENCE_LISTEN_EVENTS.SYNC}` },
+ callback: () => void
+ ): RealtimeChannel
+ on(
+ type: `${REALTIME_LISTEN_TYPES.PRESENCE}`,
+ filter: { event: `${REALTIME_PRESENCE_LISTEN_EVENTS.JOIN}` },
+ callback: (payload: RealtimePresenceJoinPayload) => void
+ ): RealtimeChannel
+ on(
+ type: `${REALTIME_LISTEN_TYPES.PRESENCE}`,
+ filter: { event: `${REALTIME_PRESENCE_LISTEN_EVENTS.LEAVE}` },
+ callback: (payload: RealtimePresenceLeavePayload) => void
+ ): RealtimeChannel
+ on(
+ type: `${REALTIME_LISTEN_TYPES.PRESENCE}`,
+ filter: { event: '*' },
+ callback: (payload?: RealtimePresenceJoinPayload | RealtimePresenceLeavePayload) => void
+ ): RealtimeChannel
+ /**
+ * Listen for Postgres database changes (insert / update / delete) streamed
+ * over this channel.
+ */
+ on(
+ type: `${REALTIME_LISTEN_TYPES.POSTGRES_CHANGES}`,
+ filter: RealtimePostgresChangesFilter<`${REALTIME_POSTGRES_CHANGES_LISTEN_EVENT.ALL}`>,
+ callback: (payload: RealtimePostgresChangesPayload) => void
+ ): RealtimeChannel
+ on(
+ type: `${REALTIME_LISTEN_TYPES.POSTGRES_CHANGES}`,
+ filter: RealtimePostgresChangesFilter<`${REALTIME_POSTGRES_CHANGES_LISTEN_EVENT.INSERT}`>,
+ callback: (payload: RealtimePostgresInsertPayload) => void
+ ): RealtimeChannel
+ on(
+ type: `${REALTIME_LISTEN_TYPES.POSTGRES_CHANGES}`,
+ filter: RealtimePostgresChangesFilter<`${REALTIME_POSTGRES_CHANGES_LISTEN_EVENT.UPDATE}`>,
+ callback: (payload: RealtimePostgresUpdatePayload) => void
+ ): RealtimeChannel
+ on(
+ type: `${REALTIME_LISTEN_TYPES.POSTGRES_CHANGES}`,
+ filter: RealtimePostgresChangesFilter<`${REALTIME_POSTGRES_CHANGES_LISTEN_EVENT.DELETE}`>,
+ callback: (payload: RealtimePostgresDeletePayload) => void
+ ): RealtimeChannel
+ on(
+ type: `${REALTIME_LISTEN_TYPES.POSTGRES_CHANGES}`,
+ filter: RealtimePostgresChangesFilter<`${REALTIME_POSTGRES_CHANGES_LISTEN_EVENT}`>,
+ callback: (payload: RealtimePostgresChangesPayload) => void
+ ): RealtimeChannel
+ /**
+ * Listen for broadcast messages sent on this channel.
+ *
+ * @param type One of "broadcast", "presence", or "postgres_changes".
+ * @param filter Custom object specific to the Realtime feature detailing which payloads to receive.
+ * @param callback Function to be invoked when event handler is triggered.
+ */
+ on(
+ type: `${REALTIME_LISTEN_TYPES.BROADCAST}`,
+ filter: { event: string },
+ callback: (payload: {
+ type: `${REALTIME_LISTEN_TYPES.BROADCAST}`
+ event: string
+ meta?: {
+ replayed?: boolean
+ id: string
+ }
+ [key: string]: any
+ }) => void
+ ): RealtimeChannel
+ on(
+ type: `${REALTIME_LISTEN_TYPES.BROADCAST}`,
+ filter: { event: string },
+ callback: (payload: {
+ type: `${REALTIME_LISTEN_TYPES.BROADCAST}`
+ event: string
+ meta?: {
+ replayed?: boolean
+ id: string
+ }
+ payload: T
+ }) => void
+ ): RealtimeChannel
+ on>(
+ type: `${REALTIME_LISTEN_TYPES.BROADCAST}`,
+ filter: { event: REALTIME_POSTGRES_CHANGES_LISTEN_EVENT.ALL },
+ callback: (payload: {
+ type: `${REALTIME_LISTEN_TYPES.BROADCAST}`
+ event: REALTIME_POSTGRES_CHANGES_LISTEN_EVENT.ALL
+ payload: RealtimeBroadcastPayload
+ }) => void
+ ): RealtimeChannel
+ on(
+ type: `${REALTIME_LISTEN_TYPES.BROADCAST}`,
+ filter: { event: REALTIME_POSTGRES_CHANGES_LISTEN_EVENT.INSERT },
+ callback: (payload: {
+ type: `${REALTIME_LISTEN_TYPES.BROADCAST}`
+ event: REALTIME_POSTGRES_CHANGES_LISTEN_EVENT.INSERT
+ payload: RealtimeBroadcastInsertPayload
+ }) => void
+ ): RealtimeChannel
+ on(
+ type: `${REALTIME_LISTEN_TYPES.BROADCAST}`,
+ filter: { event: REALTIME_POSTGRES_CHANGES_LISTEN_EVENT.UPDATE },
+ callback: (payload: {
+ type: `${REALTIME_LISTEN_TYPES.BROADCAST}`
+ event: REALTIME_POSTGRES_CHANGES_LISTEN_EVENT.UPDATE
+ payload: RealtimeBroadcastUpdatePayload
+ }) => void
+ ): RealtimeChannel
+ on(
+ type: `${REALTIME_LISTEN_TYPES.BROADCAST}`,
+ filter: { event: REALTIME_POSTGRES_CHANGES_LISTEN_EVENT.DELETE },
+ callback: (payload: {
+ type: `${REALTIME_LISTEN_TYPES.BROADCAST}`
+ event: REALTIME_POSTGRES_CHANGES_LISTEN_EVENT.DELETE
+ payload: RealtimeBroadcastDeletePayload
+ }) => void
+ ): RealtimeChannel
+ /**
+ * Listen for `system` events on this channel.
+ *
+ * The payload follows the {@link RealtimeSystemPayload} shape. Opt in to the replication-ready
+ * notification with `config.broadcast.replication_ready: true` when creating the channel, then
+ * watch for `payload.status === 'ok'` to know the Postgres replication connection is ready.
+ *
+ * @example Know when the replication connection is ready
+ * ```js
+ * const channel = supabase.channel('room1', {
+ * config: { broadcast: { replication_ready: true } },
+ * })
+ *
+ * channel
+ * .on('postgres_changes', { event: '*', schema: 'public', table: 'messages' }, (payload) => {
+ * console.log('Change received!', payload)
+ * })
+ * .on('system', {}, (payload) => {
+ * if (payload.extension === 'system' && payload.status === 'ok') {
+ * console.log('Replication connection is ready:', payload.message)
+ * }
+ * })
+ * .subscribe()
+ * ```
+ */
+ on(
+ type: `${REALTIME_LISTEN_TYPES.SYSTEM}`,
+ filter: {},
+ callback: (payload: any) => void
+ ): RealtimeChannel
+ /**
+ * Listen to realtime events on this channel.
+ * @category Realtime
+ *
+ * @remarks
+ * - By default, Broadcast and Presence are enabled for all projects.
+ * - By default, listening to database changes is disabled for new projects due to database performance and security concerns. You can turn it on by managing Realtime's [replication](/docs/guides/api#realtime-api-overview).
+ * - You can receive the "previous" data for updates and deletes by setting the table's `REPLICA IDENTITY` to `FULL` (e.g., `ALTER TABLE your_table REPLICA IDENTITY FULL;`).
+ * - Row level security is not applied to delete statements. When RLS is enabled and replica identity is set to full, only the primary key is sent to clients.
+ *
+ * @example Listen to broadcast messages
+ * ```js
+ * const channel = supabase.channel("room1")
+ *
+ * channel.on("broadcast", { event: "cursor-pos" }, (payload) => {
+ * console.log("Cursor position received!", payload);
+ * }).subscribe((status) => {
+ * if (status === "SUBSCRIBED") {
+ * channel.send({
+ * type: "broadcast",
+ * event: "cursor-pos",
+ * payload: { x: Math.random(), y: Math.random() },
+ * });
+ * }
+ * });
+ * ```
+ *
+ * @example Listen to presence sync
+ * ```js
+ * const channel = supabase.channel('room1')
+ * channel
+ * .on('presence', { event: 'sync' }, () => {
+ * console.log('Synced presence state: ', channel.presenceState())
+ * })
+ * .subscribe(async (status) => {
+ * if (status === 'SUBSCRIBED') {
+ * await channel.track({ online_at: new Date().toISOString() })
+ * }
+ * })
+ * ```
+ *
+ * @example Listen to presence join
+ * ```js
+ * const channel = supabase.channel('room1')
+ * channel
+ * .on('presence', { event: 'join' }, ({ newPresences }) => {
+ * console.log('Newly joined presences: ', newPresences)
+ * })
+ * .subscribe(async (status) => {
+ * if (status === 'SUBSCRIBED') {
+ * await channel.track({ online_at: new Date().toISOString() })
+ * }
+ * })
+ * ```
+ *
+ * @example Listen to presence leave
+ * ```js
+ * const channel = supabase.channel('room1')
+ * channel
+ * .on('presence', { event: 'leave' }, ({ leftPresences }) => {
+ * console.log('Newly left presences: ', leftPresences)
+ * })
+ * .subscribe(async (status) => {
+ * if (status === 'SUBSCRIBED') {
+ * await channel.track({ online_at: new Date().toISOString() })
+ * await channel.untrack()
+ * }
+ * })
+ * ```
+ *
+ * Registering the same `postgres_changes` filter more than once on a channel is a no-op: the
+ * duplicate is ignored and an error is logged, since the server only ever creates one
+ * subscription per distinct filter.
+ *
+ * @example Listen to all database changes
+ * ```js
+ * supabase
+ * .channel('room1')
+ * .on('postgres_changes', { event: '*', schema: '*' }, payload => {
+ * console.log('Change received!', payload)
+ * })
+ * .subscribe()
+ * ```
+ *
+ * @example Listen to a specific table
+ * ```js
+ * supabase
+ * .channel('room1')
+ * .on('postgres_changes', { event: '*', schema: 'public', table: 'countries' }, payload => {
+ * console.log('Change received!', payload)
+ * })
+ * .subscribe()
+ * ```
+ *
+ * @example Listen to inserts
+ * ```js
+ * supabase
+ * .channel('room1')
+ * .on('postgres_changes', { event: 'INSERT', schema: 'public', table: 'countries' }, payload => {
+ * console.log('Change received!', payload)
+ * })
+ * .subscribe()
+ * ```
+ *
+ * @exampleDescription Listen to updates
+ * By default, Supabase will send only the updated record. If you want to receive the previous values as well you can
+ * enable full replication for the table you are listening to:
+ *
+ * ```sql
+ * alter table "your_table" replica identity full;
+ * ```
+ *
+ * @example Listen to updates
+ * ```js
+ * supabase
+ * .channel('room1')
+ * .on('postgres_changes', { event: 'UPDATE', schema: 'public', table: 'countries' }, payload => {
+ * console.log('Change received!', payload)
+ * })
+ * .subscribe()
+ * ```
+ *
+ * @exampleDescription Listen to deletes
+ * By default, Supabase does not send deleted records. If you want to receive the deleted record you can
+ * enable full replication for the table you are listening to:
+ *
+ * ```sql
+ * alter table "your_table" replica identity full;
+ * ```
+ *
+ * @example Listen to deletes
+ * ```js
+ * supabase
+ * .channel('room1')
+ * .on('postgres_changes', { event: 'DELETE', schema: 'public', table: 'countries' }, payload => {
+ * console.log('Change received!', payload)
+ * })
+ * .subscribe()
+ * ```
+ *
+ * @exampleDescription Listen to multiple events
+ * You can chain listeners if you want to listen to multiple events for each table.
+ *
+ * @example Listen to multiple events
+ * ```js
+ * supabase
+ * .channel('room1')
+ * .on('postgres_changes', { event: 'INSERT', schema: 'public', table: 'countries' }, handleRecordInserted)
+ * .on('postgres_changes', { event: 'DELETE', schema: 'public', table: 'countries' }, handleRecordDeleted)
+ * .subscribe()
+ * ```
+ *
+ * @exampleDescription Listen to row level changes
+ * You can listen to individual rows using the format `{table}:{col}=eq.{val}` - where `{col}` is the column name, and `{val}` is the value which you want to match.
+ *
+ * @example Listen to row level changes
+ * ```js
+ * supabase
+ * .channel('room1')
+ * .on('postgres_changes', { event: 'UPDATE', schema: 'public', table: 'countries', filter: 'id=eq.200' }, handleRecordUpdated)
+ * .subscribe()
+ * ```
+ */
+ on(
+ type: `${REALTIME_LISTEN_TYPES}`,
+ filter: { event: string; [key: string]: any },
+ callback: (payload: any) => void
+ ): RealtimeChannel {
+ const stateCheck = this.channelAdapter.isJoined() || this.channelAdapter.isJoining()
+ const typeCheck =
+ type === REALTIME_LISTEN_TYPES.PRESENCE || type === REALTIME_LISTEN_TYPES.POSTGRES_CHANGES
+
+ if (stateCheck && typeCheck) {
+ this.socket.log(
+ 'channel',
+ `cannot add \`${type}\` callbacks for ${this.topic} after \`subscribe()\`.`
+ )
+ throw new Error(`cannot add \`${type}\` callbacks for ${this.topic} after \`subscribe()\`.`)
+ }
+ return this._on(type, filter, callback)
+ }
+ /**
+ * Sends a broadcast message explicitly via REST API.
+ *
+ * This method always uses the REST API endpoint regardless of WebSocket connection state.
+ * Useful when you want to guarantee REST delivery or when gradually migrating from implicit REST fallback.
+ *
+ * Payloads that are `ArrayBuffer` or `ArrayBufferView` (e.g. `Uint8Array`) are sent as
+ * `application/octet-stream`; all other payloads are JSON-encoded.
+ *
+ * @param event The name of the broadcast event
+ * @param payload Payload to be sent (required)
+ * @param opts Options including timeout
+ * @returns Promise resolving to object with success status, and error details if failed
+ *
+ * @category Realtime
+ */
+ async httpSend(
+ event: string,
+ payload: any,
+ opts: { timeout?: number } = {}
+ ): Promise<{ success: true } | { success: false; status: number; error: string }> {
+ if (payload === undefined || payload === null) {
+ return Promise.reject(new Error('Payload is required for httpSend()'))
+ }
+
+ const isBinary = payload instanceof ArrayBuffer || ArrayBuffer.isView(payload)
+
+ const headers: Record = {
+ apikey: this.socket.apiKey ? this.socket.apiKey : '',
+ 'Content-Type': isBinary ? 'application/octet-stream' : 'application/json',
+ }
+
+ if (this.socket.accessTokenValue) {
+ headers['Authorization'] = `Bearer ${this.socket.accessTokenValue}`
+ }
+
+ const url = new URL(this.broadcastEndpointURL)
+ url.pathname += `/${encodeURIComponent(this.subTopic)}/events/${encodeURIComponent(event)}`
+ if (this.private) {
+ url.searchParams.set('private', 'true')
+ }
+
+ const options = {
+ method: 'POST',
+ headers,
+ body: isBinary ? (payload as ArrayBuffer | ArrayBufferView) : JSON.stringify(payload),
+ }
+
+ const response = await this._fetchWithTimeout(
+ url.toString(),
+ options,
+ opts.timeout ?? this.timeout
+ )
+
+ if (response.status === 202) {
+ return { success: true }
+ }
+
+ if (response.status === 404) {
+ return Promise.reject(
+ new Error(
+ 'httpSend() requires Realtime server v2.97.0 or newer; the endpoint returned 404. ' +
+ 'Update your Supabase CLI to a recent version, or upgrade the Realtime server in your self-hosted setup. ' +
+ 'See https://github.com/supabase/supabase-js/blob/master/packages/core/realtime-js/migrations/httpsend-server-version.md'
+ )
+ )
+ }
+
+ let errorMessage = response.statusText
+ try {
+ const errorBody = await response.json()
+ errorMessage = errorBody.error || errorBody.message || errorMessage
+ } catch {}
+
+ return Promise.reject(new Error(errorMessage))
+ }
+
+ /**
+ * Sends a message into the channel.
+ *
+ * @param args Arguments to send to channel
+ * @param args.type The type of event to send
+ * @param args.event The name of the event being sent
+ * @param args.payload Payload to be sent
+ * @param opts Options to be used during the send process
+ *
+ * @category Realtime
+ *
+ * @remarks
+ * - When using REST you don't need to subscribe to the channel
+ * - REST calls are only available from 2.37.0 onwards
+ * - If you create a channel only to send a REST broadcast, remove it from
+ * the client when the send completes
+ *
+ * @example Send a message via websocket
+ * ```js
+ * const channel = supabase.channel('room1')
+ *
+ * channel.subscribe((status) => {
+ * if (status === 'SUBSCRIBED') {
+ * channel.send({
+ * type: 'broadcast',
+ * event: 'cursor-pos',
+ * payload: { x: Math.random(), y: Math.random() },
+ * })
+ * }
+ * })
+ * ```
+ *
+ * @exampleResponse Send a message via websocket
+ * ```js
+ * ok | timed out | error
+ * ```
+ *
+ * @example Send a message via REST
+ * ```js
+ * const channel = supabase.channel('room1')
+ *
+ * try {
+ * await channel.httpSend('cursor-pos', { x: Math.random(), y: Math.random() })
+ * } finally {
+ * await supabase.removeChannel(channel)
+ * }
+ * ```
+ */
+ async send(
+ args: {
+ type: 'broadcast' | 'presence' | 'postgres_changes'
+ event: string
+ payload?: any
+ [key: string]: any
+ },
+ opts: { [key: string]: any } = {}
+ ): Promise {
+ if (!this.channelAdapter.canPush() && args.type === 'broadcast') {
+ console.warn(
+ 'Realtime send() is automatically falling back to REST API. ' +
+ 'This behavior will be deprecated in the future. ' +
+ 'Please use httpSend() explicitly for REST delivery.'
+ )
+
+ const { event, payload: endpoint_payload } = args
+ const headers: Record = {
+ apikey: this.socket.apiKey ? this.socket.apiKey : '',
+ 'Content-Type': 'application/json',
+ }
+
+ if (this.socket.accessTokenValue) {
+ headers['Authorization'] = `Bearer ${this.socket.accessTokenValue}`
+ }
+
+ const options = {
+ method: 'POST',
+ headers,
+ body: JSON.stringify({
+ messages: [
+ {
+ topic: this.subTopic,
+ event,
+ payload: endpoint_payload,
+ private: this.private,
+ },
+ ],
+ }),
+ }
+
+ try {
+ const response = await this._fetchWithTimeout(
+ this.broadcastEndpointURL,
+ options,
+ opts.timeout ?? this.timeout
+ )
+
+ await response.body?.cancel()
+ return response.ok ? 'ok' : 'error'
+ } catch (error) {
+ if (error instanceof Error && error.name === 'AbortError') {
+ return 'timed out'
+ } else {
+ return 'error'
+ }
+ }
+ } else {
+ return new Promise((resolve) => {
+ const push = this.channelAdapter.push(args.type, args, opts.timeout || this.timeout)
+
+ if (args.type === 'broadcast' && !this.params?.config?.broadcast?.ack) {
+ resolve('ok')
+ }
+
+ push.receive('ok', () => resolve('ok'))
+ push.receive('error', () => resolve('error'))
+ push.receive('timeout', () => resolve('timed out'))
+ })
+ }
+ }
+
+ /**
+ * Updates the payload that will be sent the next time the channel joins (reconnects).
+ * Useful for rotating access tokens or updating config without re-creating the channel.
+ *
+ * @category Realtime
+ */
+ updateJoinPayload(payload: Record) {
+ this.channelAdapter.updateJoinPayload(payload)
+ }
+
+ /**
+ * Leaves the channel.
+ *
+ * Unsubscribes from server events, and instructs channel to terminate on server.
+ * Triggers onClose() hooks.
+ *
+ * To receive leave acknowledgements, use the a `receive` hook to bind to the server ack, ie:
+ * channel.unsubscribe().receive("ok", () => alert("left!") )
+ *
+ * @category Realtime
+ */
+ async unsubscribe(timeout = this.timeout) {
+ return new Promise((resolve) => {
+ this.channelAdapter
+ .unsubscribe(timeout)
+ .receive('ok', () => resolve('ok'))
+ .receive('timeout', () => resolve('timed out'))
+ .receive('error', () => resolve('error'))
+ })
+ }
+
+ /**
+ * Destroys and stops related timers.
+ *
+ * @category Realtime
+ */
+ teardown() {
+ this.channelAdapter.teardown()
+ }
+
+ /** @internal */
+ async _fetchWithTimeout(url: string, options: { [key: string]: any }, timeout: number) {
+ const controller = new AbortController()
+ const id = setTimeout(() => controller.abort(), timeout)
+
+ const response = await this.socket.fetch(url, {
+ ...options,
+ signal: controller.signal,
+ })
+
+ clearTimeout(id)
+
+ return response
+ }
+
+ /** @internal */
+ _on(type: string, filter: { [key: string]: any }, callback: ChannelBindingCallback) {
+ const typeLower = type.toLocaleLowerCase()
+
+ // Serialize a postgres_changes filter builder into its string form so the
+ // rest of the pipeline (join payload, server binding match) sees a string.
+ // Duck-type `build()` in addition to `instanceof` so a builder constructed
+ // against a duplicate copy of the package (separate module realm) still works.
+ const filterValue = filter?.filter
+ if (
+ filterValue instanceof RealtimePostgresFilterBuilder ||
+ (typeof filterValue === 'object' &&
+ filterValue !== null &&
+ typeof (filterValue as { build?: unknown }).build === 'function')
+ ) {
+ filter = { ...filter, filter: (filterValue as RealtimePostgresFilterBuilder).build() }
+ }
+
+ // The server collapses identical postgres_changes filters, so keeping a duplicate here would
+ // desync the client and server binding lists and make `subscribe()` fail with a mismatch.
+ if (typeLower === REALTIME_LISTEN_TYPES.POSTGRES_CHANGES) {
+ const duplicate = this.bindings[typeLower]?.find((bind) =>
+ RealtimeChannel.isSamePostgresFilter(bind.filter, filter)
+ )
+
+ if (duplicate) {
+ this.socket.log(
+ 'error',
+ `duplicate \`postgres_changes\` binding for ${this.topic} ignored`,
+ filter
+ )
+ return this
+ }
+ }
+
+ const ref = this.channelAdapter.on(type, callback)
+
+ const binding: Binding = {
+ type: typeLower,
+ filter: filter,
+ callback: callback,
+ ref: ref,
+ }
+
+ if (this.bindings[typeLower]) {
+ this.bindings[typeLower].push(binding)
+ } else {
+ this.bindings[typeLower] = [binding]
+ }
+
+ this._updateFilterMessage()
+
+ return this
+ }
+
+ /**
+ * Registers a callback that will be executed when the channel closes.
+ *
+ * @internal
+ */
+ private _onClose(callback: ChannelBindingCallback) {
+ this.channelAdapter.onClose(callback)
+ }
+
+ /**
+ * Registers a callback that will be executed when the channel encounteres an error.
+ *
+ * @internal
+ */
+ private _onError(callback: ChannelOnErrorCallback) {
+ this.channelAdapter.onError(callback)
+ }
+
+ /** @internal */
+ private _updateFilterMessage() {
+ this.channelAdapter.updateFilterBindings((binding, payload: any, ref) => {
+ const typeLower = binding.event.toLocaleLowerCase()
+
+ if (this._notThisChannelEvent(typeLower, ref)) {
+ return false
+ }
+
+ const bind = this.bindings[typeLower]?.find((bind) => bind.ref === binding.ref)
+
+ if (!bind) {
+ return true
+ }
+
+ if (['broadcast', 'presence', 'postgres_changes'].includes(typeLower)) {
+ if ('id' in bind) {
+ const bindId = bind.id
+ const bindEvent = bind.filter?.event
+ return (
+ bindId &&
+ payload.ids?.includes(bindId) &&
+ (bindEvent === '*' ||
+ bindEvent?.toLocaleLowerCase() === payload.data?.type.toLocaleLowerCase())
+ )
+ } else {
+ const bindEvent = bind?.filter?.event?.toLocaleLowerCase()
+ return bindEvent === '*' || bindEvent === payload?.event?.toLocaleLowerCase()
+ }
+ } else {
+ return bind.type.toLocaleLowerCase() === typeLower
+ }
+ })
+ }
+
+ /** @internal */
+ private _notThisChannelEvent(event: string, ref?: string | null) {
+ const { close, error, leave, join } = CHANNEL_EVENTS
+ const events: string[] = [close, error, leave, join]
+ return ref && events.includes(event) && ref !== this.joinPush.ref
+ }
+
+ /** @internal */
+ private _updateFilterTransform() {
+ this.channelAdapter.updatePayloadTransform((event, payload: any, ref) => {
+ if (typeof payload === 'object' && 'ids' in payload) {
+ const postgresChanges = payload.data
+ const { schema, table, commit_timestamp, type, errors } = postgresChanges
+ const enrichedPayload = {
+ schema: schema,
+ table: table,
+ commit_timestamp: commit_timestamp,
+ eventType: type,
+ new: {},
+ old: {},
+ errors: errors,
+ }
+ return {
+ ...enrichedPayload,
+ ...this._getPayloadRecords(postgresChanges),
+ }
+ }
+
+ return payload
+ })
+ }
+
+ copyBindings(other: RealtimeChannel) {
+ if (this.joinedOnce) {
+ throw new Error('cannot copy bindings into joined channel')
+ }
+ for (const kind in other.bindings) {
+ for (const binding of other.bindings[kind]) {
+ this._on(binding.type, binding.filter, binding.callback)
+ }
+ }
+ }
+
+ /**
+ * Compares two optional filter values for equality.
+ * Treats undefined, null, and empty string as equivalent empty values.
+ * @internal
+ */
+ private static isFilterValueEqual(
+ serverValue: string | undefined | null,
+ clientValue: string | undefined
+ ): boolean {
+ const normalizedServer = serverValue ?? undefined
+ const normalizedClient = clientValue ?? undefined
+ return normalizedServer === normalizedClient
+ }
+
+ /**
+ * Two `postgres_changes` filters are the same when the server would collapse them into a single
+ * subscription.
+ * @internal
+ */
+ private static isSamePostgresFilter(
+ a: PostgresChangesFilterShape,
+ b: PostgresChangesFilterShape
+ ): boolean {
+ const selectA = a?.select?.join() ?? undefined
+ const selectB = b?.select?.join() ?? undefined
+
+ return (
+ a?.event === b?.event &&
+ RealtimeChannel.isFilterValueEqual(a?.schema, b?.schema) &&
+ RealtimeChannel.isFilterValueEqual(a?.table, b?.table) &&
+ RealtimeChannel.isFilterValueEqual(a?.filter, b?.filter) &&
+ selectA === selectB
+ )
+ }
+
+ /** @internal */
+ private _getPayloadRecords(payload: any) {
+ const records = {
+ new: {},
+ old: {},
+ }
+
+ if (payload.type === 'INSERT' || payload.type === 'UPDATE') {
+ records.new = Transformers.convertChangeData(payload.columns, payload.record)
+ }
+
+ if (payload.type === 'UPDATE' || payload.type === 'DELETE') {
+ records.old = Transformers.convertChangeData(payload.columns, payload.old_record)
+ }
+
+ return records
+ }
+}
diff --git a/node_modules/@supabase/realtime-js/src/RealtimeClient.ts b/node_modules/@supabase/realtime-js/src/RealtimeClient.ts
new file mode 100644
index 0000000000000000000000000000000000000000..73ffd9180c4640132abe3ee7998bb921e6a9eab3
--- /dev/null
+++ b/node_modules/@supabase/realtime-js/src/RealtimeClient.ts
@@ -0,0 +1,867 @@
+import WebSocketFactory, { WebSocketLike } from './lib/websocket-factory'
+
+import {
+ CHANNEL_EVENTS,
+ CONNECTION_STATE,
+ DEFAULT_VERSION,
+ DEFAULT_TIMEOUT,
+ DEFAULT_VSN,
+ VSN_1_0_0,
+ VSN_2_0_0,
+} from './lib/constants'
+
+import Serializer from './lib/serializer'
+import { httpEndpointURL } from './lib/transformers'
+import RealtimeChannel from './RealtimeChannel'
+import type { RealtimeChannelOptions } from './RealtimeChannel'
+import SocketAdapter from './phoenix/socketAdapter'
+import type {
+ Message,
+ SocketOptions,
+ HeartbeatCallback,
+ Encode,
+ Decode,
+ Timer,
+ Vsn,
+} from './phoenix/types'
+
+type Fetch = typeof fetch
+
+export type LogLevel = 'info' | 'warn' | 'error' | (string & {})
+
+export type RealtimeMessage = {
+ topic: string
+ event: string
+ payload: any
+ ref: string
+ join_ref?: string
+}
+
+export type RealtimeRemoveChannelResponse = 'ok' | 'timed out' | 'error' | (string & {})
+export type HeartbeatStatus = 'sent' | 'ok' | 'error' | 'timeout' | 'disconnected' | (string & {})
+export type HeartbeatTimer = ReturnType | undefined
+
+// Connection-related constants
+const CONNECTION_TIMEOUTS = {
+ HEARTBEAT_INTERVAL: 25000,
+ RECONNECT_DELAY: 10,
+ HEARTBEAT_TIMEOUT_FALLBACK: 100,
+} as const
+
+const RECONNECT_INTERVALS = [1000, 2000, 5000, 10000] as const
+const DEFAULT_RECONNECT_FALLBACK = 10000
+
+/**
+ * Minimal WebSocket constructor interface that RealtimeClient can work with.
+ * Supply a compatible implementation (native WebSocket, `ws`, etc) when running outside the browser.
+ */
+export interface WebSocketLikeConstructor {
+ new (address: string | URL, subprotocols?: string | string[] | undefined): WebSocketLike
+ // Allow additional properties that may exist on WebSocket constructors
+ [key: string]: any
+}
+
+export type RealtimeClientOptions = {
+ transport?: WebSocketLikeConstructor
+ timeout?: number
+ heartbeatIntervalMs?: number
+ heartbeatCallback?: (status: HeartbeatStatus, latency?: number) => void
+ vsn?: string
+ logger?: (kind: string, msg: string, data?: any) => void
+ encode?: Encode
+ decode?: Decode
+ reconnectAfterMs?: (tries: number) => number
+ headers?: { [key: string]: string }
+ params?: { [key: string]: any }
+ //Deprecated: Use it in favour of correct casing `logLevel`
+ log_level?: LogLevel
+ logLevel?: LogLevel
+ fetch?: Fetch
+ worker?: boolean
+ workerUrl?: string
+ accessToken?: () => Promise
+ disconnectOnEmptyChannelsAfterMs?: number
+ /**
+ * Storage compatible object used by the underlying socket for longpoll fallback history.
+ * Provide a custom implementation in environments where reading `globalThis.sessionStorage`
+ * throws (sandboxed iframes, in-app webviews, "block third-party storage" privacy modes).
+ * Defaults to `globalThis.sessionStorage` when accessible, otherwise an in-memory store.
+ */
+ sessionStorage?: Storage
+}
+
+function createMemorySessionStorage(): Storage {
+ const store = new Map()
+ return {
+ get length() {
+ return store.size
+ },
+ clear() {
+ store.clear()
+ },
+ getItem(key: string) {
+ return store.has(key) ? (store.get(key) as string) : null
+ },
+ key(index: number) {
+ return Array.from(store.keys())[index] ?? null
+ },
+ removeItem(key: string) {
+ store.delete(key)
+ },
+ setItem(key: string, value: string) {
+ store.set(key, String(value))
+ },
+ }
+}
+
+function resolveSessionStorage(): Storage {
+ try {
+ if (typeof globalThis !== 'undefined' && globalThis.sessionStorage) {
+ return globalThis.sessionStorage
+ }
+ } catch {
+ // Property access on `sessionStorage` itself throws in restricted-storage browsers.
+ }
+ return createMemorySessionStorage()
+}
+
+const WORKER_SCRIPT = `
+ addEventListener("message", (e) => {
+ if (e.data.event === "start") {
+ setInterval(() => postMessage({ event: "keepAlive" }), e.data.interval);
+ }
+ });`
+
+export default class RealtimeClient {
+ /** @internal */
+ socketAdapter: SocketAdapter
+ channels: RealtimeChannel[] = new Array()
+
+ accessTokenValue: string | null = null
+ accessToken: (() => Promise) | null = null
+ apiKey: string | null = null
+
+ httpEndpoint: string = ''
+ /** @deprecated headers cannot be set on websocket connections */
+ headers?: { [key: string]: string } = {}
+ params?: { [key: string]: string } = {}
+
+ ref: number = 0
+
+ logLevel?: LogLevel
+
+ fetch: Fetch
+ worker?: boolean
+ workerUrl?: string
+ workerRef?: Worker
+
+ serializer: Serializer = new Serializer()
+
+ get endPoint() {
+ return this.socketAdapter.endPoint
+ }
+
+ get timeout() {
+ return this.socketAdapter.timeout
+ }
+
+ get transport() {
+ return this.socketAdapter.transport
+ }
+
+ get heartbeatCallback() {
+ return this.socketAdapter.heartbeatCallback
+ }
+
+ get heartbeatIntervalMs() {
+ return this.socketAdapter.heartbeatIntervalMs
+ }
+
+ get heartbeatTimer() {
+ if (this.worker) {
+ return this._workerHeartbeatTimer
+ }
+ return this.socketAdapter.heartbeatTimer
+ }
+
+ get pendingHeartbeatRef() {
+ if (this.worker) {
+ return this._pendingWorkerHeartbeatRef
+ }
+ return this.socketAdapter.pendingHeartbeatRef
+ }
+
+ get reconnectTimer(): Timer {
+ return this.socketAdapter.reconnectTimer
+ }
+
+ get vsn(): Vsn {
+ return this.socketAdapter.vsn
+ }
+
+ get encode() {
+ return this.socketAdapter.encode
+ }
+
+ get decode() {
+ return this.socketAdapter.decode
+ }
+
+ get reconnectAfterMs() {
+ return this.socketAdapter.reconnectAfterMs
+ }
+
+ get sendBuffer() {
+ return this.socketAdapter.sendBuffer
+ }
+
+ get stateChangeCallbacks(): {
+ open: [string, Function][]
+ close: [string, Function][]
+ error: [string, Function][]
+ message: [string, Function][]
+ } {
+ return this.socketAdapter.stateChangeCallbacks
+ }
+
+ private _manuallySetToken: boolean = false
+ private _authPromise: Promise | null = null
+ private _authGeneration: number = 0
+ private _workerHeartbeatTimer: HeartbeatTimer = undefined
+ private _pendingWorkerHeartbeatRef: string | null = null
+ private _pendingDisconnectTimer: ReturnType | null = null
+ private _disconnectOnEmptyChannelsAfterMs: number = 0
+
+ /**
+ * Initializes the Socket.
+ *
+ * @param endPoint The string WebSocket endpoint, ie, "ws://example.com/socket", "wss://example.com", "/socket" (inherited host & protocol)
+ * @param options.transport The Websocket Transport, for example WebSocket. This can be a custom implementation
+ * @param options.timeout The default timeout in milliseconds to trigger push timeouts.
+ * @param options.params The optional params to pass when connecting.
+ * @param options.headers Deprecated: headers cannot be set on websocket connections and this option will be removed in the future.
+ * @param options.heartbeatIntervalMs The millisec interval to send a heartbeat message.
+ * @param options.heartbeatCallback The optional function to handle heartbeat status and latency.
+ * @param options.logger The optional function for specialized logging, ie: logger: (kind, msg, data) => { console.log(`${kind}: ${msg}`, data) }
+ * @param options.logLevel Sets the log level for Realtime
+ * @param options.encode The function to encode outgoing messages. Defaults to JSON: (payload, callback) => callback(JSON.stringify(payload))
+ * @param options.decode The function to decode incoming messages. Defaults to Serializer's decode.
+ * @param options.reconnectAfterMs he optional function that returns the millsec reconnect interval. Defaults to stepped backoff off.
+ * @param options.worker Use Web Worker to set a side flow. Defaults to false.
+ * @param options.workerUrl The URL of the worker script. Defaults to https://realtime.supabase.com/worker.js that includes a heartbeat event call to keep the connection alive.
+ * @param options.vsn The protocol version to use when connecting. Supported versions are "1.0.0" and "2.0.0". Defaults to "2.0.0".
+ *
+ * @category Realtime
+ *
+ * @example Using supabase-js (recommended)
+ * ```ts
+ * import { createClient } from '@supabase/supabase-js'
+ *
+ * const supabase = createClient('https://xyzcompany.supabase.co', 'your-publishable-key')
+ * const channel = supabase.channel('room1')
+ * channel
+ * .on('broadcast', { event: 'cursor-pos' }, (payload) => console.log(payload))
+ * .subscribe()
+ * ```
+ *
+ * @example Standalone import for bundle-sensitive environments
+ * ```ts
+ * import RealtimeClient from '@supabase/realtime-js'
+ *
+ * const client = new RealtimeClient('https://xyzcompany.supabase.co/realtime/v1', {
+ * params: { apikey: 'your-publishable-key' },
+ * })
+ * client.connect()
+ * ```
+ */
+ constructor(endPoint: string, options?: RealtimeClientOptions) {
+ // Validate required parameters
+ if (!options?.params?.apikey) {
+ throw new Error('API key is required to connect to Realtime')
+ }
+ this.apiKey = options.params.apikey
+
+ const socketAdapterOptions = this._initializeOptions(options)
+
+ this.socketAdapter = new SocketAdapter(endPoint, socketAdapterOptions)
+ this.httpEndpoint = httpEndpointURL(endPoint)
+
+ this.fetch = this._resolveFetch(options?.fetch)
+ }
+
+ /**
+ * Connects the socket, unless already connected.
+ *
+ * @category Realtime
+ */
+ connect(): void {
+ // Skip if already connecting, disconnecting, or connected
+ if (this.isConnecting() || this.isDisconnecting() || this.isConnected()) {
+ return
+ }
+
+ // Trigger auth if needed and not already in progress
+ // This ensures auth is called for standalone RealtimeClient usage
+ // while avoiding race conditions with SupabaseClient's immediate setAuth call
+ if (this.accessToken && !this._authPromise) {
+ this._setAuthSafely('connect')
+ }
+
+ this._setupConnectionHandlers()
+
+ try {
+ this.socketAdapter.connect()
+ } catch (error) {
+ const errorMessage = (error as Error).message
+ throw new Error(`WebSocket not available: ${errorMessage}`)
+ }
+
+ this._handleNodeJsRaceCondition()
+ }
+
+ /**
+ * Returns the URL of the websocket.
+ * @returns string The URL of the websocket.
+ *
+ * @category Realtime
+ */
+ endpointURL(): string {
+ return this.socketAdapter.endPointURL()
+ }
+
+ /**
+ * Disconnects the socket.
+ *
+ * @param code A numeric status code to send on disconnect.
+ * @param reason A custom reason for the disconnect.
+ *
+ * @category Realtime
+ */
+ async disconnect(code?: number, reason?: string) {
+ this._cancelPendingDisconnect()
+ if (this.isDisconnecting()) {
+ return 'ok'
+ }
+ return await this.socketAdapter.disconnect(
+ () => {
+ clearInterval(this._workerHeartbeatTimer)
+ this._terminateWorker()
+ },
+ code,
+ reason
+ )
+ }
+
+ /**
+ * Returns all created channels
+ *
+ * @category Realtime
+ */
+ getChannels(): RealtimeChannel[] {
+ return this.channels
+ }
+
+ /**
+ * Unsubscribes, removes and tears down a single channel
+ * @param channel A RealtimeChannel instance
+ *
+ * @category Realtime
+ */
+ async removeChannel(channel: RealtimeChannel): Promise {
+ const status = await channel.unsubscribe()
+
+ if (status === 'ok') {
+ channel.teardown()
+ }
+
+ return status
+ }
+
+ /**
+ * Unsubscribes, removes and tears down all channels
+ *
+ * @category Realtime
+ */
+ async removeAllChannels(): Promise {
+ const promises = this.channels.map(async (channel) => {
+ const result = await channel.unsubscribe()
+ channel.teardown()
+ return result
+ })
+
+ const result = await Promise.all(promises)
+ await this.disconnect()
+ return result
+ }
+
+ /**
+ * Logs the message.
+ *
+ * For customized logging, `this.logger` can be overridden in Client constructor.
+ *
+ * @category Realtime
+ */
+ log(kind: string, msg: string, data?: any) {
+ this.socketAdapter.log(kind, msg, data)
+ }
+
+ /**
+ * Returns the current state of the socket.
+ *
+ * @category Realtime
+ */
+ connectionState() {
+ return this.socketAdapter.connectionState() || CONNECTION_STATE.closed
+ }
+
+ /**
+ * Returns `true` is the connection is open.
+ *
+ * @category Realtime
+ */
+ isConnected(): boolean {
+ return this.socketAdapter.isConnected()
+ }
+
+ /**
+ * Returns `true` if the connection is currently connecting.
+ *
+ * @category Realtime
+ */
+ isConnecting(): boolean {
+ return this.socketAdapter.isConnecting()
+ }
+
+ /**
+ * Returns `true` if the connection is currently disconnecting.
+ *
+ * @category Realtime
+ */
+ isDisconnecting(): boolean {
+ return this.socketAdapter.isDisconnecting()
+ }
+
+ /**
+ * Creates (or reuses) a {@link RealtimeChannel} for the provided topic.
+ *
+ * Topics are automatically prefixed with `realtime:` to match the Realtime service.
+ * If a channel with the same topic already exists it will be returned instead of creating
+ * a duplicate connection.
+ *
+ * @category Realtime
+ */
+ channel(topic: string, params: RealtimeChannelOptions = { config: {} }): RealtimeChannel {
+ const realtimeTopic = `realtime:${topic}`
+ const exists = this.getChannels().find((c: RealtimeChannel) => c.topic === realtimeTopic)
+
+ if (!exists) {
+ const chan = new RealtimeChannel(`realtime:${topic}`, params, this)
+ this._cancelPendingDisconnect()
+ this.channels.push(chan)
+
+ return chan
+ } else {
+ return exists
+ }
+ }
+
+ /**
+ * Push out a message if the socket is connected.
+ *
+ * If the socket is not connected, the message gets enqueued within a local buffer, and sent out when a connection is next established.
+ *
+ * @category Realtime
+ */
+ push(data: RealtimeMessage): void {
+ this.socketAdapter.push(data)
+ }
+
+ /**
+ * Sets the JWT access token used for channel subscription authorization and Realtime RLS.
+ *
+ * If param is null it will use the `accessToken` callback function or the token set on the client.
+ *
+ * On callback used, it will set the value of the token internal to the client.
+ *
+ * When a token is explicitly provided AND no `accessToken` callback is configured,
+ * it will be preserved across channel operations (including removeChannel and
+ * resubscribe) and the client stays in manual-token mode.
+ *
+ * When an `accessToken` callback IS configured, the callback is the source of truth:
+ * the client remains in callback mode and continues to refresh from it on heartbeat,
+ * even after a bootstrap/override `setAuth(token)` call.
+ *
+ * @param token A JWT string to override the token set on the client.
+ *
+ * @example Setting the authorization header
+ * // Use a manual token (preserved across resubscribes when no accessToken callback is set)
+ * client.realtime.setAuth('my-custom-jwt')
+ *
+ * // Switch back to using the accessToken callback
+ * client.realtime.setAuth()
+ *
+ * @category Realtime
+ */
+ async setAuth(token: string | null = null): Promise {
+ const authGeneration = ++this._authGeneration
+ const authPromise = this._performAuth(token, authGeneration)
+ if (authGeneration === this._authGeneration) {
+ this._authPromise = authPromise
+ }
+ try {
+ await authPromise
+ } finally {
+ if (this._authPromise === authPromise) {
+ this._authPromise = null
+ }
+ }
+ }
+
+ /**
+ * Returns true if the current access token was explicitly set via setAuth(token),
+ * false if it was obtained via the accessToken callback.
+ * @internal
+ */
+ _isManualToken(): boolean {
+ return this._manuallySetToken
+ }
+
+ /**
+ * Sends a heartbeat message if the socket is connected.
+ *
+ * @category Realtime
+ */
+ async sendHeartbeat() {
+ this.socketAdapter.sendHeartbeat()
+ }
+
+ /**
+ * Sets a callback that receives lifecycle events for internal heartbeat messages.
+ * Useful for instrumenting connection health (e.g. sent/ok/timeout).
+ *
+ * @category Realtime
+ */
+ onHeartbeat(callback: HeartbeatCallback) {
+ this.socketAdapter.heartbeatCallback = this._wrapHeartbeatCallback(callback)
+ }
+
+ /**
+ * Use either custom fetch, if provided, or default fetch to make HTTP requests
+ *
+ * @internal
+ */
+ _resolveFetch = (customFetch?: Fetch): Fetch => {
+ if (customFetch) {
+ return (...args) => customFetch(...args)
+ }
+ return (...args) => fetch(...args)
+ }
+
+ /**
+ * Return the next message ref, accounting for overflows
+ *
+ * @internal
+ */
+ _makeRef(): string {
+ return this.socketAdapter.makeRef()
+ }
+
+ /**
+ * Removes a channel from RealtimeClient
+ *
+ * @param channel An open subscription.
+ *
+ * @internal
+ */
+ _remove(channel: RealtimeChannel) {
+ this.channels = this.channels.filter((c) => c.topic !== channel.topic)
+ if (this.channels.length === 0) {
+ this.log('transport', 'no channels remaining, scheduling disconnect')
+ this._schedulePendingDisconnect()
+ }
+ }
+
+ /** @internal */
+ private _schedulePendingDisconnect() {
+ this._cancelPendingDisconnect()
+ if (this._disconnectOnEmptyChannelsAfterMs === 0) {
+ this.log('transport', 'disconnecting immediately - no channels')
+ this.disconnect()
+ return
+ }
+ this._pendingDisconnectTimer = setTimeout(() => {
+ this._pendingDisconnectTimer = null
+ if (this.channels.length === 0) {
+ this.log('transport', 'deferred disconnect fired - no channels, disconnecting')
+ this.disconnect()
+ }
+ }, this._disconnectOnEmptyChannelsAfterMs)
+ this.log(
+ 'transport',
+ `deferred disconnect scheduled in ${this._disconnectOnEmptyChannelsAfterMs}ms`
+ )
+ }
+
+ /** @internal */
+ private _cancelPendingDisconnect() {
+ if (this._pendingDisconnectTimer !== null) {
+ this.log('transport', 'pending disconnect cancelled - channel activity detected')
+ clearTimeout(this._pendingDisconnectTimer)
+ this._pendingDisconnectTimer = null
+ }
+ }
+
+ /**
+ * Perform the actual auth operation
+ * @internal
+ */
+ private async _performAuth(token: string | null, authGeneration: number): Promise {
+ let tokenToSend: string | null
+ let isManualToken = false
+
+ if (token) {
+ tokenToSend = token
+ // Track if this is a manually-provided token
+ isManualToken = true
+ } else if (this.accessToken) {
+ // Call the accessToken callback to get fresh token
+ try {
+ tokenToSend = await this.accessToken()
+ } catch (e) {
+ this.log('error', 'Error fetching access token from callback', e)
+ // Fall back to cached value if callback fails
+ tokenToSend = this.accessTokenValue
+ }
+ } else {
+ tokenToSend = this.accessTokenValue
+ }
+
+ if (authGeneration !== this._authGeneration) {
+ return
+ }
+
+ // Track whether this token was manually set or fetched via callback.
+ // The callback is the source of truth for token refresh
+ if (this.accessToken) {
+ this._manuallySetToken = false
+ } else if (isManualToken) {
+ this._manuallySetToken = true
+ }
+
+ if (this.accessTokenValue != tokenToSend) {
+ this.accessTokenValue = tokenToSend
+ this.channels.forEach((channel) => {
+ const payload = {
+ access_token: tokenToSend,
+ version: DEFAULT_VERSION,
+ }
+
+ channel.updateJoinPayload(payload)
+
+ if (channel.joinedOnce && channel.channelAdapter.isJoined()) {
+ channel.channelAdapter.push(CHANNEL_EVENTS.access_token, {
+ access_token: tokenToSend,
+ })
+ }
+ })
+ }
+ }
+
+ /**
+ * Wait for any in-flight auth operations to complete
+ * @internal
+ */
+ private async _waitForAuthIfNeeded(): Promise {
+ if (this._authPromise) {
+ await this._authPromise
+ }
+ }
+
+ /**
+ * Safely call setAuth with standardized error handling
+ * @internal
+ */
+ private _setAuthSafely(context = 'general'): void {
+ // Only refresh auth if using callback-based tokens
+ if (!this._isManualToken()) {
+ this.setAuth().catch((e) => {
+ this.log('error', `Error setting auth in ${context}`, e)
+ })
+ }
+ }
+
+ /** @internal */
+ private _setupConnectionHandlers(): void {
+ this.socketAdapter.onOpen(() => {
+ const authPromise =
+ this._authPromise ||
+ (this.accessToken && !this.accessTokenValue ? this.setAuth() : Promise.resolve())
+
+ authPromise.catch((e) => {
+ this.log('error', 'error waiting for auth on connect', e)
+ })
+
+ if (this.worker && !this.workerRef) {
+ this._startWorkerHeartbeat()
+ }
+ })
+ this.socketAdapter.onClose(() => {
+ if (this.worker && this.workerRef) {
+ this._terminateWorker()
+ }
+ })
+ this.socketAdapter.onMessage((message: Message) => {
+ if (message.ref && message.ref === this._pendingWorkerHeartbeatRef) {
+ this._pendingWorkerHeartbeatRef = null
+ }
+ })
+ }
+
+ /** @internal */
+ private _handleNodeJsRaceCondition() {
+ if (this.socketAdapter.isConnected()) {
+ // hack: ensure onConnOpen is called
+ this.socketAdapter.getSocket().onConnOpen()
+ }
+ }
+
+ /** @internal */
+ private _wrapHeartbeatCallback(heartbeatCallback?: HeartbeatCallback): HeartbeatCallback {
+ return (status, latency) => {
+ if (status === 'disconnected') return
+ if (status == 'sent') this._setAuthSafely()
+ if (heartbeatCallback) heartbeatCallback(status, latency)
+ }
+ }
+
+ /** @internal */
+ private _startWorkerHeartbeat() {
+ if (this.workerUrl) {
+ this.log('worker', `starting worker for from ${this.workerUrl}`)
+ } else {
+ this.log('worker', `starting default worker`)
+ }
+ const objectUrl = this._workerObjectUrl(this.workerUrl!)
+ this.workerRef = new Worker(objectUrl)
+ this.workerRef.onerror = (error) => {
+ this.log('worker', 'worker error', (error as ErrorEvent).message)
+ this._terminateWorker()
+ this.disconnect()
+ }
+ this.workerRef.onmessage = (event) => {
+ if (event.data.event === 'keepAlive') {
+ this.sendHeartbeat()
+ }
+ }
+ this.workerRef.postMessage({
+ event: 'start',
+ interval: this.heartbeatIntervalMs,
+ })
+ }
+
+ /**
+ * Terminate the Web Worker and clear the reference
+ * @internal
+ */
+ private _terminateWorker(): void {
+ if (this.workerRef) {
+ this.log('worker', 'terminating worker')
+ this.workerRef.terminate()
+ this.workerRef = undefined
+ }
+ }
+
+ /** @internal */
+ private _workerObjectUrl(url: string | undefined): string {
+ let result_url: string
+ if (url) {
+ result_url = url
+ } else {
+ const blob = new Blob([WORKER_SCRIPT], { type: 'application/javascript' })
+ result_url = URL.createObjectURL(blob)
+ }
+ return result_url
+ }
+
+ /**
+ * Initialize socket options with defaults
+ * @internal
+ */
+ private _initializeOptions(options?: RealtimeClientOptions): SocketOptions {
+ this.worker = options?.worker ?? false
+ this.accessToken = options?.accessToken ?? null
+
+ const result: SocketOptions = {}
+ result.timeout = options?.timeout ?? DEFAULT_TIMEOUT
+ result.heartbeatIntervalMs =
+ options?.heartbeatIntervalMs ?? CONNECTION_TIMEOUTS.HEARTBEAT_INTERVAL
+
+ this._disconnectOnEmptyChannelsAfterMs =
+ options?.disconnectOnEmptyChannelsAfterMs ??
+ 2 * (options?.heartbeatIntervalMs ?? CONNECTION_TIMEOUTS.HEARTBEAT_INTERVAL)
+
+ // @ts-ignore - mismatch between phoenix and supabase
+ result.transport = options?.transport ?? WebSocketFactory.getWebSocketConstructor()
+ result.params = options?.params
+ result.logger = options?.logger
+ result.heartbeatCallback = this._wrapHeartbeatCallback(options?.heartbeatCallback)
+ result.sessionStorage = options?.sessionStorage ?? resolveSessionStorage()
+ result.reconnectAfterMs =
+ options?.reconnectAfterMs ??
+ ((tries: number) => {
+ return RECONNECT_INTERVALS[tries - 1] || DEFAULT_RECONNECT_FALLBACK
+ })
+
+ let defaultEncode: Encode
+ let defaultDecode: Decode
+
+ const vsn = options?.vsn ?? DEFAULT_VSN
+
+ switch (vsn) {
+ case VSN_1_0_0:
+ defaultEncode = (payload, callback) => {
+ return callback(JSON.stringify(payload))
+ }
+ defaultDecode = (payload, callback) => {
+ return callback(JSON.parse(payload as string))
+ }
+ break
+ case VSN_2_0_0:
+ defaultEncode = this.serializer.encode.bind(this.serializer)
+ defaultDecode = this.serializer.decode.bind(this.serializer)
+ break
+ default:
+ throw new Error(`Unsupported serializer version: ${result.vsn}`)
+ }
+
+ result.vsn = vsn
+ result.encode = options?.encode ?? defaultEncode
+ result.decode = options?.decode ?? defaultDecode
+
+ result.beforeReconnect = this._reconnectAuth.bind(this)
+
+ if (options?.logLevel || options?.log_level) {
+ this.logLevel = options.logLevel || options.log_level
+ result.params = { ...result.params, log_level: this.logLevel as string }
+ }
+
+ // Handle worker setup
+ if (this.worker) {
+ if (typeof window !== 'undefined' && !window.Worker) {
+ throw new Error('Web Worker is not supported')
+ }
+ this.workerUrl = options?.workerUrl
+ result.autoSendHeartbeat = !this.worker
+ }
+
+ return result
+ }
+
+ /** @internal */
+ private async _reconnectAuth() {
+ await this._waitForAuthIfNeeded()
+ if (!this.isConnected()) {
+ this.connect()
+ }
+ }
+}
diff --git a/node_modules/@supabase/realtime-js/src/RealtimePostgresFilterBuilder.ts b/node_modules/@supabase/realtime-js/src/RealtimePostgresFilterBuilder.ts
new file mode 100644
index 0000000000000000000000000000000000000000..42facf73c408cfde252b2437b40ff746c2ea56c6
--- /dev/null
+++ b/node_modules/@supabase/realtime-js/src/RealtimePostgresFilterBuilder.ts
@@ -0,0 +1,253 @@
+/**
+ * Comparison operators accepted in a Postgres Changes `filter` string.
+ *
+ * These mirror the PostgREST operator surface and are evaluated server-side.
+ * Any operator can be negated via {@link RealtimePostgresFilterBuilder.not}
+ * (the `not.` prefix).
+ *
+ * This is the subset of PostgREST's `FilterOperator` (see `postgrest-js`) that
+ * Realtime Postgres Changes supports. Containment, range and full-text search
+ * operators (`cs`, `cd`, `ov`, range ops, `fts`, …) are intentionally not
+ * included because the Realtime server does not evaluate them.
+ *
+ * - `eq`, `neq`, `lt`, `lte`, `gt`, `gte` — comparison
+ * - `in` — membership: `status=in.(active,pending)`
+ * - `like`, `ilike` — pattern match (case-sensitive / insensitive): `title=like.%foo%`
+ * - `is` — `IS` check against `null` / `true` / `false` / `unknown`: `deleted_at=is.null`
+ * - `match`, `imatch` — POSIX regex match (`~` / `~*`)
+ * - `isdistinct` — NULL-safe inequality (`IS DISTINCT FROM`)
+ */
+export type RealtimePostgresChangesFilterOperator =
+ | 'eq'
+ | 'neq'
+ | 'lt'
+ | 'lte'
+ | 'gt'
+ | 'gte'
+ | 'in'
+ | 'like'
+ | 'ilike'
+ | 'is'
+ | 'match'
+ | 'imatch'
+ | 'isdistinct'
+
+/** Scalar value accepted by a single filter operator. */
+export type RealtimeFilterValue = string | number | boolean | null
+
+/** Value accepted by the `is` operator. */
+export type RealtimeIsFilterValue = null | boolean | 'null' | 'true' | 'false' | 'unknown'
+
+// Reserved characters that force PostgREST-style quoting: `[,()]` (which the
+// server reads as condition/list delimiters) plus `"`/`\` (escaped inside quotes).
+const PostgrestReservedCharsRegexp = /[,()"\\]/
+
+const needsQuoting = (value: string): boolean =>
+ PostgrestReservedCharsRegexp.test(value) || value !== value.trim()
+
+const quote = (value: string): string => `"${value.replace(/\\/g, '\\\\').replace(/"/g, '\\"')}"`
+
+const serializeScalar = (value: RealtimeFilterValue): string => {
+ const serialized = value === null ? 'null' : String(value)
+ return needsQuoting(serialized) ? quote(serialized) : serialized
+}
+
+const serializeIsValue = (value: RealtimeIsFilterValue): string =>
+ value === null ? 'null' : String(value)
+
+// Builds the `operator.value` portion of a filter (everything after `column=`).
+const serialize = (operator: RealtimePostgresChangesFilterOperator, value: unknown): string => {
+ if (operator === 'in') {
+ const values = Array.isArray(value) ? value : [value]
+ if (values.length === 0) {
+ throw new Error('Realtime `in` filter requires at least one value.')
+ }
+ const items = Array.from(new Set(values))
+ .map((v) => serializeScalar(v as RealtimeFilterValue))
+ .join(',')
+ return `in.(${items})`
+ }
+
+ if (operator === 'is') {
+ return `is.${serializeIsValue(value as RealtimeIsFilterValue)}`
+ }
+
+ return `${operator}.${serializeScalar(value as RealtimeFilterValue)}`
+}
+
+/**
+ * Fluent builder for Postgres Changes `filter` strings.
+ *
+ * Each method appends a single `column=operator.value` condition. Multiple
+ * conditions are combined with commas, which the Realtime server applies as an
+ * `AND`. Pass an instance straight to `channel.on('postgres_changes', …)` — the
+ * SDK serializes it to a string automatically — or call {@link build} to obtain
+ * the string yourself.
+ *
+ * The builder mirrors the `postgrest-js` filter API (`eq`, `neq`, `in`, `like`,
+ * `not`, …) for the operators that Realtime supports. Values containing reserved
+ * characters (`,`, `(`, `)`, `"`, `\`) — or surrounding whitespace — are
+ * automatically double-quoted and escaped the same way PostgREST does, so they
+ * survive the server's filter parser; all other values are sent verbatim.
+ *
+ * The filter is snapshotted when passed to `channel.on(...)`; mutating the
+ * builder afterwards does not affect an existing subscription. An empty builder
+ * serializes to `''`, which the server treats as "no filter".
+ *
+ * @example
+ * channel.on('postgres_changes', {
+ * event: '*',
+ * schema: 'public',
+ * table: 'users',
+ * filter: postgresChangesFilter().eq('id', 1).lt('age', 30), // → 'id=eq.1,age=lt.30'
+ * }, (payload) => { ... })
+ */
+export class RealtimePostgresFilterBuilder {
+ private readonly filters: string[] = []
+
+ private add(
+ column: string,
+ operator: RealtimePostgresChangesFilterOperator,
+ value: unknown,
+ negate = false
+ ): this {
+ const prefix = negate ? 'not.' : ''
+ this.filters.push(`${column}=${prefix}${serialize(operator, value)}`)
+ return this
+ }
+
+ /** Match rows where `column` equals `value` (`column=eq.value`). */
+ eq(column: string, value: RealtimeFilterValue): this {
+ return this.add(column, 'eq', value)
+ }
+
+ /** Match rows where `column` does not equal `value` (`column=neq.value`). */
+ neq(column: string, value: RealtimeFilterValue): this {
+ return this.add(column, 'neq', value)
+ }
+
+ /** Match rows where `column` is greater than `value` (`column=gt.value`). */
+ gt(column: string, value: RealtimeFilterValue): this {
+ return this.add(column, 'gt', value)
+ }
+
+ /** Match rows where `column` is greater than or equal to `value` (`column=gte.value`). */
+ gte(column: string, value: RealtimeFilterValue): this {
+ return this.add(column, 'gte', value)
+ }
+
+ /** Match rows where `column` is less than `value` (`column=lt.value`). */
+ lt(column: string, value: RealtimeFilterValue): this {
+ return this.add(column, 'lt', value)
+ }
+
+ /** Match rows where `column` is less than or equal to `value` (`column=lte.value`). */
+ lte(column: string, value: RealtimeFilterValue): this {
+ return this.add(column, 'lte', value)
+ }
+
+ /**
+ * Match rows where `column` is one of `values` (`column=in.(a,b,c)`).
+ * Requires at least one value; duplicates are removed. An element containing a
+ * reserved character is double-quoted (`in.("a,b",c)`), so commas inside an
+ * element are preserved. `null` is intentionally not accepted (`IN (null)`
+ * never matches in SQL) — use `is`/`not('col','is',null)` for null checks.
+ */
+ in(column: string, values: ReadonlyArray): this {
+ return this.add(column, 'in', values)
+ }
+
+ /** Match rows where `column` matches the case-sensitive `pattern` (`column=like.pattern`). */
+ like(column: string, pattern: string): this {
+ return this.add(column, 'like', pattern)
+ }
+
+ /** Match rows where `column` matches the case-insensitive `pattern` (`column=ilike.pattern`). */
+ ilike(column: string, pattern: string): this {
+ return this.add(column, 'ilike', pattern)
+ }
+
+ /** Match rows where `column` matches the POSIX regex `pattern` (`column=match.pattern`). */
+ match(column: string, pattern: string): this {
+ return this.add(column, 'match', pattern)
+ }
+
+ /** Match rows where `column` matches the case-insensitive POSIX regex `pattern` (`column=imatch.pattern`). */
+ imatch(column: string, pattern: string): this {
+ return this.add(column, 'imatch', pattern)
+ }
+
+ /**
+ * Match rows where `column` `IS` the given value (`column=is.null`).
+ * Accepts `null`, a boolean, or the keywords `'null' | 'true' | 'false' | 'unknown'`.
+ */
+ is(column: string, value: RealtimeIsFilterValue): this {
+ return this.add(column, 'is', value)
+ }
+
+ /** Match rows where `column` is distinct from `value` (`column=isdistinct.value`). NULL-safe inequality. */
+ isDistinct(column: string, value: RealtimeFilterValue): this {
+ return this.add(column, 'isdistinct', value)
+ }
+
+ /**
+ * Negate any operator with the `not.` prefix (`column=not.operator.value`).
+ * `in` takes an array, `is` takes an `IS` keyword/boolean/null, and every
+ * other operator takes a scalar value.
+ *
+ * @example
+ * postgresChangesFilter().not('status', 'in', ['draft', 'archived'])
+ * // → status=not.in.(draft,archived)
+ * postgresChangesFilter().not('deleted_at', 'is', null)
+ * // → deleted_at=not.is.null
+ */
+ not(column: string, operator: 'in', value: ReadonlyArray): this
+ not(column: string, operator: 'is', value: RealtimeIsFilterValue): this
+ not(
+ column: string,
+ operator: Exclude,
+ value: RealtimeFilterValue
+ ): this
+ not(
+ column: string,
+ operator: RealtimePostgresChangesFilterOperator,
+ value: RealtimeFilterValue | ReadonlyArray
+ ): this {
+ return this.add(column, operator, value, true)
+ }
+
+ /**
+ * Serialize all conditions into the comma-separated (AND) filter string.
+ *
+ * Conditions are joined by commas, which the server applies as `AND`. A scalar
+ * value (or single `in` element) that contains a reserved character — `,`,
+ * `(`, `)`, `"`, `\` — or surrounding whitespace is double-quoted and escaped
+ * the way PostgREST does, so commas inside a value are preserved rather than
+ * read as a condition boundary.
+ */
+ build(): string {
+ return this.filters.join(',')
+ }
+
+ /** Alias for {@link build}; lets the builder be used wherever a string is expected. */
+ toString(): string {
+ return this.build()
+ }
+}
+
+/**
+ * Create a {@link RealtimePostgresFilterBuilder} for composing a Postgres
+ * Changes `filter`. Conditions are combined with `AND`.
+ *
+ * @example
+ * import { postgresChangesFilter } from '@supabase/realtime-js'
+ *
+ * channel.on('postgres_changes', {
+ * event: 'UPDATE',
+ * schema: 'public',
+ * table: 'orders',
+ * filter: postgresChangesFilter().gt('amount', 100).eq('status', 'open'),
+ * }, (payload) => { ... })
+ */
+export const postgresChangesFilter = (): RealtimePostgresFilterBuilder =>
+ new RealtimePostgresFilterBuilder()
diff --git a/node_modules/@supabase/realtime-js/src/RealtimePresence.ts b/node_modules/@supabase/realtime-js/src/RealtimePresence.ts
new file mode 100644
index 0000000000000000000000000000000000000000..9ced1282d1e5cab17e004f8b64605a5c58aaad11
--- /dev/null
+++ b/node_modules/@supabase/realtime-js/src/RealtimePresence.ts
@@ -0,0 +1,71 @@
+/*
+ This file draws heavily from https://github.com/phoenixframework/phoenix/blob/d344ec0a732ab4ee204215b31de69cf4be72e3bf/assets/js/phoenix/presence.js
+ License: https://github.com/phoenixframework/phoenix/blob/d344ec0a732ab4ee204215b31de69cf4be72e3bf/LICENSE.md
+*/
+
+import type RealtimeChannel from './RealtimeChannel'
+import PresenceAdapter from './phoenix/presenceAdapter'
+
+export type Presence = {
+ presence_ref: string
+} & T
+
+export type RealtimePresenceState = {
+ [key: string]: Presence[]
+}
+
+export type RealtimePresenceJoinPayload = {
+ event: `${REALTIME_PRESENCE_LISTEN_EVENTS.JOIN}`
+ key: string
+ currentPresences: Presence[]
+ newPresences: Presence[]
+}
+
+export type RealtimePresenceLeavePayload = {
+ event: `${REALTIME_PRESENCE_LISTEN_EVENTS.LEAVE}`
+ key: string
+ currentPresences: Presence[]
+ leftPresences: Presence[]
+}
+
+export enum REALTIME_PRESENCE_LISTEN_EVENTS {
+ SYNC = 'sync',
+ JOIN = 'join',
+ LEAVE = 'leave',
+}
+
+export type RealtimePresenceOptions = {
+ events?: { state: string; diff: string }
+}
+
+export default class RealtimePresence {
+ get state() {
+ return this.presenceAdapter.state
+ }
+
+ private presenceAdapter: PresenceAdapter
+
+ /**
+ * Creates a Presence helper that keeps the local presence state in sync with the server.
+ *
+ * @param channel - The realtime channel to bind to.
+ * @param opts - Optional custom event names, e.g. `{ events: { state: 'state', diff: 'diff' } }`.
+ *
+ * @category Realtime
+ *
+ * @example Example for a presence channel
+ * ```ts
+ * const presence = new RealtimePresence(channel)
+ *
+ * channel.on('presence', ({ event, key }) => {
+ * console.log(`Presence ${event} on ${key}`)
+ * })
+ * ```
+ */
+ constructor(
+ public channel: RealtimeChannel,
+ opts?: RealtimePresenceOptions
+ ) {
+ this.presenceAdapter = new PresenceAdapter(this.channel.channelAdapter, opts)
+ }
+}
diff --git a/node_modules/@supabase/realtime-js/src/index.ts b/node_modules/@supabase/realtime-js/src/index.ts
new file mode 100644
index 0000000000000000000000000000000000000000..9185d7e842b6dbc5d68ea6271f9f077e5e94d33c
--- /dev/null
+++ b/node_modules/@supabase/realtime-js/src/index.ts
@@ -0,0 +1,61 @@
+import RealtimeClient, {
+ RealtimeClientOptions,
+ RealtimeMessage,
+ RealtimeRemoveChannelResponse,
+ WebSocketLikeConstructor,
+} from './RealtimeClient'
+import RealtimeChannel, {
+ RealtimeChannelOptions,
+ RealtimeChannelSendResponse,
+ RealtimePostgresChangesFilter,
+ RealtimePostgresChangesFilterOperator,
+ RealtimePostgresFilterBuilder,
+ postgresChangesFilter,
+ RealtimePostgresChangesPayload,
+ RealtimePostgresInsertPayload,
+ RealtimePostgresUpdatePayload,
+ RealtimePostgresDeletePayload,
+ RealtimeSystemPayload,
+ REALTIME_LISTEN_TYPES,
+ REALTIME_POSTGRES_CHANGES_LISTEN_EVENT,
+ REALTIME_SUBSCRIBE_STATES,
+ REALTIME_CHANNEL_STATES,
+} from './RealtimeChannel'
+import RealtimePresence, {
+ RealtimePresenceState,
+ RealtimePresenceJoinPayload,
+ RealtimePresenceLeavePayload,
+ REALTIME_PRESENCE_LISTEN_EVENTS,
+} from './RealtimePresence'
+import WebSocketFactory, { WebSocketLike } from './lib/websocket-factory'
+
+export {
+ RealtimePresence,
+ RealtimeChannel,
+ RealtimeChannelOptions,
+ RealtimeChannelSendResponse,
+ RealtimeClient,
+ RealtimeClientOptions,
+ RealtimeMessage,
+ RealtimePostgresChangesFilter,
+ RealtimePostgresChangesFilterOperator,
+ RealtimePostgresFilterBuilder,
+ postgresChangesFilter,
+ RealtimePostgresChangesPayload,
+ RealtimePostgresInsertPayload,
+ RealtimePostgresUpdatePayload,
+ RealtimePostgresDeletePayload,
+ RealtimeSystemPayload,
+ RealtimePresenceJoinPayload,
+ RealtimePresenceLeavePayload,
+ RealtimePresenceState,
+ RealtimeRemoveChannelResponse,
+ REALTIME_LISTEN_TYPES,
+ REALTIME_POSTGRES_CHANGES_LISTEN_EVENT,
+ REALTIME_PRESENCE_LISTEN_EVENTS,
+ REALTIME_SUBSCRIBE_STATES,
+ REALTIME_CHANNEL_STATES,
+ WebSocketFactory,
+ WebSocketLike,
+ WebSocketLikeConstructor,
+}
diff --git a/node_modules/@supabase/realtime-js/src/lib/constants.ts b/node_modules/@supabase/realtime-js/src/lib/constants.ts
new file mode 100644
index 0000000000000000000000000000000000000000..e907b020dbbe02cd6426e7e1e9017bdf077bdab0
--- /dev/null
+++ b/node_modules/@supabase/realtime-js/src/lib/constants.ts
@@ -0,0 +1,62 @@
+import { version } from './version'
+import type {
+ SocketState,
+ ChannelState,
+ ChannelEvent as PhoenixChannelEvent,
+ Transport,
+ Vsn,
+} from '../phoenix/types'
+
+export type { SocketState, ChannelState, Transport }
+
+export const DEFAULT_VERSION = `realtime-js/${version}`
+
+export const VSN_1_0_0: Vsn = '1.0.0'
+export const VSN_2_0_0: Vsn = '2.0.0'
+export const DEFAULT_VSN: Vsn = VSN_2_0_0
+
+export const VERSION = version
+
+export const DEFAULT_TIMEOUT = 10000
+
+export const WS_CLOSE_NORMAL = 1000
+export const MAX_PUSH_BUFFER_SIZE = 100
+
+export const SOCKET_STATES = {
+ connecting: 0,
+ open: 1,
+ closing: 2,
+ closed: 3,
+} as const
+
+export const CHANNEL_STATES = {
+ closed: 'closed',
+ errored: 'errored',
+ joined: 'joined',
+ joining: 'joining',
+ leaving: 'leaving',
+} as const
+
+export type ChannelEvent = PhoenixChannelEvent | 'access_token'
+
+export const CHANNEL_EVENTS = {
+ close: 'phx_close',
+ error: 'phx_error',
+ join: 'phx_join',
+ reply: 'phx_reply',
+ leave: 'phx_leave',
+ access_token: 'access_token',
+} as const
+
+export const TRANSPORTS = {
+ websocket: 'websocket',
+} as const
+
+export type ConnectionState = 'connecting' | 'open' | 'closing' | 'closed' | (string & {})
+
+export const CONNECTION_STATE = {
+ connecting: 'connecting',
+ open: 'open',
+ closing: 'closing',
+ closed: 'closed',
+} as const
diff --git a/node_modules/@supabase/realtime-js/src/lib/normalizeChannelError.ts b/node_modules/@supabase/realtime-js/src/lib/normalizeChannelError.ts
new file mode 100644
index 0000000000000000000000000000000000000000..e3954371e3eda124e038b8e241df81414eff51b6
--- /dev/null
+++ b/node_modules/@supabase/realtime-js/src/lib/normalizeChannelError.ts
@@ -0,0 +1,30 @@
+/**
+ * Normalize the various shapes a channel error reason can take into a real `Error`.
+ *
+ * Transport-level channel errors arrive as a `CloseEvent`, a transport `Event`, an `Error`,
+ * a string, or `undefined` depending on which path in the underlying socket fired. Server-reply
+ * errors arrive as a payload object. This helper produces a consistent `Error` for every case
+ * and preserves the original via `cause` so callers can still inspect the raw event.
+ */
+export function normalizeChannelError(reason: unknown): Error {
+ if (reason instanceof Error) {
+ return reason
+ }
+
+ if (typeof reason === 'string') {
+ return new Error(reason)
+ }
+
+ if (reason && typeof reason === 'object') {
+ const obj = reason as Record
+
+ if (typeof obj.code === 'number') {
+ const detail = typeof obj.reason === 'string' && obj.reason ? ` (${obj.reason})` : ''
+ return new Error(`socket closed: ${obj.code}${detail}`, { cause: reason })
+ }
+
+ return new Error('channel error: transport failure', { cause: reason })
+ }
+
+ return new Error('channel error: connection lost')
+}
diff --git a/node_modules/@supabase/realtime-js/src/lib/serializer.ts b/node_modules/@supabase/realtime-js/src/lib/serializer.ts
new file mode 100644
index 0000000000000000000000000000000000000000..34520aa23c197d1bee1fa762f534bca3b6b06b88
--- /dev/null
+++ b/node_modules/@supabase/realtime-js/src/lib/serializer.ts
@@ -0,0 +1,214 @@
+// This file draws heavily from https://github.com/phoenixframework/phoenix/commit/cf098e9cf7a44ee6479d31d911a97d3c7430c6fe
+// License: https://github.com/phoenixframework/phoenix/blob/master/LICENSE.md
+export type Msg = {
+ join_ref?: string | null
+ ref?: string | null
+ topic: string
+ event: string
+ payload: T
+}
+
+export default class Serializer {
+ HEADER_LENGTH = 1
+ USER_BROADCAST_PUSH_META_LENGTH = 6
+ KINDS = { userBroadcastPush: 3, userBroadcast: 4 }
+ BINARY_ENCODING = 0
+ JSON_ENCODING = 1
+ BROADCAST_EVENT = 'broadcast'
+
+ allowedMetadataKeys: string[] = []
+
+ constructor(allowedMetadataKeys?: string[] | null) {
+ this.allowedMetadataKeys = allowedMetadataKeys ?? []
+ }
+
+ encode(msg: Msg<{ [key: string]: any }>, callback: (result: ArrayBuffer | string) => any) {
+ if (
+ msg.event === this.BROADCAST_EVENT &&
+ !(msg.payload instanceof ArrayBuffer) &&
+ typeof msg.payload.event === 'string'
+ ) {
+ return callback(
+ this._binaryEncodeUserBroadcastPush(msg as Msg<{ event: string } & { [key: string]: any }>)
+ )
+ }
+
+ let payload = [msg.join_ref, msg.ref, msg.topic, msg.event, msg.payload]
+ return callback(JSON.stringify(payload))
+ }
+
+ private _binaryEncodeUserBroadcastPush(message: Msg<{ event: string } & { [key: string]: any }>) {
+ if (this._isArrayBuffer(message.payload?.payload)) {
+ return this._encodeBinaryUserBroadcastPush(message)
+ } else {
+ return this._encodeJsonUserBroadcastPush(message)
+ }
+ }
+
+ private _encodeBinaryUserBroadcastPush(message: Msg<{ event: string } & { [key: string]: any }>) {
+ const userPayload = message.payload?.payload ?? new ArrayBuffer(0)
+ return this._encodeUserBroadcastPush(message, this.BINARY_ENCODING, userPayload)
+ }
+
+ private _encodeJsonUserBroadcastPush(message: Msg<{ event: string } & { [key: string]: any }>) {
+ const userPayload = message.payload?.payload ?? {}
+ const encoder = new TextEncoder()
+ const encodedUserPayload = encoder.encode(JSON.stringify(userPayload)).buffer
+ return this._encodeUserBroadcastPush(message, this.JSON_ENCODING, encodedUserPayload)
+ }
+
+ private _encodeUserBroadcastPush(
+ message: Msg<{ event: string } & { [key: string]: any }>,
+ encodingType: number,
+ encodedPayload: ArrayBuffer
+ ) {
+ // Encode each header field as UTF-8. The length prefixes are byte counts and
+ // the decode side uses TextDecoder (UTF-8), so measuring with String.length
+ // and writing with charCodeAt would corrupt any multi-byte character (e.g.
+ // accents or emoji) and desynchronize the buffer.
+ const encoder = new TextEncoder()
+ const topic = encoder.encode(message.topic)
+ const ref = encoder.encode(message.ref ?? '')
+ const joinRef = encoder.encode(message.join_ref ?? '')
+ const userEvent = encoder.encode(message.payload.event)
+
+ // Filter metadata based on allowed keys
+ const rest = this.allowedMetadataKeys
+ ? this._pick(message.payload, this.allowedMetadataKeys)
+ : {}
+
+ const metadata = encoder.encode(Object.keys(rest).length === 0 ? '' : JSON.stringify(rest))
+
+ // Validate byte lengths don't exceed uint8 max value (255)
+ if (joinRef.length > 255) {
+ throw new Error(`joinRef length ${joinRef.length} exceeds maximum of 255`)
+ }
+ if (ref.length > 255) {
+ throw new Error(`ref length ${ref.length} exceeds maximum of 255`)
+ }
+ if (topic.length > 255) {
+ throw new Error(`topic length ${topic.length} exceeds maximum of 255`)
+ }
+ if (userEvent.length > 255) {
+ throw new Error(`userEvent length ${userEvent.length} exceeds maximum of 255`)
+ }
+ if (metadata.length > 255) {
+ throw new Error(`metadata length ${metadata.length} exceeds maximum of 255`)
+ }
+
+ const metaLength =
+ this.USER_BROADCAST_PUSH_META_LENGTH +
+ joinRef.length +
+ ref.length +
+ topic.length +
+ userEvent.length +
+ metadata.length
+
+ const header = new ArrayBuffer(this.HEADER_LENGTH + metaLength)
+ const view = new DataView(header)
+ const bytes = new Uint8Array(header)
+ let offset = 0
+
+ view.setUint8(offset++, this.KINDS.userBroadcastPush) // kind
+ view.setUint8(offset++, joinRef.length)
+ view.setUint8(offset++, ref.length)
+ view.setUint8(offset++, topic.length)
+ view.setUint8(offset++, userEvent.length)
+ view.setUint8(offset++, metadata.length)
+ view.setUint8(offset++, encodingType)
+ bytes.set(joinRef, offset)
+ offset += joinRef.length
+ bytes.set(ref, offset)
+ offset += ref.length
+ bytes.set(topic, offset)
+ offset += topic.length
+ bytes.set(userEvent, offset)
+ offset += userEvent.length
+ bytes.set(metadata, offset)
+ offset += metadata.length
+
+ var combined = new Uint8Array(header.byteLength + encodedPayload.byteLength)
+ combined.set(new Uint8Array(header), 0)
+ combined.set(new Uint8Array(encodedPayload), header.byteLength)
+
+ return combined.buffer
+ }
+
+ decode(rawPayload: ArrayBuffer | string, callback: Function) {
+ if (this._isArrayBuffer(rawPayload)) {
+ let result = this._binaryDecode(rawPayload as ArrayBuffer)
+ return callback(result)
+ }
+
+ if (typeof rawPayload === 'string') {
+ const jsonPayload = JSON.parse(rawPayload)
+ const [join_ref, ref, topic, event, payload] = jsonPayload
+ return callback({ join_ref, ref, topic, event, payload })
+ }
+
+ return callback({})
+ }
+
+ private _binaryDecode(buffer: ArrayBuffer) {
+ const view = new DataView(buffer)
+ const kind = view.getUint8(0)
+ const decoder = new TextDecoder()
+ switch (kind) {
+ case this.KINDS.userBroadcast:
+ return this._decodeUserBroadcast(buffer, view, decoder)
+ }
+ }
+
+ private _decodeUserBroadcast(
+ buffer: ArrayBuffer,
+ view: DataView,
+ decoder: TextDecoder
+ ): {
+ join_ref: null
+ ref: null
+ topic: string
+ event: string
+ payload: { [key: string]: any }
+ } {
+ const topicSize = view.getUint8(1)
+ const userEventSize = view.getUint8(2)
+ const metadataSize = view.getUint8(3)
+ const payloadEncoding = view.getUint8(4)
+
+ let offset = this.HEADER_LENGTH + 4
+ const topic = decoder.decode(buffer.slice(offset, offset + topicSize))
+ offset = offset + topicSize
+ const userEvent = decoder.decode(buffer.slice(offset, offset + userEventSize))
+ offset = offset + userEventSize
+ const metadata = decoder.decode(buffer.slice(offset, offset + metadataSize))
+ offset = offset + metadataSize
+
+ const payload = buffer.slice(offset, buffer.byteLength)
+ const parsedPayload =
+ payloadEncoding === this.JSON_ENCODING ? JSON.parse(decoder.decode(payload)) : payload
+
+ const data: { [key: string]: any } = {
+ type: this.BROADCAST_EVENT,
+ event: userEvent,
+ payload: parsedPayload,
+ }
+
+ // Metadata is optional and always JSON encoded
+ if (metadataSize > 0) {
+ data['meta'] = JSON.parse(metadata)
+ }
+
+ return { join_ref: null, ref: null, topic: topic, event: this.BROADCAST_EVENT, payload: data }
+ }
+
+ private _isArrayBuffer(buffer: any): boolean {
+ return buffer instanceof ArrayBuffer || buffer?.constructor?.name === 'ArrayBuffer'
+ }
+
+ private _pick(obj: Record | null | undefined, keys: string[]): Record {
+ if (!obj || typeof obj !== 'object') {
+ return {}
+ }
+ return Object.fromEntries(Object.entries(obj).filter(([key]) => keys.includes(key)))
+ }
+}
diff --git a/node_modules/@supabase/realtime-js/src/lib/transformers.ts b/node_modules/@supabase/realtime-js/src/lib/transformers.ts
new file mode 100644
index 0000000000000000000000000000000000000000..f9cade703db15e20d558b6b37c4ca010bdf5af2d
--- /dev/null
+++ b/node_modules/@supabase/realtime-js/src/lib/transformers.ts
@@ -0,0 +1,270 @@
+/**
+ * Helpers to convert the change Payload into native JS types.
+ */
+
+// Adapted from epgsql (src/epgsql_binary.erl), this module licensed under
+// 3-clause BSD found here: https://raw.githubusercontent.com/epgsql/epgsql/devel/LICENSE
+
+export enum PostgresTypes {
+ abstime = 'abstime',
+ bool = 'bool',
+ date = 'date',
+ daterange = 'daterange',
+ float4 = 'float4',
+ float8 = 'float8',
+ int2 = 'int2',
+ int4 = 'int4',
+ int4range = 'int4range',
+ int8 = 'int8',
+ int8range = 'int8range',
+ json = 'json',
+ jsonb = 'jsonb',
+ money = 'money',
+ numeric = 'numeric',
+ oid = 'oid',
+ reltime = 'reltime',
+ text = 'text',
+ time = 'time',
+ timestamp = 'timestamp',
+ timestamptz = 'timestamptz',
+ timetz = 'timetz',
+ tsrange = 'tsrange',
+ tstzrange = 'tstzrange',
+}
+
+type Columns = {
+ name: string // the column name. eg: "user_id"
+ type: string // the column type. eg: "uuid"
+ flags?: string[] // any special flags for the column. eg: ["key"]
+ type_modifier?: number // the type modifier. eg: 4294967295
+}[]
+
+type BaseValue = null | string | number | boolean
+type RecordValue = BaseValue | BaseValue[]
+
+type Record = {
+ [key: string]: RecordValue
+}
+
+/**
+ * Takes an array of columns and an object of string values then converts each string value
+ * to its mapped type.
+ *
+ * @param {{name: String, type: String}[]} columns
+ * @param {Object} record
+ * @param {Object} options The map of various options that can be applied to the mapper
+ * @param {Array} options.skipTypes The array of types that should not be converted
+ *
+ * @example convertChangeData([{name: 'first_name', type: 'text'}, {name: 'age', type: 'int4'}], {first_name: 'Paul', age:'33'}, {})
+ * //=>{ first_name: 'Paul', age: 33 }
+ */
+export const convertChangeData = (
+ columns: Columns,
+ record: Record | null,
+ options: { skipTypes?: string[] } = {}
+): Record => {
+ const skipTypes = options.skipTypes ?? []
+
+ if (!record) {
+ return {}
+ }
+
+ return Object.keys(record).reduce((acc, rec_key) => {
+ acc[rec_key] = convertColumn(rec_key, columns, record, skipTypes)
+ return acc
+ }, {} as Record)
+}
+
+/**
+ * Converts the value of an individual column.
+ *
+ * @param {String} columnName The column that you want to convert
+ * @param {{name: String, type: String}[]} columns All of the columns
+ * @param {Object} record The map of string values
+ * @param {Array} skipTypes An array of types that should not be converted
+ * @return {object} Useless information
+ *
+ * @example convertColumn('age', [{name: 'first_name', type: 'text'}, {name: 'age', type: 'int4'}], {first_name: 'Paul', age: '33'}, [])
+ * //=> 33
+ * @example convertColumn('age', [{name: 'first_name', type: 'text'}, {name: 'age', type: 'int4'}], {first_name: 'Paul', age: '33'}, ['int4'])
+ * //=> "33"
+ */
+export const convertColumn = (
+ columnName: string,
+ columns: Columns,
+ record: Record,
+ skipTypes: string[]
+): RecordValue => {
+ const column = columns.find((x) => x.name === columnName)
+ const colType = column?.type
+ const value = record[columnName]
+
+ if (colType && !skipTypes.includes(colType)) {
+ return convertCell(colType, value)
+ }
+
+ return noop(value)
+}
+
+/**
+ * If the value of the cell is `null`, returns null.
+ * Otherwise converts the string value to the correct type.
+ * @param {String} type A postgres column type
+ * @param {String} value The cell value
+ *
+ * @example convertCell('bool', 't')
+ * //=> true
+ * @example convertCell('int8', '10')
+ * //=> 10
+ * @example convertCell('_int4', '{1,2,3,4}')
+ * //=> [1,2,3,4]
+ */
+export const convertCell = (type: string, value: RecordValue): RecordValue => {
+ // if data type is an array
+ if (type.charAt(0) === '_') {
+ const dataType = type.slice(1, type.length)
+ return toArray(value, dataType)
+ }
+
+ // If not null, convert to correct type.
+ switch (type) {
+ case PostgresTypes.bool:
+ return toBoolean(value)
+ case PostgresTypes.float4:
+ case PostgresTypes.float8:
+ case PostgresTypes.int2:
+ case PostgresTypes.int4:
+ case PostgresTypes.int8:
+ case PostgresTypes.numeric:
+ case PostgresTypes.oid:
+ return toNumber(value)
+ case PostgresTypes.json:
+ case PostgresTypes.jsonb:
+ return toJson(value)
+ case PostgresTypes.timestamp:
+ return toTimestampString(value) // Format to be consistent with PostgREST
+ case PostgresTypes.abstime: // To allow users to cast it based on Timezone
+ case PostgresTypes.date: // To allow users to cast it based on Timezone
+ case PostgresTypes.daterange:
+ case PostgresTypes.int4range:
+ case PostgresTypes.int8range:
+ case PostgresTypes.money:
+ case PostgresTypes.reltime: // To allow users to cast it based on Timezone
+ case PostgresTypes.text:
+ case PostgresTypes.time: // To allow users to cast it based on Timezone
+ case PostgresTypes.timestamptz: // To allow users to cast it based on Timezone
+ case PostgresTypes.timetz: // To allow users to cast it based on Timezone
+ case PostgresTypes.tsrange:
+ case PostgresTypes.tstzrange:
+ return noop(value)
+ default:
+ // Return the value for remaining types
+ return noop(value)
+ }
+}
+
+const noop = (value: RecordValue): RecordValue => {
+ return value
+}
+export const toBoolean = (value: RecordValue): RecordValue => {
+ switch (value) {
+ case 't':
+ return true
+ case 'f':
+ return false
+ default:
+ return value
+ }
+}
+export const toNumber = (value: RecordValue): RecordValue => {
+ if (typeof value === 'string') {
+ const parsedValue = parseFloat(value)
+ if (!Number.isNaN(parsedValue)) {
+ return parsedValue
+ }
+ }
+ return value
+}
+export const toJson = (value: RecordValue): RecordValue => {
+ if (typeof value === 'string') {
+ try {
+ return JSON.parse(value)
+ } catch {
+ return value
+ }
+ }
+ return value
+}
+
+/**
+ * Converts a Postgres Array into a native JS array
+ *
+ * @example toArray('{}', 'int4')
+ * //=> []
+ * @example toArray('{"[2021-01-01,2021-12-31)","(2021-01-01,2021-12-32]"}', 'daterange')
+ * //=> ['[2021-01-01,2021-12-31)', '(2021-01-01,2021-12-32]']
+ * @example toArray([1,2,3,4], 'int4')
+ * //=> [1,2,3,4]
+ */
+export const toArray = (value: RecordValue, type: string): RecordValue => {
+ if (typeof value !== 'string') {
+ return value
+ }
+
+ const lastIdx = value.length - 1
+ const closeBrace = value[lastIdx]
+ const openBrace = value[0]
+
+ // Confirm value is a Postgres array by checking curly brackets
+ if (openBrace === '{' && closeBrace === '}') {
+ let arr
+ const valTrim = value.slice(1, lastIdx)
+
+ // TODO: find a better solution to separate Postgres array data
+ try {
+ arr = JSON.parse('[' + valTrim + ']')
+ } catch (_) {
+ // WARNING: splitting on comma does not cover all edge cases
+ arr = valTrim ? valTrim.split(',') : []
+ }
+
+ return arr.map((val: BaseValue) => convertCell(type, val))
+ }
+
+ return value
+}
+
+/**
+ * Fixes timestamp to be ISO-8601. Swaps the space between the date and time for a 'T'
+ * See https://github.com/supabase/supabase/issues/18
+ *
+ * @example toTimestampString('2019-09-10 00:00:00')
+ * //=> '2019-09-10T00:00:00'
+ */
+export const toTimestampString = (value: RecordValue): RecordValue => {
+ if (typeof value === 'string') {
+ return value.replace(' ', 'T')
+ }
+
+ return value
+}
+
+export const httpEndpointURL = (socketUrl: string): string => {
+ const wsUrl = new URL(socketUrl)
+
+ wsUrl.protocol = wsUrl.protocol.replace(/^ws/i, 'http')
+
+ wsUrl.pathname = wsUrl.pathname
+ .replace(/\/+$/, '') // remove all trailing slashes
+ .replace(/\/socket\/websocket$/i, '') // remove the socket/websocket path
+ .replace(/\/socket$/i, '') // remove the socket path
+ .replace(/\/websocket$/i, '') // remove the websocket path
+
+ if (wsUrl.pathname === '' || wsUrl.pathname === '/') {
+ wsUrl.pathname = '/api/broadcast'
+ } else {
+ wsUrl.pathname = wsUrl.pathname + '/api/broadcast'
+ }
+
+ return wsUrl.href
+}
diff --git a/node_modules/@supabase/realtime-js/src/lib/version.ts b/node_modules/@supabase/realtime-js/src/lib/version.ts
new file mode 100644
index 0000000000000000000000000000000000000000..728b243d9860d462498beea4f7212d24b085dddf
--- /dev/null
+++ b/node_modules/@supabase/realtime-js/src/lib/version.ts
@@ -0,0 +1,7 @@
+// Generated automatically during releases by scripts/update-version-files.ts
+// This file provides runtime access to the package version for:
+// - HTTP request headers (e.g., X-Client-Info header for API requests)
+// - Debugging and support (identifying which version is running)
+// - Telemetry and logging (version reporting in errors/analytics)
+// - Ensuring build artifacts match the published package version
+export const version = '2.112.3'
diff --git a/node_modules/@supabase/realtime-js/src/lib/websocket-factory.ts b/node_modules/@supabase/realtime-js/src/lib/websocket-factory.ts
new file mode 100644
index 0000000000000000000000000000000000000000..caf37f34659a97f7cbf8b62c5e99567ae992ba5e
--- /dev/null
+++ b/node_modules/@supabase/realtime-js/src/lib/websocket-factory.ts
@@ -0,0 +1,185 @@
+export interface WebSocketLike {
+ readonly CONNECTING: number
+ readonly OPEN: number
+ readonly CLOSING: number
+ readonly CLOSED: number
+ readonly readyState: number
+ readonly url: string
+ readonly protocol: string
+
+ /**
+ * Closes the socket, optionally providing a close code and reason.
+ */
+ close(code?: number, reason?: string): void
+ /**
+ * Sends data through the socket using the underlying implementation.
+ */
+ send(data: string | ArrayBufferLike | Blob | ArrayBufferView): void
+
+ onopen: ((this: any, ev: Event) => any) | null
+ onmessage: ((this: any, ev: MessageEvent) => any) | null
+ onclose: ((this: any, ev: CloseEvent) => any) | null
+ onerror: ((this: any, ev: Event) => any) | null
+
+ /**
+ * Registers an event listener on the socket (compatible with browser WebSocket API).
+ */
+ addEventListener(type: string, listener: EventListener): void
+ /**
+ * Removes a previously registered event listener.
+ */
+ removeEventListener(type: string, listener: EventListener): void
+
+ // Add additional properties that may exist on WebSocket implementations
+ binaryType?: string
+ bufferedAmount?: number
+ extensions?: string
+ dispatchEvent?: (event: Event) => boolean
+}
+
+export interface WebSocketEnvironment {
+ type: 'native' | 'cloudflare' | 'unsupported'
+ /** WebSocket constructor for this environment, if available. */
+ wsConstructor?: typeof WebSocket
+ error?: string
+ workaround?: string
+}
+
+/**
+ * Extended globalThis with optional runtime-specific properties
+ * that may or may not exist depending on the environment.
+ */
+interface RuntimeGlobals {
+ WebSocket?: { new (url: string, protocols?: string | string[]): WebSocketLike }
+ WebSocketPair?: unknown
+ EdgeRuntime?: unknown
+}
+
+/**
+ * Utilities for creating WebSocket instances across runtimes.
+ */
+export class WebSocketFactory {
+ /**
+ * Static-only utility – prevent instantiation.
+ */
+ private constructor() {}
+ private static detectEnvironment(): WebSocketEnvironment {
+ if (typeof WebSocket !== 'undefined') {
+ return { type: 'native', wsConstructor: WebSocket }
+ }
+
+ const gt = globalThis as typeof globalThis & RuntimeGlobals
+ if (typeof globalThis !== 'undefined' && typeof gt.WebSocket !== 'undefined') {
+ return { type: 'native', wsConstructor: gt.WebSocket as typeof WebSocket }
+ }
+
+ const gl =
+ typeof global !== 'undefined' ? (global as typeof global & RuntimeGlobals) : undefined
+ if (gl && typeof gl.WebSocket !== 'undefined') {
+ return { type: 'native', wsConstructor: gl.WebSocket as typeof WebSocket }
+ }
+
+ if (
+ typeof globalThis !== 'undefined' &&
+ typeof gt.WebSocketPair !== 'undefined' &&
+ typeof globalThis.WebSocket === 'undefined'
+ ) {
+ return {
+ type: 'cloudflare',
+ error:
+ 'Cloudflare Workers detected. WebSocket clients are not supported in Cloudflare Workers.',
+ workaround:
+ 'Use Cloudflare Workers WebSocket API for server-side WebSocket handling, or deploy to a different runtime.',
+ }
+ }
+
+ if (
+ (typeof globalThis !== 'undefined' && gt.EdgeRuntime) ||
+ (typeof navigator !== 'undefined' && navigator.userAgent?.includes('Vercel-Edge'))
+ ) {
+ return {
+ type: 'unsupported',
+ error:
+ 'Edge runtime detected (Vercel Edge/Netlify Edge). WebSockets are not supported in edge functions.',
+ workaround:
+ 'Use serverless functions or a different deployment target for WebSocket functionality.',
+ }
+ }
+
+ // Use dynamic property access to avoid Next.js Edge Runtime static analysis warnings
+ const _process = (globalThis as Record)['process'] as
+ | { versions?: { node?: string } }
+ | undefined
+ if (_process) {
+ const processVersions = _process['versions']
+ if (processVersions && processVersions['node']) {
+ // Reaching here means an earlier check did not find a native WebSocket,
+ // so this Node.js process is missing the global WebSocket (Node.js 22+).
+ return {
+ type: 'unsupported',
+ error: 'Node.js detected but native WebSocket not found.',
+ workaround:
+ 'Ensure you are running Node.js 22+ or provide a WebSocket implementation via the transport option.',
+ }
+ }
+ }
+
+ return {
+ type: 'unsupported',
+ error: 'Unknown JavaScript runtime without WebSocket support.',
+ workaround:
+ "Ensure you're running in a supported environment (browser, Node.js, Deno) or provide a custom WebSocket implementation.",
+ }
+ }
+
+ /**
+ * Returns the best available WebSocket constructor for the current runtime.
+ *
+ * @category Realtime
+ *
+ * @example Example with error handling
+ * ```ts
+ * try {
+ * const WS = WebSocketFactory.getWebSocketConstructor()
+ * const socket = new WS('wss://example.com/socket')
+ * } catch (error) {
+ * console.error('WebSocket not available in this environment.', error)
+ * }
+ * ```
+ */
+ public static getWebSocketConstructor(): typeof WebSocket {
+ const env = this.detectEnvironment()
+ if (env.wsConstructor) {
+ return env.wsConstructor
+ }
+ let errorMessage = env.error || 'WebSocket not supported in this environment.'
+ if (env.workaround) {
+ errorMessage += `\n\nSuggested solution: ${env.workaround}`
+ }
+ throw new Error(errorMessage)
+ }
+
+ /**
+ * Detects whether the runtime can establish WebSocket connections.
+ *
+ * @category Realtime
+ *
+ * @example Example in a Node.js script
+ * ```ts
+ * if (!WebSocketFactory.isWebSocketSupported()) {
+ * console.error('WebSockets are required for this script.')
+ * process.exitCode = 1
+ * }
+ * ```
+ */
+ public static isWebSocketSupported(): boolean {
+ try {
+ const env = this.detectEnvironment()
+ return env.type === 'native'
+ } catch {
+ return false
+ }
+ }
+}
+
+export default WebSocketFactory
diff --git a/node_modules/@supabase/realtime-js/src/phoenix/channelAdapter.ts b/node_modules/@supabase/realtime-js/src/phoenix/channelAdapter.ts
new file mode 100644
index 0000000000000000000000000000000000000000..6c9570e22a1e0efd6d81de3719a6cdbbe7812f80
--- /dev/null
+++ b/node_modules/@supabase/realtime-js/src/phoenix/channelAdapter.ts
@@ -0,0 +1,149 @@
+import { Channel } from '@supabase/phoenix'
+import { CHANNEL_STATES, MAX_PUSH_BUFFER_SIZE } from '../lib/constants'
+import type { RealtimeChannelOptions } from '../RealtimeChannel'
+import SocketAdapter from './socketAdapter'
+import type {
+ ChannelBindingCallback,
+ ChannelOnMessage,
+ ChannelOnErrorCallback,
+ ChannelFilterBindings,
+ Params,
+ ChannelState,
+ Push,
+ Timer,
+} from './types'
+
+export default class ChannelAdapter {
+ private channel: Channel
+ private socket: SocketAdapter
+
+ constructor(socket: SocketAdapter, topic: string, params: RealtimeChannelOptions) {
+ const phoenixParams = phoenixChannelParams(params)
+ this.channel = socket.getSocket().channel(topic, phoenixParams)
+ this.socket = socket
+ }
+
+ get state(): ChannelState {
+ return this.channel.state
+ }
+
+ set state(state: ChannelState) {
+ this.channel.state = state
+ }
+
+ get joinedOnce(): boolean {
+ return this.channel.joinedOnce
+ }
+
+ get joinPush(): Push {
+ return this.channel.joinPush
+ }
+
+ get rejoinTimer(): Timer {
+ return this.channel.rejoinTimer
+ }
+
+ on(event: string, callback: ChannelBindingCallback): number {
+ return this.channel.on(event, callback)
+ }
+
+ off(event: string, refNumber?: number) {
+ this.channel.off(event, refNumber)
+ }
+
+ subscribe(timeout?: number): Push {
+ return this.channel.join(timeout)
+ }
+
+ unsubscribe(timeout?: number): Push {
+ return this.channel.leave(timeout)
+ }
+
+ teardown() {
+ this.channel.teardown()
+ }
+
+ onClose(callback: ChannelBindingCallback) {
+ this.channel.onClose(callback)
+ }
+
+ onError(callback: ChannelOnErrorCallback): number {
+ return this.channel.onError(callback)
+ }
+
+ push(event: string, payload: { [key: string]: any }, timeout?: number): Push {
+ let push: Push
+
+ try {
+ push = this.channel.push(event, payload, timeout)
+ } catch (error) {
+ throw new Error(
+ `tried to push '${event}' to '${this.channel.topic}' before joining. Use channel.subscribe() before pushing events`
+ )
+ }
+
+ if (this.channel.pushBuffer.length > MAX_PUSH_BUFFER_SIZE) {
+ const removedPush = this.channel.pushBuffer.shift()!
+ removedPush.cancelTimeout()
+ this.socket.log(
+ 'channel',
+ `discarded push due to buffer overflow: ${removedPush.event}`,
+ removedPush.payload()
+ )
+ }
+ return push
+ }
+
+ updateJoinPayload(payload: Record) {
+ const oldPayload = this.channel.joinPush.payload()
+ this.channel.joinPush.payload = () => ({ ...oldPayload, ...payload })
+ }
+
+ canPush() {
+ return this.socket.isConnected() && this.state === CHANNEL_STATES.joined
+ }
+
+ isJoined() {
+ return this.state === CHANNEL_STATES.joined
+ }
+
+ isJoining() {
+ return this.state === CHANNEL_STATES.joining
+ }
+
+ isClosed() {
+ return this.state === CHANNEL_STATES.closed
+ }
+
+ isLeaving() {
+ return this.state === CHANNEL_STATES.leaving
+ }
+
+ updateFilterBindings(filterBindings: ChannelFilterBindings) {
+ this.channel.filterBindings = filterBindings
+ }
+
+ updatePayloadTransform(callback: ChannelOnMessage) {
+ this.channel.onMessage = callback
+ }
+
+ /**
+ * @internal
+ */
+ getChannel() {
+ return this.channel
+ }
+}
+
+function phoenixChannelParams(options: RealtimeChannelOptions): Params {
+ return {
+ config: {
+ ...{
+ broadcast: { ack: false, self: false },
+ presence: { key: '', enabled: false },
+ private: false,
+ },
+ ...options.config,
+ },
+ }
+}
diff --git a/node_modules/@supabase/realtime-js/src/phoenix/presenceAdapter.ts b/node_modules/@supabase/realtime-js/src/phoenix/presenceAdapter.ts
new file mode 100644
index 0000000000000000000000000000000000000000..2b69dcff68433538ce48d6d174ab492c7c864c30
--- /dev/null
+++ b/node_modules/@supabase/realtime-js/src/phoenix/presenceAdapter.ts
@@ -0,0 +1,119 @@
+import { Presence } from '@supabase/phoenix'
+import type { PresenceState, PresenceStates } from './types'
+import type {
+ RealtimePresenceOptions,
+ RealtimePresenceState,
+ Presence as RealtimePresenceType,
+} from '../RealtimePresence'
+import ChannelAdapter from './channelAdapter'
+
+export default class PresenceAdapter {
+ private presence: Presence
+
+ constructor(channel: ChannelAdapter, opts?: RealtimePresenceOptions) {
+ const phoenixOptions = phoenixPresenceOptions(opts)
+ this.presence = new Presence(channel.getChannel(), phoenixOptions)
+
+ this.presence.onJoin((key, currentPresence, newPresence) => {
+ const onJoinPayload = PresenceAdapter.onJoinPayload(key, currentPresence, newPresence)
+ channel.getChannel().trigger('presence', onJoinPayload)
+ })
+
+ this.presence.onLeave((key, currentPresence, leftPresence) => {
+ const onLeavePayload = PresenceAdapter.onLeavePayload(key, currentPresence, leftPresence)
+ channel.getChannel().trigger('presence', onLeavePayload)
+ })
+
+ this.presence.onSync(() => {
+ channel.getChannel().trigger('presence', { event: 'sync' })
+ })
+ }
+
+ get state() {
+ return PresenceAdapter.transformState(this.presence.state)
+ }
+
+ /**
+ * @private
+ * Remove 'metas' key
+ * Change 'phx_ref' to 'presence_ref'
+ * Remove 'phx_ref' and 'phx_ref_prev'
+ *
+ * @example Transform state
+ * // returns {
+ * abc123: [
+ * { presence_ref: '2', user_id: 1 },
+ * { presence_ref: '3', user_id: 2 }
+ * ]
+ * }
+ * RealtimePresence.transformState({
+ * abc123: {
+ * metas: [
+ * { phx_ref: '2', phx_ref_prev: '1' user_id: 1 },
+ * { phx_ref: '3', user_id: 2 }
+ * ]
+ * }
+ * })
+ *
+ */
+ static transformState(state: PresenceStates): RealtimePresenceState {
+ state = cloneState(state)
+
+ return Object.getOwnPropertyNames(state).reduce((newState, key) => {
+ const presences = state[key]
+ newState[key] = transformState(presences)
+
+ return newState
+ }, {} as RealtimePresenceState)
+ }
+
+ static onJoinPayload(key: string, currentPresence: PresenceState, newPresence: PresenceState) {
+ const currentPresences = parseCurrentPresences(currentPresence)
+ const newPresences = transformState(newPresence)
+
+ return {
+ event: 'join',
+ key,
+ currentPresences,
+ newPresences,
+ }
+ }
+
+ static onLeavePayload(key: string, currentPresence: PresenceState, leftPresence: PresenceState) {
+ const currentPresences = parseCurrentPresences(currentPresence)
+ const leftPresences = transformState(leftPresence)
+
+ return {
+ event: 'leave',
+ key,
+ currentPresences,
+ leftPresences,
+ }
+ }
+}
+
+function transformState(presences: PresenceState) {
+ return presences.metas.map((presence) => {
+ // Object spread compiles to Object.assign for ES2017, which treats __proto__ as a setter.
+ const descriptors = Object.getOwnPropertyDescriptors(presence)
+ const transformedPresence = Object.defineProperties({}, descriptors) as typeof presence
+ transformedPresence['presence_ref'] = transformedPresence['phx_ref']
+
+ delete transformedPresence['phx_ref']
+ delete transformedPresence['phx_ref_prev']
+
+ return transformedPresence
+ }) as RealtimePresenceType[]
+}
+
+function cloneState(state: PresenceStates): PresenceStates {
+ return JSON.parse(JSON.stringify(state))
+}
+
+function phoenixPresenceOptions(opts?: RealtimePresenceOptions) {
+ return opts?.events && { events: opts.events }
+}
+
+function parseCurrentPresences(currentPresences?: PresenceState) {
+ return currentPresences?.metas ? transformState(currentPresences) : []
+}
diff --git a/node_modules/@supabase/realtime-js/src/phoenix/socketAdapter.ts b/node_modules/@supabase/realtime-js/src/phoenix/socketAdapter.ts
new file mode 100644
index 0000000000000000000000000000000000000000..38203323ca4958e5cb99ff88e2acd041b2a9f372
--- /dev/null
+++ b/node_modules/@supabase/realtime-js/src/phoenix/socketAdapter.ts
@@ -0,0 +1,168 @@
+import { Socket } from '@supabase/phoenix'
+import type {
+ Message,
+ SocketOnClose,
+ SocketOnMessage,
+ SocketOnOpen,
+ SocketOnError,
+ SocketOptions,
+ SocketStateChangeCallbacks,
+ Vsn,
+ Encode,
+ Decode,
+ HeartbeatCallback,
+ Timer,
+} from './types'
+import { CONNECTION_STATE, ConnectionState } from '../lib/constants'
+import type { HeartbeatTimer, WebSocketLikeConstructor } from '../RealtimeClient'
+
+export default class SocketAdapter {
+ private socket: Socket
+
+ constructor(endPoint: string, options: SocketOptions) {
+ this.socket = new Socket(endPoint, options)
+ }
+
+ get timeout(): number {
+ return this.socket.timeout
+ }
+
+ get endPoint(): string {
+ return this.socket.endPoint
+ }
+
+ get transport(): WebSocketLikeConstructor {
+ return this.socket.transport as WebSocketLikeConstructor
+ }
+
+ get heartbeatIntervalMs(): number {
+ return this.socket.heartbeatIntervalMs
+ }
+
+ get heartbeatCallback(): HeartbeatCallback {
+ return this.socket.heartbeatCallback
+ }
+
+ set heartbeatCallback(callback: HeartbeatCallback) {
+ this.socket.heartbeatCallback = callback
+ }
+
+ get heartbeatTimer(): HeartbeatTimer {
+ return this.socket.heartbeatTimer
+ }
+
+ get pendingHeartbeatRef(): string | null {
+ return this.socket.pendingHeartbeatRef
+ }
+
+ get reconnectTimer(): Timer {
+ return this.socket.reconnectTimer
+ }
+
+ get vsn(): Vsn {
+ return this.socket.vsn
+ }
+
+ get encode(): Encode {
+ return this.socket.encode
+ }
+
+ get decode(): Decode {
+ return this.socket.decode
+ }
+
+ get reconnectAfterMs(): (tries: number) => number {
+ return this.socket.reconnectAfterMs
+ }
+
+ get sendBuffer(): (() => void)[] {
+ return this.socket.sendBuffer
+ }
+
+ get stateChangeCallbacks(): SocketStateChangeCallbacks {
+ return this.socket.stateChangeCallbacks
+ }
+
+ connect() {
+ this.socket.connect()
+ }
+
+ disconnect(
+ callback: () => void,
+ code?: number,
+ reason?: string,
+ timeout: number = 10000
+ ): Promise<'ok' | 'timeout'> {
+ return new Promise((resolve) => {
+ setTimeout(() => resolve('timeout'), timeout)
+ this.socket.disconnect(
+ () => {
+ callback()
+ resolve('ok')
+ },
+ code,
+ reason
+ )
+ })
+ }
+
+ push(data: Message>) {
+ this.socket.push(data)
+ }
+
+ log(kind: string, msg: string, data?: any) {
+ this.socket.log(kind, msg, data)
+ }
+
+ makeRef(): string {
+ return this.socket.makeRef()
+ }
+
+ onOpen(callback: SocketOnOpen) {
+ this.socket.onOpen(callback)
+ }
+
+ onClose(callback: SocketOnClose) {
+ this.socket.onClose(callback)
+ }
+
+ onError(callback: SocketOnError) {
+ this.socket.onError(callback)
+ }
+
+ onMessage(callback: SocketOnMessage) {
+ this.socket.onMessage(callback)
+ }
+
+ isConnected() {
+ return this.socket.isConnected()
+ }
+
+ isConnecting() {
+ return this.socket.connectionState() == CONNECTION_STATE.connecting
+ }
+
+ isDisconnecting() {
+ return this.socket.connectionState() == CONNECTION_STATE.closing
+ }
+
+ connectionState(): ConnectionState {
+ // @ts-ignore - requires better typing and exposing type in phoenix
+ return this.socket.connectionState()
+ }
+
+ endPointURL(): string {
+ return this.socket.endPointURL()
+ }
+
+ sendHeartbeat() {
+ this.socket.sendHeartbeat()
+ }
+
+ /**
+ * @internal
+ */
+ getSocket() {
+ return this.socket
+ }
+}
diff --git a/node_modules/@supabase/realtime-js/src/phoenix/types.ts b/node_modules/@supabase/realtime-js/src/phoenix/types.ts
new file mode 100644
index 0000000000000000000000000000000000000000..917a471b6394f59abd2b2cb0d7e13d3efde7b78b
--- /dev/null
+++ b/node_modules/@supabase/realtime-js/src/phoenix/types.ts
@@ -0,0 +1,32 @@
+export type {
+ Socket,
+ SocketOptions,
+ SocketState,
+ SocketOnOpen,
+ SocketOnError,
+ SocketOnMessage,
+ SocketOnClose,
+ SocketStateChangeCallbacks,
+ Channel,
+ ChannelState,
+ ChannelEvent,
+ ChannelBindingCallback,
+ ChannelFilterBindings,
+ ChannelOnMessage,
+ ChannelOnErrorCallback,
+ PresenceState,
+ Message,
+ Params,
+ Transport,
+ Timer,
+ Vsn,
+ Encode,
+ Decode,
+ HeartbeatCallback,
+ HeartbeatStatus,
+} from '@supabase/phoenix'
+
+import type { Channel, PresenceState } from '@supabase/phoenix'
+
+export type Push = ReturnType
+export type PresenceStates = Record
diff --git a/node_modules/@supabase/storage-js/AGENTS.md b/node_modules/@supabase/storage-js/AGENTS.md
new file mode 100644
index 0000000000000000000000000000000000000000..6ec5e2b2db085eede7169747f23c3a8c9e558f28
--- /dev/null
+++ b/node_modules/@supabase/storage-js/AGENTS.md
@@ -0,0 +1,11 @@
+# Agent instructions for `@supabase/storage-js`
+
+Isomorphic storage client for Supabase. Handles bucket and object operations: upload, download, list, signed URLs, transformations.
+
+When helping a user work with this package:
+
+- **Usage and quick start**: [`README.md`](./README.md)
+- **Full API reference**: [`src/`](./src/) — every public method and type has TSDoc with `@example` blocks. Read the source for the canonical, version-pinned answer.
+- **Migration notes**: [`migrations/`](./migrations/) — per-theme markdown files for changes that need caller action.
+
+For broader Supabase guidance (docs site, MCP tools, schema and project workflows), use the centralized [Supabase agent skills](https://github.com/supabase/agent-skills): `npx skills add supabase/agent-skills`. Or pair with the Supabase MCP server via the [Supabase Plugin for AI Coding Agents](https://supabase.com/docs/guides/getting-started/plugins).
diff --git a/node_modules/@supabase/storage-js/LICENSE b/node_modules/@supabase/storage-js/LICENSE
new file mode 100644
index 0000000000000000000000000000000000000000..ddeba6a00ae5ec536d5429e040bc73ef2c6a07d6
--- /dev/null
+++ b/node_modules/@supabase/storage-js/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2020 Supabase
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/node_modules/@supabase/storage-js/README.md b/node_modules/@supabase/storage-js/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..ea1e739764262b252e16c4e9d43db4af0aad3afc
--- /dev/null
+++ b/node_modules/@supabase/storage-js/README.md
@@ -0,0 +1,1266 @@
+
+
+
+
+
+
+
+
+
+
+
Supabase Storage JS SDK
+
+ JavaScript SDK to interact with Supabase Storage, including file storage and vector embeddings.
+
+
+ Guides
+ ·
+ Reference Docs
+ ·
+ TypeDoc
+
+
+
+
+
+[](https://github.com/supabase/supabase-js/actions?query=branch%3Amaster)
+[](https://www.npmjs.com/package/@supabase/storage-js)
+[](#license)
+[](https://pkg.pr.new/~/supabase/storage-js)
+
+
+
+## Requirements
+
+- **Node.js 22 or later** (Node.js 20 support dropped in v2.110.0)
+- For browser support, all modern browsers are supported
+
+> ⚠️ **Node.js 18 Deprecation Notice**
+>
+> Node.js 18 reached end-of-life on April 30, 2025. As announced in [our deprecation notice](https://github.com/orgs/supabase/discussions/37217), support for Node.js 18 was dropped on October 31, 2025.
+
+> ⚠️ **Node.js 20 Deprecation Notice**
+>
+> Node.js 20 reached end-of-life on April 30, 2026. As announced in [our deprecation notice](https://github.com/orgs/supabase/discussions/45715), support for Node.js 20 was dropped in v2.110.0.
+
+## Features
+
+- **File Storage**: Upload, download, list, move, and delete files
+- **Access Control**: Public and private buckets with fine-grained permissions
+- **Signed URLs**: Generate time-limited URLs for secure file access
+- **Image Transformations**: On-the-fly image resizing and optimization
+- **Vector Embeddings**: Store and query high-dimensional embeddings with similarity search
+- **Analytics Buckets**: Iceberg table-based buckets optimized for analytical queries and data processing
+
+## Quick Start Guide
+
+### Installing the module
+
+```bash
+npm install @supabase/storage-js
+```
+
+### Connecting to the storage backend
+
+There are two ways to use the Storage SDK:
+
+#### Option 1: Via Supabase Client (Recommended)
+
+If you're already using `@supabase/supabase-js`, access storage through the client:
+
+```js
+import { createClient } from '@supabase/supabase-js'
+
+// Use publishable key for frontend applications
+const supabase = createClient('https://.supabase.co', '')
+
+// Access storage
+const storage = supabase.storage
+
+// Access different bucket types
+const regularBucket = storage.from('my-bucket')
+const vectorBucket = storage.vectors.from('embeddings-bucket')
+const analyticsBucket = storage.analytics // Analytics API
+```
+
+#### Option 2: Standalone StorageClient
+
+For backend applications or when you need to bypass Row Level Security:
+
+```js
+import { StorageClient } from '@supabase/storage-js'
+
+const STORAGE_URL = 'https://.supabase.co/storage/v1'
+const SERVICE_KEY = '' // Use secret key for backend operations
+
+const storageClient = new StorageClient(STORAGE_URL, {
+ apikey: SERVICE_KEY,
+ Authorization: `Bearer ${SERVICE_KEY}`,
+})
+
+// Access different bucket types
+const regularBucket = storageClient.from('my-bucket')
+const vectorBucket = storageClient.vectors.from('embeddings-bucket')
+const analyticsBucket = storageClient.analytics // Analytics API
+```
+
+> **When to use each approach:**
+>
+> - Use `supabase.storage` when working with other Supabase features (auth, database, etc.) in frontend applications
+> - Use `new StorageClient()` for backend applications, Edge Functions, or when you need to bypass RLS policies
+
+> **Note:** Refer to the [Storage Access Control guide](https://supabase.com/docs/guides/storage/access-control) for detailed information on creating RLS policies.
+
+### Understanding Bucket Types
+
+Supabase Storage supports three types of buckets, each optimized for different use cases:
+
+#### 1. Regular Storage Buckets (File Storage)
+
+Standard buckets for storing files, images, videos, and other assets.
+
+```js
+// Create regular storage bucket
+const { data, error } = await storageClient.createBucket('my-files', {
+ public: false,
+})
+
+// Upload files
+await storageClient.from('my-files').upload('avatar.png', file)
+```
+
+**Use cases:** User uploads, media assets, documents, backups
+
+#### 2. Vector Buckets (Embeddings Storage)
+
+Specialized buckets for storing and querying high-dimensional vector embeddings.
+
+```js
+// Create vector bucket
+await storageClient.vectors.createBucket('embeddings-prod')
+
+// Create index and insert vectors
+const bucket = storageClient.vectors.from('embeddings-prod')
+await bucket.createIndex({
+ indexName: 'documents',
+ dimension: 1536,
+ distanceMetric: 'cosine',
+})
+```
+
+**Use cases:** Semantic search, AI-powered recommendations, similarity matching
+
+**[See full Vector Embeddings documentation below](#vector-embeddings)**
+
+#### 3. Analytics Buckets
+
+Specialized buckets using Apache Iceberg table format, optimized for analytical queries and large-scale data processing.
+
+```js
+// Create analytics bucket
+await storageClient.analytics.createBucket('analytics-data')
+
+// List analytics buckets
+const { data, error } = await storageClient.analytics.listBuckets()
+
+// Delete analytics bucket
+await storageClient.analytics.deleteBucket('analytics-data')
+```
+
+**Use cases:** Time-series data, analytical queries, data lakes, large-scale data processing, business intelligence
+
+**[See full Analytics Buckets documentation below](#analytics-buckets)**
+
+---
+
+### Handling resources
+
+#### Handling Storage Buckets
+
+- Create a new Storage bucket:
+
+ ```js
+ const { data, error } = await storageClient.createBucket(
+ 'test_bucket', // Bucket name (must be unique)
+ { public: false } // Bucket options
+ )
+ ```
+
+- Retrieve the details of an existing Storage bucket:
+
+ ```js
+ const { data, error } = await storageClient.getBucket('test_bucket')
+ ```
+
+- Update a new Storage bucket:
+
+ ```js
+ const { data, error } = await storageClient.updateBucket(
+ 'test_bucket', // Bucket name
+ { public: false } // Bucket options
+ )
+ ```
+
+- Remove all objects inside a single bucket:
+
+ ```js
+ const { data, error } = await storageClient.emptyBucket('test_bucket')
+ ```
+
+- Delete an existing bucket (a bucket can't be deleted with existing objects inside it):
+
+ ```js
+ const { data, error } = await storageClient.deleteBucket('test_bucket')
+ ```
+
+- Retrieve the details of all Storage buckets within an existing project:
+
+ ```js
+ // List all buckets
+ const { data, error } = await storageClient.listBuckets()
+
+ // List buckets with options (pagination, sorting, search)
+ const { data, error } = await storageClient.listBuckets({
+ limit: 10,
+ offset: 0,
+ sortColumn: 'created_at',
+ sortOrder: 'desc',
+ search: 'prod',
+ })
+ ```
+
+#### Handling Files
+
+- Upload a file to an existing bucket:
+
+ ```js
+ const fileBody = ... // load your file here
+
+ const { data, error } = await storageClient.from('bucket').upload('path/to/file', fileBody)
+ ```
+
+ > Note:
+ > The path in `data.Key` is prefixed by the bucket ID and is not the value which should be passed to the `download` method in order to fetch the file.
+ > To fetch the file via the `download` method, use `data.path` and `data.bucketId` as follows:
+ >
+ > ```javascript
+ > const { data, error } = await storageClient.from('bucket').upload('/folder/file.txt', fileBody)
+ > // check for errors
+ > const { data2, error2 } = await storageClient.from(data.bucketId).download(data.path)
+ > ```
+
+ > Note: The `upload` method also accepts a map of optional parameters. For a complete list see the [Supabase API reference](https://supabase.com/docs/reference/javascript/storage-from-upload).
+
+- Download a file from an exisiting bucket:
+
+ ```js
+ const { data, error } = await storageClient.from('bucket').download('path/to/file')
+ ```
+
+- List all the files within a bucket:
+
+ ```js
+ const { data, error } = await storageClient.from('bucket').list('folder')
+ ```
+
+ > Note: The `list` method also accepts a map of optional parameters. For a complete list see the [Supabase API reference](https://supabase.com/docs/reference/javascript/storage-from-list).
+
+- Replace an existing file at the specified path with a new one:
+
+ ```js
+ const fileBody = ... // load your file here
+
+ const { data, error } = await storageClient
+ .from('bucket')
+ .update('path/to/file', fileBody)
+ ```
+
+ > Note: The `upload` method also accepts a map of optional parameters. For a complete list see the [Supabase API reference](https://supabase.com/docs/reference/javascript/storage-from-upload).
+
+- Move an existing file:
+
+ ```js
+ const { data, error } = await storageClient
+ .from('bucket')
+ .move('old/path/to/file', 'new/path/to/file')
+ ```
+
+- Delete files within the same bucket:
+
+ ```js
+ const { data, error } = await storageClient.from('bucket').remove(['path/to/file'])
+ ```
+
+- Create signed URL to download file without requiring permissions:
+
+ ```js
+ const expireIn = 60
+
+ const { data, error } = await storageClient
+ .from('bucket')
+ .createSignedUrl('path/to/file', expireIn)
+ ```
+
+- Retrieve URLs for assets in public buckets:
+
+ ```js
+ const { data, error } = await storageClient.from('public-bucket').getPublicUrl('path/to/file')
+ ```
+
+## Analytics Buckets
+
+Supabase Storage provides specialized analytics buckets using Apache Iceberg table format, optimized for analytical workloads and large-scale data processing. These buckets are designed for data lake architectures, time-series data, and business intelligence applications.
+
+### What are Analytics Buckets?
+
+Analytics buckets use the Apache Iceberg open table format, providing:
+
+- **ACID transactions** for data consistency
+- **Schema evolution** without data rewrites
+- **Time travel** to query historical data
+- **Efficient metadata management** for large datasets
+- **Optimized for analytical queries** rather than individual file operations
+
+### When to Use Analytics Buckets
+
+**Use analytics buckets for:**
+
+- Time-series data (logs, metrics, events)
+- Data lake architectures
+- Business intelligence and reporting
+- Large-scale batch processing
+- Analytical workloads requiring ACID guarantees
+
+**Use regular storage buckets for:**
+
+- User file uploads (images, documents, videos)
+- Individual file management
+- Content delivery
+- Simple object storage needs
+
+### Quick Start
+
+You can access analytics functionality through the `analytics` property on your storage client:
+
+#### Via Supabase Client
+
+```typescript
+import { createClient } from '@supabase/supabase-js'
+
+const supabase = createClient('https://your-project.supabase.co', 'your-publishable-key')
+
+// Access analytics operations
+const analytics = supabase.storage.analytics
+
+// Create an analytics bucket
+const { data, error } = await analytics.createBucket('analytics-data')
+if (error) {
+ console.error('Failed to create analytics bucket:', error.message)
+} else {
+ console.log('Created bucket:', data.name)
+}
+```
+
+#### Via StorageClient
+
+```typescript
+import { StorageClient } from '@supabase/storage-js'
+
+const storageClient = new StorageClient('https://your-project.supabase.co/storage/v1', {
+ apikey: 'YOUR_API_KEY',
+ Authorization: 'Bearer YOUR_TOKEN',
+})
+
+// Access analytics operations
+const analytics = storageClient.analytics
+
+// Create an analytics bucket
+await analytics.createBucket('analytics-data')
+```
+
+### API Reference
+
+#### Create Analytics Bucket
+
+Creates a new analytics bucket using Iceberg table format:
+
+```typescript
+const { data, error } = await analytics.createBucket('my-analytics-bucket')
+
+if (error) {
+ console.error('Error:', error.message)
+} else {
+ console.log('Created bucket:', data)
+}
+```
+
+**Returns:**
+
+```typescript
+{
+ data: {
+ id: string
+ type: 'ANALYTICS'
+ format: string
+ created_at: string
+ updated_at: string
+ } | null
+ error: StorageError | null
+}
+```
+
+#### List Analytics Buckets
+
+Retrieves all analytics buckets in your project with optional filtering and pagination:
+
+```typescript
+const { data, error } = await analytics.listBuckets({
+ limit: 10,
+ offset: 0,
+ sortColumn: 'created_at',
+ sortOrder: 'desc',
+ search: 'prod',
+})
+
+if (data) {
+ console.log(`Found ${data.length} analytics buckets`)
+ data.forEach((bucket) => {
+ console.log(`- ${bucket.id} (created: ${bucket.created_at})`)
+ })
+}
+```
+
+**Parameters:**
+
+- `limit?: number` - Maximum number of buckets to return
+- `offset?: number` - Number of buckets to skip (for pagination)
+- `sortColumn?: 'id' | 'name' | 'created_at' | 'updated_at'` - Column to sort by
+- `sortOrder?: 'asc' | 'desc'` - Sort direction
+- `search?: string` - Search term to filter bucket names
+
+**Returns:**
+
+```typescript
+{
+ data: AnalyticBucket[] | null
+ error: StorageError | null
+}
+```
+
+**Example with Pagination:**
+
+```typescript
+// Fetch first page
+const firstPage = await analytics.listBuckets({
+ limit: 100,
+ offset: 0,
+ sortColumn: 'created_at',
+ sortOrder: 'desc',
+})
+
+// Fetch second page
+const secondPage = await analytics.listBuckets({
+ limit: 100,
+ offset: 100,
+ sortColumn: 'created_at',
+ sortOrder: 'desc',
+})
+```
+
+#### Delete Analytics Bucket
+
+Deletes an analytics bucket. The bucket must be empty before deletion.
+
+```typescript
+const { data, error } = await analytics.deleteBucket('old-analytics-bucket')
+
+if (error) {
+ console.error('Failed to delete:', error.message)
+} else {
+ console.log('Bucket deleted:', data.message)
+}
+```
+
+**Returns:**
+
+```typescript
+{
+ data: { message: string } | null
+ error: StorageError | null
+}
+```
+
+> **Note:** A bucket cannot be deleted if it contains data. You must empty the bucket first.
+
+#### Get Iceberg Catalog for Advanced Operations
+
+For advanced operations like creating tables, namespaces, and querying Iceberg metadata, use the `from()` method to get a configured [iceberg-js](https://github.com/supabase/iceberg-js) client:
+
+```typescript
+// Get an Iceberg REST Catalog client for your analytics bucket
+const catalog = analytics.from('analytics-data')
+
+// Create a namespace
+await catalog.createNamespace({ namespace: ['default'] }, { properties: { owner: 'data-team' } })
+
+// Create a table with schema
+await catalog.createTable(
+ { namespace: ['default'] },
+ {
+ name: 'events',
+ schema: {
+ type: 'struct',
+ fields: [
+ { id: 1, name: 'id', type: 'long', required: true },
+ { id: 2, name: 'timestamp', type: 'timestamp', required: true },
+ { id: 3, name: 'user_id', type: 'string', required: false },
+ ],
+ 'schema-id': 0,
+ 'identifier-field-ids': [1],
+ },
+ 'partition-spec': {
+ 'spec-id': 0,
+ fields: [],
+ },
+ 'write-order': {
+ 'order-id': 0,
+ fields: [],
+ },
+ properties: {
+ 'write.format.default': 'parquet',
+ },
+ }
+)
+
+// List tables in namespace
+const tables = await catalog.listTables({ namespace: ['default'] })
+console.log(tables) // [{ namespace: ['default'], name: 'events' }]
+
+// Load table metadata
+const table = await catalog.loadTable({ namespace: ['default'], name: 'events' })
+
+// Update table properties
+await catalog.updateTable(
+ { namespace: ['default'], name: 'events' },
+ { properties: { 'read.split.target-size': '134217728' } }
+)
+
+// Drop table
+await catalog.dropTable({ namespace: ['default'], name: 'events' })
+
+// Drop namespace
+await catalog.dropNamespace({ namespace: ['default'] })
+```
+
+**Returns:** `IcebergRestCatalog` instance from [iceberg-js](https://github.com/supabase/iceberg-js)
+
+> **Note:** The `from()` method returns an Iceberg REST Catalog client that provides full access to the Apache Iceberg REST API. For complete documentation of available operations, see the [iceberg-js documentation](https://supabase.github.io/iceberg-js/).
+
+### Error Handling
+
+Analytics buckets use the same error handling pattern as the rest of the Storage SDK:
+
+```typescript
+const { data, error } = await analytics.createBucket('my-bucket')
+
+if (error) {
+ console.error('Error:', error.message)
+ console.error('Status:', error.status)
+ console.error('Status Code:', error.statusCode)
+ // Handle error appropriately
+}
+```
+
+#### Throwing Errors
+
+You can configure the client to throw errors instead of returning them:
+
+```typescript
+const analytics = storageClient.analytics
+analytics.throwOnError()
+
+try {
+ const { data } = await analytics.createBucket('my-bucket')
+ // data is guaranteed to be present
+ console.log('Success:', data)
+} catch (error) {
+ if (error instanceof StorageApiError) {
+ console.error('API Error:', error.statusCode, error.message)
+ }
+}
+```
+
+### TypeScript Types
+
+The library exports TypeScript types for analytics buckets:
+
+```typescript
+import type { AnalyticBucket, BucketType, StorageError } from '@supabase/storage-js'
+
+// AnalyticBucket type
+interface AnalyticBucket {
+ id: string
+ type: 'ANALYTICS'
+ format: string
+ created_at: string
+ updated_at: string
+}
+```
+
+### Common Patterns
+
+#### Checking if a Bucket Exists
+
+```typescript
+async function bucketExists(bucketName: string): Promise {
+ const { data, error } = await analytics.listBuckets({
+ search: bucketName,
+ })
+
+ if (error) {
+ console.error('Error checking bucket:', error.message)
+ return false
+ }
+
+ return data?.some((bucket) => bucket.id === bucketName) ?? false
+}
+```
+
+#### Creating Bucket with Error Handling
+
+```typescript
+async function ensureAnalyticsBucket(bucketName: string) {
+ // Try to create the bucket
+ const { data, error } = await analytics.createBucket(bucketName)
+
+ if (error) {
+ // Check if bucket already exists (conflict error)
+ if (error.statusCode === '409') {
+ console.log(`Bucket '${bucketName}' already exists`)
+ return { success: true, created: false }
+ }
+
+ // Other error occurred
+ console.error('Failed to create bucket:', error.message)
+ return { success: false, error }
+ }
+
+ console.log(`Created new bucket: '${bucketName}'`)
+ return { success: true, created: true, data }
+}
+```
+
+#### Listing All Buckets with Pagination
+
+```typescript
+async function getAllAnalyticsBuckets() {
+ const allBuckets: AnalyticBucket[] = []
+ let offset = 0
+ const limit = 100
+
+ while (true) {
+ const { data, error } = await analytics.listBuckets({
+ limit,
+ offset,
+ sortColumn: 'created_at',
+ sortOrder: 'desc',
+ })
+
+ if (error) {
+ console.error('Error fetching buckets:', error.message)
+ break
+ }
+
+ if (!data || data.length === 0) {
+ break
+ }
+
+ allBuckets.push(...data)
+
+ // If we got fewer results than the limit, we've reached the end
+ if (data.length < limit) {
+ break
+ }
+
+ offset += limit
+ }
+
+ return allBuckets
+}
+```
+
+## Vector Embeddings
+
+Supabase Storage provides built-in support for storing and querying high-dimensional vector embeddings, powered by S3 Vectors. This enables semantic search, similarity matching, and AI-powered applications without needing a separate vector database.
+
+> **Note:** Vector embeddings functionality is available in `@supabase/storage-js` v2.76 and later.
+
+### Features
+
+- **Vector Buckets**: Organize vector indexes into logical containers
+- **Vector Indexes**: Define schemas with configurable dimensions and distance metrics
+- **Batch Operations**: Insert/update/delete up to 500 vectors per request
+- **Similarity Search**: Query for nearest neighbors using cosine, euclidean, or dot product distance
+- **Metadata Filtering**: Store and filter vectors by arbitrary JSON metadata
+- **Pagination**: Efficiently scan large vector datasets
+- **Parallel Scanning**: Distribute scans across multiple workers for high throughput
+- **Cross-platform**: Works in Node.js, browsers, and edge runtimes
+
+### Quick Start
+
+You can access vector functionality in three ways, depending on your use case:
+
+#### Option 1: Via Supabase Client (Most Common)
+
+If you're using the full Supabase client:
+
+```typescript
+import { createClient } from '@supabase/supabase-js'
+
+const supabase = createClient('https://your-project.supabase.co', 'your-publishable-key')
+
+// Access vector operations through storage
+const vectors = supabase.storage.vectors
+
+// Create a vector bucket
+await vectors.createBucket('embeddings-prod')
+
+// Create an index
+const bucket = vectors.from('embeddings-prod')
+await bucket.createIndex({
+ indexName: 'documents-openai',
+ dataType: 'float32',
+ dimension: 1536,
+ distanceMetric: 'cosine',
+})
+
+// Insert vectors
+const index = bucket.index('documents-openai')
+await index.putVectors({
+ vectors: [
+ {
+ key: 'doc-1',
+ data: { float32: [0.1, 0.2, 0.3 /* ...1536 dimensions */] },
+ metadata: { title: 'Introduction', category: 'docs' },
+ },
+ ],
+})
+
+// Query similar vectors
+const { data, error } = await index.queryVectors({
+ queryVector: { float32: [0.15, 0.25, 0.35 /* ...1536 dimensions */] },
+ topK: 5,
+ returnDistance: true,
+ returnMetadata: true,
+})
+
+if (data) {
+ data.matches.forEach((match) => {
+ console.log(`${match.key}: distance=${match.distance}`)
+ console.log('Metadata:', match.metadata)
+ })
+}
+```
+
+#### Option 2: Via StorageClient
+
+If you're using the standalone `StorageClient` for storage operations, access vectors through the `vectors` property:
+
+```typescript
+import { StorageClient } from '@supabase/storage-js'
+
+const storageClient = new StorageClient('https://your-project.supabase.co/storage/v1', {
+ apikey: 'YOUR_API_KEY',
+ Authorization: 'Bearer YOUR_TOKEN',
+})
+
+// Access vector operations
+const vectors = storageClient.vectors
+
+// Use the same API as shown in Option 1
+await vectors.createBucket('embeddings-prod')
+const bucket = vectors.from('embeddings-prod')
+// ... rest of operations
+```
+
+#### Option 3: Standalone Vector Client
+
+For vector-only applications that don't need regular file storage operations:
+
+```typescript
+import { StorageVectorsClient } from '@supabase/storage-js'
+
+// Initialize standalone vector client
+const vectorClient = new StorageVectorsClient('https://your-project.supabase.co/storage/v1', {
+ headers: { Authorization: 'Bearer YOUR_TOKEN' },
+})
+
+// Use the same API as shown in Option 1
+await vectorClient.createBucket('embeddings-prod')
+const bucket = vectorClient.from('embeddings-prod')
+// ... rest of operations
+```
+
+> **When to use each approach:**
+>
+> - **Option 1**: When using other Supabase features (auth, database, realtime)
+> - **Option 2**: When working with both file storage and vectors
+> - **Option 3**: For dedicated vector-only applications without file storage
+
+### API Reference
+
+#### Client Initialization
+
+```typescript
+const vectorClient = new StorageVectorsClient(url, options?)
+```
+
+**Options:**
+
+- `headers?: Record` - Custom HTTP headers (e.g., Authorization)
+- `fetch?: Fetch` - Custom fetch implementation
+
+#### Vector Buckets
+
+Vector buckets are top-level containers for organizing vector indexes.
+
+##### Create Bucket
+
+```typescript
+const { data, error } = await vectorClient.createBucket('my-bucket')
+```
+
+##### Get Bucket
+
+```typescript
+const { data, error } = await vectorClient.getBucket('my-bucket')
+console.log('Created at:', new Date(data.vectorBucket.creationTime! * 1000))
+```
+
+##### List Buckets
+
+```typescript
+const { data, error } = await vectorClient.listBuckets({
+ prefix: 'prod-',
+ maxResults: 100,
+})
+
+// Pagination
+if (data?.nextToken) {
+ const next = await vectorClient.listBuckets({ nextToken: data.nextToken })
+}
+```
+
+##### Delete Bucket
+
+```typescript
+// Bucket must be empty (all indexes deleted first)
+const { error } = await vectorClient.deleteBucket('my-bucket')
+```
+
+#### Vector Indexes
+
+Vector indexes define the schema for embeddings including dimension and distance metric.
+
+##### Create Index
+
+```typescript
+const bucket = vectorClient.from('my-bucket')
+
+await bucket.createIndex({
+ indexName: 'my-index',
+ dataType: 'float32',
+ dimension: 1536,
+ distanceMetric: 'cosine', // 'cosine' | 'euclidean' | 'dotproduct'
+ metadataConfiguration: {
+ nonFilterableMetadataKeys: ['raw_text', 'internal_id'],
+ },
+})
+```
+
+**Distance Metrics:**
+
+- `cosine` - Cosine similarity (normalized dot product)
+- `euclidean` - Euclidean distance (L2 norm)
+- `dotproduct` - Dot product similarity
+
+##### Get Index
+
+```typescript
+const { data, error } = await bucket.getIndex('my-index')
+console.log('Dimension:', data?.index.dimension)
+console.log('Distance metric:', data?.index.distanceMetric)
+```
+
+##### List Indexes
+
+```typescript
+const { data, error } = await bucket.listIndexes({
+ prefix: 'documents-',
+ maxResults: 100,
+})
+```
+
+##### Delete Index
+
+```typescript
+// Deletes index and all its vectors
+await bucket.deleteIndex('my-index')
+```
+
+#### Vector Operations
+
+##### Insert/Update Vectors (Upsert)
+
+```typescript
+const index = vectorClient.from('my-bucket').index('my-index')
+
+await index.putVectors({
+ vectors: [
+ {
+ key: 'unique-id-1',
+ data: {
+ float32: [
+ /* 1536 numbers */
+ ],
+ },
+ metadata: {
+ title: 'Document Title',
+ category: 'technical',
+ page: 1,
+ },
+ },
+ // ... up to 500 vectors per request
+ ],
+})
+```
+
+**Limitations:**
+
+- 1-500 vectors per request
+- Vectors must match index dimension
+- Keys must be unique within index
+
+##### Get Vectors by Key
+
+```typescript
+const { data, error } = await index.getVectors({
+ keys: ['doc-1', 'doc-2', 'doc-3'],
+ returnData: true, // Include embeddings
+ returnMetadata: true, // Include metadata
+})
+
+data?.vectors.forEach((v) => {
+ console.log(v.key, v.metadata)
+})
+```
+
+##### Query Similar Vectors (ANN Search)
+
+```typescript
+const { data, error } = await index.queryVectors({
+ queryVector: {
+ float32: [
+ /* 1536 numbers */
+ ],
+ },
+ topK: 10,
+ filter: {
+ category: 'technical',
+ published: true,
+ },
+ returnDistance: true,
+ returnMetadata: true,
+})
+
+// Results ordered by similarity
+data?.matches.forEach((match) => {
+ console.log(`${match.key}: distance=${match.distance}`)
+})
+```
+
+**Filter Syntax:**
+The `filter` parameter accepts arbitrary JSON for metadata filtering. Non-filterable keys (configured at index creation) cannot be used in filters but can still be returned.
+
+##### List/Scan Vectors
+
+```typescript
+// Simple pagination
+let nextToken: string | undefined
+do {
+ const { data } = await index.listVectors({
+ maxResults: 500,
+ nextToken,
+ returnMetadata: true,
+ })
+
+ console.log('Batch:', data?.vectors.length)
+ nextToken = data?.nextToken
+} while (nextToken)
+
+// Parallel scanning (4 workers)
+const workers = [0, 1, 2, 3].map(async (segmentIndex) => {
+ const { data } = await index.listVectors({
+ segmentCount: 4,
+ segmentIndex,
+ returnMetadata: true,
+ })
+ return data?.vectors || []
+})
+
+const results = await Promise.all(workers)
+const allVectors = results.flat()
+```
+
+**Limitations:**
+
+- `maxResults`: 1-1000 (default: 500)
+- `segmentCount`: 1-16
+- Response may be limited by 1MB size
+
+##### Delete Vectors
+
+```typescript
+await index.deleteVectors({
+ keys: ['doc-1', 'doc-2', 'doc-3'],
+ // ... up to 500 keys per request
+})
+```
+
+### Error Handling
+
+The library uses a consistent error handling pattern:
+
+```typescript
+const { data, error } = await vectorClient.createBucket('my-bucket')
+
+if (error) {
+ console.error('Error:', error.message)
+ console.error('Status:', error.status)
+ console.error('Code:', error.statusCode)
+}
+```
+
+#### Error Codes
+
+| Code | HTTP | Description |
+| ---------------------------- | ---- | ----------------------- |
+| `InternalError` | 500 | Internal server error |
+| `S3VectorConflictException` | 409 | Resource already exists |
+| `S3VectorNotFoundException` | 404 | Resource not found |
+| `S3VectorBucketNotEmpty` | 400 | Bucket contains indexes |
+| `S3VectorMaxBucketsExceeded` | 400 | Bucket quota exceeded |
+| `S3VectorMaxIndexesExceeded` | 400 | Index quota exceeded |
+
+#### Throwing Errors
+
+You can configure the client to throw errors instead:
+
+```typescript
+const vectorClient = new StorageVectorsClient(url, options)
+vectorClient.throwOnError()
+
+try {
+ const { data } = await vectorClient.createBucket('my-bucket')
+ // data is guaranteed to be present
+} catch (error) {
+ if (error instanceof StorageVectorsApiError) {
+ console.error('API Error:', error.statusCode)
+ }
+}
+```
+
+### Advanced Usage
+
+#### Scoped Clients
+
+Create scoped clients for cleaner code:
+
+```typescript
+// Bucket-scoped operations
+const bucket = vectorClient.from('embeddings-prod')
+await bucket.createIndex({
+ /* ... */
+})
+await bucket.listIndexes()
+
+// Index-scoped operations
+const index = bucket.index('documents-openai')
+await index.putVectors({
+ /* ... */
+})
+await index.queryVectors({
+ /* ... */
+})
+```
+
+#### Custom Fetch
+
+Provide a custom fetch implementation:
+
+```typescript
+import { StorageVectorsClient } from '@supabase/storage-js'
+
+const vectorClient = new StorageVectorsClient(url, {
+ fetch: customFetch,
+ headers: {
+ /* ... */
+ },
+})
+```
+
+#### Batch Processing
+
+Process large datasets in batches:
+
+```typescript
+async function insertLargeDataset(vectors: VectorObject[]) {
+ const batchSize = 500
+
+ for (let i = 0; i < vectors.length; i += batchSize) {
+ const batch = vectors.slice(i, i + batchSize)
+ await index.putVectors({ vectors: batch })
+ console.log(`Inserted ${i + batch.length}/${vectors.length}`)
+ }
+}
+```
+
+#### Float32 Validation
+
+Ensure vectors are properly normalized to float32:
+
+```typescript
+import { normalizeToFloat32 } from '@supabase/storage-js'
+
+const vector = normalizeToFloat32([0.1, 0.2, 0.3 /* ... */])
+```
+
+### Type Definitions
+
+The library exports comprehensive TypeScript types:
+
+```typescript
+import type {
+ VectorBucket,
+ VectorIndex,
+ VectorData,
+ VectorObject,
+ VectorMatch,
+ VectorMetadata,
+ DistanceMetric,
+ ApiResponse,
+ StorageVectorsError,
+} from '@supabase/storage-js'
+```
+
+## Development
+
+This package is part of the [Supabase JavaScript monorepo](https://github.com/supabase/supabase-js). To work on this package:
+
+### Building
+
+#### Build Scripts Overview
+
+```bash
+# Build the package
+pnpm nx build storage-js
+
+# Watch mode for development
+pnpm nx build storage-js --watch
+
+# Generate documentation
+pnpm nx docs storage-js
+```
+
+### Testing
+
+**Important:** The storage-js tests require a local Supabase stack running via the Supabase CLI. Docker must be running since the Supabase CLI uses it internally.
+
+#### Prerequisites
+
+1. **Docker** must be installed and running (used by Supabase CLI internally)
+2. **Supabase CLI** — installed automatically via `pnpm exec supabase`
+
+#### Test Scripts Overview
+
+| Script | Description | What it does |
+| ----------------- | --------------------------------- | ----------------------------------------------------------------- |
+| `test:storage` | **Complete test workflow** | Runs the full test cycle: clean → start infra → run tests → clean |
+| `test:suite` | **Jest tests only** | Runs Jest tests with coverage (requires infra to be running) |
+| `test:infra` | **Start test infrastructure** | Starts Supabase CLI stack (PostgreSQL, Storage API, Kong, etc.) |
+| `test:clean-post` | **Stop and clean infrastructure** | Stops the Supabase CLI stack |
+
+#### Running Tests
+
+##### Option 1: Complete Test Run (Recommended)
+
+This handles everything automatically - starting infrastructure, running tests, and cleaning up:
+
+```bash
+# From monorepo root
+pnpm nx test:storage storage-js
+```
+
+This command will:
+
+1. Stop any existing test containers
+2. Build and start fresh test infrastructure
+3. Wait for services to be ready
+4. Run all Jest tests with coverage
+5. Clean up all containers after tests complete
+
+##### Option 2: Manual Infrastructure Management
+
+Useful for development when you want to run tests multiple times without restarting Docker:
+
+```bash
+# Step 1: Start the test infrastructure
+# From root
+pnpm nx test:infra storage-js
+# This starts: PostgreSQL, Storage API, Kong Gateway, and imgproxy
+
+# Step 2: Run tests (can run multiple times)
+pnpm nx test:suite storage-js
+
+# Step 3: When done, clean up the infrastructure
+pnpm nx test:clean-post storage-js
+```
+
+##### Option 3: Development Mode
+
+For actively developing and debugging tests:
+
+```bash
+# Start infrastructure once (from root)
+pnpm nx test:infra storage-js
+
+# Run tests in watch mode
+pnpm nx test:suite storage-js --watch
+
+# Clean up when done
+pnpm nx test:clean-post storage-js
+```
+
+#### Test Infrastructure Details
+
+The test infrastructure is managed via the Supabase CLI (`pnpm exec supabase start --workdir test`), which starts a local Supabase stack defined by the config in `test/`. This includes PostgreSQL, the Storage API, Kong Gateway, and supporting services.
+
+#### Common Issues and Solutions
+
+| Issue | Solution |
+| --------------------------------- | ------------------------------------------------------------------------------------------------- |
+| Port conflicts | Another service is using a required port. Run `pnpm nx test:clean-post storage-js` then try again |
+| "request failed, reason:" errors | Infrastructure isn't running. Run `pnpm nx test:infra storage-js` first |
+| Tests fail with connection errors | Ensure Docker is running (Supabase CLI requires Docker) |
+| Stack already running | Run `pnpm nx test:clean-post storage-js` to stop it before restarting |
+
+#### Understanding Test Failures
+
+- **StorageUnknownError with "request failed"**: Infrastructure not running
+- **Snapshot failures**: Expected test data has changed — review and update snapshots if needed
+
+### Contributing
+
+We welcome contributions! Please see our [Contributing Guide](../../../CONTRIBUTING.md) for details on how to get started.
+
+For major changes or if you're unsure about something, please open an issue first to discuss your proposed changes.
diff --git a/node_modules/@supabase/storage-js/dist/index.cjs b/node_modules/@supabase/storage-js/dist/index.cjs
new file mode 100644
index 0000000000000000000000000000000000000000..6656b512bed4f91f558adaf746721363be2760fa
--- /dev/null
+++ b/node_modules/@supabase/storage-js/dist/index.cjs
@@ -0,0 +1,3135 @@
+let iceberg_js = require("iceberg-js");
+
+//#region \0@oxc-project+runtime@0.103.0/helpers/typeof.js
+function _typeof(o) {
+ "@babel/helpers - typeof";
+ return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function(o$1) {
+ return typeof o$1;
+ } : function(o$1) {
+ return o$1 && "function" == typeof Symbol && o$1.constructor === Symbol && o$1 !== Symbol.prototype ? "symbol" : typeof o$1;
+ }, _typeof(o);
+}
+
+//#endregion
+//#region \0@oxc-project+runtime@0.103.0/helpers/toPrimitive.js
+function toPrimitive(t, r) {
+ if ("object" != _typeof(t) || !t) return t;
+ var e = t[Symbol.toPrimitive];
+ if (void 0 !== e) {
+ var i = e.call(t, r || "default");
+ if ("object" != _typeof(i)) return i;
+ throw new TypeError("@@toPrimitive must return a primitive value.");
+ }
+ return ("string" === r ? String : Number)(t);
+}
+
+//#endregion
+//#region \0@oxc-project+runtime@0.103.0/helpers/toPropertyKey.js
+function toPropertyKey(t) {
+ var i = toPrimitive(t, "string");
+ return "symbol" == _typeof(i) ? i : i + "";
+}
+
+//#endregion
+//#region \0@oxc-project+runtime@0.103.0/helpers/defineProperty.js
+function _defineProperty(e, r, t) {
+ return (r = toPropertyKey(r)) in e ? Object.defineProperty(e, r, {
+ value: t,
+ enumerable: !0,
+ configurable: !0,
+ writable: !0
+ }) : e[r] = t, e;
+}
+
+//#endregion
+//#region \0@oxc-project+runtime@0.103.0/helpers/objectSpread2.js
+function ownKeys(e, r) {
+ var t = Object.keys(e);
+ if (Object.getOwnPropertySymbols) {
+ var o = Object.getOwnPropertySymbols(e);
+ r && (o = o.filter(function(r$1) {
+ return Object.getOwnPropertyDescriptor(e, r$1).enumerable;
+ })), t.push.apply(t, o);
+ }
+ return t;
+}
+function _objectSpread2(e) {
+ for (var r = 1; r < arguments.length; r++) {
+ var t = null != arguments[r] ? arguments[r] : {};
+ r % 2 ? ownKeys(Object(t), !0).forEach(function(r$1) {
+ _defineProperty(e, r$1, t[r$1]);
+ }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function(r$1) {
+ Object.defineProperty(e, r$1, Object.getOwnPropertyDescriptor(t, r$1));
+ });
+ }
+ return e;
+}
+
+//#endregion
+//#region src/lib/common/errors.ts
+/**
+* Base error class for all Storage errors
+* Supports both 'storage' and 'vectors' namespaces
+*/
+var StorageError = class extends Error {
+ constructor(message, namespace = "storage", status, statusCode) {
+ super(message);
+ this.__isStorageError = true;
+ this.namespace = namespace;
+ this.name = namespace === "vectors" ? "StorageVectorsError" : "StorageError";
+ this.status = status;
+ this.statusCode = statusCode;
+ }
+ toJSON() {
+ return {
+ name: this.name,
+ message: this.message,
+ status: this.status,
+ statusCode: this.statusCode
+ };
+ }
+};
+/**
+* Type guard to check if an error is a StorageError
+* @param error - The error to check
+* @returns True if the error is a StorageError
+*/
+function isStorageError(error) {
+ return typeof error === "object" && error !== null && "__isStorageError" in error;
+}
+/**
+* API error returned from Storage service
+* Includes HTTP status code and service-specific error code
+*/
+var StorageApiError = class extends StorageError {
+ constructor(message, status, statusCode, namespace = "storage", code) {
+ super(message, namespace, status, statusCode);
+ this.name = namespace === "vectors" ? "StorageVectorsApiError" : "StorageApiError";
+ this.status = status;
+ this.statusCode = statusCode;
+ this.code = code;
+ }
+ toJSON() {
+ return _objectSpread2(_objectSpread2({}, super.toJSON()), {}, { code: this.code });
+ }
+};
+/**
+* Unknown error that doesn't match expected error patterns
+* Wraps the original error for debugging
+*/
+var StorageUnknownError = class extends StorageError {
+ constructor(message, originalError, namespace = "storage") {
+ super(message, namespace);
+ this.name = namespace === "vectors" ? "StorageVectorsUnknownError" : "StorageUnknownError";
+ this.originalError = originalError;
+ }
+};
+/**
+* @deprecated Use StorageError with namespace='vectors' instead
+* Alias for backward compatibility with existing vector storage code
+*/
+var StorageVectorsError = class extends StorageError {
+ constructor(message) {
+ super(message, "vectors");
+ }
+};
+/**
+* Type guard to check if an error is a StorageVectorsError
+* @param error - The error to check
+* @returns True if the error is a StorageVectorsError
+*/
+function isStorageVectorsError(error) {
+ return isStorageError(error) && error["namespace"] === "vectors";
+}
+/**
+* @deprecated Use StorageApiError with namespace='vectors' instead
+* Alias for backward compatibility with existing vector storage code
+*/
+var StorageVectorsApiError = class extends StorageApiError {
+ constructor(message, status, statusCode) {
+ super(message, status, statusCode, "vectors");
+ }
+};
+/**
+* @deprecated Use StorageUnknownError with namespace='vectors' instead
+* Alias for backward compatibility with existing vector storage code
+*/
+var StorageVectorsUnknownError = class extends StorageUnknownError {
+ constructor(message, originalError) {
+ super(message, originalError, "vectors");
+ }
+};
+/**
+* Error codes specific to S3 Vectors API
+* Maps AWS service errors to application-friendly error codes
+*/
+let StorageVectorsErrorCode = /* @__PURE__ */ function(StorageVectorsErrorCode$1) {
+ /** Internal server fault (HTTP 500) */
+ StorageVectorsErrorCode$1["InternalError"] = "InternalError";
+ /** Resource already exists / conflict (HTTP 409) */
+ StorageVectorsErrorCode$1["S3VectorConflictException"] = "S3VectorConflictException";
+ /** Resource not found (HTTP 404) */
+ StorageVectorsErrorCode$1["S3VectorNotFoundException"] = "S3VectorNotFoundException";
+ /** Delete bucket while not empty (HTTP 400) */
+ StorageVectorsErrorCode$1["S3VectorBucketNotEmpty"] = "S3VectorBucketNotEmpty";
+ /** Exceeds bucket quota/limit (HTTP 400) */
+ StorageVectorsErrorCode$1["S3VectorMaxBucketsExceeded"] = "S3VectorMaxBucketsExceeded";
+ /** Exceeds index quota/limit (HTTP 400) */
+ StorageVectorsErrorCode$1["S3VectorMaxIndexesExceeded"] = "S3VectorMaxIndexesExceeded";
+ return StorageVectorsErrorCode$1;
+}({});
+
+//#endregion
+//#region src/lib/common/headers.ts
+/**
+* Sets a header with case-insensitive deduplication.
+* Removes any existing headers whose name matches (case-insensitive),
+* then sets the value under the lowercase key. Does not mutate the input object.
+*
+* @param headers - Existing headers object
+* @param name - Header name to set (stored as lowercase)
+* @param value - Header value
+* @returns New headers object with the header set
+*/
+function setHeader(headers, name, value) {
+ const result = _objectSpread2({}, headers);
+ const nameLower = name.toLowerCase();
+ for (const key of Object.keys(result)) if (key.toLowerCase() === nameLower) delete result[key];
+ result[nameLower] = value;
+ return result;
+}
+/**
+* Normalizes all header keys to lowercase with case-insensitive deduplication.
+* When duplicate keys exist (differing only in case), the last value wins.
+* Does not mutate the input object.
+*
+* @param headers - Headers object to normalize
+* @returns New headers object with all keys lowercased
+*/
+function normalizeHeaders(headers) {
+ const result = {};
+ for (const [key, value] of Object.entries(headers)) result[key.toLowerCase()] = value;
+ return result;
+}
+
+//#endregion
+//#region src/lib/common/helpers.ts
+/**
+* Resolves the fetch implementation to use
+* Uses custom fetch if provided, otherwise uses native fetch
+*
+* @param customFetch - Optional custom fetch implementation
+* @returns Resolved fetch function
+*/
+const resolveFetch = (customFetch) => {
+ if (customFetch) return (...args) => customFetch(...args);
+ return (...args) => fetch(...args);
+};
+/**
+* Determine if input is a plain object
+* An object is plain if it's created by either {}, new Object(), or Object.create(null)
+*
+* @param value - Value to check
+* @returns True if value is a plain object
+* @source https://github.com/sindresorhus/is-plain-obj
+*/
+const isPlainObject = (value) => {
+ if (typeof value !== "object" || value === null) return false;
+ const prototype = Object.getPrototypeOf(value);
+ return (prototype === null || prototype === Object.prototype || Object.getPrototypeOf(prototype) === null) && !(Symbol.toStringTag in value) && !(Symbol.iterator in value);
+};
+/**
+* Recursively converts object keys from snake_case to camelCase
+* Used for normalizing API responses
+*
+* @param item - Object to convert
+* @returns Converted object with camelCase keys
+*/
+const recursiveToCamel = (item) => {
+ if (Array.isArray(item)) return item.map((el) => recursiveToCamel(el));
+ else if (typeof item === "function" || item !== Object(item)) return item;
+ const result = {};
+ Object.entries(item).forEach(([key, value]) => {
+ const newKey = key.replace(/([-_][a-z])/gi, (c) => c.toUpperCase().replace(/[-_]/g, ""));
+ result[newKey] = recursiveToCamel(value);
+ });
+ return result;
+};
+/**
+* Validates if a given bucket name is valid according to Supabase Storage API rules
+* Mirrors backend validation from: storage/src/storage/limits.ts:isValidBucketName()
+*
+* Rules:
+* - Length: 1-100 characters
+* - Allowed characters: alphanumeric (a-z, A-Z, 0-9), underscore (_), and safe special characters
+* - Safe special characters: ! - . * ' ( ) space & $ @ = ; : + , ?
+* - Forbidden: path separators (/, \), path traversal (..), leading/trailing whitespace
+*
+* AWS S3 Reference: https://docs.aws.amazon.com/AmazonS3/latest/userguide/object-keys.html
+*
+* @param bucketName - The bucket name to validate
+* @returns true if valid, false otherwise
+*/
+const isValidBucketName = (bucketName) => {
+ if (!bucketName || typeof bucketName !== "string") return false;
+ if (bucketName.length === 0 || bucketName.length > 100) return false;
+ if (bucketName.trim() !== bucketName) return false;
+ if (bucketName.includes("/") || bucketName.includes("\\")) return false;
+ return /^[\w!.\*'() &$@=;:+,?-]+$/.test(bucketName);
+};
+/**
+* Percent-encodes each segment of a storage path so URL delimiters within a
+* key (e.g. `?`, `#`) can't be interpreted as a querystring/fragment start.
+*
+* Splits on `/` so real path separators stay literal — the storage server
+* routes on them and decodes each segment back to the original key.
+*
+* @param path - A bucket id or `bucketId/objectKey` path
+* @returns The path with each `/`-delimited segment percent-encoded
+*/
+const encodeStoragePath = (path) => path.split("/").map(encodeURIComponent).join("/");
+
+//#endregion
+//#region src/lib/common/fetch.ts
+/**
+* Extracts error message from various error response formats
+* @param err - Error object from API
+* @returns Human-readable error message
+*/
+const _getErrorMessage = (err) => {
+ if (typeof err === "object" && err !== null) {
+ const e = err;
+ if (typeof e.msg === "string") return e.msg;
+ if (typeof e.message === "string") return e.message;
+ if (typeof e.error_description === "string") return e.error_description;
+ if (typeof e.error === "string") return e.error;
+ if (typeof e.error === "object" && e.error !== null) {
+ const nested = e.error;
+ if (typeof nested.message === "string") return nested.message;
+ }
+ }
+ return JSON.stringify(err);
+};
+/**
+* Handles fetch errors and converts them to Storage error types
+* @param error - The error caught from fetch
+* @param reject - Promise rejection function
+* @param options - Fetch options that may affect error handling
+* @param namespace - Error namespace ('storage' or 'vectors')
+*/
+const handleError = async (error, reject, options, namespace) => {
+ if (error !== null && typeof error === "object" && "json" in error && typeof error.json === "function") {
+ const responseError = error;
+ let status = parseInt(String(responseError.status), 10);
+ if (!Number.isFinite(status)) status = 500;
+ responseError.json().then((err) => {
+ const statusCode = (err === null || err === void 0 ? void 0 : err.statusCode) || (err === null || err === void 0 ? void 0 : err.code) || status + "";
+ reject(new StorageApiError(_getErrorMessage(err), status, statusCode, namespace, err === null || err === void 0 ? void 0 : err.code));
+ }).catch(() => {
+ const statusCode = status + "";
+ reject(new StorageApiError(responseError.statusText || `HTTP ${status} error`, status, statusCode, namespace));
+ });
+ } else reject(new StorageUnknownError(_getErrorMessage(error), error, namespace));
+};
+/**
+* Builds request parameters for fetch calls
+* @param method - HTTP method
+* @param options - Custom fetch options
+* @param parameters - Additional fetch parameters like AbortSignal
+* @param body - Request body (will be JSON stringified if plain object)
+* @returns Complete fetch request parameters
+*/
+const _getRequestParams = (method, options, parameters, body) => {
+ const params = {
+ method,
+ headers: (options === null || options === void 0 ? void 0 : options.headers) || {}
+ };
+ if (method === "GET" || method === "HEAD" || !body) return _objectSpread2(_objectSpread2({}, params), parameters);
+ if (isPlainObject(body)) {
+ var _contentType;
+ const headers = (options === null || options === void 0 ? void 0 : options.headers) || {};
+ let contentType;
+ for (const [key, value] of Object.entries(headers)) if (key.toLowerCase() === "content-type") contentType = value;
+ params.headers = setHeader(headers, "Content-Type", (_contentType = contentType) !== null && _contentType !== void 0 ? _contentType : "application/json");
+ params.body = JSON.stringify(body);
+ } else params.body = body;
+ if (options === null || options === void 0 ? void 0 : options.duplex) params.duplex = options.duplex;
+ return _objectSpread2(_objectSpread2({}, params), parameters);
+};
+/**
+* Internal request handler that wraps fetch with error handling
+* @param fetcher - Fetch function to use
+* @param method - HTTP method
+* @param url - Request URL
+* @param options - Custom fetch options
+* @param parameters - Additional fetch parameters
+* @param body - Request body
+* @param namespace - Error namespace ('storage' or 'vectors')
+* @returns Promise with parsed response or error
+*/
+async function _handleRequest(fetcher, method, url, options, parameters, body, namespace) {
+ return new Promise((resolve, reject) => {
+ fetcher(url, _getRequestParams(method, options, parameters, body)).then((result) => {
+ if (!result.ok) throw result;
+ if (options === null || options === void 0 ? void 0 : options.noResolveJson) return result;
+ if (namespace === "vectors") {
+ const contentType = result.headers.get("content-type");
+ if (result.headers.get("content-length") === "0" || result.status === 204) return {};
+ if (!contentType || !contentType.includes("application/json")) return {};
+ }
+ return result.json();
+ }).then((data) => resolve(data)).catch((error) => handleError(error, reject, options, namespace));
+ });
+}
+/**
+* Creates a fetch API with the specified namespace
+* @param namespace - Error namespace ('storage' or 'vectors')
+* @returns Object with HTTP method functions
+*/
+function createFetchApi(namespace = "storage") {
+ return {
+ get: async (fetcher, url, options, parameters) => {
+ return _handleRequest(fetcher, "GET", url, options, parameters, void 0, namespace);
+ },
+ post: async (fetcher, url, body, options, parameters) => {
+ return _handleRequest(fetcher, "POST", url, options, parameters, body, namespace);
+ },
+ put: async (fetcher, url, body, options, parameters) => {
+ return _handleRequest(fetcher, "PUT", url, options, parameters, body, namespace);
+ },
+ head: async (fetcher, url, options, parameters) => {
+ return _handleRequest(fetcher, "HEAD", url, _objectSpread2(_objectSpread2({}, options), {}, { noResolveJson: true }), parameters, void 0, namespace);
+ },
+ remove: async (fetcher, url, body, options, parameters) => {
+ return _handleRequest(fetcher, "DELETE", url, options, parameters, body, namespace);
+ }
+ };
+}
+const defaultApi = createFetchApi("storage");
+const { get, post, put, head, remove } = defaultApi;
+const vectorsApi = createFetchApi("vectors");
+
+//#endregion
+//#region src/lib/common/BaseApiClient.ts
+/**
+* @ignore
+* Base API client class for all Storage API classes
+* Provides common infrastructure for error handling and configuration
+*
+* @typeParam TError - The error type (StorageError or subclass)
+*/
+var BaseApiClient = class {
+ /**
+ * Creates a new BaseApiClient instance
+ * @param url - Base URL for API requests
+ * @param headers - Default headers for API requests
+ * @param fetch - Optional custom fetch implementation
+ * @param namespace - Error namespace ('storage' or 'vectors')
+ */
+ constructor(url, headers = {}, fetch$1, namespace = "storage") {
+ this.shouldThrowOnError = false;
+ this.url = url;
+ this.headers = normalizeHeaders(headers);
+ this.fetch = resolveFetch(fetch$1);
+ this.namespace = namespace;
+ }
+ /**
+ * Enable throwing errors instead of returning them.
+ * When enabled, errors are thrown instead of returned in { data, error } format.
+ *
+ * @returns this - For method chaining
+ */
+ throwOnError() {
+ this.shouldThrowOnError = true;
+ return this;
+ }
+ /**
+ * Set an HTTP header for the request.
+ * Creates a shallow copy of headers to avoid mutating shared state.
+ *
+ * @param name - Header name
+ * @param value - Header value
+ * @returns this - For method chaining
+ */
+ setHeader(name, value) {
+ this.headers = setHeader(this.headers, name, value);
+ return this;
+ }
+ /**
+ * Handles API operation with standardized error handling
+ * Eliminates repetitive try-catch blocks across all API methods
+ *
+ * This wrapper:
+ * 1. Executes the operation
+ * 2. Returns { data, error: null } on success
+ * 3. Returns { data: null, error } on failure (if shouldThrowOnError is false)
+ * 4. Throws error on failure (if shouldThrowOnError is true)
+ *
+ * @typeParam T - The expected data type from the operation
+ * @param operation - Async function that performs the API call
+ * @returns Promise with { data, error } tuple
+ *
+ * @example Handling an operation
+ * ```typescript
+ * async listBuckets() {
+ * return this.handleOperation(async () => {
+ * return await get(this.fetch, `${this.url}/bucket`, {
+ * headers: this.headers,
+ * })
+ * })
+ * }
+ * ```
+ */
+ async handleOperation(operation) {
+ var _this = this;
+ try {
+ return {
+ data: await operation(),
+ error: null
+ };
+ } catch (error) {
+ if (_this.shouldThrowOnError) throw error;
+ if (isStorageError(error)) return {
+ data: null,
+ error
+ };
+ throw error;
+ }
+ }
+};
+
+//#endregion
+//#region src/packages/StreamDownloadBuilder.ts
+let _Symbol$toStringTag$1;
+_Symbol$toStringTag$1 = Symbol.toStringTag;
+var StreamDownloadBuilder = class {
+ constructor(downloadFn, shouldThrowOnError) {
+ this.downloadFn = downloadFn;
+ this.shouldThrowOnError = shouldThrowOnError;
+ this[_Symbol$toStringTag$1] = "StreamDownloadBuilder";
+ this.promise = null;
+ }
+ then(onfulfilled, onrejected) {
+ return this.getPromise().then(onfulfilled, onrejected);
+ }
+ catch(onrejected) {
+ return this.getPromise().catch(onrejected);
+ }
+ finally(onfinally) {
+ return this.getPromise().finally(onfinally);
+ }
+ getPromise() {
+ if (!this.promise) this.promise = this.execute();
+ return this.promise;
+ }
+ async execute() {
+ var _this = this;
+ try {
+ return {
+ data: (await _this.downloadFn()).body,
+ error: null
+ };
+ } catch (error) {
+ if (_this.shouldThrowOnError) throw error;
+ if (isStorageError(error)) return {
+ data: null,
+ error
+ };
+ throw error;
+ }
+ }
+};
+
+//#endregion
+//#region src/packages/BlobDownloadBuilder.ts
+let _Symbol$toStringTag;
+_Symbol$toStringTag = Symbol.toStringTag;
+var BlobDownloadBuilder = class {
+ constructor(downloadFn, shouldThrowOnError) {
+ this.downloadFn = downloadFn;
+ this.shouldThrowOnError = shouldThrowOnError;
+ this[_Symbol$toStringTag] = "BlobDownloadBuilder";
+ this.promise = null;
+ }
+ asStream() {
+ return new StreamDownloadBuilder(this.downloadFn, this.shouldThrowOnError);
+ }
+ then(onfulfilled, onrejected) {
+ return this.getPromise().then(onfulfilled, onrejected);
+ }
+ catch(onrejected) {
+ return this.getPromise().catch(onrejected);
+ }
+ finally(onfinally) {
+ return this.getPromise().finally(onfinally);
+ }
+ getPromise() {
+ if (!this.promise) this.promise = this.execute();
+ return this.promise;
+ }
+ async execute() {
+ var _this = this;
+ try {
+ return {
+ data: await (await _this.downloadFn()).blob(),
+ error: null
+ };
+ } catch (error) {
+ if (_this.shouldThrowOnError) throw error;
+ if (isStorageError(error)) return {
+ data: null,
+ error
+ };
+ throw error;
+ }
+ }
+};
+
+//#endregion
+//#region src/packages/StorageFileApi.ts
+const DEFAULT_SEARCH_OPTIONS = {
+ limit: 100,
+ offset: 0,
+ sortBy: {
+ column: "name",
+ order: "asc"
+ }
+};
+const DEFAULT_FILE_OPTIONS = {
+ cacheControl: "3600",
+ contentType: "text/plain;charset=UTF-8",
+ upsert: false
+};
+var StorageFileApi = class extends BaseApiClient {
+ constructor(url, headers = {}, bucketId, fetch$1) {
+ super(url, headers, fetch$1, "storage");
+ this.bucketId = bucketId;
+ }
+ /**
+ * Uploads a file to an existing bucket or replaces an existing file at the specified path with a new one.
+ *
+ * @param method HTTP method.
+ * @param path The relative file path. Should be of the format `folder/subfolder/filename.png`. The bucket must already exist before attempting to upload.
+ * @param fileBody The body of the file to be stored in the bucket.
+ */
+ async uploadOrUpdate(method, path, fileBody, fileOptions) {
+ var _this = this;
+ return _this.handleOperation(async () => {
+ let body;
+ const options = _objectSpread2(_objectSpread2({}, DEFAULT_FILE_OPTIONS), fileOptions);
+ let headers = _objectSpread2(_objectSpread2({}, _this.headers), method === "POST" && { "x-upsert": String(options.upsert) });
+ const metadata = options.metadata;
+ if (typeof Blob !== "undefined" && fileBody instanceof Blob) {
+ body = new FormData();
+ body.append("cacheControl", options.cacheControl);
+ if (metadata) body.append("metadata", _this.encodeMetadata(metadata));
+ body.append("", fileBody);
+ } else if (typeof FormData !== "undefined" && fileBody instanceof FormData) {
+ body = fileBody;
+ if (!body.has("cacheControl")) body.append("cacheControl", options.cacheControl);
+ if (metadata && !body.has("metadata")) body.append("metadata", _this.encodeMetadata(metadata));
+ } else {
+ body = fileBody;
+ headers["cache-control"] = `max-age=${options.cacheControl}`;
+ headers["content-type"] = options.contentType;
+ if (metadata) headers["x-metadata"] = _this.toBase64(_this.encodeMetadata(metadata));
+ if ((typeof ReadableStream !== "undefined" && body instanceof ReadableStream || body && typeof body === "object" && "pipe" in body && typeof body.pipe === "function") && !options.duplex) options.duplex = "half";
+ }
+ if (fileOptions === null || fileOptions === void 0 ? void 0 : fileOptions.headers) for (const [key, value] of Object.entries(fileOptions.headers)) headers = setHeader(headers, key, value);
+ const cleanPath = _this._removeEmptyFolders(path);
+ const _path = _this._getFinalPath(cleanPath);
+ const data = await (method == "PUT" ? put : post)(_this.fetch, `${_this.url}/object/${_path}`, body, _objectSpread2({ headers }, (options === null || options === void 0 ? void 0 : options.duplex) ? { duplex: options.duplex } : {}));
+ return {
+ path: cleanPath,
+ id: data.Id,
+ fullPath: data.Key
+ };
+ });
+ }
+ /**
+ * Uploads a file to an existing bucket.
+ *
+ * @category Storage
+ * @subcategory File Buckets
+ * @param path The file path, including the file name. Should be of the format `folder/subfolder/filename.png`. The bucket must already exist before attempting to upload.
+ * @param fileBody The body of the file to be stored in the bucket.
+ * @param fileOptions Optional file upload options including cacheControl, contentType, upsert, and metadata.
+ * @returns Promise with response containing file path, id, and fullPath or error
+ *
+ * @example Upload file
+ * ```js
+ * const avatarFile = event.target.files[0]
+ * const { data, error } = await supabase
+ * .storage
+ * .from('avatars')
+ * .upload('public/avatar1.png', avatarFile, {
+ * cacheControl: '3600',
+ * upsert: false
+ * })
+ * ```
+ *
+ * Response:
+ * ```json
+ * {
+ * "data": {
+ * "path": "public/avatar1.png",
+ * "fullPath": "avatars/public/avatar1.png"
+ * },
+ * "error": null
+ * }
+ * ```
+ *
+ * @example Upload file using `ArrayBuffer` from base64 file data
+ * ```js
+ * import { decode } from 'base64-arraybuffer'
+ *
+ * const { data, error } = await supabase
+ * .storage
+ * .from('avatars')
+ * .upload('public/avatar1.png', decode('base64FileData'), {
+ * contentType: 'image/png'
+ * })
+ * ```
+ *
+ * @example Handling errors
+ * ```js
+ * const { data, error } = await supabase
+ * .storage
+ * .from('avatars')
+ * .upload('public/avatar1.png', avatarFile)
+ *
+ * if (error) {
+ * // Log the full error so fields like `statusCode` and `error` (the
+ * // Storage error name, e.g. "Duplicate") aren't hidden behind `error.message`.
+ * console.error(error)
+ * return
+ * }
+ * ```
+ *
+ * @remarks
+ * - RLS policy permissions required:
+ * - `buckets` table permissions: none
+ * - `objects` table permissions: only `insert` when you are uploading new files and `select`, `insert` and `update` when you are upserting files
+ * - Refer to the [Storage guide](/docs/guides/storage/security/access-control) on how access control works
+ * - For React Native, using either `Blob`, `File` or `FormData` does not work as intended. Upload file using `ArrayBuffer` from base64 file data instead, see example below.
+ */
+ async upload(path, fileBody, fileOptions) {
+ return this.uploadOrUpdate("POST", path, fileBody, fileOptions);
+ }
+ /**
+ * Upload a file with a token generated from `createSignedUploadUrl`.
+ *
+ * @category Storage
+ * @subcategory File Buckets
+ * @param path The file path, including the file name. Should be of the format `folder/subfolder/filename.png`. The bucket must already exist before attempting to upload.
+ * @param token The token generated from `createSignedUploadUrl`
+ * @param fileBody The body of the file to be stored in the bucket.
+ * @param fileOptions HTTP headers (cacheControl, contentType, etc.).
+ * **Note:** The `upsert` option has no effect here. To enable upsert behavior,
+ * pass `{ upsert: true }` when calling `createSignedUploadUrl()` instead.
+ * @returns Promise with response containing file path and fullPath or error
+ *
+ * @example Upload to a signed URL
+ * ```js
+ * const { data, error } = await supabase
+ * .storage
+ * .from('avatars')
+ * .uploadToSignedUrl('folder/cat.jpg', 'token-from-createSignedUploadUrl', file)
+ * ```
+ *
+ * Response:
+ * ```json
+ * {
+ * "data": {
+ * "path": "folder/cat.jpg",
+ * "fullPath": "avatars/folder/cat.jpg"
+ * },
+ * "error": null
+ * }
+ * ```
+ *
+ * @remarks
+ * - RLS policy permissions required:
+ * - `buckets` table permissions: none
+ * - `objects` table permissions: none
+ * - Refer to the [Storage guide](/docs/guides/storage/security/access-control) on how access control works
+ */
+ async uploadToSignedUrl(path, token, fileBody, fileOptions) {
+ var _this3 = this;
+ const cleanPath = _this3._removeEmptyFolders(path);
+ const _path = _this3._getFinalPath(cleanPath);
+ const url = new URL(_this3.url + `/object/upload/sign/${_path}`);
+ url.searchParams.set("token", token);
+ return _this3.handleOperation(async () => {
+ let body;
+ const options = _objectSpread2(_objectSpread2({}, DEFAULT_FILE_OPTIONS), fileOptions);
+ let headers = _objectSpread2(_objectSpread2({}, _this3.headers), { "x-upsert": String(options.upsert) });
+ const metadata = options.metadata;
+ if (typeof Blob !== "undefined" && fileBody instanceof Blob) {
+ body = new FormData();
+ body.append("cacheControl", options.cacheControl);
+ if (metadata) body.append("metadata", _this3.encodeMetadata(metadata));
+ body.append("", fileBody);
+ } else if (typeof FormData !== "undefined" && fileBody instanceof FormData) {
+ body = fileBody;
+ if (!body.has("cacheControl")) body.append("cacheControl", options.cacheControl);
+ if (metadata && !body.has("metadata")) body.append("metadata", _this3.encodeMetadata(metadata));
+ } else {
+ body = fileBody;
+ headers["cache-control"] = `max-age=${options.cacheControl}`;
+ headers["content-type"] = options.contentType;
+ if (metadata) headers["x-metadata"] = _this3.toBase64(_this3.encodeMetadata(metadata));
+ if ((typeof ReadableStream !== "undefined" && body instanceof ReadableStream || body && typeof body === "object" && "pipe" in body && typeof body.pipe === "function") && !options.duplex) options.duplex = "half";
+ }
+ if (fileOptions === null || fileOptions === void 0 ? void 0 : fileOptions.headers) for (const [key, value] of Object.entries(fileOptions.headers)) headers = setHeader(headers, key, value);
+ return {
+ path: cleanPath,
+ fullPath: (await put(_this3.fetch, url.toString(), body, _objectSpread2({ headers }, (options === null || options === void 0 ? void 0 : options.duplex) ? { duplex: options.duplex } : {}))).Key
+ };
+ });
+ }
+ /**
+ * Creates a signed upload URL.
+ * Signed upload URLs can be used to upload files to the bucket without further authentication.
+ * They are valid for 2 hours.
+ *
+ * @category Storage
+ * @subcategory File Buckets
+ * @param path The file path, including the current file name. For example `folder/image.png`.
+ * @param options.upsert If set to true, allows the file to be overwritten if it already exists.
+ * @returns Promise with response containing signed upload URL, token, and path or error
+ *
+ * @example Create Signed Upload URL
+ * ```js
+ * const { data, error } = await supabase
+ * .storage
+ * .from('avatars')
+ * .createSignedUploadUrl('folder/cat.jpg')
+ * ```
+ *
+ * Response:
+ * ```json
+ * {
+ * "data": {
+ * "signedUrl": "https://example.supabase.co/storage/v1/object/upload/sign/avatars/folder/cat.jpg?token=",
+ * "path": "folder/cat.jpg",
+ * "token": ""
+ * },
+ * "error": null
+ * }
+ * ```
+ *
+ * @remarks
+ * - RLS policy permissions required:
+ * - `buckets` table permissions: none
+ * - `objects` table permissions: `insert`
+ * - Refer to the [Storage guide](/docs/guides/storage/security/access-control) on how access control works
+ */
+ async createSignedUploadUrl(path, options) {
+ var _this4 = this;
+ return _this4.handleOperation(async () => {
+ let _path = _this4._getFinalPath(path);
+ const headers = _objectSpread2({}, _this4.headers);
+ if (options === null || options === void 0 ? void 0 : options.upsert) headers["x-upsert"] = "true";
+ const data = await post(_this4.fetch, `${_this4.url}/object/upload/sign/${_path}`, {}, { headers });
+ const url = new URL(_this4.url + data.url);
+ const token = url.searchParams.get("token");
+ if (!token) throw new StorageError("No token returned by API");
+ return {
+ signedUrl: url.toString(),
+ path,
+ token
+ };
+ });
+ }
+ /**
+ * Replaces an existing file at the specified path with a new one.
+ *
+ * @category Storage
+ * @subcategory File Buckets
+ * @param path The relative file path. Should be of the format `folder/subfolder/filename.png`. The bucket must already exist before attempting to update.
+ * @param fileBody The body of the file to be stored in the bucket.
+ * @param fileOptions Optional file upload options including cacheControl, contentType, and metadata.
+ * **Note:** The `upsert` option has no effect here. `update()` always replaces the
+ * file at the given path, so the `x-upsert` header is not sent. To control upsert
+ * behavior, use `upload()` instead.
+ * @returns Promise with response containing file path, id, and fullPath or error
+ *
+ * @example Update file
+ * ```js
+ * const avatarFile = event.target.files[0]
+ * const { data, error } = await supabase
+ * .storage
+ * .from('avatars')
+ * .update('public/avatar1.png', avatarFile, {
+ * cacheControl: '3600'
+ * })
+ * ```
+ *
+ * Response:
+ * ```json
+ * {
+ * "data": {
+ * "path": "public/avatar1.png",
+ * "fullPath": "avatars/public/avatar1.png"
+ * },
+ * "error": null
+ * }
+ * ```
+ *
+ * @example Update file using `ArrayBuffer` from base64 file data
+ * ```js
+ * import {decode} from 'base64-arraybuffer'
+ *
+ * const { data, error } = await supabase
+ * .storage
+ * .from('avatars')
+ * .update('public/avatar1.png', decode('base64FileData'), {
+ * contentType: 'image/png'
+ * })
+ * ```
+ *
+ * @remarks
+ * - RLS policy permissions required:
+ * - `buckets` table permissions: none
+ * - `objects` table permissions: `update` and `select`
+ * - `update()` always replaces the file at the given path regardless of the `upsert` option.
+ * - Refer to the [Storage guide](/docs/guides/storage/security/access-control) on how access control works
+ * - For React Native, using either `Blob`, `File` or `FormData` does not work as intended. Update file using `ArrayBuffer` from base64 file data instead, see example below.
+ */
+ async update(path, fileBody, fileOptions) {
+ return this.uploadOrUpdate("PUT", path, fileBody, fileOptions);
+ }
+ /**
+ * Moves an existing file to a new path in the same bucket.
+ *
+ * @category Storage
+ * @subcategory File Buckets
+ * @param fromPath The original file path, including the current file name. For example `folder/image.png`.
+ * @param toPath The new file path, including the new file name. For example `folder/image-new.png`.
+ * @param options The destination options.
+ * @returns Promise with response containing success message or error
+ *
+ * @example Move file
+ * ```js
+ * const { data, error } = await supabase
+ * .storage
+ * .from('avatars')
+ * .move('public/avatar1.png', 'private/avatar2.png')
+ * ```
+ *
+ * Response:
+ * ```json
+ * {
+ * "data": {
+ * "message": "Successfully moved"
+ * },
+ * "error": null
+ * }
+ * ```
+ *
+ * @remarks
+ * - RLS policy permissions required:
+ * - `buckets` table permissions: none
+ * - `objects` table permissions: `update` and `select`
+ * - Refer to the [Storage guide](/docs/guides/storage/security/access-control) on how access control works
+ */
+ async move(fromPath, toPath, options) {
+ var _this6 = this;
+ return _this6.handleOperation(async () => {
+ return await post(_this6.fetch, `${_this6.url}/object/move`, {
+ bucketId: _this6.bucketId,
+ sourceKey: fromPath,
+ destinationKey: toPath,
+ destinationBucket: options === null || options === void 0 ? void 0 : options.destinationBucket
+ }, { headers: _this6.headers });
+ });
+ }
+ /**
+ * Copies an existing file to a new path in the same bucket.
+ *
+ * @category Storage
+ * @subcategory File Buckets
+ * @param fromPath The original file path, including the current file name. For example `folder/image.png`.
+ * @param toPath The new file path, including the new file name. For example `folder/image-copy.png`.
+ * @param options The destination options.
+ * @returns Promise with response containing copied file path or error
+ *
+ * @example Copy file
+ * ```js
+ * const { data, error } = await supabase
+ * .storage
+ * .from('avatars')
+ * .copy('public/avatar1.png', 'private/avatar2.png')
+ * ```
+ *
+ * Response:
+ * ```json
+ * {
+ * "data": {
+ * "path": "avatars/private/avatar2.png"
+ * },
+ * "error": null
+ * }
+ * ```
+ *
+ * @remarks
+ * - RLS policy permissions required:
+ * - `buckets` table permissions: none
+ * - `objects` table permissions: `insert` and `select`
+ * - Refer to the [Storage guide](/docs/guides/storage/security/access-control) on how access control works
+ */
+ async copy(fromPath, toPath, options) {
+ var _this7 = this;
+ return _this7.handleOperation(async () => {
+ return { path: (await post(_this7.fetch, `${_this7.url}/object/copy`, {
+ bucketId: _this7.bucketId,
+ sourceKey: fromPath,
+ destinationKey: toPath,
+ destinationBucket: options === null || options === void 0 ? void 0 : options.destinationBucket
+ }, { headers: _this7.headers })).Key };
+ });
+ }
+ /**
+ * Creates a signed URL. Use a signed URL to share a file for a fixed amount of time.
+ *
+ * @category Storage
+ * @subcategory File Buckets
+ * @param path The file path, including the current file name. For example `folder/image.png`.
+ * @param expiresIn The number of seconds until the signed URL expires. For example, `60` for a URL which is valid for one minute.
+ * @param options.download triggers the file as a download if set to true. Set this parameter as the name of the file if you want to trigger the download with a different filename.
+ * @param options.transform Transform the asset before serving it to the client.
+ * @param options.cacheNonce Append a cache nonce parameter to the URL to invalidate the cache.
+ * @returns Promise with response containing signed URL or error
+ *
+ * @example Create Signed URL
+ * ```js
+ * const { data, error } = await supabase
+ * .storage
+ * .from('avatars')
+ * .createSignedUrl('folder/avatar1.png', 60)
+ * ```
+ *
+ * Response:
+ * ```json
+ * {
+ * "data": {
+ * "signedUrl": "https://example.supabase.co/storage/v1/object/sign/avatars/folder/avatar1.png?token="
+ * },
+ * "error": null
+ * }
+ * ```
+ *
+ * @example Create a signed URL for an asset with transformations
+ * ```js
+ * const { data } = await supabase
+ * .storage
+ * .from('avatars')
+ * .createSignedUrl('folder/avatar1.png', 60, {
+ * transform: {
+ * width: 100,
+ * height: 100,
+ * }
+ * })
+ * ```
+ *
+ * @example Create a signed URL which triggers the download of the asset
+ * ```js
+ * const { data } = await supabase
+ * .storage
+ * .from('avatars')
+ * .createSignedUrl('folder/avatar1.png', 60, {
+ * download: true,
+ * })
+ * ```
+ *
+ * @remarks
+ * - RLS policy permissions required:
+ * - `buckets` table permissions: none
+ * - `objects` table permissions: `select`
+ * - Refer to the [Storage guide](/docs/guides/storage/security/access-control) on how access control works
+ */
+ async createSignedUrl(path, expiresIn, options) {
+ var _this8 = this;
+ return _this8.handleOperation(async () => {
+ let _path = _this8._getFinalPath(path);
+ const hasTransform = typeof (options === null || options === void 0 ? void 0 : options.transform) === "object" && options.transform !== null && Object.keys(options.transform).length > 0;
+ let data = await post(_this8.fetch, `${_this8.url}/object/sign/${_path}`, _objectSpread2({ expiresIn }, hasTransform ? { transform: options.transform } : {}), { headers: _this8.headers });
+ const query = new URLSearchParams();
+ if (options === null || options === void 0 ? void 0 : options.download) query.set("download", options.download === true ? "" : options.download);
+ if ((options === null || options === void 0 ? void 0 : options.cacheNonce) != null) query.set("cacheNonce", String(options.cacheNonce));
+ const queryString = query.toString();
+ return { signedUrl: encodeURI(`${_this8.url}${data.signedURL}${queryString ? `&${queryString}` : ""}`) };
+ });
+ }
+ /**
+ * Creates multiple signed URLs. Use a signed URL to share a file for a fixed amount of time.
+ *
+ * @category Storage
+ * @subcategory File Buckets
+ * @param paths The file paths to be downloaded, including the current file names. For example `['folder/image.png', 'folder2/image2.png']`.
+ * @param expiresIn The number of seconds until the signed URLs expire. For example, `60` for URLs which are valid for one minute.
+ * @param options.download triggers the file as a download if set to true. Set this parameter as the name of the file if you want to trigger the download with a different filename.
+ * @param options.cacheNonce Append a cache nonce parameter to the URL to invalidate the cache.
+ * @returns Promise with response containing array of objects with signedUrl, path, and error or error
+ *
+ * @example Create Signed URLs
+ * ```js
+ * const { data, error } = await supabase
+ * .storage
+ * .from('avatars')
+ * .createSignedUrls(['folder/avatar1.png', 'folder/avatar2.png'], 60)
+ * ```
+ *
+ * Response:
+ * ```json
+ * {
+ * "data": [
+ * {
+ * "error": null,
+ * "path": "folder/avatar1.png",
+ * "signedURL": "/object/sign/avatars/folder/avatar1.png?token=",
+ * "signedUrl": "https://example.supabase.co/storage/v1/object/sign/avatars/folder/avatar1.png?token="
+ * },
+ * {
+ * "error": null,
+ * "path": "folder/avatar2.png",
+ * "signedURL": "/object/sign/avatars/folder/avatar2.png?token=",
+ * "signedUrl": "https://example.supabase.co/storage/v1/object/sign/avatars/folder/avatar2.png?token="
+ * }
+ * ],
+ * "error": null
+ * }
+ * ```
+ *
+ * @remarks
+ * - RLS policy permissions required:
+ * - `buckets` table permissions: none
+ * - `objects` table permissions: `select`
+ * - Refer to the [Storage guide](/docs/guides/storage/security/access-control) on how access control works
+ */
+ async createSignedUrls(paths, expiresIn, options) {
+ var _this9 = this;
+ return _this9.handleOperation(async () => {
+ const data = await post(_this9.fetch, `${_this9.url}/object/sign/${_this9.bucketId}`, {
+ expiresIn,
+ paths
+ }, { headers: _this9.headers });
+ const query = new URLSearchParams();
+ if (options === null || options === void 0 ? void 0 : options.download) query.set("download", options.download === true ? "" : options.download);
+ if ((options === null || options === void 0 ? void 0 : options.cacheNonce) != null) query.set("cacheNonce", String(options.cacheNonce));
+ const queryString = query.toString();
+ return data.map((datum) => _objectSpread2(_objectSpread2({}, datum), {}, { signedUrl: datum.signedURL ? encodeURI(`${_this9.url}${datum.signedURL}${queryString ? `&${queryString}` : ""}`) : null }));
+ });
+ }
+ /**
+ * Downloads a file from a private bucket. For public buckets, make a request to the URL returned from `getPublicUrl` instead.
+ *
+ * @category Storage
+ * @subcategory File Buckets
+ * @param path The full path and file name of the file to be downloaded. For example `folder/image.png`.
+ * @param options Optional settings: `transform` to transform the asset before serving it to the client, and `cacheNonce` to append a cache nonce parameter to the URL to invalidate the cache.
+ * @param parameters Additional fetch parameters like signal for cancellation. Supports standard fetch options including cache control.
+ * @returns BlobDownloadBuilder instance for downloading the file
+ *
+ * @example Download file
+ * ```js
+ * const { data, error } = await supabase
+ * .storage
+ * .from('avatars')
+ * .download('folder/avatar1.png')
+ * ```
+ *
+ * Response:
+ * ```json
+ * {
+ * "data": ,
+ * "error": null
+ * }
+ * ```
+ *
+ * @example Download file with transformations
+ * ```js
+ * const { data, error } = await supabase
+ * .storage
+ * .from('avatars')
+ * .download('folder/avatar1.png', {
+ * transform: {
+ * width: 100,
+ * height: 100,
+ * quality: 80
+ * }
+ * })
+ * ```
+ *
+ * @example Download with cache control (useful in Edge Functions)
+ * ```js
+ * const { data, error } = await supabase
+ * .storage
+ * .from('avatars')
+ * .download('folder/avatar1.png', {}, { cache: 'no-store' })
+ * ```
+ *
+ * @example Download with abort signal
+ * ```js
+ * const controller = new AbortController()
+ * setTimeout(() => controller.abort(), 5000)
+ *
+ * const { data, error } = await supabase
+ * .storage
+ * .from('avatars')
+ * .download('folder/avatar1.png', {}, { signal: controller.signal })
+ * ```
+ *
+ * @remarks
+ * - RLS policy permissions required:
+ * - `buckets` table permissions: none
+ * - `objects` table permissions: `select`
+ * - Refer to the [Storage guide](/docs/guides/storage/security/access-control) on how access control works
+ */
+ download(path, options, parameters) {
+ const renderPath = typeof (options === null || options === void 0 ? void 0 : options.transform) === "object" && options.transform !== null && Object.keys(options.transform).length > 0 ? "render/image/authenticated" : "object";
+ const query = new URLSearchParams();
+ if (options === null || options === void 0 ? void 0 : options.transform) this.applyTransformOptsToQuery(query, options.transform);
+ if ((options === null || options === void 0 ? void 0 : options.cacheNonce) != null) query.set("cacheNonce", String(options.cacheNonce));
+ const queryString = query.toString();
+ const _path = this._getFinalPath(path);
+ const downloadFn = () => get(this.fetch, `${this.url}/${renderPath}/${_path}${queryString ? `?${queryString}` : ""}`, {
+ headers: this.headers,
+ noResolveJson: true
+ }, parameters);
+ return new BlobDownloadBuilder(downloadFn, this.shouldThrowOnError);
+ }
+ /**
+ * Retrieves the details of an existing file.
+ *
+ * Returns detailed file metadata including size, content type, and timestamps.
+ * Note: The API returns `last_modified` field, not `updated_at`.
+ *
+ * @category Storage
+ * @subcategory File Buckets
+ * @param path The file path, including the file name. For example `folder/image.png`.
+ * @returns Promise with response containing file metadata or error
+ *
+ * @example Get file info
+ * ```js
+ * const { data, error } = await supabase
+ * .storage
+ * .from('avatars')
+ * .info('folder/avatar1.png')
+ *
+ * if (data) {
+ * console.log('Last modified:', data.lastModified)
+ * console.log('Size:', data.size)
+ * }
+ * ```
+ */
+ async info(path) {
+ var _this10 = this;
+ const _path = _this10._getFinalPath(path);
+ return _this10.handleOperation(async () => {
+ return recursiveToCamel(await get(_this10.fetch, `${_this10.url}/object/info/${_path}`, { headers: _this10.headers }));
+ });
+ }
+ /**
+ * Checks the existence of a file.
+ *
+ * @category Storage
+ * @subcategory File Buckets
+ * @param path The file path, including the file name. For example `folder/image.png`.
+ * @returns Promise with response containing boolean indicating file existence or error
+ *
+ * @example Check file existence
+ * ```js
+ * const { data, error } = await supabase
+ * .storage
+ * .from('avatars')
+ * .exists('folder/avatar1.png')
+ * ```
+ */
+ async exists(path) {
+ var _this11 = this;
+ const _path = _this11._getFinalPath(path);
+ try {
+ await head(_this11.fetch, `${_this11.url}/object/${_path}`, { headers: _this11.headers });
+ return {
+ data: true,
+ error: null
+ };
+ } catch (error) {
+ if (_this11.shouldThrowOnError) throw error;
+ if (isStorageError(error)) {
+ var _error$originalError;
+ const status = error instanceof StorageApiError ? error.status : error instanceof StorageUnknownError ? (_error$originalError = error.originalError) === null || _error$originalError === void 0 ? void 0 : _error$originalError.status : void 0;
+ if (status !== void 0 && [400, 404].includes(status)) return {
+ data: false,
+ error
+ };
+ }
+ throw error;
+ }
+ }
+ /**
+ * A simple convenience function to get the URL for an asset in a public bucket. If you do not want to use this function, you can construct the public URL by concatenating the bucket URL with the path to the asset.
+ * This function does not verify if the bucket is public. If a public URL is created for a bucket which is not public, you will not be able to download the asset.
+ *
+ * @category Storage
+ * @subcategory File Buckets
+ * @param path The path and name of the file to generate the public URL for. For example `folder/image.png`.
+ * @param options.download Triggers the file as a download if set to true. Set this parameter as the name of the file if you want to trigger the download with a different filename.
+ * @param options.transform Transform the asset before serving it to the client.
+ * @param options.cacheNonce Append a cache nonce parameter to the URL to invalidate the cache.
+ * @returns Object with public URL
+ *
+ * @example Returns the URL for an asset in a public bucket
+ * ```js
+ * const { data } = supabase
+ * .storage
+ * .from('public-bucket')
+ * .getPublicUrl('folder/avatar1.png')
+ * ```
+ *
+ * Response:
+ * ```json
+ * {
+ * "data": {
+ * "publicUrl": "https://example.supabase.co/storage/v1/object/public/public-bucket/folder/avatar1.png"
+ * }
+ * }
+ * ```
+ *
+ * @example Returns the URL for an asset in a public bucket with transformations
+ * ```js
+ * const { data } = supabase
+ * .storage
+ * .from('public-bucket')
+ * .getPublicUrl('folder/avatar1.png', {
+ * transform: {
+ * width: 100,
+ * height: 100,
+ * }
+ * })
+ * ```
+ *
+ * @example Returns the URL which triggers the download of an asset in a public bucket
+ * ```js
+ * const { data } = supabase
+ * .storage
+ * .from('public-bucket')
+ * .getPublicUrl('folder/avatar1.png', {
+ * download: true,
+ * })
+ * ```
+ *
+ * @remarks
+ * - The bucket needs to be set to public, either via [updateBucket()](/docs/reference/javascript/storage-updatebucket) or by going to Storage on [supabase.com/dashboard](https://supabase.com/dashboard), clicking the overflow menu on a bucket and choosing "Make public"
+ * - RLS policy permissions required:
+ * - `buckets` table permissions: none
+ * - `objects` table permissions: none
+ * - Refer to the [Storage guide](/docs/guides/storage/security/access-control) on how access control works
+ */
+ getPublicUrl(path, options) {
+ const _path = this._getFinalPath(path);
+ const query = new URLSearchParams();
+ if (options === null || options === void 0 ? void 0 : options.download) query.set("download", options.download === true ? "" : options.download);
+ if (options === null || options === void 0 ? void 0 : options.transform) this.applyTransformOptsToQuery(query, options.transform);
+ if ((options === null || options === void 0 ? void 0 : options.cacheNonce) != null) query.set("cacheNonce", String(options.cacheNonce));
+ const queryString = query.toString();
+ const renderPath = typeof (options === null || options === void 0 ? void 0 : options.transform) === "object" && options.transform !== null && Object.keys(options.transform).length > 0 ? "render/image" : "object";
+ return { data: { publicUrl: encodeURI(`${this.url}/${renderPath}/public/${_path}`) + (queryString ? `?${queryString}` : "") } };
+ }
+ /**
+ * Deletes files within the same bucket
+ *
+ * Returns an array of FileObject entries for the deleted files. Note that deprecated
+ * fields like `bucket_id` may or may not be present in the response - do not rely on them.
+ *
+ * @category Storage
+ * @subcategory File Buckets
+ * @param paths An array of files to delete, including the path and file name. For example [`'folder/image.png'`].
+ * @returns Promise with response containing array of deleted file objects or error
+ *
+ * @example Delete file
+ * ```js
+ * const { data, error } = await supabase
+ * .storage
+ * .from('avatars')
+ * .remove(['folder/avatar1.png'])
+ * ```
+ *
+ * Response:
+ * ```json
+ * {
+ * "data": [],
+ * "error": null
+ * }
+ * ```
+ *
+ * @remarks
+ * - RLS policy permissions required:
+ * - `buckets` table permissions: none
+ * - `objects` table permissions: `delete` and `select`
+ * - Refer to the [Storage guide](/docs/guides/storage/security/access-control) on how access control works
+ */
+ async remove(paths) {
+ var _this12 = this;
+ return _this12.handleOperation(async () => {
+ return await remove(_this12.fetch, `${_this12.url}/object/${_this12.bucketId}`, { prefixes: paths }, { headers: _this12.headers });
+ });
+ }
+ /**
+ * Purges the CDN cache for a single object in this bucket.
+ *
+ * Maps to `DELETE /cdn/{bucket}/{path}` on the Storage API. The server
+ * issues a CDN invalidation for the object and returns `{ message: 'success' }`.
+ *
+ * **Requires the `service_role` key.** The underlying endpoint enforces
+ * `service_role` JWT — calls made with the anon key or a user JWT will be
+ * rejected by the server.
+ *
+ * **Hosted CDN feature.** On self-hosted Supabase, the Storage service must
+ * have `CDN_PURGE_ENDPOINT_URL` configured and the `purgeCache` tenant
+ * feature enabled, otherwise the server returns an error.
+ *
+ * Operates on a single object path. There is no wildcard or recursion: pass
+ * the exact path of the object you want invalidated.
+ *
+ * @category Storage
+ * @subcategory File Buckets
+ * @param path The path (relative to the bucket) of the object to purge, e.g. `folder/avatar.png`.
+ * @param options Optional purge cache options.
+ * @param options.transformations If true, purges only transformations (resized/formatted variants), leaving the original cached file intact.
+ * @param parameters Optional fetch parameters such as an `AbortController` signal.
+ * @returns Promise with `{ data: { message }, error: null }` on success or `{ data: null, error }` on failure.
+ *
+ * @example Purge a single cached object
+ * ```js
+ * const { data, error } = await supabase
+ * .storage
+ * .from('avatars')
+ * .purgeCache('folder/avatar1.png')
+ * ```
+ *
+ * @example Purge only transformations for a single object
+ * ```js
+ * const { data, error } = await supabase
+ * .storage
+ * .from('avatars')
+ * .purgeCache('folder/avatar1.png', { transformations: true })
+ * ```
+ */
+ async purgeCache(path, options, parameters) {
+ var _this13 = this;
+ return _this13.handleOperation(async () => {
+ const _path = encodeStoragePath(_this13._getFinalPath(path));
+ const query = new URLSearchParams();
+ if (options === null || options === void 0 ? void 0 : options.transformations) query.set("transformations", "true");
+ const queryString = query.toString();
+ return await remove(_this13.fetch, `${_this13.url}/cdn/${_path}${queryString ? `?${queryString}` : ""}`, {}, { headers: _this13.headers }, parameters);
+ });
+ }
+ /**
+ * Get file metadata
+ * @param id the file id to retrieve metadata
+ */
+ /**
+ * Update file metadata
+ * @param id the file id to update metadata
+ * @param meta the new file metadata
+ */
+ /**
+ * Lists all the files and folders within a path of the bucket.
+ *
+ * **Important:** For folder entries, fields like `id`, `updated_at`, `created_at`,
+ * `last_accessed_at`, and `metadata` will be `null`. Only files have these fields populated.
+ * Additionally, deprecated fields like `bucket_id`, `owner`, and `buckets` are NOT returned
+ * by this method.
+ *
+ * @category Storage
+ * @subcategory File Buckets
+ * @param path The folder path.
+ * @param options Search options including limit (defaults to 100), offset, sortBy, and search
+ * @param parameters Optional fetch parameters including signal for cancellation
+ * @returns Promise with response containing array of files/folders or error
+ *
+ * @example List files in a bucket
+ * ```js
+ * const { data, error } = await supabase
+ * .storage
+ * .from('avatars')
+ * .list('folder', {
+ * limit: 100,
+ * offset: 0,
+ * sortBy: { column: 'name', order: 'asc' },
+ * })
+ *
+ * // Handle files vs folders
+ * data?.forEach(item => {
+ * if (item.id !== null) {
+ * // It's a file
+ * console.log('File:', item.name, 'Size:', item.metadata?.size)
+ * } else {
+ * // It's a folder
+ * console.log('Folder:', item.name)
+ * }
+ * })
+ * ```
+ *
+ * Response:
+ * ```json
+ * {
+ * "data": [
+ * {
+ * "name": "avatar1.png",
+ * "id": "e668cf7f-821b-4a2f-9dce-7dfa5dd1cfd2",
+ * "updated_at": "2024-05-22T23:06:05.580Z",
+ * "created_at": "2024-05-22T23:04:34.443Z",
+ * "last_accessed_at": "2024-05-22T23:04:34.443Z",
+ * "metadata": {
+ * "eTag": "\"c5e8c553235d9af30ef4f6e280790b92\"",
+ * "size": 32175,
+ * "mimetype": "image/png",
+ * "cacheControl": "max-age=3600",
+ * "lastModified": "2024-05-22T23:06:05.574Z",
+ * "contentLength": 32175,
+ * "httpStatusCode": 200
+ * }
+ * }
+ * ],
+ * "error": null
+ * }
+ * ```
+ *
+ * @example Search files in a bucket
+ * ```js
+ * const { data, error } = await supabase
+ * .storage
+ * .from('avatars')
+ * .list('folder', {
+ * limit: 100,
+ * offset: 0,
+ * sortBy: { column: 'name', order: 'asc' },
+ * search: 'jon'
+ * })
+ * ```
+ *
+ * @remarks
+ * - RLS policy permissions required:
+ * - `buckets` table permissions: none
+ * - `objects` table permissions: `select`
+ * - Refer to the [Storage guide](/docs/guides/storage/security/access-control) on how access control works
+ */
+ async list(path, options, parameters) {
+ var _this14 = this;
+ return _this14.handleOperation(async () => {
+ const sortBy = (options === null || options === void 0 ? void 0 : options.sortBy) ? _objectSpread2(_objectSpread2({}, DEFAULT_SEARCH_OPTIONS.sortBy), options.sortBy) : DEFAULT_SEARCH_OPTIONS.sortBy;
+ const body = _objectSpread2(_objectSpread2(_objectSpread2({}, DEFAULT_SEARCH_OPTIONS), options), {}, {
+ sortBy,
+ prefix: path || ""
+ });
+ return await post(_this14.fetch, `${_this14.url}/object/list/${_this14.bucketId}`, body, { headers: _this14.headers }, parameters);
+ });
+ }
+ /**
+ * Lists all the files and folders within a bucket using the V2 API with pagination support.
+ *
+ * **Important:** Folder entries in the `folders` array only contain `name` and optionally `key` —
+ * they have no `id`, timestamps, or `metadata` fields. Full file metadata is only available
+ * on entries in the `objects` array.
+ *
+ * @experimental this method signature might change in the future
+ *
+ * @category Storage
+ * @subcategory File Buckets
+ * @param options Search options including prefix, cursor for pagination, limit, with_delimiter
+ * @param parameters Optional fetch parameters including signal for cancellation
+ * @returns Promise with response containing folders/objects arrays with pagination info or error
+ *
+ * @example List files with pagination
+ * ```js
+ * const { data, error } = await supabase
+ * .storage
+ * .from('avatars')
+ * .listV2({
+ * prefix: 'folder/',
+ * limit: 100,
+ * })
+ *
+ * // Handle pagination
+ * if (data?.hasNext) {
+ * const nextPage = await supabase
+ * .storage
+ * .from('avatars')
+ * .listV2({
+ * prefix: 'folder/',
+ * cursor: data.nextCursor,
+ * })
+ * }
+ *
+ * // Handle files vs folders
+ * data?.objects.forEach(file => {
+ * if (file.id !== null) {
+ * console.log('File:', file.name, 'Size:', file.metadata?.size)
+ * }
+ * })
+ * data?.folders.forEach(folder => {
+ * console.log('Folder:', folder.name)
+ * })
+ * ```
+ */
+ async listV2(options, parameters) {
+ var _this15 = this;
+ return _this15.handleOperation(async () => {
+ const body = _objectSpread2({}, options);
+ return await post(_this15.fetch, `${_this15.url}/object/list-v2/${_this15.bucketId}`, body, { headers: _this15.headers }, parameters);
+ });
+ }
+ encodeMetadata(metadata) {
+ return JSON.stringify(metadata);
+ }
+ toBase64(data) {
+ if (typeof Buffer !== "undefined") return Buffer.from(data).toString("base64");
+ return btoa(data);
+ }
+ _getFinalPath(path) {
+ return `${this.bucketId}/${path.replace(/^\/+/, "")}`;
+ }
+ _removeEmptyFolders(path) {
+ return path.replace(/^\/|\/$/g, "").replace(/\/+/g, "/");
+ }
+ /** Modifies the `query`, appending values the from `transform` */
+ applyTransformOptsToQuery(query, transform) {
+ if (transform.width) query.set("width", transform.width.toString());
+ if (transform.height) query.set("height", transform.height.toString());
+ if (transform.resize) query.set("resize", transform.resize);
+ if (transform.format) query.set("format", transform.format);
+ if (transform.quality) query.set("quality", transform.quality.toString());
+ return query;
+ }
+};
+
+//#endregion
+//#region src/lib/version.ts
+const version = "2.112.3";
+
+//#endregion
+//#region src/lib/constants.ts
+const DEFAULT_HEADERS = { "X-Client-Info": `storage-js/${version}` };
+
+//#endregion
+//#region src/packages/StorageBucketApi.ts
+var StorageBucketApi = class extends BaseApiClient {
+ constructor(url, headers = {}, fetch$1, opts) {
+ const baseUrl = new URL(url);
+ if (opts === null || opts === void 0 ? void 0 : opts.useNewHostname) {
+ if (/supabase\.(co|in|red)$/.test(baseUrl.hostname) && !baseUrl.hostname.includes("storage.supabase.")) baseUrl.hostname = baseUrl.hostname.replace("supabase.", "storage.supabase.");
+ }
+ const finalUrl = baseUrl.href.replace(/\/$/, "");
+ const finalHeaders = _objectSpread2(_objectSpread2({}, DEFAULT_HEADERS), headers);
+ super(finalUrl, finalHeaders, fetch$1, "storage");
+ }
+ /**
+ * Retrieves the details of all Storage buckets within an existing project.
+ *
+ * @category Storage
+ * @subcategory File Buckets
+ * @param options Query parameters for listing buckets
+ * @param options.limit Maximum number of buckets to return
+ * @param options.offset Number of buckets to skip
+ * @param options.sortColumn Column to sort by ('id', 'name', 'created_at', 'updated_at')
+ * @param options.sortOrder Sort order ('asc' or 'desc')
+ * @param options.search Search term to filter bucket names
+ * @returns Promise with response containing array of buckets or error
+ *
+ * @example List buckets
+ * ```js
+ * const { data, error } = await supabase
+ * .storage
+ * .listBuckets()
+ * ```
+ *
+ * @example List buckets with options
+ * ```js
+ * const { data, error } = await supabase
+ * .storage
+ * .listBuckets({
+ * limit: 10,
+ * offset: 0,
+ * sortColumn: 'created_at',
+ * sortOrder: 'desc',
+ * search: 'prod'
+ * })
+ * ```
+ *
+ * @remarks
+ * - RLS policy permissions required:
+ * - `buckets` table permissions: `select`
+ * - `objects` table permissions: none
+ * - Refer to the [Storage guide](/docs/guides/storage/security/access-control) on how access control works
+ */
+ async listBuckets(options) {
+ var _this = this;
+ return _this.handleOperation(async () => {
+ const queryString = _this.listBucketOptionsToQueryString(options);
+ return await get(_this.fetch, `${_this.url}/bucket${queryString}`, { headers: _this.headers });
+ });
+ }
+ /**
+ * Retrieves the details of an existing Storage bucket.
+ *
+ * @category Storage
+ * @subcategory File Buckets
+ * @param id The unique identifier of the bucket you would like to retrieve.
+ * @returns Promise with response containing bucket details or error
+ *
+ * @example Get bucket
+ * ```js
+ * const { data, error } = await supabase
+ * .storage
+ * .getBucket('avatars')
+ * ```
+ *
+ * Response:
+ * ```json
+ * {
+ * "data": {
+ * "id": "avatars",
+ * "name": "avatars",
+ * "owner": "",
+ * "public": false,
+ * "file_size_limit": 1024,
+ * "allowed_mime_types": [
+ * "image/png"
+ * ],
+ * "created_at": "2024-05-22T22:26:05.100Z",
+ * "updated_at": "2024-05-22T22:26:05.100Z"
+ * },
+ * "error": null
+ * }
+ * ```
+ *
+ * @remarks
+ * - RLS policy permissions required:
+ * - `buckets` table permissions: `select`
+ * - `objects` table permissions: none
+ * - Refer to the [Storage guide](/docs/guides/storage/security/access-control) on how access control works
+ */
+ async getBucket(id) {
+ var _this2 = this;
+ return _this2.handleOperation(async () => {
+ return await get(_this2.fetch, `${_this2.url}/bucket/${id}`, { headers: _this2.headers });
+ });
+ }
+ /**
+ * Creates a new Storage bucket
+ *
+ * @category Storage
+ * @subcategory File Buckets
+ * @param id A unique identifier for the bucket you are creating.
+ * @param options.public The visibility of the bucket. Public buckets don't require an authorization token to download objects, but still require a valid token for all other operations. By default, buckets are private.
+ * @param options.fileSizeLimit specifies the max file size in bytes that can be uploaded to this bucket.
+ * The global file size limit takes precedence over this value.
+ * The default value is null, which doesn't set a per bucket file size limit.
+ * @param options.allowedMimeTypes specifies the allowed mime types that this bucket can accept during upload.
+ * The default value is null, which allows files with all mime types to be uploaded.
+ * Each mime type specified can be a wildcard, e.g. image/*, or a specific mime type, e.g. image/png.
+ * @param options.type (private-beta) specifies the bucket type. see `BucketType` for more details.
+ * - default bucket type is `STANDARD`
+ * @returns Promise with response containing newly created bucket name or error
+ *
+ * @example Create bucket
+ * ```js
+ * const { data, error } = await supabase
+ * .storage
+ * .createBucket('avatars', {
+ * public: false,
+ * allowedMimeTypes: ['image/png'],
+ * fileSizeLimit: 1024
+ * })
+ * ```
+ *
+ * Response:
+ * ```json
+ * {
+ * "data": {
+ * "name": "avatars"
+ * },
+ * "error": null
+ * }
+ * ```
+ *
+ * @remarks
+ * - RLS policy permissions required:
+ * - `buckets` table permissions: `insert`
+ * - `objects` table permissions: none
+ * - Refer to the [Storage guide](/docs/guides/storage/security/access-control) on how access control works
+ */
+ async createBucket(id, options = { public: false }) {
+ var _this3 = this;
+ return _this3.handleOperation(async () => {
+ return await post(_this3.fetch, `${_this3.url}/bucket`, {
+ id,
+ name: id,
+ type: options.type,
+ public: options.public,
+ file_size_limit: options.fileSizeLimit,
+ allowed_mime_types: options.allowedMimeTypes
+ }, { headers: _this3.headers });
+ });
+ }
+ /**
+ * Updates a Storage bucket
+ *
+ * @category Storage
+ * @subcategory File Buckets
+ * @param id A unique identifier for the bucket you are updating.
+ * @param options.public The visibility of the bucket. Public buckets don't require an authorization token to download objects, but still require a valid token for all other operations.
+ * @param options.fileSizeLimit specifies the max file size in bytes that can be uploaded to this bucket.
+ * The global file size limit takes precedence over this value.
+ * The default value is null, which doesn't set a per bucket file size limit.
+ * @param options.allowedMimeTypes specifies the allowed mime types that this bucket can accept during upload.
+ * The default value is null, which allows files with all mime types to be uploaded.
+ * Each mime type specified can be a wildcard, e.g. image/*, or a specific mime type, e.g. image/png.
+ * @returns Promise with response containing success message or error
+ *
+ * @example Update bucket
+ * ```js
+ * const { data, error } = await supabase
+ * .storage
+ * .updateBucket('avatars', {
+ * public: false,
+ * allowedMimeTypes: ['image/png'],
+ * fileSizeLimit: 1024
+ * })
+ * ```
+ *
+ * Response:
+ * ```json
+ * {
+ * "data": {
+ * "message": "Successfully updated"
+ * },
+ * "error": null
+ * }
+ * ```
+ *
+ * @remarks
+ * - RLS policy permissions required:
+ * - `buckets` table permissions: `select` and `update`
+ * - `objects` table permissions: none
+ * - Refer to the [Storage guide](/docs/guides/storage/security/access-control) on how access control works
+ */
+ async updateBucket(id, options) {
+ var _this4 = this;
+ return _this4.handleOperation(async () => {
+ return await put(_this4.fetch, `${_this4.url}/bucket/${id}`, {
+ id,
+ name: id,
+ public: options.public,
+ file_size_limit: options.fileSizeLimit,
+ allowed_mime_types: options.allowedMimeTypes
+ }, { headers: _this4.headers });
+ });
+ }
+ /**
+ * Removes all objects inside a single bucket.
+ *
+ * @category Storage
+ * @subcategory File Buckets
+ * @param id The unique identifier of the bucket you would like to empty.
+ * @returns Promise with success message or error
+ *
+ * @example Empty bucket
+ * ```js
+ * const { data, error } = await supabase
+ * .storage
+ * .emptyBucket('avatars')
+ * ```
+ *
+ * Response:
+ * ```json
+ * {
+ * "data": {
+ * "message": "Successfully emptied"
+ * },
+ * "error": null
+ * }
+ * ```
+ *
+ * @remarks
+ * - RLS policy permissions required:
+ * - `buckets` table permissions: `select`
+ * - `objects` table permissions: `select` and `delete`
+ * - Refer to the [Storage guide](/docs/guides/storage/security/access-control) on how access control works
+ */
+ async emptyBucket(id) {
+ var _this5 = this;
+ return _this5.handleOperation(async () => {
+ return await post(_this5.fetch, `${_this5.url}/bucket/${id}/empty`, {}, { headers: _this5.headers });
+ });
+ }
+ /**
+ * Deletes an existing bucket. A bucket can't be deleted with existing objects inside it.
+ * You must first `empty()` the bucket.
+ *
+ * @category Storage
+ * @subcategory File Buckets
+ * @param id The unique identifier of the bucket you would like to delete.
+ * @returns Promise with success message or error
+ *
+ * @example Delete bucket
+ * ```js
+ * const { data, error } = await supabase
+ * .storage
+ * .deleteBucket('avatars')
+ * ```
+ *
+ * Response:
+ * ```json
+ * {
+ * "data": {
+ * "message": "Successfully deleted"
+ * },
+ * "error": null
+ * }
+ * ```
+ *
+ * @remarks
+ * - RLS policy permissions required:
+ * - `buckets` table permissions: `select` and `delete`
+ * - `objects` table permissions: none
+ * - Refer to the [Storage guide](/docs/guides/storage/security/access-control) on how access control works
+ */
+ async deleteBucket(id) {
+ var _this6 = this;
+ return _this6.handleOperation(async () => {
+ return await remove(_this6.fetch, `${_this6.url}/bucket/${id}`, {}, { headers: _this6.headers });
+ });
+ }
+ /**
+ * Purges the CDN cache for an entire bucket.
+ *
+ * Maps to `DELETE /cdn/{bucket}` on the Storage API. The server
+ * issues a CDN invalidation for the bucket and returns `{ message: 'success' }`.
+ *
+ * **Requires the `service_role` key.** The underlying endpoint enforces
+ * `service_role` JWT — calls made with the anon key or a user JWT will be
+ * rejected by the server.
+ *
+ * **Hosted CDN feature.** On self-hosted Supabase, the Storage service must
+ * have `CDN_PURGE_ENDPOINT_URL` configured and the `purgeCache` tenant
+ * feature enabled, otherwise the server returns an error.
+ *
+ * @category Storage
+ * @subcategory File Buckets
+ * @param id The unique identifier of the bucket you would like to purge from cache.
+ * @param options Optional purge cache options.
+ * @param options.transformations If true, purges only transformations (resized/formatted variants), leaving original cached files intact.
+ * @param parameters Optional fetch parameters such as an `AbortController` signal.
+ * @returns Promise with `{ data: { message }, error: null }` on success or `{ data: null, error }` on failure.
+ *
+ * @example Purge cache for an entire bucket
+ * ```js
+ * const { data, error } = await supabase
+ * .storage
+ * .purgeBucketCache('avatars')
+ * ```
+ *
+ * @example Purge only transformations for an entire bucket
+ * ```js
+ * const { data, error } = await supabase
+ * .storage
+ * .purgeBucketCache('avatars', { transformations: true })
+ * ```
+ */
+ async purgeBucketCache(id, options, parameters) {
+ var _this7 = this;
+ return _this7.handleOperation(async () => {
+ const query = new URLSearchParams();
+ if (options === null || options === void 0 ? void 0 : options.transformations) query.set("transformations", "true");
+ const queryString = query.toString();
+ return await remove(_this7.fetch, `${_this7.url}/cdn/${encodeStoragePath(id)}${queryString ? `?${queryString}` : ""}`, {}, { headers: _this7.headers }, parameters);
+ });
+ }
+ listBucketOptionsToQueryString(options) {
+ const params = {};
+ if (options) {
+ if ("limit" in options) params.limit = String(options.limit);
+ if ("offset" in options) params.offset = String(options.offset);
+ if (options.search) params.search = options.search;
+ if (options.sortColumn) params.sortColumn = options.sortColumn;
+ if (options.sortOrder) params.sortOrder = options.sortOrder;
+ }
+ return Object.keys(params).length > 0 ? "?" + new URLSearchParams(params).toString() : "";
+ }
+};
+
+//#endregion
+//#region src/packages/StorageAnalyticsClient.ts
+/**
+* Client class for managing Analytics Buckets using Iceberg tables
+* Provides methods for creating, listing, and deleting analytics buckets
+*/
+var StorageAnalyticsClient = class extends BaseApiClient {
+ /**
+ * @alpha
+ *
+ * Creates a new StorageAnalyticsClient instance
+ *
+ * **Public alpha:** This API is part of a public alpha release and may not be available to your account type.
+ *
+ * @category Storage
+ * @subcategory Analytics Buckets
+ * @param url - The base URL for the storage API
+ * @param headers - HTTP headers to include in requests
+ * @param fetch - Optional custom fetch implementation
+ *
+ * @example Using supabase-js (recommended)
+ * ```typescript
+ * import { createClient } from '@supabase/supabase-js'
+ *
+ * const supabase = createClient('https://xyzcompany.supabase.co', 'your-publishable-key')
+ * const { data, error } = await supabase.storage.analytics.listBuckets()
+ * ```
+ *
+ * @example Standalone import for bundle-sensitive environments
+ * ```typescript
+ * import { StorageAnalyticsClient } from '@supabase/storage-js'
+ *
+ * const client = new StorageAnalyticsClient(url, headers)
+ * ```
+ */
+ constructor(url, headers = {}, fetch$1) {
+ const finalUrl = url.replace(/\/$/, "");
+ const finalHeaders = _objectSpread2(_objectSpread2({}, DEFAULT_HEADERS), headers);
+ super(finalUrl, finalHeaders, fetch$1, "storage");
+ }
+ /**
+ * @alpha
+ *
+ * Creates a new analytics bucket using Iceberg tables
+ * Analytics buckets are optimized for analytical queries and data processing
+ *
+ * **Public alpha:** This API is part of a public alpha release and may not be available to your account type.
+ *
+ * @category Storage
+ * @subcategory Analytics Buckets
+ * @param name A unique name for the bucket you are creating
+ * @returns Promise with response containing newly created analytics bucket or error
+ *
+ * @example Create analytics bucket
+ * ```js
+ * const { data, error } = await supabase
+ * .storage
+ * .analytics
+ * .createBucket('analytics-data')
+ * ```
+ *
+ * Response:
+ * ```json
+ * {
+ * "data": {
+ * "name": "analytics-data",
+ * "type": "ANALYTICS",
+ * "format": "iceberg",
+ * "created_at": "2024-05-22T22:26:05.100Z",
+ * "updated_at": "2024-05-22T22:26:05.100Z"
+ * },
+ * "error": null
+ * }
+ * ```
+ *
+ * @remarks
+ * - Creates a new analytics bucket using Iceberg tables
+ * - Analytics buckets are optimized for analytical queries and data processing
+ */
+ async createBucket(name) {
+ var _this = this;
+ return _this.handleOperation(async () => {
+ return await post(_this.fetch, `${_this.url}/bucket`, { name }, { headers: _this.headers });
+ });
+ }
+ /**
+ * @alpha
+ *
+ * Retrieves the details of all Analytics Storage buckets within an existing project
+ * Only returns buckets of type 'ANALYTICS'
+ *
+ * **Public alpha:** This API is part of a public alpha release and may not be available to your account type.
+ *
+ * @category Storage
+ * @subcategory Analytics Buckets
+ * @param options Query parameters for listing buckets
+ * @param options.limit Maximum number of buckets to return
+ * @param options.offset Number of buckets to skip
+ * @param options.sortColumn Column to sort by ('name', 'created_at', 'updated_at')
+ * @param options.sortOrder Sort order ('asc' or 'desc')
+ * @param options.search Search term to filter bucket names
+ * @returns Promise with response containing array of analytics buckets or error
+ *
+ * @example List analytics buckets
+ * ```js
+ * const { data, error } = await supabase
+ * .storage
+ * .analytics
+ * .listBuckets({
+ * limit: 10,
+ * offset: 0,
+ * sortColumn: 'created_at',
+ * sortOrder: 'desc'
+ * })
+ * ```
+ *
+ * Response:
+ * ```json
+ * {
+ * "data": [
+ * {
+ * "name": "analytics-data",
+ * "type": "ANALYTICS",
+ * "format": "iceberg",
+ * "created_at": "2024-05-22T22:26:05.100Z",
+ * "updated_at": "2024-05-22T22:26:05.100Z"
+ * }
+ * ],
+ * "error": null
+ * }
+ * ```
+ *
+ * @remarks
+ * - Retrieves the details of all Analytics Storage buckets within an existing project
+ * - Only returns buckets of type 'ANALYTICS'
+ */
+ async listBuckets(options) {
+ var _this2 = this;
+ return _this2.handleOperation(async () => {
+ const queryParams = new URLSearchParams();
+ if ((options === null || options === void 0 ? void 0 : options.limit) !== void 0) queryParams.set("limit", options.limit.toString());
+ if ((options === null || options === void 0 ? void 0 : options.offset) !== void 0) queryParams.set("offset", options.offset.toString());
+ if (options === null || options === void 0 ? void 0 : options.sortColumn) queryParams.set("sortColumn", options.sortColumn);
+ if (options === null || options === void 0 ? void 0 : options.sortOrder) queryParams.set("sortOrder", options.sortOrder);
+ if (options === null || options === void 0 ? void 0 : options.search) queryParams.set("search", options.search);
+ const queryString = queryParams.toString();
+ const url = queryString ? `${_this2.url}/bucket?${queryString}` : `${_this2.url}/bucket`;
+ return await get(_this2.fetch, url, { headers: _this2.headers });
+ });
+ }
+ /**
+ * @alpha
+ *
+ * Deletes an existing analytics bucket
+ * A bucket can't be deleted with existing objects inside it
+ * You must first empty the bucket before deletion
+ *
+ * **Public alpha:** This API is part of a public alpha release and may not be available to your account type.
+ *
+ * @category Storage
+ * @subcategory Analytics Buckets
+ * @param bucketName The unique identifier of the bucket you would like to delete
+ * @returns Promise with response containing success message or error
+ *
+ * @example Delete analytics bucket
+ * ```js
+ * const { data, error } = await supabase
+ * .storage
+ * .analytics
+ * .deleteBucket('analytics-data')
+ * ```
+ *
+ * Response:
+ * ```json
+ * {
+ * "data": {
+ * "message": "Successfully deleted"
+ * },
+ * "error": null
+ * }
+ * ```
+ *
+ * @remarks
+ * - Deletes an analytics bucket
+ */
+ async deleteBucket(bucketName) {
+ var _this3 = this;
+ return _this3.handleOperation(async () => {
+ return await remove(_this3.fetch, `${_this3.url}/bucket/${bucketName}`, {}, { headers: _this3.headers });
+ });
+ }
+ /**
+ * @alpha
+ *
+ * Get an Iceberg REST Catalog client configured for a specific analytics bucket
+ * Use this to perform advanced table and namespace operations within the bucket
+ * The returned client provides full access to the Apache Iceberg REST Catalog API
+ * with the Supabase `{ data, error }` pattern for consistent error handling on all operations.
+ *
+ * **Public alpha:** This API is part of a public alpha release and may not be available to your account type.
+ *
+ * @category Storage
+ * @subcategory Analytics Buckets
+ * @param bucketName - The name of the analytics bucket (warehouse) to connect to
+ * @returns The wrapped Iceberg catalog client
+ * @throws {StorageError} If the bucket name is invalid
+ *
+ * @example Get catalog and create table
+ * ```js
+ * // First, create an analytics bucket
+ * const { data: bucket, error: bucketError } = await supabase
+ * .storage
+ * .analytics
+ * .createBucket('analytics-data')
+ *
+ * // Get the Iceberg catalog for that bucket
+ * const catalog = supabase.storage.analytics.from('analytics-data')
+ *
+ * // Create a namespace
+ * const { error: nsError } = await catalog.createNamespace({ namespace: ['default'] })
+ *
+ * // Create a table with schema
+ * const { data: tableMetadata, error: tableError } = await catalog.createTable(
+ * { namespace: ['default'] },
+ * {
+ * name: 'events',
+ * schema: {
+ * type: 'struct',
+ * fields: [
+ * { id: 1, name: 'id', type: 'long', required: true },
+ * { id: 2, name: 'timestamp', type: 'timestamp', required: true },
+ * { id: 3, name: 'user_id', type: 'string', required: false }
+ * ],
+ * 'schema-id': 0,
+ * 'identifier-field-ids': [1]
+ * },
+ * 'partition-spec': {
+ * 'spec-id': 0,
+ * fields: []
+ * },
+ * 'write-order': {
+ * 'order-id': 0,
+ * fields: []
+ * },
+ * properties: {
+ * 'write.format.default': 'parquet'
+ * }
+ * }
+ * )
+ * ```
+ *
+ * @example List tables in namespace
+ * ```js
+ * const catalog = supabase.storage.analytics.from('analytics-data')
+ *
+ * // List all tables in the default namespace
+ * const { data: tables, error: listError } = await catalog.listTables({ namespace: ['default'] })
+ * if (listError) {
+ * if (listError.isNotFound()) {
+ * console.log('Namespace not found')
+ * }
+ * return
+ * }
+ * console.log(tables) // [{ namespace: ['default'], name: 'events' }]
+ * ```
+ *
+ * @example Working with namespaces
+ * ```js
+ * const catalog = supabase.storage.analytics.from('analytics-data')
+ *
+ * // List all namespaces
+ * const { data: namespaces } = await catalog.listNamespaces()
+ *
+ * // Create namespace with properties
+ * await catalog.createNamespace(
+ * { namespace: ['production'] },
+ * { properties: { owner: 'data-team', env: 'prod' } }
+ * )
+ * ```
+ *
+ * @example Cleanup operations
+ * ```js
+ * const catalog = supabase.storage.analytics.from('analytics-data')
+ *
+ * // Drop table with purge option (removes all data)
+ * const { error: dropError } = await catalog.dropTable(
+ * { namespace: ['default'], name: 'events' },
+ * { purge: true }
+ * )
+ *
+ * if (dropError?.isNotFound()) {
+ * console.log('Table does not exist')
+ * }
+ *
+ * // Drop namespace (must be empty)
+ * await catalog.dropNamespace({ namespace: ['default'] })
+ * ```
+ *
+ * @remarks
+ * This method provides a bridge between Supabase's bucket management and the standard
+ * Apache Iceberg REST Catalog API. The bucket name maps to the Iceberg warehouse parameter.
+ * All authentication and configuration is handled automatically using your Supabase credentials.
+ *
+ * **Error Handling**: Invalid bucket names throw immediately. All catalog
+ * operations return `{ data, error }` where errors are `IcebergError` instances from iceberg-js.
+ * Use helper methods like `error.isNotFound()` or check `error.status` for specific error handling.
+ * Use `.throwOnError()` on the analytics client if you prefer exceptions for catalog operations.
+ *
+ * **Cleanup Operations**: When using `dropTable`, the `purge: true` option permanently
+ * deletes all table data. Without it, the table is marked as deleted but data remains.
+ *
+ * **Library Dependency**: The returned catalog wraps `IcebergRestCatalog` from iceberg-js.
+ * For complete API documentation and advanced usage, refer to the
+ * [iceberg-js documentation](https://supabase.github.io/iceberg-js/).
+ */
+ from(bucketName) {
+ var _this4 = this;
+ if (!isValidBucketName(bucketName)) throw new StorageError("Invalid bucket name: File, folder, and bucket names must follow AWS object key naming guidelines and should avoid the use of any other characters.");
+ const catalog = new iceberg_js.IcebergRestCatalog({
+ baseUrl: this.url,
+ catalogName: bucketName,
+ auth: {
+ type: "custom",
+ getHeaders: async () => _this4.headers
+ },
+ fetch: this.fetch
+ });
+ const shouldThrowOnError = this.shouldThrowOnError;
+ return new Proxy(catalog, { get(target, prop) {
+ const value = target[prop];
+ if (typeof value !== "function") return value;
+ return async (...args) => {
+ try {
+ return {
+ data: await value.apply(target, args),
+ error: null
+ };
+ } catch (error) {
+ if (shouldThrowOnError) throw error;
+ return {
+ data: null,
+ error
+ };
+ }
+ };
+ } });
+ }
+};
+
+//#endregion
+//#region src/packages/VectorIndexApi.ts
+/**
+* @hidden
+* Base implementation for vector index operations.
+* Use {@link VectorBucketScope} via `supabase.storage.vectors.from('bucket')` instead.
+*/
+var VectorIndexApi = class extends BaseApiClient {
+ /** Creates a new VectorIndexApi instance */
+ constructor(url, headers = {}, fetch$1) {
+ const finalUrl = url.replace(/\/$/, "");
+ const finalHeaders = _objectSpread2(_objectSpread2({}, DEFAULT_HEADERS), {}, { "Content-Type": "application/json" }, headers);
+ super(finalUrl, finalHeaders, fetch$1, "vectors");
+ }
+ /** Creates a new vector index within a bucket */
+ async createIndex(options) {
+ var _this = this;
+ return _this.handleOperation(async () => {
+ return await vectorsApi.post(_this.fetch, `${_this.url}/CreateIndex`, options, { headers: _this.headers }) || {};
+ });
+ }
+ /** Retrieves metadata for a specific vector index */
+ async getIndex(vectorBucketName, indexName) {
+ var _this2 = this;
+ return _this2.handleOperation(async () => {
+ return await vectorsApi.post(_this2.fetch, `${_this2.url}/GetIndex`, {
+ vectorBucketName,
+ indexName
+ }, { headers: _this2.headers });
+ });
+ }
+ /** Lists vector indexes within a bucket with optional filtering and pagination */
+ async listIndexes(options) {
+ var _this3 = this;
+ return _this3.handleOperation(async () => {
+ return await vectorsApi.post(_this3.fetch, `${_this3.url}/ListIndexes`, options, { headers: _this3.headers });
+ });
+ }
+ /** Deletes a vector index and all its data */
+ async deleteIndex(vectorBucketName, indexName) {
+ var _this4 = this;
+ return _this4.handleOperation(async () => {
+ return await vectorsApi.post(_this4.fetch, `${_this4.url}/DeleteIndex`, {
+ vectorBucketName,
+ indexName
+ }, { headers: _this4.headers }) || {};
+ });
+ }
+};
+
+//#endregion
+//#region src/packages/VectorDataApi.ts
+/**
+* @hidden
+* Base implementation for vector data operations.
+* Use {@link VectorIndexScope} via `supabase.storage.vectors.from('bucket').index('idx')` instead.
+*/
+var VectorDataApi = class extends BaseApiClient {
+ /** Creates a new VectorDataApi instance */
+ constructor(url, headers = {}, fetch$1) {
+ const finalUrl = url.replace(/\/$/, "");
+ const finalHeaders = _objectSpread2(_objectSpread2({}, DEFAULT_HEADERS), {}, { "Content-Type": "application/json" }, headers);
+ super(finalUrl, finalHeaders, fetch$1, "vectors");
+ }
+ /** Inserts or updates vectors in batch (1-500 per request) */
+ async putVectors(options) {
+ var _this = this;
+ if (options.vectors.length < 1 || options.vectors.length > 500) throw new Error("Vector batch size must be between 1 and 500 items");
+ return _this.handleOperation(async () => {
+ return await vectorsApi.post(_this.fetch, `${_this.url}/PutVectors`, options, { headers: _this.headers }) || {};
+ });
+ }
+ /** Retrieves vectors by their keys in batch */
+ async getVectors(options) {
+ var _this2 = this;
+ return _this2.handleOperation(async () => {
+ return await vectorsApi.post(_this2.fetch, `${_this2.url}/GetVectors`, options, { headers: _this2.headers });
+ });
+ }
+ /** Lists vectors in an index with pagination */
+ async listVectors(options) {
+ var _this3 = this;
+ if (options.segmentCount !== void 0) {
+ if (options.segmentCount < 1 || options.segmentCount > 16) throw new Error("segmentCount must be between 1 and 16");
+ if (options.segmentIndex !== void 0) {
+ if (options.segmentIndex < 0 || options.segmentIndex >= options.segmentCount) throw new Error(`segmentIndex must be between 0 and ${options.segmentCount - 1}`);
+ }
+ }
+ return _this3.handleOperation(async () => {
+ return await vectorsApi.post(_this3.fetch, `${_this3.url}/ListVectors`, options, { headers: _this3.headers });
+ });
+ }
+ /** Queries for similar vectors using approximate nearest neighbor search */
+ async queryVectors(options) {
+ var _this4 = this;
+ return _this4.handleOperation(async () => {
+ return await vectorsApi.post(_this4.fetch, `${_this4.url}/QueryVectors`, options, { headers: _this4.headers });
+ });
+ }
+ /** Deletes vectors by their keys in batch (1-500 per request) */
+ async deleteVectors(options) {
+ var _this5 = this;
+ if (options.keys.length < 1 || options.keys.length > 500) throw new Error("Keys batch size must be between 1 and 500 items");
+ return _this5.handleOperation(async () => {
+ return await vectorsApi.post(_this5.fetch, `${_this5.url}/DeleteVectors`, options, { headers: _this5.headers }) || {};
+ });
+ }
+};
+
+//#endregion
+//#region src/packages/VectorBucketApi.ts
+/**
+* @hidden
+* Base implementation for vector bucket operations.
+* Use {@link StorageVectorsClient} via `supabase.storage.vectors` instead.
+*/
+var VectorBucketApi = class extends BaseApiClient {
+ /** Creates a new VectorBucketApi instance */
+ constructor(url, headers = {}, fetch$1) {
+ const finalUrl = url.replace(/\/$/, "");
+ const finalHeaders = _objectSpread2(_objectSpread2({}, DEFAULT_HEADERS), {}, { "Content-Type": "application/json" }, headers);
+ super(finalUrl, finalHeaders, fetch$1, "vectors");
+ }
+ /** Creates a new vector bucket */
+ async createBucket(vectorBucketName) {
+ var _this = this;
+ return _this.handleOperation(async () => {
+ return await vectorsApi.post(_this.fetch, `${_this.url}/CreateVectorBucket`, { vectorBucketName }, { headers: _this.headers }) || {};
+ });
+ }
+ /** Retrieves metadata for a specific vector bucket */
+ async getBucket(vectorBucketName) {
+ var _this2 = this;
+ return _this2.handleOperation(async () => {
+ return await vectorsApi.post(_this2.fetch, `${_this2.url}/GetVectorBucket`, { vectorBucketName }, { headers: _this2.headers });
+ });
+ }
+ /** Lists vector buckets with optional filtering and pagination */
+ async listBuckets(options = {}) {
+ var _this3 = this;
+ return _this3.handleOperation(async () => {
+ return await vectorsApi.post(_this3.fetch, `${_this3.url}/ListVectorBuckets`, options, { headers: _this3.headers });
+ });
+ }
+ /** Deletes a vector bucket (must be empty first) */
+ async deleteBucket(vectorBucketName) {
+ var _this4 = this;
+ return _this4.handleOperation(async () => {
+ return await vectorsApi.post(_this4.fetch, `${_this4.url}/DeleteVectorBucket`, { vectorBucketName }, { headers: _this4.headers }) || {};
+ });
+ }
+};
+
+//#endregion
+//#region src/packages/StorageVectorsClient.ts
+/**
+*
+* @alpha
+*
+* Main client for interacting with S3 Vectors API
+* Provides access to bucket, index, and vector data operations
+*
+* **Public alpha:** This API is part of a public alpha release and may not be available to your account type.
+*
+* **Usage Patterns:**
+*
+* ```typescript
+* const { data, error } = await supabase
+* .storage
+* .vectors
+* .createBucket('embeddings-prod')
+*
+* // Access index operations via buckets
+* const bucket = supabase.storage.vectors.from('embeddings-prod')
+* await bucket.createIndex({
+* indexName: 'documents',
+* dataType: 'float32',
+* dimension: 1536,
+* distanceMetric: 'cosine'
+* })
+*
+* // Access vector operations via index
+* const index = bucket.index('documents')
+* await index.putVectors({
+* vectors: [
+* { key: 'doc-1', data: { float32: [...] }, metadata: { title: 'Intro' } }
+* ]
+* })
+*
+* // Query similar vectors
+* const { data } = await index.queryVectors({
+* queryVector: { float32: [...] },
+* topK: 5,
+* returnDistance: true
+* })
+* ```
+*/
+var StorageVectorsClient = class extends VectorBucketApi {
+ /**
+ * @alpha
+ *
+ * Creates a StorageVectorsClient that can manage buckets, indexes, and vectors.
+ *
+ * **Public alpha:** This API is part of a public alpha release and may not be available to your account type.
+ *
+ * @category Storage
+ * @subcategory Vector Buckets
+ * @param url - Base URL of the Storage Vectors REST API.
+ * @param options.headers - Optional headers (for example `Authorization`) applied to every request.
+ * @param options.fetch - Optional custom `fetch` implementation for non-browser runtimes.
+ *
+ * @example Using supabase-js (recommended)
+ * ```typescript
+ * import { createClient } from '@supabase/supabase-js'
+ *
+ * const supabase = createClient('https://xyzcompany.supabase.co', 'your-publishable-key')
+ * const bucket = supabase.storage.vectors.from('embeddings-prod')
+ * ```
+ *
+ * @example Standalone import for bundle-sensitive environments
+ * ```typescript
+ * import { StorageVectorsClient } from '@supabase/storage-js'
+ *
+ * const client = new StorageVectorsClient(url, options)
+ * ```
+ */
+ constructor(url, options = {}) {
+ super(url, options.headers || {}, options.fetch);
+ }
+ /**
+ *
+ * @alpha
+ *
+ * Access operations for a specific vector bucket
+ * Returns a scoped client for index and vector operations within the bucket
+ *
+ * **Public alpha:** This API is part of a public alpha release and may not be available to your account type.
+ *
+ * @category Storage
+ * @subcategory Vector Buckets
+ * @param vectorBucketName - Name of the vector bucket
+ * @returns Bucket-scoped client with index and vector operations
+ *
+ * @example Accessing a vector bucket
+ * ```typescript
+ * const bucket = supabase.storage.vectors.from('embeddings-prod')
+ * ```
+ */
+ from(vectorBucketName) {
+ return new VectorBucketScope(this.url, this.headers, vectorBucketName, this.fetch);
+ }
+ /**
+ *
+ * @alpha
+ *
+ * Creates a new vector bucket
+ * Vector buckets are containers for vector indexes and their data
+ *
+ * **Public alpha:** This API is part of a public alpha release and may not be available to your account type.
+ *
+ * @category Storage
+ * @subcategory Vector Buckets
+ * @param vectorBucketName - Unique name for the vector bucket
+ * @returns Promise with empty response on success or error
+ *
+ * @example Creating a vector bucket
+ * ```typescript
+ * const { data, error } = await supabase
+ * .storage
+ * .vectors
+ * .createBucket('embeddings-prod')
+ * ```
+ */
+ async createBucket(vectorBucketName) {
+ var _superprop_getCreateBucket = () => super.createBucket, _this = this;
+ return _superprop_getCreateBucket().call(_this, vectorBucketName);
+ }
+ /**
+ *
+ * @alpha
+ *
+ * Retrieves metadata for a specific vector bucket
+ *
+ * **Public alpha:** This API is part of a public alpha release and may not be available to your account type.
+ *
+ * @category Storage
+ * @subcategory Vector Buckets
+ * @param vectorBucketName - Name of the vector bucket
+ * @returns Promise with bucket metadata or error
+ *
+ * @example Get bucket metadata
+ * ```typescript
+ * const { data, error } = await supabase
+ * .storage
+ * .vectors
+ * .getBucket('embeddings-prod')
+ *
+ * console.log('Bucket created:', data?.vectorBucket.creationTime)
+ * ```
+ */
+ async getBucket(vectorBucketName) {
+ var _superprop_getGetBucket = () => super.getBucket, _this2 = this;
+ return _superprop_getGetBucket().call(_this2, vectorBucketName);
+ }
+ /**
+ *
+ * @alpha
+ *
+ * Lists all vector buckets with optional filtering and pagination
+ *
+ * **Public alpha:** This API is part of a public alpha release and may not be available to your account type.
+ *
+ * @category Storage
+ * @subcategory Vector Buckets
+ * @param options - Optional filters (prefix, maxResults, nextToken)
+ * @returns Promise with list of buckets or error
+ *
+ * @example List vector buckets
+ * ```typescript
+ * const { data, error } = await supabase
+ * .storage
+ * .vectors
+ * .listBuckets({ prefix: 'embeddings-' })
+ *
+ * data?.vectorBuckets.forEach(bucket => {
+ * console.log(bucket.vectorBucketName)
+ * })
+ * ```
+ */
+ async listBuckets(options = {}) {
+ var _superprop_getListBuckets = () => super.listBuckets, _this3 = this;
+ return _superprop_getListBuckets().call(_this3, options);
+ }
+ /**
+ *
+ * @alpha
+ *
+ * Deletes a vector bucket (bucket must be empty)
+ * All indexes must be deleted before deleting the bucket
+ *
+ * **Public alpha:** This API is part of a public alpha release and may not be available to your account type.
+ *
+ * @category Storage
+ * @subcategory Vector Buckets
+ * @param vectorBucketName - Name of the vector bucket to delete
+ * @returns Promise with empty response on success or error
+ *
+ * @example Delete a vector bucket
+ * ```typescript
+ * const { data, error } = await supabase
+ * .storage
+ * .vectors
+ * .deleteBucket('embeddings-old')
+ * ```
+ */
+ async deleteBucket(vectorBucketName) {
+ var _superprop_getDeleteBucket = () => super.deleteBucket, _this4 = this;
+ return _superprop_getDeleteBucket().call(_this4, vectorBucketName);
+ }
+};
+/**
+*
+* @alpha
+*
+* Scoped client for operations within a specific vector bucket
+* Provides index management and access to vector operations
+*
+* **Public alpha:** This API is part of a public alpha release and may not be available to your account type.
+*/
+var VectorBucketScope = class extends VectorIndexApi {
+ /**
+ * @alpha
+ *
+ * Creates a helper that automatically scopes all index operations to the provided bucket.
+ *
+ * **Public alpha:** This API is part of a public alpha release and may not be available to your account type.
+ *
+ * @category Storage
+ * @subcategory Vector Buckets
+ * @example Creating a vector bucket scope
+ * ```typescript
+ * const bucket = supabase.storage.vectors.from('embeddings-prod')
+ * ```
+ */
+ constructor(url, headers, vectorBucketName, fetch$1) {
+ super(url, headers, fetch$1);
+ this.vectorBucketName = vectorBucketName;
+ }
+ /**
+ *
+ * @alpha
+ *
+ * Creates a new vector index in this bucket
+ * Convenience method that automatically includes the bucket name
+ *
+ * **Public alpha:** This API is part of a public alpha release and may not be available to your account type.
+ *
+ * @category Storage
+ * @subcategory Vector Buckets
+ * @param options - Index configuration (vectorBucketName is automatically set)
+ * @returns Promise with empty response on success or error
+ *
+ * @example Creating a vector index
+ * ```typescript
+ * const bucket = supabase.storage.vectors.from('embeddings-prod')
+ * await bucket.createIndex({
+ * indexName: 'documents-openai',
+ * dataType: 'float32',
+ * dimension: 1536,
+ * distanceMetric: 'cosine',
+ * metadataConfiguration: {
+ * nonFilterableMetadataKeys: ['raw_text']
+ * }
+ * })
+ * ```
+ */
+ async createIndex(options) {
+ var _superprop_getCreateIndex = () => super.createIndex, _this5 = this;
+ return _superprop_getCreateIndex().call(_this5, _objectSpread2(_objectSpread2({}, options), {}, { vectorBucketName: _this5.vectorBucketName }));
+ }
+ /**
+ *
+ * @alpha
+ *
+ * Lists indexes in this bucket
+ * Convenience method that automatically includes the bucket name
+ *
+ * **Public alpha:** This API is part of a public alpha release and may not be available to your account type.
+ *
+ * @category Storage
+ * @subcategory Vector Buckets
+ * @param options - Listing options (vectorBucketName is automatically set)
+ * @returns Promise with response containing indexes array and pagination token or error
+ *
+ * @example List indexes
+ * ```typescript
+ * const bucket = supabase.storage.vectors.from('embeddings-prod')
+ * const { data } = await bucket.listIndexes({ prefix: 'documents-' })
+ * ```
+ */
+ async listIndexes(options = {}) {
+ var _superprop_getListIndexes = () => super.listIndexes, _this6 = this;
+ return _superprop_getListIndexes().call(_this6, _objectSpread2(_objectSpread2({}, options), {}, { vectorBucketName: _this6.vectorBucketName }));
+ }
+ /**
+ *
+ * @alpha
+ *
+ * Retrieves metadata for a specific index in this bucket
+ * Convenience method that automatically includes the bucket name
+ *
+ * **Public alpha:** This API is part of a public alpha release and may not be available to your account type.
+ *
+ * @category Storage
+ * @subcategory Vector Buckets
+ * @param indexName - Name of the index to retrieve
+ * @returns Promise with index metadata or error
+ *
+ * @example Get index metadata
+ * ```typescript
+ * const bucket = supabase.storage.vectors.from('embeddings-prod')
+ * const { data } = await bucket.getIndex('documents-openai')
+ * console.log('Dimension:', data?.index.dimension)
+ * ```
+ */
+ async getIndex(indexName) {
+ var _superprop_getGetIndex = () => super.getIndex, _this7 = this;
+ return _superprop_getGetIndex().call(_this7, _this7.vectorBucketName, indexName);
+ }
+ /**
+ *
+ * @alpha
+ *
+ * Deletes an index from this bucket
+ * Convenience method that automatically includes the bucket name
+ *
+ * **Public alpha:** This API is part of a public alpha release and may not be available to your account type.
+ *
+ * @category Storage
+ * @subcategory Vector Buckets
+ * @param indexName - Name of the index to delete
+ * @returns Promise with empty response on success or error
+ *
+ * @example Delete an index
+ * ```typescript
+ * const bucket = supabase.storage.vectors.from('embeddings-prod')
+ * await bucket.deleteIndex('old-index')
+ * ```
+ */
+ async deleteIndex(indexName) {
+ var _superprop_getDeleteIndex = () => super.deleteIndex, _this8 = this;
+ return _superprop_getDeleteIndex().call(_this8, _this8.vectorBucketName, indexName);
+ }
+ /**
+ *
+ * @alpha
+ *
+ * Access operations for a specific index within this bucket
+ * Returns a scoped client for vector data operations
+ *
+ * **Public alpha:** This API is part of a public alpha release and may not be available to your account type.
+ *
+ * @category Storage
+ * @subcategory Vector Buckets
+ * @param indexName - Name of the index
+ * @returns Index-scoped client with vector data operations
+ *
+ * @example Accessing an index
+ * ```typescript
+ * const index = supabase.storage.vectors.from('embeddings-prod').index('documents-openai')
+ *
+ * // Insert vectors
+ * await index.putVectors({
+ * vectors: [
+ * { key: 'doc-1', data: { float32: [...] }, metadata: { title: 'Intro' } }
+ * ]
+ * })
+ *
+ * // Query similar vectors
+ * const { data } = await index.queryVectors({
+ * queryVector: { float32: [...] },
+ * topK: 5
+ * })
+ * ```
+ */
+ index(indexName) {
+ return new VectorIndexScope(this.url, this.headers, this.vectorBucketName, indexName, this.fetch);
+ }
+};
+/**
+*
+* @alpha
+*
+* Scoped client for operations within a specific vector index
+* Provides vector data operations (put, get, list, query, delete)
+*
+* **Public alpha:** This API is part of a public alpha release and may not be available to your account type.
+*/
+var VectorIndexScope = class extends VectorDataApi {
+ /**
+ *
+ * @alpha
+ *
+ * Creates a helper that automatically scopes all vector operations to the provided bucket/index names.
+ *
+ * **Public alpha:** This API is part of a public alpha release and may not be available to your account type.
+ *
+ * @category Storage
+ * @subcategory Vector Buckets
+ * @example Creating a vector index scope
+ * ```typescript
+ * const index = supabase.storage.vectors.from('embeddings-prod').index('documents-openai')
+ * ```
+ */
+ constructor(url, headers, vectorBucketName, indexName, fetch$1) {
+ super(url, headers, fetch$1);
+ this.vectorBucketName = vectorBucketName;
+ this.indexName = indexName;
+ }
+ /**
+ *
+ * @alpha
+ *
+ * Inserts or updates vectors in this index
+ * Convenience method that automatically includes bucket and index names
+ *
+ * **Public alpha:** This API is part of a public alpha release and may not be available to your account type.
+ *
+ * @category Storage
+ * @subcategory Vector Buckets
+ * @param options - Vector insertion options (bucket and index names automatically set)
+ * @returns Promise with empty response on success or error
+ *
+ * @example Insert vectors into an index
+ * ```typescript
+ * const index = supabase.storage.vectors.from('embeddings-prod').index('documents-openai')
+ * await index.putVectors({
+ * vectors: [
+ * {
+ * key: 'doc-1',
+ * data: { float32: [0.1, 0.2, ...] },
+ * metadata: { title: 'Introduction', page: 1 }
+ * }
+ * ]
+ * })
+ * ```
+ */
+ async putVectors(options) {
+ var _superprop_getPutVectors = () => super.putVectors, _this9 = this;
+ return _superprop_getPutVectors().call(_this9, _objectSpread2(_objectSpread2({}, options), {}, {
+ vectorBucketName: _this9.vectorBucketName,
+ indexName: _this9.indexName
+ }));
+ }
+ /**
+ *
+ * @alpha
+ *
+ * Retrieves vectors by keys from this index
+ * Convenience method that automatically includes bucket and index names
+ *
+ * **Public alpha:** This API is part of a public alpha release and may not be available to your account type.
+ *
+ * @category Storage
+ * @subcategory Vector Buckets
+ * @param options - Vector retrieval options (bucket and index names automatically set)
+ * @returns Promise with response containing vectors array or error
+ *
+ * @example Get vectors by keys
+ * ```typescript
+ * const index = supabase.storage.vectors.from('embeddings-prod').index('documents-openai')
+ * const { data } = await index.getVectors({
+ * keys: ['doc-1', 'doc-2'],
+ * returnMetadata: true
+ * })
+ * ```
+ */
+ async getVectors(options) {
+ var _superprop_getGetVectors = () => super.getVectors, _this10 = this;
+ return _superprop_getGetVectors().call(_this10, _objectSpread2(_objectSpread2({}, options), {}, {
+ vectorBucketName: _this10.vectorBucketName,
+ indexName: _this10.indexName
+ }));
+ }
+ /**
+ *
+ * @alpha
+ *
+ * Lists vectors in this index with pagination
+ * Convenience method that automatically includes bucket and index names
+ *
+ * **Public alpha:** This API is part of a public alpha release and may not be available to your account type.
+ *
+ * @category Storage
+ * @subcategory Vector Buckets
+ * @param options - Listing options (bucket and index names automatically set)
+ * @returns Promise with response containing vectors array and pagination token or error
+ *
+ * @example List vectors with pagination
+ * ```typescript
+ * const index = supabase.storage.vectors.from('embeddings-prod').index('documents-openai')
+ * const { data } = await index.listVectors({
+ * maxResults: 500,
+ * returnMetadata: true
+ * })
+ * ```
+ */
+ async listVectors(options = {}) {
+ var _superprop_getListVectors = () => super.listVectors, _this11 = this;
+ return _superprop_getListVectors().call(_this11, _objectSpread2(_objectSpread2({}, options), {}, {
+ vectorBucketName: _this11.vectorBucketName,
+ indexName: _this11.indexName
+ }));
+ }
+ /**
+ *
+ * @alpha
+ *
+ * Queries for similar vectors in this index
+ * Convenience method that automatically includes bucket and index names
+ *
+ * **Public alpha:** This API is part of a public alpha release and may not be available to your account type.
+ *
+ * @category Storage
+ * @subcategory Vector Buckets
+ * @param options - Query options (bucket and index names automatically set)
+ * @returns Promise with response containing matches array of similar vectors ordered by distance or error
+ *
+ * @example Query similar vectors
+ * ```typescript
+ * const index = supabase.storage.vectors.from('embeddings-prod').index('documents-openai')
+ * const { data } = await index.queryVectors({
+ * queryVector: { float32: [0.1, 0.2, ...] },
+ * topK: 5,
+ * filter: { category: 'technical' },
+ * returnDistance: true,
+ * returnMetadata: true
+ * })
+ * ```
+ */
+ async queryVectors(options) {
+ var _superprop_getQueryVectors = () => super.queryVectors, _this12 = this;
+ return _superprop_getQueryVectors().call(_this12, _objectSpread2(_objectSpread2({}, options), {}, {
+ vectorBucketName: _this12.vectorBucketName,
+ indexName: _this12.indexName
+ }));
+ }
+ /**
+ *
+ * @alpha
+ *
+ * Deletes vectors by keys from this index
+ * Convenience method that automatically includes bucket and index names
+ *
+ * **Public alpha:** This API is part of a public alpha release and may not be available to your account type.
+ *
+ * @category Storage
+ * @subcategory Vector Buckets
+ * @param options - Deletion options (bucket and index names automatically set)
+ * @returns Promise with empty response on success or error
+ *
+ * @example Delete vectors by keys
+ * ```typescript
+ * const index = supabase.storage.vectors.from('embeddings-prod').index('documents-openai')
+ * await index.deleteVectors({
+ * keys: ['doc-1', 'doc-2', 'doc-3']
+ * })
+ * ```
+ */
+ async deleteVectors(options) {
+ var _superprop_getDeleteVectors = () => super.deleteVectors, _this13 = this;
+ return _superprop_getDeleteVectors().call(_this13, _objectSpread2(_objectSpread2({}, options), {}, {
+ vectorBucketName: _this13.vectorBucketName,
+ indexName: _this13.indexName
+ }));
+ }
+};
+
+//#endregion
+//#region src/StorageClient.ts
+var StorageClient = class extends StorageBucketApi {
+ /**
+ * Creates a client for Storage buckets, files, analytics, and vectors.
+ *
+ * @category Storage
+ * @subcategory File Buckets
+ *
+ * @example Using supabase-js (recommended)
+ * ```ts
+ * import { createClient } from '@supabase/supabase-js'
+ *
+ * const supabase = createClient('https://xyzcompany.supabase.co', 'your-publishable-key')
+ * const avatars = supabase.storage.from('avatars')
+ * ```
+ *
+ * @example Standalone import for bundle-sensitive environments
+ * ```ts
+ * import { StorageClient } from '@supabase/storage-js'
+ *
+ * const storage = new StorageClient('https://xyzcompany.supabase.co/storage/v1', {
+ * apikey: 'your-publishable-key',
+ * })
+ * const avatars = storage.from('avatars')
+ * ```
+ */
+ constructor(url, headers = {}, fetch$1, opts) {
+ super(url, headers, fetch$1, opts);
+ }
+ /**
+ * Perform file operation in a bucket.
+ *
+ * @category Storage
+ * @subcategory File Buckets
+ *
+ * @param id The bucket id to operate on.
+ *
+ * @example Accessing a bucket
+ * ```typescript
+ * const avatars = supabase.storage.from('avatars')
+ * ```
+ */
+ from(id) {
+ return new StorageFileApi(this.url, this.headers, id, this.fetch);
+ }
+ /**
+ *
+ * @alpha
+ *
+ * Access vector storage operations.
+ *
+ * **Public alpha:** This API is part of a public alpha release and may not be available to your account type.
+ *
+ * @category Storage
+ * @subcategory Vector Buckets
+ *
+ * @returns A StorageVectorsClient instance configured with the current storage settings.
+ */
+ get vectors() {
+ return new StorageVectorsClient(this.url + "/vector", {
+ headers: this.headers,
+ fetch: this.fetch
+ });
+ }
+ /**
+ *
+ * @alpha
+ *
+ * Access analytics storage operations using Iceberg tables.
+ *
+ * **Public alpha:** This API is part of a public alpha release and may not be available to your account type.
+ *
+ * @category Storage
+ * @subcategory Analytics Buckets
+ *
+ * @returns A StorageAnalyticsClient instance configured with the current storage settings.
+ */
+ get analytics() {
+ return new StorageAnalyticsClient(this.url + "/iceberg", this.headers, this.fetch);
+ }
+};
+
+//#endregion
+exports.StorageAnalyticsClient = StorageAnalyticsClient;
+exports.StorageApiError = StorageApiError;
+exports.StorageClient = StorageClient;
+exports.StorageError = StorageError;
+exports.StorageUnknownError = StorageUnknownError;
+exports.StorageVectorsApiError = StorageVectorsApiError;
+exports.StorageVectorsClient = StorageVectorsClient;
+exports.StorageVectorsError = StorageVectorsError;
+exports.StorageVectorsErrorCode = StorageVectorsErrorCode;
+exports.StorageVectorsUnknownError = StorageVectorsUnknownError;
+exports.VectorBucketApi = VectorBucketApi;
+exports.VectorBucketScope = VectorBucketScope;
+exports.VectorDataApi = VectorDataApi;
+exports.VectorIndexApi = VectorIndexApi;
+exports.VectorIndexScope = VectorIndexScope;
+exports.isStorageError = isStorageError;
+exports.isStorageVectorsError = isStorageVectorsError;
+//# sourceMappingURL=index.cjs.map
\ No newline at end of file
diff --git a/node_modules/@supabase/storage-js/dist/index.cjs.map b/node_modules/@supabase/storage-js/dist/index.cjs.map
new file mode 100644
index 0000000000000000000000000000000000000000..3b3c2d97d702e9867f18dc8ea76b7469cb28bfdd
--- /dev/null
+++ b/node_modules/@supabase/storage-js/dist/index.cjs.map
@@ -0,0 +1 @@
+{"version":3,"file":"index.cjs","names":["result: Record","result: Record","params: { [k: string]: any }","contentType: string | undefined","fetch","setHeaderUtil","this","downloadFn: () => Promise","shouldThrowOnError: boolean","this","downloadFn: () => Promise","shouldThrowOnError: boolean","this","DEFAULT_FILE_OPTIONS: FileOptions","fetch","this","headers: Record","fetch","this","params: Record","fetch","this","IcebergRestCatalog","fetch","this","fetch","this","fetch","this","fetch","this","fetch"],"sources":["../src/lib/common/errors.ts","../src/lib/common/headers.ts","../src/lib/common/helpers.ts","../src/lib/common/fetch.ts","../src/lib/common/BaseApiClient.ts","../src/packages/StreamDownloadBuilder.ts","../src/packages/BlobDownloadBuilder.ts","../src/packages/StorageFileApi.ts","../src/lib/version.ts","../src/lib/constants.ts","../src/packages/StorageBucketApi.ts","../src/packages/StorageAnalyticsClient.ts","../src/packages/VectorIndexApi.ts","../src/packages/VectorDataApi.ts","../src/packages/VectorBucketApi.ts","../src/packages/StorageVectorsClient.ts","../src/StorageClient.ts"],"sourcesContent":["/**\n * Namespace type for error classes\n * Determines the error class names and type guards\n */\nexport type ErrorNamespace = 'storage' | 'vectors'\n\n/**\n * Base error class for all Storage errors\n * Supports both 'storage' and 'vectors' namespaces\n */\nexport class StorageError extends Error {\n protected __isStorageError = true\n protected namespace: ErrorNamespace\n status: number | undefined\n statusCode: string | undefined\n\n constructor(\n message: string,\n namespace: ErrorNamespace = 'storage',\n status?: number,\n statusCode?: string\n ) {\n super(message)\n this.namespace = namespace\n this.name = namespace === 'vectors' ? 'StorageVectorsError' : 'StorageError'\n this.status = status\n this.statusCode = statusCode\n }\n\n toJSON(): {\n name: string\n message: string\n status: number | undefined\n statusCode: string | undefined\n } {\n return {\n name: this.name,\n message: this.message,\n status: this.status,\n statusCode: this.statusCode,\n }\n }\n}\n\n/**\n * Type guard to check if an error is a StorageError\n * @param error - The error to check\n * @returns True if the error is a StorageError\n */\nexport function isStorageError(error: unknown): error is StorageError {\n return typeof error === 'object' && error !== null && '__isStorageError' in error\n}\n\n/**\n * API error returned from Storage service\n * Includes HTTP status code and service-specific error code\n */\nexport class StorageApiError extends StorageError {\n override status: number\n override statusCode: string\n /**\n * Service-specific error code from the Storage API response body, such as\n * `NoSuchKey`, `AccessDenied` or `ResourceAlreadyExists`. Use this to branch\n * on the specific error rather than parsing the message.\n * @see https://supabase.com/docs/guides/storage/debugging/error-codes\n */\n code: string | undefined\n\n constructor(\n message: string,\n status: number,\n statusCode: string,\n namespace: ErrorNamespace = 'storage',\n code?: string\n ) {\n super(message, namespace, status, statusCode)\n this.name = namespace === 'vectors' ? 'StorageVectorsApiError' : 'StorageApiError'\n this.status = status\n this.statusCode = statusCode\n this.code = code\n }\n\n toJSON(): {\n name: string\n message: string\n status: number | undefined\n statusCode: string | undefined\n code: string | undefined\n } {\n return {\n ...super.toJSON(),\n code: this.code,\n }\n }\n}\n\n/**\n * Unknown error that doesn't match expected error patterns\n * Wraps the original error for debugging\n */\nexport class StorageUnknownError extends StorageError {\n originalError: unknown\n\n constructor(message: string, originalError: unknown, namespace: ErrorNamespace = 'storage') {\n super(message, namespace)\n this.name = namespace === 'vectors' ? 'StorageVectorsUnknownError' : 'StorageUnknownError'\n this.originalError = originalError\n }\n}\n\n// ============================================================================\n// Backward Compatibility Exports for Vectors\n// ============================================================================\n\n/**\n * @deprecated Use StorageError with namespace='vectors' instead\n * Alias for backward compatibility with existing vector storage code\n */\nexport class StorageVectorsError extends StorageError {\n constructor(message: string) {\n super(message, 'vectors')\n }\n}\n\n/**\n * Type guard to check if an error is a StorageVectorsError\n * @param error - The error to check\n * @returns True if the error is a StorageVectorsError\n */\nexport function isStorageVectorsError(error: unknown): error is StorageVectorsError {\n return isStorageError(error) && (error as StorageError)['namespace'] === 'vectors'\n}\n\n/**\n * @deprecated Use StorageApiError with namespace='vectors' instead\n * Alias for backward compatibility with existing vector storage code\n */\nexport class StorageVectorsApiError extends StorageApiError {\n constructor(message: string, status: number, statusCode: string) {\n super(message, status, statusCode, 'vectors')\n }\n}\n\n/**\n * @deprecated Use StorageUnknownError with namespace='vectors' instead\n * Alias for backward compatibility with existing vector storage code\n */\nexport class StorageVectorsUnknownError extends StorageUnknownError {\n constructor(message: string, originalError: unknown) {\n super(message, originalError, 'vectors')\n }\n}\n\n/**\n * Error codes specific to S3 Vectors API\n * Maps AWS service errors to application-friendly error codes\n */\nexport enum StorageVectorsErrorCode {\n /** Internal server fault (HTTP 500) */\n InternalError = 'InternalError',\n /** Resource already exists / conflict (HTTP 409) */\n S3VectorConflictException = 'S3VectorConflictException',\n /** Resource not found (HTTP 404) */\n S3VectorNotFoundException = 'S3VectorNotFoundException',\n /** Delete bucket while not empty (HTTP 400) */\n S3VectorBucketNotEmpty = 'S3VectorBucketNotEmpty',\n /** Exceeds bucket quota/limit (HTTP 400) */\n S3VectorMaxBucketsExceeded = 'S3VectorMaxBucketsExceeded',\n /** Exceeds index quota/limit (HTTP 400) */\n S3VectorMaxIndexesExceeded = 'S3VectorMaxIndexesExceeded',\n}\n","/**\n * Sets a header with case-insensitive deduplication.\n * Removes any existing headers whose name matches (case-insensitive),\n * then sets the value under the lowercase key. Does not mutate the input object.\n *\n * @param headers - Existing headers object\n * @param name - Header name to set (stored as lowercase)\n * @param value - Header value\n * @returns New headers object with the header set\n */\nexport function setHeader(\n headers: Record,\n name: string,\n value: string\n): Record {\n const result = { ...headers }\n const nameLower = name.toLowerCase()\n\n for (const key of Object.keys(result)) {\n if (key.toLowerCase() === nameLower) {\n delete result[key]\n }\n }\n\n result[nameLower] = value\n return result\n}\n\n/**\n * Normalizes all header keys to lowercase with case-insensitive deduplication.\n * When duplicate keys exist (differing only in case), the last value wins.\n * Does not mutate the input object.\n *\n * @param headers - Headers object to normalize\n * @returns New headers object with all keys lowercased\n */\nexport function normalizeHeaders(headers: Record): Record {\n const result: Record = {}\n for (const [key, value] of Object.entries(headers)) {\n result[key.toLowerCase()] = value\n }\n return result\n}\n","type Fetch = typeof fetch\n\n/**\n * Resolves the fetch implementation to use\n * Uses custom fetch if provided, otherwise uses native fetch\n *\n * @param customFetch - Optional custom fetch implementation\n * @returns Resolved fetch function\n */\nexport const resolveFetch = (customFetch?: Fetch): Fetch => {\n if (customFetch) {\n return (...args) => customFetch(...args)\n }\n return (...args) => fetch(...args)\n}\n\n/**\n * Resolves the Response constructor to use\n * Returns native Response constructor\n *\n * @returns Response constructor\n */\nexport const resolveResponse = (): typeof Response => {\n return Response\n}\n\n/**\n * Determine if input is a plain object\n * An object is plain if it's created by either {}, new Object(), or Object.create(null)\n *\n * @param value - Value to check\n * @returns True if value is a plain object\n * @source https://github.com/sindresorhus/is-plain-obj\n */\nexport const isPlainObject = (value: object): boolean => {\n if (typeof value !== 'object' || value === null) {\n return false\n }\n\n const prototype = Object.getPrototypeOf(value)\n return (\n (prototype === null ||\n prototype === Object.prototype ||\n Object.getPrototypeOf(prototype) === null) &&\n !(Symbol.toStringTag in value) &&\n !(Symbol.iterator in value)\n )\n}\n\n/**\n * Recursively converts object keys from snake_case to camelCase\n * Used for normalizing API responses\n *\n * @param item - Object to convert\n * @returns Converted object with camelCase keys\n */\nexport const recursiveToCamel = (item: Record): unknown => {\n if (Array.isArray(item)) {\n return item.map((el) => recursiveToCamel(el))\n } else if (typeof item === 'function' || item !== Object(item)) {\n return item\n }\n\n const result: Record = {}\n Object.entries(item).forEach(([key, value]) => {\n const newKey = key.replace(/([-_][a-z])/gi, (c) => c.toUpperCase().replace(/[-_]/g, ''))\n result[newKey] = recursiveToCamel(value)\n })\n\n return result\n}\n\n/**\n * Validates if a given bucket name is valid according to Supabase Storage API rules\n * Mirrors backend validation from: storage/src/storage/limits.ts:isValidBucketName()\n *\n * Rules:\n * - Length: 1-100 characters\n * - Allowed characters: alphanumeric (a-z, A-Z, 0-9), underscore (_), and safe special characters\n * - Safe special characters: ! - . * ' ( ) space & $ @ = ; : + , ?\n * - Forbidden: path separators (/, \\), path traversal (..), leading/trailing whitespace\n *\n * AWS S3 Reference: https://docs.aws.amazon.com/AmazonS3/latest/userguide/object-keys.html\n *\n * @param bucketName - The bucket name to validate\n * @returns true if valid, false otherwise\n */\nexport const isValidBucketName = (bucketName: string): boolean => {\n if (!bucketName || typeof bucketName !== 'string') {\n return false\n }\n\n // Check length constraints (1-100 characters)\n if (bucketName.length === 0 || bucketName.length > 100) {\n return false\n }\n\n // Check for leading/trailing whitespace\n if (bucketName.trim() !== bucketName) {\n return false\n }\n\n // Explicitly reject path separators (security)\n // Note: Consecutive periods (..) are allowed by backend - the AWS restriction\n // on relative paths applies to object keys, not bucket names\n if (bucketName.includes('/') || bucketName.includes('\\\\')) {\n return false\n }\n\n // Validate against allowed character set\n // Pattern matches backend regex: /^(\\w|!|-|\\.|\\*|'|\\(|\\)| |&|\\$|@|=|;|:|\\+|,|\\?)*$/\n // This explicitly excludes path separators (/, \\) and other problematic characters\n const bucketNameRegex = /^[\\w!.\\*'() &$@=;:+,?-]+$/\n return bucketNameRegex.test(bucketName)\n}\n\n/**\n * Normalizes a number array to float32 format\n * Ensures all vector values are valid 32-bit floats\n *\n * @param values - Array of numbers to normalize\n * @returns Normalized float32 array\n */\nexport const normalizeToFloat32 = (values: number[]): number[] => {\n // Use Float32Array to ensure proper precision\n return Array.from(new Float32Array(values))\n}\n\n/**\n * Validates vector dimensions match expected dimension\n * Throws error if dimensions don't match\n *\n * @param vector - Vector data to validate\n * @param expectedDimension - Expected vector dimension\n * @throws Error if dimensions don't match\n */\nexport const validateVectorDimension = (\n vector: { float32: number[] },\n expectedDimension?: number\n): void => {\n if (expectedDimension !== undefined && vector.float32.length !== expectedDimension) {\n throw new Error(\n `Vector dimension mismatch: expected ${expectedDimension}, got ${vector.float32.length}`\n )\n }\n}\n\n/**\n * Percent-encodes each segment of a storage path so URL delimiters within a\n * key (e.g. `?`, `#`) can't be interpreted as a querystring/fragment start.\n *\n * Splits on `/` so real path separators stay literal — the storage server\n * routes on them and decodes each segment back to the original key.\n *\n * @param path - A bucket id or `bucketId/objectKey` path\n * @returns The path with each `/`-delimited segment percent-encoded\n */\nexport const encodeStoragePath = (path: string): string =>\n path.split('/').map(encodeURIComponent).join('/')\n","import { StorageApiError, StorageError, StorageUnknownError, ErrorNamespace } from './errors'\nimport { setHeader } from './headers'\nimport { isPlainObject, resolveResponse } from './helpers'\nimport { FetchParameters } from '../types'\n\nexport type Fetch = typeof fetch\n\n/**\n * Options for fetch requests\n */\nexport interface FetchOptions {\n headers?: {\n [key: string]: string\n }\n duplex?: string\n noResolveJson?: boolean\n}\n\n/**\n * HTTP methods supported by the API\n */\nexport type RequestMethodType = 'GET' | 'POST' | 'PUT' | 'DELETE' | 'HEAD'\n\n/**\n * Extracts error message from various error response formats\n * @param err - Error object from API\n * @returns Human-readable error message\n */\nconst _getErrorMessage = (err: unknown): string => {\n if (typeof err === 'object' && err !== null) {\n const e = err as Record\n if (typeof e.msg === 'string') return e.msg\n if (typeof e.message === 'string') return e.message\n if (typeof e.error_description === 'string') return e.error_description\n if (typeof e.error === 'string') return e.error\n if (typeof e.error === 'object' && e.error !== null) {\n const nested = e.error as Record\n if (typeof nested.message === 'string') return nested.message\n }\n }\n return JSON.stringify(err)\n}\n\n/**\n * Handles fetch errors and converts them to Storage error types\n * @param error - The error caught from fetch\n * @param reject - Promise rejection function\n * @param options - Fetch options that may affect error handling\n * @param namespace - Error namespace ('storage' or 'vectors')\n */\nconst handleError = async (\n error: unknown,\n reject: (reason: StorageError) => void,\n options: FetchOptions | undefined,\n namespace: ErrorNamespace\n) => {\n // Structural detection of json() method, present in all Response implementations\n // (native, node-fetch, cross-fetch, undici) and absent from standard Error objects.\n // Checking 'ok' or 'status' via `in` is unreliable across fetch polyfills/realms.\n const isResponseLike =\n error !== null &&\n typeof error === 'object' &&\n 'json' in error &&\n typeof (error as Record).json === 'function'\n\n if (isResponseLike) {\n const responseError = error as Response\n // Defensive coercion: some fetch polyfills have historically returned status as a string.\n let status = parseInt(String(responseError.status), 10)\n if (!Number.isFinite(status)) {\n status = 500\n }\n\n responseError\n .json()\n .then(\n (err: { statusCode?: string; code?: string; error?: string; message?: string } | null) => {\n const statusCode = err?.statusCode || err?.code || status + ''\n reject(\n new StorageApiError(_getErrorMessage(err), status, statusCode, namespace, err?.code)\n )\n }\n )\n .catch(() => {\n const statusCode = status + ''\n const message = responseError.statusText || `HTTP ${status} error`\n reject(new StorageApiError(message, status, statusCode, namespace))\n })\n } else {\n reject(new StorageUnknownError(_getErrorMessage(error), error, namespace))\n }\n}\n\n/**\n * Builds request parameters for fetch calls\n * @param method - HTTP method\n * @param options - Custom fetch options\n * @param parameters - Additional fetch parameters like AbortSignal\n * @param body - Request body (will be JSON stringified if plain object)\n * @returns Complete fetch request parameters\n */\nconst _getRequestParams = (\n method: RequestMethodType,\n options?: FetchOptions,\n parameters?: FetchParameters,\n body?: object\n) => {\n const params: { [k: string]: any } = { method, headers: options?.headers || {} }\n\n if (method === 'GET' || method === 'HEAD' || !body) {\n return { ...params, ...parameters }\n }\n\n if (isPlainObject(body)) {\n const headers = options?.headers || {}\n let contentType: string | undefined\n\n for (const [key, value] of Object.entries(headers)) {\n if (key.toLowerCase() === 'content-type') {\n contentType = value\n }\n }\n\n params.headers = setHeader(headers, 'Content-Type', contentType ?? 'application/json')\n params.body = JSON.stringify(body)\n } else {\n params.body = body\n }\n\n if (options?.duplex) {\n params.duplex = options.duplex\n }\n\n return { ...params, ...parameters }\n}\n\n/**\n * Internal request handler that wraps fetch with error handling\n * @param fetcher - Fetch function to use\n * @param method - HTTP method\n * @param url - Request URL\n * @param options - Custom fetch options\n * @param parameters - Additional fetch parameters\n * @param body - Request body\n * @param namespace - Error namespace ('storage' or 'vectors')\n * @returns Promise with parsed response or error\n */\nasync function _handleRequest(\n fetcher: Fetch,\n method: RequestMethodType,\n url: string,\n options: FetchOptions | undefined,\n parameters: FetchParameters | undefined,\n body: object | undefined,\n namespace: ErrorNamespace\n): Promise {\n return new Promise((resolve, reject) => {\n fetcher(url, _getRequestParams(method, options, parameters, body))\n .then((result) => {\n if (!result.ok) throw result\n if (options?.noResolveJson) return result\n\n // AWS S3 Vectors API returns 200 OK with content-length: 0 for successful mutations\n // (putVectors, deleteVectors) instead of 204 or JSON response. This is AWS's design choice\n // for performance optimization of bulk operations (up to 500 vectors per request).\n // We handle this to prevent \"Unexpected end of JSON input\" errors when calling result.json()\n if (namespace === 'vectors') {\n const contentType = result.headers.get('content-type')\n const contentLength = result.headers.get('content-length')\n\n // Return empty object for explicitly empty responses\n if (contentLength === '0' || result.status === 204) {\n return {}\n }\n\n // Return empty object if no JSON content type\n if (!contentType || !contentType.includes('application/json')) {\n return {}\n }\n }\n\n return result.json()\n })\n .then((data) => resolve(data))\n .catch((error) => handleError(error, reject, options, namespace))\n })\n}\n\n/**\n * Creates a fetch API with the specified namespace\n * @param namespace - Error namespace ('storage' or 'vectors')\n * @returns Object with HTTP method functions\n */\nexport function createFetchApi(namespace: ErrorNamespace = 'storage') {\n return {\n /**\n * Performs a GET request\n * @param fetcher - Fetch function to use\n * @param url - Request URL\n * @param options - Custom fetch options\n * @param parameters - Additional fetch parameters\n * @returns Promise with parsed response\n */\n get: async (\n fetcher: Fetch,\n url: string,\n options?: FetchOptions,\n parameters?: FetchParameters\n ): Promise => {\n return _handleRequest(fetcher, 'GET', url, options, parameters, undefined, namespace)\n },\n\n /**\n * Performs a POST request\n * @param fetcher - Fetch function to use\n * @param url - Request URL\n * @param body - Request body to be JSON stringified\n * @param options - Custom fetch options\n * @param parameters - Additional fetch parameters\n * @returns Promise with parsed response\n */\n post: async (\n fetcher: Fetch,\n url: string,\n body: object,\n options?: FetchOptions,\n parameters?: FetchParameters\n ): Promise => {\n return _handleRequest(fetcher, 'POST', url, options, parameters, body, namespace)\n },\n\n /**\n * Performs a PUT request\n * @param fetcher - Fetch function to use\n * @param url - Request URL\n * @param body - Request body to be JSON stringified\n * @param options - Custom fetch options\n * @param parameters - Additional fetch parameters\n * @returns Promise with parsed response\n */\n put: async (\n fetcher: Fetch,\n url: string,\n body: object,\n options?: FetchOptions,\n parameters?: FetchParameters\n ): Promise => {\n return _handleRequest(fetcher, 'PUT', url, options, parameters, body, namespace)\n },\n\n /**\n * Performs a HEAD request\n * @param fetcher - Fetch function to use\n * @param url - Request URL\n * @param options - Custom fetch options\n * @param parameters - Additional fetch parameters\n * @returns Promise with Response object (not JSON parsed)\n */\n head: async (\n fetcher: Fetch,\n url: string,\n options?: FetchOptions,\n parameters?: FetchParameters\n ): Promise => {\n return _handleRequest(\n fetcher,\n 'HEAD',\n url,\n {\n ...options,\n noResolveJson: true,\n },\n parameters,\n undefined,\n namespace\n )\n },\n\n /**\n * Performs a DELETE request\n * @param fetcher - Fetch function to use\n * @param url - Request URL\n * @param body - Request body to be JSON stringified\n * @param options - Custom fetch options\n * @param parameters - Additional fetch parameters\n * @returns Promise with parsed response\n */\n remove: async (\n fetcher: Fetch,\n url: string,\n body: object,\n options?: FetchOptions,\n parameters?: FetchParameters\n ): Promise => {\n return _handleRequest(fetcher, 'DELETE', url, options, parameters, body, namespace)\n },\n }\n}\n\n// Default exports for backward compatibility with 'storage' namespace\nconst defaultApi = createFetchApi('storage')\nexport const { get, post, put, head, remove } = defaultApi\n\n// Vectors API with 'vectors' namespace for proper error handling\nexport const vectorsApi = createFetchApi('vectors')\n","import { ErrorNamespace, isStorageError, StorageError } from './errors'\nimport { Fetch } from './fetch'\nimport { normalizeHeaders, setHeader as setHeaderUtil } from './headers'\nimport { resolveFetch } from './helpers'\n\n/**\n * @ignore\n * Base API client class for all Storage API classes\n * Provides common infrastructure for error handling and configuration\n *\n * @typeParam TError - The error type (StorageError or subclass)\n */\nexport default abstract class BaseApiClient {\n protected url: string\n protected headers: { [key: string]: string }\n protected fetch: Fetch\n protected shouldThrowOnError = false\n protected namespace: ErrorNamespace\n\n /**\n * Creates a new BaseApiClient instance\n * @param url - Base URL for API requests\n * @param headers - Default headers for API requests\n * @param fetch - Optional custom fetch implementation\n * @param namespace - Error namespace ('storage' or 'vectors')\n */\n constructor(\n url: string,\n headers: { [key: string]: string } = {},\n fetch?: Fetch,\n namespace: ErrorNamespace = 'storage'\n ) {\n this.url = url\n this.headers = normalizeHeaders(headers)\n this.fetch = resolveFetch(fetch)\n this.namespace = namespace\n }\n\n /**\n * Enable throwing errors instead of returning them.\n * When enabled, errors are thrown instead of returned in { data, error } format.\n *\n * @returns this - For method chaining\n */\n public throwOnError(): this {\n this.shouldThrowOnError = true\n return this\n }\n\n /**\n * Set an HTTP header for the request.\n * Creates a shallow copy of headers to avoid mutating shared state.\n *\n * @param name - Header name\n * @param value - Header value\n * @returns this - For method chaining\n */\n public setHeader(name: string, value: string): this {\n this.headers = setHeaderUtil(this.headers, name, value)\n return this\n }\n\n /**\n * Handles API operation with standardized error handling\n * Eliminates repetitive try-catch blocks across all API methods\n *\n * This wrapper:\n * 1. Executes the operation\n * 2. Returns { data, error: null } on success\n * 3. Returns { data: null, error } on failure (if shouldThrowOnError is false)\n * 4. Throws error on failure (if shouldThrowOnError is true)\n *\n * @typeParam T - The expected data type from the operation\n * @param operation - Async function that performs the API call\n * @returns Promise with { data, error } tuple\n *\n * @example Handling an operation\n * ```typescript\n * async listBuckets() {\n * return this.handleOperation(async () => {\n * return await get(this.fetch, `${this.url}/bucket`, {\n * headers: this.headers,\n * })\n * })\n * }\n * ```\n */\n protected async handleOperation(\n operation: () => Promise\n ): Promise<{ data: T; error: null } | { data: null; error: TError }> {\n try {\n const data = await operation()\n return { data, error: null }\n } catch (error) {\n if (this.shouldThrowOnError) {\n throw error\n }\n if (isStorageError(error)) {\n return { data: null, error: error as TError }\n }\n throw error\n }\n }\n}\n","import { isStorageError } from '../lib/common/errors'\nimport { DownloadResult } from '../lib/types'\n\nexport default class StreamDownloadBuilder implements Promise> {\n readonly [Symbol.toStringTag]: string = 'StreamDownloadBuilder'\n private promise: Promise> | null = null\n\n constructor(\n private downloadFn: () => Promise,\n private shouldThrowOnError: boolean\n ) {}\n\n then, TResult2 = never>(\n onfulfilled?:\n | ((value: DownloadResult) => TResult1 | PromiseLike)\n | null,\n onrejected?: ((reason: any) => TResult2 | PromiseLike) | null\n ): Promise {\n return this.getPromise().then(onfulfilled, onrejected)\n }\n\n catch(\n onrejected?: ((reason: any) => TResult | PromiseLike) | null\n ): Promise | TResult> {\n return this.getPromise().catch(onrejected)\n }\n\n finally(onfinally?: (() => void) | null): Promise> {\n return this.getPromise().finally(onfinally)\n }\n\n private getPromise(): Promise> {\n if (!this.promise) {\n this.promise = this.execute()\n }\n return this.promise\n }\n\n private async execute(): Promise> {\n try {\n const result = await this.downloadFn()\n\n return {\n data: result.body as ReadableStream,\n error: null,\n }\n } catch (error) {\n if (this.shouldThrowOnError) {\n throw error\n }\n\n if (isStorageError(error)) {\n return { data: null, error }\n }\n\n throw error\n }\n }\n}\n","import { isStorageError } from '../lib/common/errors'\nimport { DownloadResult } from '../lib/types'\nimport StreamDownloadBuilder from './StreamDownloadBuilder'\n\nexport default class BlobDownloadBuilder implements Promise> {\n readonly [Symbol.toStringTag]: string = 'BlobDownloadBuilder'\n private promise: Promise> | null = null\n\n constructor(\n private downloadFn: () => Promise,\n private shouldThrowOnError: boolean\n ) {}\n\n asStream(): StreamDownloadBuilder {\n return new StreamDownloadBuilder(this.downloadFn, this.shouldThrowOnError)\n }\n\n then, TResult2 = never>(\n onfulfilled?: ((value: DownloadResult) => TResult1 | PromiseLike) | null,\n onrejected?: ((reason: any) => TResult2 | PromiseLike) | null\n ): Promise {\n return this.getPromise().then(onfulfilled, onrejected)\n }\n\n catch(\n onrejected?: ((reason: any) => TResult | PromiseLike) | null\n ): Promise | TResult> {\n return this.getPromise().catch(onrejected)\n }\n\n finally(onfinally?: (() => void) | null): Promise> {\n return this.getPromise().finally(onfinally)\n }\n\n private getPromise(): Promise> {\n if (!this.promise) {\n this.promise = this.execute()\n }\n return this.promise\n }\n\n private async execute(): Promise> {\n try {\n const result = await this.downloadFn()\n\n return {\n data: await result.blob(),\n error: null,\n }\n } catch (error) {\n if (this.shouldThrowOnError) {\n throw error\n }\n\n if (isStorageError(error)) {\n return { data: null, error }\n }\n\n throw error\n }\n }\n}\n","import {\n StorageApiError,\n StorageError,\n StorageUnknownError,\n isStorageError,\n} from '../lib/common/errors'\nimport { get, head, post, put, remove, Fetch } from '../lib/common/fetch'\nimport { setHeader } from '../lib/common/headers'\nimport { encodeStoragePath, recursiveToCamel } from '../lib/common/helpers'\nimport BaseApiClient from '../lib/common/BaseApiClient'\nimport {\n FileObject,\n FileOptions,\n SearchOptions,\n FetchParameters,\n TransformOptions,\n DestinationOptions,\n FileObjectV2,\n Camelize,\n SearchV2Options,\n SearchV2Result,\n PurgeCacheOptions,\n} from '../lib/types'\nimport BlobDownloadBuilder from './BlobDownloadBuilder'\n\nconst DEFAULT_SEARCH_OPTIONS = {\n limit: 100,\n offset: 0,\n sortBy: {\n column: 'name',\n order: 'asc',\n },\n}\n\nconst DEFAULT_FILE_OPTIONS: FileOptions = {\n cacheControl: '3600',\n contentType: 'text/plain;charset=UTF-8',\n upsert: false,\n}\n\ntype FileBody =\n | ArrayBuffer\n | ArrayBufferView\n | Blob\n | Buffer\n | File\n | FormData\n | NodeJS.ReadableStream\n | ReadableStream\n | URLSearchParams\n | string\n\nexport default class StorageFileApi extends BaseApiClient {\n protected bucketId: string | undefined\n\n constructor(\n url: string,\n headers: { [key: string]: string } = {},\n bucketId?: string,\n fetch?: Fetch\n ) {\n super(url, headers, fetch, 'storage')\n this.bucketId = bucketId\n }\n\n /**\n * Uploads a file to an existing bucket or replaces an existing file at the specified path with a new one.\n *\n * @param method HTTP method.\n * @param path The relative file path. Should be of the format `folder/subfolder/filename.png`. The bucket must already exist before attempting to upload.\n * @param fileBody The body of the file to be stored in the bucket.\n */\n private async uploadOrUpdate(\n method: 'POST' | 'PUT',\n path: string,\n fileBody: FileBody,\n fileOptions?: FileOptions\n ): Promise<\n | {\n data: { id: string; path: string; fullPath: string }\n error: null\n }\n | {\n data: null\n error: StorageError\n }\n > {\n return this.handleOperation(async () => {\n let body\n const options = { ...DEFAULT_FILE_OPTIONS, ...fileOptions }\n let headers: Record = {\n ...this.headers,\n ...(method === 'POST' && { 'x-upsert': String(options.upsert as boolean) }),\n }\n\n const metadata = options.metadata\n\n if (typeof Blob !== 'undefined' && fileBody instanceof Blob) {\n body = new FormData()\n body.append('cacheControl', options.cacheControl as string)\n if (metadata) {\n body.append('metadata', this.encodeMetadata(metadata))\n }\n body.append('', fileBody)\n } else if (typeof FormData !== 'undefined' && fileBody instanceof FormData) {\n body = fileBody\n // Only append if not already present\n if (!body.has('cacheControl')) {\n body.append('cacheControl', options.cacheControl as string)\n }\n if (metadata && !body.has('metadata')) {\n body.append('metadata', this.encodeMetadata(metadata))\n }\n } else {\n body = fileBody\n headers['cache-control'] = `max-age=${options.cacheControl}`\n headers['content-type'] = options.contentType as string\n\n if (metadata) {\n headers['x-metadata'] = this.toBase64(this.encodeMetadata(metadata))\n }\n\n // Node.js streams require duplex option for fetch in Node 20+\n // Check for both web ReadableStream and Node.js streams\n const isStream =\n (typeof ReadableStream !== 'undefined' && body instanceof ReadableStream) ||\n (body && typeof body === 'object' && 'pipe' in body && typeof body.pipe === 'function')\n\n if (isStream && !options.duplex) {\n options.duplex = 'half'\n }\n }\n\n if (fileOptions?.headers) {\n for (const [key, value] of Object.entries(fileOptions.headers)) {\n headers = setHeader(headers, key, value)\n }\n }\n\n const cleanPath = this._removeEmptyFolders(path)\n const _path = this._getFinalPath(cleanPath)\n const data = await (method == 'PUT' ? put : post)(\n this.fetch,\n `${this.url}/object/${_path}`,\n body as object,\n { headers, ...(options?.duplex ? { duplex: options.duplex } : {}) }\n )\n\n return { path: cleanPath, id: data.Id, fullPath: data.Key }\n })\n }\n\n /**\n * Uploads a file to an existing bucket.\n *\n * @category Storage\n * @subcategory File Buckets\n * @param path The file path, including the file name. Should be of the format `folder/subfolder/filename.png`. The bucket must already exist before attempting to upload.\n * @param fileBody The body of the file to be stored in the bucket.\n * @param fileOptions Optional file upload options including cacheControl, contentType, upsert, and metadata.\n * @returns Promise with response containing file path, id, and fullPath or error\n *\n * @example Upload file\n * ```js\n * const avatarFile = event.target.files[0]\n * const { data, error } = await supabase\n * .storage\n * .from('avatars')\n * .upload('public/avatar1.png', avatarFile, {\n * cacheControl: '3600',\n * upsert: false\n * })\n * ```\n *\n * Response:\n * ```json\n * {\n * \"data\": {\n * \"path\": \"public/avatar1.png\",\n * \"fullPath\": \"avatars/public/avatar1.png\"\n * },\n * \"error\": null\n * }\n * ```\n *\n * @example Upload file using `ArrayBuffer` from base64 file data\n * ```js\n * import { decode } from 'base64-arraybuffer'\n *\n * const { data, error } = await supabase\n * .storage\n * .from('avatars')\n * .upload('public/avatar1.png', decode('base64FileData'), {\n * contentType: 'image/png'\n * })\n * ```\n *\n * @example Handling errors\n * ```js\n * const { data, error } = await supabase\n * .storage\n * .from('avatars')\n * .upload('public/avatar1.png', avatarFile)\n *\n * if (error) {\n * // Log the full error so fields like `statusCode` and `error` (the\n * // Storage error name, e.g. \"Duplicate\") aren't hidden behind `error.message`.\n * console.error(error)\n * return\n * }\n * ```\n *\n * @remarks\n * - RLS policy permissions required:\n * - `buckets` table permissions: none\n * - `objects` table permissions: only `insert` when you are uploading new files and `select`, `insert` and `update` when you are upserting files\n * - Refer to the [Storage guide](/docs/guides/storage/security/access-control) on how access control works\n * - For React Native, using either `Blob`, `File` or `FormData` does not work as intended. Upload file using `ArrayBuffer` from base64 file data instead, see example below.\n */\n async upload(\n path: string,\n fileBody: FileBody,\n fileOptions?: FileOptions\n ): Promise<\n | {\n data: { id: string; path: string; fullPath: string }\n error: null\n }\n | {\n data: null\n error: StorageError\n }\n > {\n return this.uploadOrUpdate('POST', path, fileBody, fileOptions)\n }\n\n /**\n * Upload a file with a token generated from `createSignedUploadUrl`.\n *\n * @category Storage\n * @subcategory File Buckets\n * @param path The file path, including the file name. Should be of the format `folder/subfolder/filename.png`. The bucket must already exist before attempting to upload.\n * @param token The token generated from `createSignedUploadUrl`\n * @param fileBody The body of the file to be stored in the bucket.\n * @param fileOptions HTTP headers (cacheControl, contentType, etc.).\n * **Note:** The `upsert` option has no effect here. To enable upsert behavior,\n * pass `{ upsert: true }` when calling `createSignedUploadUrl()` instead.\n * @returns Promise with response containing file path and fullPath or error\n *\n * @example Upload to a signed URL\n * ```js\n * const { data, error } = await supabase\n * .storage\n * .from('avatars')\n * .uploadToSignedUrl('folder/cat.jpg', 'token-from-createSignedUploadUrl', file)\n * ```\n *\n * Response:\n * ```json\n * {\n * \"data\": {\n * \"path\": \"folder/cat.jpg\",\n * \"fullPath\": \"avatars/folder/cat.jpg\"\n * },\n * \"error\": null\n * }\n * ```\n *\n * @remarks\n * - RLS policy permissions required:\n * - `buckets` table permissions: none\n * - `objects` table permissions: none\n * - Refer to the [Storage guide](/docs/guides/storage/security/access-control) on how access control works\n */\n async uploadToSignedUrl(\n path: string,\n token: string,\n fileBody: FileBody,\n fileOptions?: FileOptions\n ) {\n const cleanPath = this._removeEmptyFolders(path)\n const _path = this._getFinalPath(cleanPath)\n\n const url = new URL(this.url + `/object/upload/sign/${_path}`)\n url.searchParams.set('token', token)\n\n return this.handleOperation(async () => {\n let body\n const options = { ...DEFAULT_FILE_OPTIONS, ...fileOptions }\n let headers: Record = {\n ...this.headers,\n ...{ 'x-upsert': String(options.upsert as boolean) },\n }\n\n const metadata = options.metadata\n\n if (typeof Blob !== 'undefined' && fileBody instanceof Blob) {\n body = new FormData()\n body.append('cacheControl', options.cacheControl as string)\n if (metadata) {\n body.append('metadata', this.encodeMetadata(metadata))\n }\n body.append('', fileBody)\n } else if (typeof FormData !== 'undefined' && fileBody instanceof FormData) {\n body = fileBody\n if (!body.has('cacheControl')) {\n body.append('cacheControl', options.cacheControl as string)\n }\n if (metadata && !body.has('metadata')) {\n body.append('metadata', this.encodeMetadata(metadata))\n }\n } else {\n body = fileBody\n headers['cache-control'] = `max-age=${options.cacheControl}`\n headers['content-type'] = options.contentType as string\n if (metadata) {\n headers['x-metadata'] = this.toBase64(this.encodeMetadata(metadata))\n }\n\n const isStream =\n (typeof ReadableStream !== 'undefined' && body instanceof ReadableStream) ||\n (body && typeof body === 'object' && 'pipe' in body && typeof body.pipe === 'function')\n\n if (isStream && !options.duplex) {\n options.duplex = 'half'\n }\n }\n\n if (fileOptions?.headers) {\n for (const [key, value] of Object.entries(fileOptions.headers)) {\n headers = setHeader(headers, key, value)\n }\n }\n\n const data = await put(this.fetch, url.toString(), body as object, {\n headers,\n ...(options?.duplex ? { duplex: options.duplex } : {}),\n })\n\n return { path: cleanPath, fullPath: data.Key }\n })\n }\n\n /**\n * Creates a signed upload URL.\n * Signed upload URLs can be used to upload files to the bucket without further authentication.\n * They are valid for 2 hours.\n *\n * @category Storage\n * @subcategory File Buckets\n * @param path The file path, including the current file name. For example `folder/image.png`.\n * @param options.upsert If set to true, allows the file to be overwritten if it already exists.\n * @returns Promise with response containing signed upload URL, token, and path or error\n *\n * @example Create Signed Upload URL\n * ```js\n * const { data, error } = await supabase\n * .storage\n * .from('avatars')\n * .createSignedUploadUrl('folder/cat.jpg')\n * ```\n *\n * Response:\n * ```json\n * {\n * \"data\": {\n * \"signedUrl\": \"https://example.supabase.co/storage/v1/object/upload/sign/avatars/folder/cat.jpg?token=\",\n * \"path\": \"folder/cat.jpg\",\n * \"token\": \"\"\n * },\n * \"error\": null\n * }\n * ```\n *\n * @remarks\n * - RLS policy permissions required:\n * - `buckets` table permissions: none\n * - `objects` table permissions: `insert`\n * - Refer to the [Storage guide](/docs/guides/storage/security/access-control) on how access control works\n */\n async createSignedUploadUrl(\n path: string,\n options?: { upsert: boolean }\n ): Promise<\n | {\n data: { signedUrl: string; token: string; path: string }\n error: null\n }\n | {\n data: null\n error: StorageError\n }\n > {\n return this.handleOperation(async () => {\n let _path = this._getFinalPath(path)\n\n const headers = { ...this.headers }\n\n if (options?.upsert) {\n headers['x-upsert'] = 'true'\n }\n\n const data = await post(\n this.fetch,\n `${this.url}/object/upload/sign/${_path}`,\n {},\n { headers }\n )\n\n const url = new URL(this.url + data.url)\n\n const token = url.searchParams.get('token')\n\n if (!token) {\n throw new StorageError('No token returned by API')\n }\n\n return { signedUrl: url.toString(), path, token }\n })\n }\n\n /**\n * Replaces an existing file at the specified path with a new one.\n *\n * @category Storage\n * @subcategory File Buckets\n * @param path The relative file path. Should be of the format `folder/subfolder/filename.png`. The bucket must already exist before attempting to update.\n * @param fileBody The body of the file to be stored in the bucket.\n * @param fileOptions Optional file upload options including cacheControl, contentType, and metadata.\n * **Note:** The `upsert` option has no effect here. `update()` always replaces the\n * file at the given path, so the `x-upsert` header is not sent. To control upsert\n * behavior, use `upload()` instead.\n * @returns Promise with response containing file path, id, and fullPath or error\n *\n * @example Update file\n * ```js\n * const avatarFile = event.target.files[0]\n * const { data, error } = await supabase\n * .storage\n * .from('avatars')\n * .update('public/avatar1.png', avatarFile, {\n * cacheControl: '3600'\n * })\n * ```\n *\n * Response:\n * ```json\n * {\n * \"data\": {\n * \"path\": \"public/avatar1.png\",\n * \"fullPath\": \"avatars/public/avatar1.png\"\n * },\n * \"error\": null\n * }\n * ```\n *\n * @example Update file using `ArrayBuffer` from base64 file data\n * ```js\n * import {decode} from 'base64-arraybuffer'\n *\n * const { data, error } = await supabase\n * .storage\n * .from('avatars')\n * .update('public/avatar1.png', decode('base64FileData'), {\n * contentType: 'image/png'\n * })\n * ```\n *\n * @remarks\n * - RLS policy permissions required:\n * - `buckets` table permissions: none\n * - `objects` table permissions: `update` and `select`\n * - `update()` always replaces the file at the given path regardless of the `upsert` option.\n * - Refer to the [Storage guide](/docs/guides/storage/security/access-control) on how access control works\n * - For React Native, using either `Blob`, `File` or `FormData` does not work as intended. Update file using `ArrayBuffer` from base64 file data instead, see example below.\n */\n async update(\n path: string,\n fileBody:\n | ArrayBuffer\n | ArrayBufferView\n | Blob\n | Buffer\n | File\n | FormData\n | NodeJS.ReadableStream\n | ReadableStream\n | URLSearchParams\n | string,\n fileOptions?: FileOptions\n ): Promise<\n | {\n data: { id: string; path: string; fullPath: string }\n error: null\n }\n | {\n data: null\n error: StorageError\n }\n > {\n return this.uploadOrUpdate('PUT', path, fileBody, fileOptions)\n }\n\n /**\n * Moves an existing file to a new path in the same bucket.\n *\n * @category Storage\n * @subcategory File Buckets\n * @param fromPath The original file path, including the current file name. For example `folder/image.png`.\n * @param toPath The new file path, including the new file name. For example `folder/image-new.png`.\n * @param options The destination options.\n * @returns Promise with response containing success message or error\n *\n * @example Move file\n * ```js\n * const { data, error } = await supabase\n * .storage\n * .from('avatars')\n * .move('public/avatar1.png', 'private/avatar2.png')\n * ```\n *\n * Response:\n * ```json\n * {\n * \"data\": {\n * \"message\": \"Successfully moved\"\n * },\n * \"error\": null\n * }\n * ```\n *\n * @remarks\n * - RLS policy permissions required:\n * - `buckets` table permissions: none\n * - `objects` table permissions: `update` and `select`\n * - Refer to the [Storage guide](/docs/guides/storage/security/access-control) on how access control works\n */\n async move(\n fromPath: string,\n toPath: string,\n options?: DestinationOptions\n ): Promise<\n | {\n data: { message: string }\n error: null\n }\n | {\n data: null\n error: StorageError\n }\n > {\n return this.handleOperation(async () => {\n return await post(\n this.fetch,\n `${this.url}/object/move`,\n {\n bucketId: this.bucketId,\n sourceKey: fromPath,\n destinationKey: toPath,\n destinationBucket: options?.destinationBucket,\n },\n { headers: this.headers }\n )\n })\n }\n\n /**\n * Copies an existing file to a new path in the same bucket.\n *\n * @category Storage\n * @subcategory File Buckets\n * @param fromPath The original file path, including the current file name. For example `folder/image.png`.\n * @param toPath The new file path, including the new file name. For example `folder/image-copy.png`.\n * @param options The destination options.\n * @returns Promise with response containing copied file path or error\n *\n * @example Copy file\n * ```js\n * const { data, error } = await supabase\n * .storage\n * .from('avatars')\n * .copy('public/avatar1.png', 'private/avatar2.png')\n * ```\n *\n * Response:\n * ```json\n * {\n * \"data\": {\n * \"path\": \"avatars/private/avatar2.png\"\n * },\n * \"error\": null\n * }\n * ```\n *\n * @remarks\n * - RLS policy permissions required:\n * - `buckets` table permissions: none\n * - `objects` table permissions: `insert` and `select`\n * - Refer to the [Storage guide](/docs/guides/storage/security/access-control) on how access control works\n */\n async copy(\n fromPath: string,\n toPath: string,\n options?: DestinationOptions\n ): Promise<\n | {\n data: { path: string }\n error: null\n }\n | {\n data: null\n error: StorageError\n }\n > {\n return this.handleOperation(async () => {\n const data = await post(\n this.fetch,\n `${this.url}/object/copy`,\n {\n bucketId: this.bucketId,\n sourceKey: fromPath,\n destinationKey: toPath,\n destinationBucket: options?.destinationBucket,\n },\n { headers: this.headers }\n )\n return { path: data.Key }\n })\n }\n\n /**\n * Creates a signed URL. Use a signed URL to share a file for a fixed amount of time.\n *\n * @category Storage\n * @subcategory File Buckets\n * @param path The file path, including the current file name. For example `folder/image.png`.\n * @param expiresIn The number of seconds until the signed URL expires. For example, `60` for a URL which is valid for one minute.\n * @param options.download triggers the file as a download if set to true. Set this parameter as the name of the file if you want to trigger the download with a different filename.\n * @param options.transform Transform the asset before serving it to the client.\n * @param options.cacheNonce Append a cache nonce parameter to the URL to invalidate the cache.\n * @returns Promise with response containing signed URL or error\n *\n * @example Create Signed URL\n * ```js\n * const { data, error } = await supabase\n * .storage\n * .from('avatars')\n * .createSignedUrl('folder/avatar1.png', 60)\n * ```\n *\n * Response:\n * ```json\n * {\n * \"data\": {\n * \"signedUrl\": \"https://example.supabase.co/storage/v1/object/sign/avatars/folder/avatar1.png?token=\"\n * },\n * \"error\": null\n * }\n * ```\n *\n * @example Create a signed URL for an asset with transformations\n * ```js\n * const { data } = await supabase\n * .storage\n * .from('avatars')\n * .createSignedUrl('folder/avatar1.png', 60, {\n * transform: {\n * width: 100,\n * height: 100,\n * }\n * })\n * ```\n *\n * @example Create a signed URL which triggers the download of the asset\n * ```js\n * const { data } = await supabase\n * .storage\n * .from('avatars')\n * .createSignedUrl('folder/avatar1.png', 60, {\n * download: true,\n * })\n * ```\n *\n * @remarks\n * - RLS policy permissions required:\n * - `buckets` table permissions: none\n * - `objects` table permissions: `select`\n * - Refer to the [Storage guide](/docs/guides/storage/security/access-control) on how access control works\n */\n async createSignedUrl(\n path: string,\n expiresIn: number,\n options?: {\n download?: string | boolean\n transform?: TransformOptions\n cacheNonce?: string\n }\n ): Promise<\n | {\n data: { signedUrl: string }\n error: null\n }\n | {\n data: null\n error: StorageError\n }\n > {\n return this.handleOperation(async () => {\n let _path = this._getFinalPath(path)\n\n const hasTransform =\n typeof options?.transform === 'object' &&\n options.transform !== null &&\n Object.keys(options.transform).length > 0\n\n let data = await post(\n this.fetch,\n `${this.url}/object/sign/${_path}`,\n { expiresIn, ...(hasTransform ? { transform: options!.transform } : {}) },\n { headers: this.headers }\n )\n\n const query = new URLSearchParams()\n if (options?.download)\n query.set('download', options.download === true ? '' : options.download)\n if (options?.cacheNonce != null) query.set('cacheNonce', String(options.cacheNonce))\n const queryString = query.toString()\n\n // `data.signedURL` contains a `token` query parameter, so append extra params with `&`\n // only when we actually have something to add.\n const signedUrl = encodeURI(\n `${this.url}${data.signedURL}${queryString ? `&${queryString}` : ''}`\n )\n\n return { signedUrl }\n })\n }\n\n /**\n * Creates multiple signed URLs. Use a signed URL to share a file for a fixed amount of time.\n *\n * @category Storage\n * @subcategory File Buckets\n * @param paths The file paths to be downloaded, including the current file names. For example `['folder/image.png', 'folder2/image2.png']`.\n * @param expiresIn The number of seconds until the signed URLs expire. For example, `60` for URLs which are valid for one minute.\n * @param options.download triggers the file as a download if set to true. Set this parameter as the name of the file if you want to trigger the download with a different filename.\n * @param options.cacheNonce Append a cache nonce parameter to the URL to invalidate the cache.\n * @returns Promise with response containing array of objects with signedUrl, path, and error or error\n *\n * @example Create Signed URLs\n * ```js\n * const { data, error } = await supabase\n * .storage\n * .from('avatars')\n * .createSignedUrls(['folder/avatar1.png', 'folder/avatar2.png'], 60)\n * ```\n *\n * Response:\n * ```json\n * {\n * \"data\": [\n * {\n * \"error\": null,\n * \"path\": \"folder/avatar1.png\",\n * \"signedURL\": \"/object/sign/avatars/folder/avatar1.png?token=\",\n * \"signedUrl\": \"https://example.supabase.co/storage/v1/object/sign/avatars/folder/avatar1.png?token=\"\n * },\n * {\n * \"error\": null,\n * \"path\": \"folder/avatar2.png\",\n * \"signedURL\": \"/object/sign/avatars/folder/avatar2.png?token=\",\n * \"signedUrl\": \"https://example.supabase.co/storage/v1/object/sign/avatars/folder/avatar2.png?token=\"\n * }\n * ],\n * \"error\": null\n * }\n * ```\n *\n * @remarks\n * - RLS policy permissions required:\n * - `buckets` table permissions: none\n * - `objects` table permissions: `select`\n * - Refer to the [Storage guide](/docs/guides/storage/security/access-control) on how access control works\n */\n async createSignedUrls(\n paths: string[],\n expiresIn: number,\n options?: { download?: string | boolean; cacheNonce?: string }\n ): Promise<\n | {\n data: {\n error: string | null\n path: string | null\n signedURL: string | null\n signedUrl: string | null\n }[]\n error: null\n }\n | {\n data: null\n error: StorageError\n }\n > {\n return this.handleOperation(async () => {\n const data = await post(\n this.fetch,\n `${this.url}/object/sign/${this.bucketId}`,\n { expiresIn, paths },\n { headers: this.headers }\n )\n\n const query = new URLSearchParams()\n\n if (options?.download)\n query.set('download', options.download === true ? '' : options.download)\n if (options?.cacheNonce != null) query.set('cacheNonce', String(options.cacheNonce))\n\n const queryString = query.toString()\n\n return data.map(\n (datum: { error: string | null; path: string | null; signedURL: string | null }) => ({\n ...datum,\n signedUrl: datum.signedURL\n ? encodeURI(`${this.url}${datum.signedURL}${queryString ? `&${queryString}` : ''}`)\n : null,\n })\n )\n })\n }\n\n /**\n * Downloads a file from a private bucket. For public buckets, make a request to the URL returned from `getPublicUrl` instead.\n *\n * @category Storage\n * @subcategory File Buckets\n * @param path The full path and file name of the file to be downloaded. For example `folder/image.png`.\n * @param options Optional settings: `transform` to transform the asset before serving it to the client, and `cacheNonce` to append a cache nonce parameter to the URL to invalidate the cache.\n * @param parameters Additional fetch parameters like signal for cancellation. Supports standard fetch options including cache control.\n * @returns BlobDownloadBuilder instance for downloading the file\n *\n * @example Download file\n * ```js\n * const { data, error } = await supabase\n * .storage\n * .from('avatars')\n * .download('folder/avatar1.png')\n * ```\n *\n * Response:\n * ```json\n * {\n * \"data\": ,\n * \"error\": null\n * }\n * ```\n *\n * @example Download file with transformations\n * ```js\n * const { data, error } = await supabase\n * .storage\n * .from('avatars')\n * .download('folder/avatar1.png', {\n * transform: {\n * width: 100,\n * height: 100,\n * quality: 80\n * }\n * })\n * ```\n *\n * @example Download with cache control (useful in Edge Functions)\n * ```js\n * const { data, error } = await supabase\n * .storage\n * .from('avatars')\n * .download('folder/avatar1.png', {}, { cache: 'no-store' })\n * ```\n *\n * @example Download with abort signal\n * ```js\n * const controller = new AbortController()\n * setTimeout(() => controller.abort(), 5000)\n *\n * const { data, error } = await supabase\n * .storage\n * .from('avatars')\n * .download('folder/avatar1.png', {}, { signal: controller.signal })\n * ```\n *\n * @remarks\n * - RLS policy permissions required:\n * - `buckets` table permissions: none\n * - `objects` table permissions: `select`\n * - Refer to the [Storage guide](/docs/guides/storage/security/access-control) on how access control works\n */\n download(\n path: string,\n options?: Options,\n parameters?: FetchParameters\n ): BlobDownloadBuilder {\n const wantsTransformation =\n typeof options?.transform === 'object' &&\n options.transform !== null &&\n Object.keys(options.transform).length > 0\n const renderPath = wantsTransformation ? 'render/image/authenticated' : 'object'\n\n const query = new URLSearchParams()\n if (options?.transform) this.applyTransformOptsToQuery(query, options.transform)\n if (options?.cacheNonce != null) query.set('cacheNonce', String(options.cacheNonce))\n const queryString = query.toString()\n\n const _path = this._getFinalPath(path)\n const downloadFn = () =>\n get(\n this.fetch,\n `${this.url}/${renderPath}/${_path}${queryString ? `?${queryString}` : ''}`,\n {\n headers: this.headers,\n noResolveJson: true,\n },\n parameters\n )\n return new BlobDownloadBuilder(downloadFn, this.shouldThrowOnError)\n }\n\n /**\n * Retrieves the details of an existing file.\n *\n * Returns detailed file metadata including size, content type, and timestamps.\n * Note: The API returns `last_modified` field, not `updated_at`.\n *\n * @category Storage\n * @subcategory File Buckets\n * @param path The file path, including the file name. For example `folder/image.png`.\n * @returns Promise with response containing file metadata or error\n *\n * @example Get file info\n * ```js\n * const { data, error } = await supabase\n * .storage\n * .from('avatars')\n * .info('folder/avatar1.png')\n *\n * if (data) {\n * console.log('Last modified:', data.lastModified)\n * console.log('Size:', data.size)\n * }\n * ```\n */\n async info(path: string): Promise<\n | {\n data: Camelize\n error: null\n }\n | {\n data: null\n error: StorageError\n }\n > {\n const _path = this._getFinalPath(path)\n\n return this.handleOperation(async () => {\n const data = await get(this.fetch, `${this.url}/object/info/${_path}`, {\n headers: this.headers,\n })\n\n return recursiveToCamel(data) as Camelize\n })\n }\n\n /**\n * Checks the existence of a file.\n *\n * @category Storage\n * @subcategory File Buckets\n * @param path The file path, including the file name. For example `folder/image.png`.\n * @returns Promise with response containing boolean indicating file existence or error\n *\n * @example Check file existence\n * ```js\n * const { data, error } = await supabase\n * .storage\n * .from('avatars')\n * .exists('folder/avatar1.png')\n * ```\n */\n async exists(path: string): Promise<\n | {\n data: boolean\n error: null\n }\n | {\n data: boolean\n error: StorageError\n }\n > {\n const _path = this._getFinalPath(path)\n\n try {\n await head(this.fetch, `${this.url}/object/${_path}`, {\n headers: this.headers,\n })\n\n return { data: true, error: null }\n } catch (error) {\n if (this.shouldThrowOnError) {\n throw error\n }\n if (isStorageError(error)) {\n // HEAD requests produce StorageApiError (via handleError) or StorageUnknownError (legacy)\n const status =\n error instanceof StorageApiError\n ? error.status\n : error instanceof StorageUnknownError\n ? (error.originalError as { status: number })?.status\n : undefined\n\n if (status !== undefined && [400, 404].includes(status)) {\n return { data: false, error }\n }\n }\n\n throw error\n }\n }\n\n /**\n * A simple convenience function to get the URL for an asset in a public bucket. If you do not want to use this function, you can construct the public URL by concatenating the bucket URL with the path to the asset.\n * This function does not verify if the bucket is public. If a public URL is created for a bucket which is not public, you will not be able to download the asset.\n *\n * @category Storage\n * @subcategory File Buckets\n * @param path The path and name of the file to generate the public URL for. For example `folder/image.png`.\n * @param options.download Triggers the file as a download if set to true. Set this parameter as the name of the file if you want to trigger the download with a different filename.\n * @param options.transform Transform the asset before serving it to the client.\n * @param options.cacheNonce Append a cache nonce parameter to the URL to invalidate the cache.\n * @returns Object with public URL\n *\n * @example Returns the URL for an asset in a public bucket\n * ```js\n * const { data } = supabase\n * .storage\n * .from('public-bucket')\n * .getPublicUrl('folder/avatar1.png')\n * ```\n *\n * Response:\n * ```json\n * {\n * \"data\": {\n * \"publicUrl\": \"https://example.supabase.co/storage/v1/object/public/public-bucket/folder/avatar1.png\"\n * }\n * }\n * ```\n *\n * @example Returns the URL for an asset in a public bucket with transformations\n * ```js\n * const { data } = supabase\n * .storage\n * .from('public-bucket')\n * .getPublicUrl('folder/avatar1.png', {\n * transform: {\n * width: 100,\n * height: 100,\n * }\n * })\n * ```\n *\n * @example Returns the URL which triggers the download of an asset in a public bucket\n * ```js\n * const { data } = supabase\n * .storage\n * .from('public-bucket')\n * .getPublicUrl('folder/avatar1.png', {\n * download: true,\n * })\n * ```\n *\n * @remarks\n * - The bucket needs to be set to public, either via [updateBucket()](/docs/reference/javascript/storage-updatebucket) or by going to Storage on [supabase.com/dashboard](https://supabase.com/dashboard), clicking the overflow menu on a bucket and choosing \"Make public\"\n * - RLS policy permissions required:\n * - `buckets` table permissions: none\n * - `objects` table permissions: none\n * - Refer to the [Storage guide](/docs/guides/storage/security/access-control) on how access control works\n */\n getPublicUrl(\n path: string,\n options?: {\n download?: string | boolean\n transform?: TransformOptions\n cacheNonce?: string\n }\n ): { data: { publicUrl: string } } {\n const _path = this._getFinalPath(path)\n\n const query = new URLSearchParams()\n if (options?.download) query.set('download', options.download === true ? '' : options.download)\n if (options?.transform) this.applyTransformOptsToQuery(query, options.transform)\n if (options?.cacheNonce != null) query.set('cacheNonce', String(options.cacheNonce))\n const queryString = query.toString()\n\n const wantsTransformation =\n typeof options?.transform === 'object' &&\n options.transform !== null &&\n Object.keys(options.transform).length > 0\n const renderPath = wantsTransformation ? 'render/image' : 'object'\n\n return {\n data: {\n publicUrl:\n encodeURI(`${this.url}/${renderPath}/public/${_path}`) +\n (queryString ? `?${queryString}` : ''),\n },\n }\n }\n\n /**\n * Deletes files within the same bucket\n *\n * Returns an array of FileObject entries for the deleted files. Note that deprecated\n * fields like `bucket_id` may or may not be present in the response - do not rely on them.\n *\n * @category Storage\n * @subcategory File Buckets\n * @param paths An array of files to delete, including the path and file name. For example [`'folder/image.png'`].\n * @returns Promise with response containing array of deleted file objects or error\n *\n * @example Delete file\n * ```js\n * const { data, error } = await supabase\n * .storage\n * .from('avatars')\n * .remove(['folder/avatar1.png'])\n * ```\n *\n * Response:\n * ```json\n * {\n * \"data\": [],\n * \"error\": null\n * }\n * ```\n *\n * @remarks\n * - RLS policy permissions required:\n * - `buckets` table permissions: none\n * - `objects` table permissions: `delete` and `select`\n * - Refer to the [Storage guide](/docs/guides/storage/security/access-control) on how access control works\n */\n async remove(paths: string[]): Promise<\n | {\n data: FileObject[]\n error: null\n }\n | {\n data: null\n error: StorageError\n }\n > {\n return this.handleOperation(async () => {\n return await remove(\n this.fetch,\n `${this.url}/object/${this.bucketId}`,\n { prefixes: paths },\n { headers: this.headers }\n )\n })\n }\n\n /**\n * Purges the CDN cache for a single object in this bucket.\n *\n * Maps to `DELETE /cdn/{bucket}/{path}` on the Storage API. The server\n * issues a CDN invalidation for the object and returns `{ message: 'success' }`.\n *\n * **Requires the `service_role` key.** The underlying endpoint enforces\n * `service_role` JWT — calls made with the anon key or a user JWT will be\n * rejected by the server.\n *\n * **Hosted CDN feature.** On self-hosted Supabase, the Storage service must\n * have `CDN_PURGE_ENDPOINT_URL` configured and the `purgeCache` tenant\n * feature enabled, otherwise the server returns an error.\n *\n * Operates on a single object path. There is no wildcard or recursion: pass\n * the exact path of the object you want invalidated.\n *\n * @category Storage\n * @subcategory File Buckets\n * @param path The path (relative to the bucket) of the object to purge, e.g. `folder/avatar.png`.\n * @param options Optional purge cache options.\n * @param options.transformations If true, purges only transformations (resized/formatted variants), leaving the original cached file intact.\n * @param parameters Optional fetch parameters such as an `AbortController` signal.\n * @returns Promise with `{ data: { message }, error: null }` on success or `{ data: null, error }` on failure.\n *\n * @example Purge a single cached object\n * ```js\n * const { data, error } = await supabase\n * .storage\n * .from('avatars')\n * .purgeCache('folder/avatar1.png')\n * ```\n *\n * @example Purge only transformations for a single object\n * ```js\n * const { data, error } = await supabase\n * .storage\n * .from('avatars')\n * .purgeCache('folder/avatar1.png', { transformations: true })\n * ```\n */\n async purgeCache(\n path: string,\n options?: PurgeCacheOptions,\n parameters?: FetchParameters\n ): Promise<\n | {\n data: { message: string }\n error: null\n }\n | {\n data: null\n error: StorageError\n }\n > {\n return this.handleOperation(async () => {\n const _path = encodeStoragePath(this._getFinalPath(path))\n const query = new URLSearchParams()\n if (options?.transformations) {\n query.set('transformations', 'true')\n }\n const queryString = query.toString()\n\n return await remove(\n this.fetch,\n `${this.url}/cdn/${_path}${queryString ? `?${queryString}` : ''}`,\n {},\n { headers: this.headers },\n parameters\n )\n })\n }\n\n /**\n * Get file metadata\n * @param id the file id to retrieve metadata\n */\n // async getMetadata(\n // id: string\n // ): Promise<\n // | {\n // data: Metadata\n // error: null\n // }\n // | {\n // data: null\n // error: StorageError\n // }\n // > {\n // try {\n // const data = await get(this.fetch, `${this.url}/metadata/${id}`, { headers: this.headers })\n // return { data, error: null }\n // } catch (error) {\n // if (isStorageError(error)) {\n // return { data: null, error }\n // }\n\n // throw error\n // }\n // }\n\n /**\n * Update file metadata\n * @param id the file id to update metadata\n * @param meta the new file metadata\n */\n // async updateMetadata(\n // id: string,\n // meta: Metadata\n // ): Promise<\n // | {\n // data: Metadata\n // error: null\n // }\n // | {\n // data: null\n // error: StorageError\n // }\n // > {\n // try {\n // const data = await post(\n // this.fetch,\n // `${this.url}/metadata/${id}`,\n // { ...meta },\n // { headers: this.headers }\n // )\n // return { data, error: null }\n // } catch (error) {\n // if (isStorageError(error)) {\n // return { data: null, error }\n // }\n\n // throw error\n // }\n // }\n\n /**\n * Lists all the files and folders within a path of the bucket.\n *\n * **Important:** For folder entries, fields like `id`, `updated_at`, `created_at`,\n * `last_accessed_at`, and `metadata` will be `null`. Only files have these fields populated.\n * Additionally, deprecated fields like `bucket_id`, `owner`, and `buckets` are NOT returned\n * by this method.\n *\n * @category Storage\n * @subcategory File Buckets\n * @param path The folder path.\n * @param options Search options including limit (defaults to 100), offset, sortBy, and search\n * @param parameters Optional fetch parameters including signal for cancellation\n * @returns Promise with response containing array of files/folders or error\n *\n * @example List files in a bucket\n * ```js\n * const { data, error } = await supabase\n * .storage\n * .from('avatars')\n * .list('folder', {\n * limit: 100,\n * offset: 0,\n * sortBy: { column: 'name', order: 'asc' },\n * })\n *\n * // Handle files vs folders\n * data?.forEach(item => {\n * if (item.id !== null) {\n * // It's a file\n * console.log('File:', item.name, 'Size:', item.metadata?.size)\n * } else {\n * // It's a folder\n * console.log('Folder:', item.name)\n * }\n * })\n * ```\n *\n * Response:\n * ```json\n * {\n * \"data\": [\n * {\n * \"name\": \"avatar1.png\",\n * \"id\": \"e668cf7f-821b-4a2f-9dce-7dfa5dd1cfd2\",\n * \"updated_at\": \"2024-05-22T23:06:05.580Z\",\n * \"created_at\": \"2024-05-22T23:04:34.443Z\",\n * \"last_accessed_at\": \"2024-05-22T23:04:34.443Z\",\n * \"metadata\": {\n * \"eTag\": \"\\\"c5e8c553235d9af30ef4f6e280790b92\\\"\",\n * \"size\": 32175,\n * \"mimetype\": \"image/png\",\n * \"cacheControl\": \"max-age=3600\",\n * \"lastModified\": \"2024-05-22T23:06:05.574Z\",\n * \"contentLength\": 32175,\n * \"httpStatusCode\": 200\n * }\n * }\n * ],\n * \"error\": null\n * }\n * ```\n *\n * @example Search files in a bucket\n * ```js\n * const { data, error } = await supabase\n * .storage\n * .from('avatars')\n * .list('folder', {\n * limit: 100,\n * offset: 0,\n * sortBy: { column: 'name', order: 'asc' },\n * search: 'jon'\n * })\n * ```\n *\n * @remarks\n * - RLS policy permissions required:\n * - `buckets` table permissions: none\n * - `objects` table permissions: `select`\n * - Refer to the [Storage guide](/docs/guides/storage/security/access-control) on how access control works\n */\n async list(\n path?: string,\n options?: SearchOptions,\n parameters?: FetchParameters\n ): Promise<\n | {\n data: FileObject[]\n error: null\n }\n | {\n data: null\n error: StorageError\n }\n > {\n return this.handleOperation(async () => {\n // Deep-merge `sortBy` so overriding only one of its keys (e.g. `column`) keeps the\n // default for the other (e.g. `order`), matching how the top-level defaults behave.\n const sortBy = options?.sortBy\n ? { ...DEFAULT_SEARCH_OPTIONS.sortBy, ...options.sortBy }\n : DEFAULT_SEARCH_OPTIONS.sortBy\n const body = { ...DEFAULT_SEARCH_OPTIONS, ...options, sortBy, prefix: path || '' }\n return await post(\n this.fetch,\n `${this.url}/object/list/${this.bucketId}`,\n body,\n { headers: this.headers },\n parameters\n )\n })\n }\n\n /**\n * Lists all the files and folders within a bucket using the V2 API with pagination support.\n *\n * **Important:** Folder entries in the `folders` array only contain `name` and optionally `key` —\n * they have no `id`, timestamps, or `metadata` fields. Full file metadata is only available\n * on entries in the `objects` array.\n *\n * @experimental this method signature might change in the future\n *\n * @category Storage\n * @subcategory File Buckets\n * @param options Search options including prefix, cursor for pagination, limit, with_delimiter\n * @param parameters Optional fetch parameters including signal for cancellation\n * @returns Promise with response containing folders/objects arrays with pagination info or error\n *\n * @example List files with pagination\n * ```js\n * const { data, error } = await supabase\n * .storage\n * .from('avatars')\n * .listV2({\n * prefix: 'folder/',\n * limit: 100,\n * })\n *\n * // Handle pagination\n * if (data?.hasNext) {\n * const nextPage = await supabase\n * .storage\n * .from('avatars')\n * .listV2({\n * prefix: 'folder/',\n * cursor: data.nextCursor,\n * })\n * }\n *\n * // Handle files vs folders\n * data?.objects.forEach(file => {\n * if (file.id !== null) {\n * console.log('File:', file.name, 'Size:', file.metadata?.size)\n * }\n * })\n * data?.folders.forEach(folder => {\n * console.log('Folder:', folder.name)\n * })\n * ```\n */\n async listV2(\n options?: SearchV2Options,\n parameters?: FetchParameters\n ): Promise<\n | {\n data: SearchV2Result\n error: null\n }\n | {\n data: null\n error: StorageError\n }\n > {\n return this.handleOperation(async () => {\n const body = { ...options }\n return await post(\n this.fetch,\n `${this.url}/object/list-v2/${this.bucketId}`,\n body,\n { headers: this.headers },\n parameters\n )\n })\n }\n\n protected encodeMetadata(metadata: Record) {\n return JSON.stringify(metadata)\n }\n\n toBase64(data: string) {\n if (typeof Buffer !== 'undefined') {\n return Buffer.from(data).toString('base64')\n }\n return btoa(data)\n }\n\n private _getFinalPath(path: string) {\n return `${this.bucketId}/${path.replace(/^\\/+/, '')}`\n }\n\n private _removeEmptyFolders(path: string) {\n return path.replace(/^\\/|\\/$/g, '').replace(/\\/+/g, '/')\n }\n\n /** Modifies the `query`, appending values the from `transform` */\n private applyTransformOptsToQuery(\n query: URLSearchParams,\n transform: TransformOptions\n ): URLSearchParams {\n if (transform.width) query.set('width', transform.width.toString())\n if (transform.height) query.set('height', transform.height.toString())\n if (transform.resize) query.set('resize', transform.resize)\n if (transform.format) query.set('format', transform.format)\n if (transform.quality) query.set('quality', transform.quality.toString())\n\n return query\n }\n}\n","// Generated automatically during releases by scripts/update-version-files.ts\n// This file provides runtime access to the package version for:\n// - HTTP request headers (e.g., X-Client-Info header for API requests)\n// - Debugging and support (identifying which version is running)\n// - Telemetry and logging (version reporting in errors/analytics)\n// - Ensuring build artifacts match the published package version\nexport const version = '2.112.3'\n","import { version } from './version'\nexport const DEFAULT_HEADERS = {\n 'X-Client-Info': `storage-js/${version}`,\n}\n","import { DEFAULT_HEADERS } from '../lib/constants'\nimport { StorageError } from '../lib/common/errors'\nimport { Fetch, get, post, put, remove } from '../lib/common/fetch'\nimport { encodeStoragePath } from '../lib/common/helpers'\nimport BaseApiClient from '../lib/common/BaseApiClient'\nimport {\n Bucket,\n BucketType,\n FetchParameters,\n ListBucketOptions,\n PurgeCacheOptions,\n} from '../lib/types'\nimport { StorageClientOptions } from '../StorageClient'\n\nexport default class StorageBucketApi extends BaseApiClient {\n constructor(\n url: string,\n headers: { [key: string]: string } = {},\n fetch?: Fetch,\n opts?: StorageClientOptions\n ) {\n const baseUrl = new URL(url)\n\n // if legacy uri is used, replace with new storage host (disables request buffering to allow > 50GB uploads)\n // \"project-ref.supabase.co\" becomes \"project-ref.storage.supabase.co\"\n if (opts?.useNewHostname) {\n const isSupabaseHost = /supabase\\.(co|in|red)$/.test(baseUrl.hostname)\n if (isSupabaseHost && !baseUrl.hostname.includes('storage.supabase.')) {\n baseUrl.hostname = baseUrl.hostname.replace('supabase.', 'storage.supabase.')\n }\n }\n\n const finalUrl = baseUrl.href.replace(/\\/$/, '')\n const finalHeaders = { ...DEFAULT_HEADERS, ...headers }\n\n super(finalUrl, finalHeaders, fetch, 'storage')\n }\n\n /**\n * Retrieves the details of all Storage buckets within an existing project.\n *\n * @category Storage\n * @subcategory File Buckets\n * @param options Query parameters for listing buckets\n * @param options.limit Maximum number of buckets to return\n * @param options.offset Number of buckets to skip\n * @param options.sortColumn Column to sort by ('id', 'name', 'created_at', 'updated_at')\n * @param options.sortOrder Sort order ('asc' or 'desc')\n * @param options.search Search term to filter bucket names\n * @returns Promise with response containing array of buckets or error\n *\n * @example List buckets\n * ```js\n * const { data, error } = await supabase\n * .storage\n * .listBuckets()\n * ```\n *\n * @example List buckets with options\n * ```js\n * const { data, error } = await supabase\n * .storage\n * .listBuckets({\n * limit: 10,\n * offset: 0,\n * sortColumn: 'created_at',\n * sortOrder: 'desc',\n * search: 'prod'\n * })\n * ```\n *\n * @remarks\n * - RLS policy permissions required:\n * - `buckets` table permissions: `select`\n * - `objects` table permissions: none\n * - Refer to the [Storage guide](/docs/guides/storage/security/access-control) on how access control works\n */\n async listBuckets(options?: ListBucketOptions): Promise<\n | {\n data: Bucket[]\n error: null\n }\n | {\n data: null\n error: StorageError\n }\n > {\n return this.handleOperation(async () => {\n const queryString = this.listBucketOptionsToQueryString(options)\n return await get(this.fetch, `${this.url}/bucket${queryString}`, {\n headers: this.headers,\n })\n })\n }\n\n /**\n * Retrieves the details of an existing Storage bucket.\n *\n * @category Storage\n * @subcategory File Buckets\n * @param id The unique identifier of the bucket you would like to retrieve.\n * @returns Promise with response containing bucket details or error\n *\n * @example Get bucket\n * ```js\n * const { data, error } = await supabase\n * .storage\n * .getBucket('avatars')\n * ```\n *\n * Response:\n * ```json\n * {\n * \"data\": {\n * \"id\": \"avatars\",\n * \"name\": \"avatars\",\n * \"owner\": \"\",\n * \"public\": false,\n * \"file_size_limit\": 1024,\n * \"allowed_mime_types\": [\n * \"image/png\"\n * ],\n * \"created_at\": \"2024-05-22T22:26:05.100Z\",\n * \"updated_at\": \"2024-05-22T22:26:05.100Z\"\n * },\n * \"error\": null\n * }\n * ```\n *\n * @remarks\n * - RLS policy permissions required:\n * - `buckets` table permissions: `select`\n * - `objects` table permissions: none\n * - Refer to the [Storage guide](/docs/guides/storage/security/access-control) on how access control works\n */\n async getBucket(id: string): Promise<\n | {\n data: Bucket\n error: null\n }\n | {\n data: null\n error: StorageError\n }\n > {\n return this.handleOperation(async () => {\n return await get(this.fetch, `${this.url}/bucket/${id}`, { headers: this.headers })\n })\n }\n\n /**\n * Creates a new Storage bucket\n *\n * @category Storage\n * @subcategory File Buckets\n * @param id A unique identifier for the bucket you are creating.\n * @param options.public The visibility of the bucket. Public buckets don't require an authorization token to download objects, but still require a valid token for all other operations. By default, buckets are private.\n * @param options.fileSizeLimit specifies the max file size in bytes that can be uploaded to this bucket.\n * The global file size limit takes precedence over this value.\n * The default value is null, which doesn't set a per bucket file size limit.\n * @param options.allowedMimeTypes specifies the allowed mime types that this bucket can accept during upload.\n * The default value is null, which allows files with all mime types to be uploaded.\n * Each mime type specified can be a wildcard, e.g. image/*, or a specific mime type, e.g. image/png.\n * @param options.type (private-beta) specifies the bucket type. see `BucketType` for more details.\n * - default bucket type is `STANDARD`\n * @returns Promise with response containing newly created bucket name or error\n *\n * @example Create bucket\n * ```js\n * const { data, error } = await supabase\n * .storage\n * .createBucket('avatars', {\n * public: false,\n * allowedMimeTypes: ['image/png'],\n * fileSizeLimit: 1024\n * })\n * ```\n *\n * Response:\n * ```json\n * {\n * \"data\": {\n * \"name\": \"avatars\"\n * },\n * \"error\": null\n * }\n * ```\n *\n * @remarks\n * - RLS policy permissions required:\n * - `buckets` table permissions: `insert`\n * - `objects` table permissions: none\n * - Refer to the [Storage guide](/docs/guides/storage/security/access-control) on how access control works\n */\n async createBucket(\n id: string,\n options: {\n public: boolean\n fileSizeLimit?: number | string | null\n allowedMimeTypes?: string[] | null\n type?: BucketType\n } = {\n public: false,\n }\n ): Promise<\n | {\n data: Pick\n error: null\n }\n | {\n data: null\n error: StorageError\n }\n > {\n return this.handleOperation(async () => {\n return await post(\n this.fetch,\n `${this.url}/bucket`,\n {\n id,\n name: id,\n type: options.type,\n public: options.public,\n file_size_limit: options.fileSizeLimit,\n allowed_mime_types: options.allowedMimeTypes,\n },\n { headers: this.headers }\n )\n })\n }\n\n /**\n * Updates a Storage bucket\n *\n * @category Storage\n * @subcategory File Buckets\n * @param id A unique identifier for the bucket you are updating.\n * @param options.public The visibility of the bucket. Public buckets don't require an authorization token to download objects, but still require a valid token for all other operations.\n * @param options.fileSizeLimit specifies the max file size in bytes that can be uploaded to this bucket.\n * The global file size limit takes precedence over this value.\n * The default value is null, which doesn't set a per bucket file size limit.\n * @param options.allowedMimeTypes specifies the allowed mime types that this bucket can accept during upload.\n * The default value is null, which allows files with all mime types to be uploaded.\n * Each mime type specified can be a wildcard, e.g. image/*, or a specific mime type, e.g. image/png.\n * @returns Promise with response containing success message or error\n *\n * @example Update bucket\n * ```js\n * const { data, error } = await supabase\n * .storage\n * .updateBucket('avatars', {\n * public: false,\n * allowedMimeTypes: ['image/png'],\n * fileSizeLimit: 1024\n * })\n * ```\n *\n * Response:\n * ```json\n * {\n * \"data\": {\n * \"message\": \"Successfully updated\"\n * },\n * \"error\": null\n * }\n * ```\n *\n * @remarks\n * - RLS policy permissions required:\n * - `buckets` table permissions: `select` and `update`\n * - `objects` table permissions: none\n * - Refer to the [Storage guide](/docs/guides/storage/security/access-control) on how access control works\n */\n async updateBucket(\n id: string,\n options: {\n public: boolean\n fileSizeLimit?: number | string | null\n allowedMimeTypes?: string[] | null\n }\n ): Promise<\n | {\n data: { message: string }\n error: null\n }\n | {\n data: null\n error: StorageError\n }\n > {\n return this.handleOperation(async () => {\n return await put(\n this.fetch,\n `${this.url}/bucket/${id}`,\n {\n id,\n name: id,\n public: options.public,\n file_size_limit: options.fileSizeLimit,\n allowed_mime_types: options.allowedMimeTypes,\n },\n { headers: this.headers }\n )\n })\n }\n\n /**\n * Removes all objects inside a single bucket.\n *\n * @category Storage\n * @subcategory File Buckets\n * @param id The unique identifier of the bucket you would like to empty.\n * @returns Promise with success message or error\n *\n * @example Empty bucket\n * ```js\n * const { data, error } = await supabase\n * .storage\n * .emptyBucket('avatars')\n * ```\n *\n * Response:\n * ```json\n * {\n * \"data\": {\n * \"message\": \"Successfully emptied\"\n * },\n * \"error\": null\n * }\n * ```\n *\n * @remarks\n * - RLS policy permissions required:\n * - `buckets` table permissions: `select`\n * - `objects` table permissions: `select` and `delete`\n * - Refer to the [Storage guide](/docs/guides/storage/security/access-control) on how access control works\n */\n async emptyBucket(id: string): Promise<\n | {\n data: { message: string }\n error: null\n }\n | {\n data: null\n error: StorageError\n }\n > {\n return this.handleOperation(async () => {\n return await post(this.fetch, `${this.url}/bucket/${id}/empty`, {}, { headers: this.headers })\n })\n }\n\n /**\n * Deletes an existing bucket. A bucket can't be deleted with existing objects inside it.\n * You must first `empty()` the bucket.\n *\n * @category Storage\n * @subcategory File Buckets\n * @param id The unique identifier of the bucket you would like to delete.\n * @returns Promise with success message or error\n *\n * @example Delete bucket\n * ```js\n * const { data, error } = await supabase\n * .storage\n * .deleteBucket('avatars')\n * ```\n *\n * Response:\n * ```json\n * {\n * \"data\": {\n * \"message\": \"Successfully deleted\"\n * },\n * \"error\": null\n * }\n * ```\n *\n * @remarks\n * - RLS policy permissions required:\n * - `buckets` table permissions: `select` and `delete`\n * - `objects` table permissions: none\n * - Refer to the [Storage guide](/docs/guides/storage/security/access-control) on how access control works\n */\n async deleteBucket(id: string): Promise<\n | {\n data: { message: string }\n error: null\n }\n | {\n data: null\n error: StorageError\n }\n > {\n return this.handleOperation(async () => {\n return await remove(this.fetch, `${this.url}/bucket/${id}`, {}, { headers: this.headers })\n })\n }\n\n /**\n * Purges the CDN cache for an entire bucket.\n *\n * Maps to `DELETE /cdn/{bucket}` on the Storage API. The server\n * issues a CDN invalidation for the bucket and returns `{ message: 'success' }`.\n *\n * **Requires the `service_role` key.** The underlying endpoint enforces\n * `service_role` JWT — calls made with the anon key or a user JWT will be\n * rejected by the server.\n *\n * **Hosted CDN feature.** On self-hosted Supabase, the Storage service must\n * have `CDN_PURGE_ENDPOINT_URL` configured and the `purgeCache` tenant\n * feature enabled, otherwise the server returns an error.\n *\n * @category Storage\n * @subcategory File Buckets\n * @param id The unique identifier of the bucket you would like to purge from cache.\n * @param options Optional purge cache options.\n * @param options.transformations If true, purges only transformations (resized/formatted variants), leaving original cached files intact.\n * @param parameters Optional fetch parameters such as an `AbortController` signal.\n * @returns Promise with `{ data: { message }, error: null }` on success or `{ data: null, error }` on failure.\n *\n * @example Purge cache for an entire bucket\n * ```js\n * const { data, error } = await supabase\n * .storage\n * .purgeBucketCache('avatars')\n * ```\n *\n * @example Purge only transformations for an entire bucket\n * ```js\n * const { data, error } = await supabase\n * .storage\n * .purgeBucketCache('avatars', { transformations: true })\n * ```\n */\n async purgeBucketCache(\n id: string,\n options?: PurgeCacheOptions,\n parameters?: FetchParameters\n ): Promise<\n | {\n data: { message: string }\n error: null\n }\n | {\n data: null\n error: StorageError\n }\n > {\n return this.handleOperation(async () => {\n const query = new URLSearchParams()\n if (options?.transformations) {\n query.set('transformations', 'true')\n }\n const queryString = query.toString()\n\n return await remove(\n this.fetch,\n `${this.url}/cdn/${encodeStoragePath(id)}${queryString ? `?${queryString}` : ''}`,\n {},\n { headers: this.headers },\n parameters\n )\n })\n }\n\n private listBucketOptionsToQueryString(options?: ListBucketOptions): string {\n const params: Record = {}\n if (options) {\n if ('limit' in options) {\n params.limit = String(options.limit)\n }\n if ('offset' in options) {\n params.offset = String(options.offset)\n }\n if (options.search) {\n params.search = options.search\n }\n if (options.sortColumn) {\n params.sortColumn = options.sortColumn\n }\n if (options.sortOrder) {\n params.sortOrder = options.sortOrder\n }\n }\n return Object.keys(params).length > 0 ? '?' + new URLSearchParams(params).toString() : ''\n }\n}\n","import { IcebergRestCatalog, IcebergError } from 'iceberg-js'\nimport { DEFAULT_HEADERS } from '../lib/constants'\nimport { StorageError } from '../lib/common/errors'\nimport { Fetch, get, post, remove } from '../lib/common/fetch'\nimport { isValidBucketName } from '../lib/common/helpers'\nimport BaseApiClient from '../lib/common/BaseApiClient'\nimport { AnalyticBucket } from '../lib/types'\n\ntype WrapAsyncMethod = T extends (...args: infer A) => Promise\n ? (...args: A) => Promise<{ data: R; error: null } | { data: null; error: IcebergError }>\n : T\n\nexport type WrappedIcebergRestCatalog = {\n [K in keyof IcebergRestCatalog]: WrapAsyncMethod\n}\n\n/**\n * Client class for managing Analytics Buckets using Iceberg tables\n * Provides methods for creating, listing, and deleting analytics buckets\n */\nexport default class StorageAnalyticsClient extends BaseApiClient {\n /**\n * @alpha\n *\n * Creates a new StorageAnalyticsClient instance\n *\n * **Public alpha:** This API is part of a public alpha release and may not be available to your account type.\n *\n * @category Storage\n * @subcategory Analytics Buckets\n * @param url - The base URL for the storage API\n * @param headers - HTTP headers to include in requests\n * @param fetch - Optional custom fetch implementation\n *\n * @example Using supabase-js (recommended)\n * ```typescript\n * import { createClient } from '@supabase/supabase-js'\n *\n * const supabase = createClient('https://xyzcompany.supabase.co', 'your-publishable-key')\n * const { data, error } = await supabase.storage.analytics.listBuckets()\n * ```\n *\n * @example Standalone import for bundle-sensitive environments\n * ```typescript\n * import { StorageAnalyticsClient } from '@supabase/storage-js'\n *\n * const client = new StorageAnalyticsClient(url, headers)\n * ```\n */\n constructor(url: string, headers: { [key: string]: string } = {}, fetch?: Fetch) {\n const finalUrl = url.replace(/\\/$/, '')\n const finalHeaders = { ...DEFAULT_HEADERS, ...headers }\n super(finalUrl, finalHeaders, fetch, 'storage')\n }\n\n /**\n * @alpha\n *\n * Creates a new analytics bucket using Iceberg tables\n * Analytics buckets are optimized for analytical queries and data processing\n *\n * **Public alpha:** This API is part of a public alpha release and may not be available to your account type.\n *\n * @category Storage\n * @subcategory Analytics Buckets\n * @param name A unique name for the bucket you are creating\n * @returns Promise with response containing newly created analytics bucket or error\n *\n * @example Create analytics bucket\n * ```js\n * const { data, error } = await supabase\n * .storage\n * .analytics\n * .createBucket('analytics-data')\n * ```\n *\n * Response:\n * ```json\n * {\n * \"data\": {\n * \"name\": \"analytics-data\",\n * \"type\": \"ANALYTICS\",\n * \"format\": \"iceberg\",\n * \"created_at\": \"2024-05-22T22:26:05.100Z\",\n * \"updated_at\": \"2024-05-22T22:26:05.100Z\"\n * },\n * \"error\": null\n * }\n * ```\n *\n * @remarks\n * - Creates a new analytics bucket using Iceberg tables\n * - Analytics buckets are optimized for analytical queries and data processing\n */\n async createBucket(name: string): Promise<\n | {\n data: AnalyticBucket\n error: null\n }\n | {\n data: null\n error: StorageError\n }\n > {\n return this.handleOperation(async () => {\n return await post(this.fetch, `${this.url}/bucket`, { name }, { headers: this.headers })\n })\n }\n\n /**\n * @alpha\n *\n * Retrieves the details of all Analytics Storage buckets within an existing project\n * Only returns buckets of type 'ANALYTICS'\n *\n * **Public alpha:** This API is part of a public alpha release and may not be available to your account type.\n *\n * @category Storage\n * @subcategory Analytics Buckets\n * @param options Query parameters for listing buckets\n * @param options.limit Maximum number of buckets to return\n * @param options.offset Number of buckets to skip\n * @param options.sortColumn Column to sort by ('name', 'created_at', 'updated_at')\n * @param options.sortOrder Sort order ('asc' or 'desc')\n * @param options.search Search term to filter bucket names\n * @returns Promise with response containing array of analytics buckets or error\n *\n * @example List analytics buckets\n * ```js\n * const { data, error } = await supabase\n * .storage\n * .analytics\n * .listBuckets({\n * limit: 10,\n * offset: 0,\n * sortColumn: 'created_at',\n * sortOrder: 'desc'\n * })\n * ```\n *\n * Response:\n * ```json\n * {\n * \"data\": [\n * {\n * \"name\": \"analytics-data\",\n * \"type\": \"ANALYTICS\",\n * \"format\": \"iceberg\",\n * \"created_at\": \"2024-05-22T22:26:05.100Z\",\n * \"updated_at\": \"2024-05-22T22:26:05.100Z\"\n * }\n * ],\n * \"error\": null\n * }\n * ```\n *\n * @remarks\n * - Retrieves the details of all Analytics Storage buckets within an existing project\n * - Only returns buckets of type 'ANALYTICS'\n */\n async listBuckets(options?: {\n limit?: number\n offset?: number\n sortColumn?: 'name' | 'created_at' | 'updated_at'\n sortOrder?: 'asc' | 'desc'\n search?: string\n }): Promise<\n | {\n data: AnalyticBucket[]\n error: null\n }\n | {\n data: null\n error: StorageError\n }\n > {\n return this.handleOperation(async () => {\n // Build query string from options\n const queryParams = new URLSearchParams()\n if (options?.limit !== undefined) queryParams.set('limit', options.limit.toString())\n if (options?.offset !== undefined) queryParams.set('offset', options.offset.toString())\n if (options?.sortColumn) queryParams.set('sortColumn', options.sortColumn)\n if (options?.sortOrder) queryParams.set('sortOrder', options.sortOrder)\n if (options?.search) queryParams.set('search', options.search)\n\n const queryString = queryParams.toString()\n const url = queryString ? `${this.url}/bucket?${queryString}` : `${this.url}/bucket`\n\n return await get(this.fetch, url, { headers: this.headers })\n })\n }\n\n /**\n * @alpha\n *\n * Deletes an existing analytics bucket\n * A bucket can't be deleted with existing objects inside it\n * You must first empty the bucket before deletion\n *\n * **Public alpha:** This API is part of a public alpha release and may not be available to your account type.\n *\n * @category Storage\n * @subcategory Analytics Buckets\n * @param bucketName The unique identifier of the bucket you would like to delete\n * @returns Promise with response containing success message or error\n *\n * @example Delete analytics bucket\n * ```js\n * const { data, error } = await supabase\n * .storage\n * .analytics\n * .deleteBucket('analytics-data')\n * ```\n *\n * Response:\n * ```json\n * {\n * \"data\": {\n * \"message\": \"Successfully deleted\"\n * },\n * \"error\": null\n * }\n * ```\n *\n * @remarks\n * - Deletes an analytics bucket\n */\n async deleteBucket(bucketName: string): Promise<\n | {\n data: { message: string }\n error: null\n }\n | {\n data: null\n error: StorageError\n }\n > {\n return this.handleOperation(async () => {\n return await remove(\n this.fetch,\n `${this.url}/bucket/${bucketName}`,\n {},\n { headers: this.headers }\n )\n })\n }\n\n /**\n * @alpha\n *\n * Get an Iceberg REST Catalog client configured for a specific analytics bucket\n * Use this to perform advanced table and namespace operations within the bucket\n * The returned client provides full access to the Apache Iceberg REST Catalog API\n * with the Supabase `{ data, error }` pattern for consistent error handling on all operations.\n *\n * **Public alpha:** This API is part of a public alpha release and may not be available to your account type.\n *\n * @category Storage\n * @subcategory Analytics Buckets\n * @param bucketName - The name of the analytics bucket (warehouse) to connect to\n * @returns The wrapped Iceberg catalog client\n * @throws {StorageError} If the bucket name is invalid\n *\n * @example Get catalog and create table\n * ```js\n * // First, create an analytics bucket\n * const { data: bucket, error: bucketError } = await supabase\n * .storage\n * .analytics\n * .createBucket('analytics-data')\n *\n * // Get the Iceberg catalog for that bucket\n * const catalog = supabase.storage.analytics.from('analytics-data')\n *\n * // Create a namespace\n * const { error: nsError } = await catalog.createNamespace({ namespace: ['default'] })\n *\n * // Create a table with schema\n * const { data: tableMetadata, error: tableError } = await catalog.createTable(\n * { namespace: ['default'] },\n * {\n * name: 'events',\n * schema: {\n * type: 'struct',\n * fields: [\n * { id: 1, name: 'id', type: 'long', required: true },\n * { id: 2, name: 'timestamp', type: 'timestamp', required: true },\n * { id: 3, name: 'user_id', type: 'string', required: false }\n * ],\n * 'schema-id': 0,\n * 'identifier-field-ids': [1]\n * },\n * 'partition-spec': {\n * 'spec-id': 0,\n * fields: []\n * },\n * 'write-order': {\n * 'order-id': 0,\n * fields: []\n * },\n * properties: {\n * 'write.format.default': 'parquet'\n * }\n * }\n * )\n * ```\n *\n * @example List tables in namespace\n * ```js\n * const catalog = supabase.storage.analytics.from('analytics-data')\n *\n * // List all tables in the default namespace\n * const { data: tables, error: listError } = await catalog.listTables({ namespace: ['default'] })\n * if (listError) {\n * if (listError.isNotFound()) {\n * console.log('Namespace not found')\n * }\n * return\n * }\n * console.log(tables) // [{ namespace: ['default'], name: 'events' }]\n * ```\n *\n * @example Working with namespaces\n * ```js\n * const catalog = supabase.storage.analytics.from('analytics-data')\n *\n * // List all namespaces\n * const { data: namespaces } = await catalog.listNamespaces()\n *\n * // Create namespace with properties\n * await catalog.createNamespace(\n * { namespace: ['production'] },\n * { properties: { owner: 'data-team', env: 'prod' } }\n * )\n * ```\n *\n * @example Cleanup operations\n * ```js\n * const catalog = supabase.storage.analytics.from('analytics-data')\n *\n * // Drop table with purge option (removes all data)\n * const { error: dropError } = await catalog.dropTable(\n * { namespace: ['default'], name: 'events' },\n * { purge: true }\n * )\n *\n * if (dropError?.isNotFound()) {\n * console.log('Table does not exist')\n * }\n *\n * // Drop namespace (must be empty)\n * await catalog.dropNamespace({ namespace: ['default'] })\n * ```\n *\n * @remarks\n * This method provides a bridge between Supabase's bucket management and the standard\n * Apache Iceberg REST Catalog API. The bucket name maps to the Iceberg warehouse parameter.\n * All authentication and configuration is handled automatically using your Supabase credentials.\n *\n * **Error Handling**: Invalid bucket names throw immediately. All catalog\n * operations return `{ data, error }` where errors are `IcebergError` instances from iceberg-js.\n * Use helper methods like `error.isNotFound()` or check `error.status` for specific error handling.\n * Use `.throwOnError()` on the analytics client if you prefer exceptions for catalog operations.\n *\n * **Cleanup Operations**: When using `dropTable`, the `purge: true` option permanently\n * deletes all table data. Without it, the table is marked as deleted but data remains.\n *\n * **Library Dependency**: The returned catalog wraps `IcebergRestCatalog` from iceberg-js.\n * For complete API documentation and advanced usage, refer to the\n * [iceberg-js documentation](https://supabase.github.io/iceberg-js/).\n */\n from(bucketName: string): WrappedIcebergRestCatalog {\n // Validate bucket name using same rules as Supabase Storage API backend\n if (!isValidBucketName(bucketName)) {\n throw new StorageError(\n 'Invalid bucket name: File, folder, and bucket names must follow AWS object key naming guidelines ' +\n 'and should avoid the use of any other characters.'\n )\n }\n\n // Construct the Iceberg REST Catalog URL\n // The base URL is /storage/v1/iceberg\n // Note: IcebergRestCatalog from iceberg-js automatically adds /v1/ prefix to API paths\n // so we should NOT append /v1 here (it would cause double /v1/v1/ in the URL)\n const catalog = new IcebergRestCatalog({\n baseUrl: this.url,\n catalogName: bucketName, // Maps to the warehouse parameter in Supabase's implementation\n auth: {\n type: 'custom',\n getHeaders: async () => this.headers,\n },\n fetch: this.fetch,\n })\n\n const shouldThrowOnError = this.shouldThrowOnError\n\n const wrappedCatalog = new Proxy(catalog, {\n get(target, prop: keyof IcebergRestCatalog) {\n const value = target[prop]\n if (typeof value !== 'function') {\n return value\n }\n\n return async (...args: unknown[]) => {\n try {\n const data = await (value as Function).apply(target, args)\n return { data, error: null }\n } catch (error) {\n if (shouldThrowOnError) {\n throw error\n }\n return { data: null, error: error as IcebergError }\n }\n }\n },\n }) as unknown as WrappedIcebergRestCatalog\n\n return wrappedCatalog\n }\n}\n","import { DEFAULT_HEADERS } from '../lib/constants'\nimport { StorageError } from '../lib/common/errors'\nimport { Fetch, vectorsApi } from '../lib/common/fetch'\nimport BaseApiClient from '../lib/common/BaseApiClient'\nimport {\n ApiResponse,\n VectorIndex,\n ListIndexesOptions,\n ListIndexesResponse,\n VectorDataType,\n DistanceMetric,\n MetadataConfiguration,\n} from '../lib/types'\n\n/**\n * @alpha\n *\n * Options for creating a vector index\n *\n * **Public alpha:** This API is part of a public alpha release and may not be available to your account type.\n */\nexport interface CreateIndexOptions {\n vectorBucketName: string\n indexName: string\n dataType: VectorDataType\n dimension: number\n distanceMetric: DistanceMetric\n metadataConfiguration?: MetadataConfiguration\n}\n\n/**\n * @hidden\n * Base implementation for vector index operations.\n * Use {@link VectorBucketScope} via `supabase.storage.vectors.from('bucket')` instead.\n */\nexport default class VectorIndexApi extends BaseApiClient {\n /** Creates a new VectorIndexApi instance */\n constructor(url: string, headers: { [key: string]: string } = {}, fetch?: Fetch) {\n const finalUrl = url.replace(/\\/$/, '')\n const finalHeaders = { ...DEFAULT_HEADERS, 'Content-Type': 'application/json', ...headers }\n super(finalUrl, finalHeaders, fetch, 'vectors')\n }\n\n /** Creates a new vector index within a bucket */\n async createIndex(options: CreateIndexOptions): Promise> {\n return this.handleOperation(async () => {\n const data = await vectorsApi.post(this.fetch, `${this.url}/CreateIndex`, options, {\n headers: this.headers,\n })\n return data || {}\n })\n }\n\n /** Retrieves metadata for a specific vector index */\n async getIndex(\n vectorBucketName: string,\n indexName: string\n ): Promise> {\n return this.handleOperation(async () => {\n return await vectorsApi.post(\n this.fetch,\n `${this.url}/GetIndex`,\n { vectorBucketName, indexName },\n { headers: this.headers }\n )\n })\n }\n\n /** Lists vector indexes within a bucket with optional filtering and pagination */\n async listIndexes(options: ListIndexesOptions): Promise> {\n return this.handleOperation(async () => {\n return await vectorsApi.post(this.fetch, `${this.url}/ListIndexes`, options, {\n headers: this.headers,\n })\n })\n }\n\n /** Deletes a vector index and all its data */\n async deleteIndex(vectorBucketName: string, indexName: string): Promise> {\n return this.handleOperation(async () => {\n const data = await vectorsApi.post(\n this.fetch,\n `${this.url}/DeleteIndex`,\n { vectorBucketName, indexName },\n { headers: this.headers }\n )\n return data || {}\n })\n }\n}\n","import { DEFAULT_HEADERS } from '../lib/constants'\nimport { StorageError } from '../lib/common/errors'\nimport { Fetch, vectorsApi } from '../lib/common/fetch'\nimport BaseApiClient from '../lib/common/BaseApiClient'\nimport {\n ApiResponse,\n PutVectorsOptions,\n GetVectorsOptions,\n GetVectorsResponse,\n DeleteVectorsOptions,\n ListVectorsOptions,\n ListVectorsResponse,\n QueryVectorsOptions,\n QueryVectorsResponse,\n} from '../lib/types'\n\n/**\n * @hidden\n * Base implementation for vector data operations.\n * Use {@link VectorIndexScope} via `supabase.storage.vectors.from('bucket').index('idx')` instead.\n */\nexport default class VectorDataApi extends BaseApiClient {\n /** Creates a new VectorDataApi instance */\n constructor(url: string, headers: { [key: string]: string } = {}, fetch?: Fetch) {\n const finalUrl = url.replace(/\\/$/, '')\n const finalHeaders = { ...DEFAULT_HEADERS, 'Content-Type': 'application/json', ...headers }\n super(finalUrl, finalHeaders, fetch, 'vectors')\n }\n\n /** Inserts or updates vectors in batch (1-500 per request) */\n async putVectors(options: PutVectorsOptions): Promise> {\n // Validate batch size\n if (options.vectors.length < 1 || options.vectors.length > 500) {\n throw new Error('Vector batch size must be between 1 and 500 items')\n }\n\n return this.handleOperation(async () => {\n const data = await vectorsApi.post(this.fetch, `${this.url}/PutVectors`, options, {\n headers: this.headers,\n })\n return data || {}\n })\n }\n\n /** Retrieves vectors by their keys in batch */\n async getVectors(options: GetVectorsOptions): Promise> {\n return this.handleOperation(async () => {\n return await vectorsApi.post(this.fetch, `${this.url}/GetVectors`, options, {\n headers: this.headers,\n })\n })\n }\n\n /** Lists vectors in an index with pagination */\n async listVectors(options: ListVectorsOptions): Promise> {\n // Validate segment configuration\n if (options.segmentCount !== undefined) {\n if (options.segmentCount < 1 || options.segmentCount > 16) {\n throw new Error('segmentCount must be between 1 and 16')\n }\n if (options.segmentIndex !== undefined) {\n if (options.segmentIndex < 0 || options.segmentIndex >= options.segmentCount) {\n throw new Error(`segmentIndex must be between 0 and ${options.segmentCount - 1}`)\n }\n }\n }\n\n return this.handleOperation(async () => {\n return await vectorsApi.post(this.fetch, `${this.url}/ListVectors`, options, {\n headers: this.headers,\n })\n })\n }\n\n /** Queries for similar vectors using approximate nearest neighbor search */\n async queryVectors(options: QueryVectorsOptions): Promise> {\n return this.handleOperation(async () => {\n return await vectorsApi.post(this.fetch, `${this.url}/QueryVectors`, options, {\n headers: this.headers,\n })\n })\n }\n\n /** Deletes vectors by their keys in batch (1-500 per request) */\n async deleteVectors(options: DeleteVectorsOptions): Promise> {\n // Validate batch size\n if (options.keys.length < 1 || options.keys.length > 500) {\n throw new Error('Keys batch size must be between 1 and 500 items')\n }\n\n return this.handleOperation(async () => {\n const data = await vectorsApi.post(this.fetch, `${this.url}/DeleteVectors`, options, {\n headers: this.headers,\n })\n return data || {}\n })\n }\n}\n","import { DEFAULT_HEADERS } from '../lib/constants'\nimport { StorageError } from '../lib/common/errors'\nimport { Fetch, vectorsApi } from '../lib/common/fetch'\nimport BaseApiClient from '../lib/common/BaseApiClient'\nimport {\n ApiResponse,\n VectorBucket,\n ListVectorBucketsOptions,\n ListVectorBucketsResponse,\n} from '../lib/types'\n\n/**\n * @hidden\n * Base implementation for vector bucket operations.\n * Use {@link StorageVectorsClient} via `supabase.storage.vectors` instead.\n */\nexport default class VectorBucketApi extends BaseApiClient {\n /** Creates a new VectorBucketApi instance */\n constructor(url: string, headers: { [key: string]: string } = {}, fetch?: Fetch) {\n const finalUrl = url.replace(/\\/$/, '')\n const finalHeaders = { ...DEFAULT_HEADERS, 'Content-Type': 'application/json', ...headers }\n super(finalUrl, finalHeaders, fetch, 'vectors')\n }\n\n /** Creates a new vector bucket */\n async createBucket(vectorBucketName: string): Promise> {\n return this.handleOperation(async () => {\n const data = await vectorsApi.post(\n this.fetch,\n `${this.url}/CreateVectorBucket`,\n { vectorBucketName },\n { headers: this.headers }\n )\n return data || {}\n })\n }\n\n /** Retrieves metadata for a specific vector bucket */\n async getBucket(vectorBucketName: string): Promise> {\n return this.handleOperation(async () => {\n return await vectorsApi.post(\n this.fetch,\n `${this.url}/GetVectorBucket`,\n { vectorBucketName },\n { headers: this.headers }\n )\n })\n }\n\n /** Lists vector buckets with optional filtering and pagination */\n async listBuckets(\n options: ListVectorBucketsOptions = {}\n ): Promise> {\n return this.handleOperation(async () => {\n return await vectorsApi.post(this.fetch, `${this.url}/ListVectorBuckets`, options, {\n headers: this.headers,\n })\n })\n }\n\n /** Deletes a vector bucket (must be empty first) */\n async deleteBucket(vectorBucketName: string): Promise> {\n return this.handleOperation(async () => {\n const data = await vectorsApi.post(\n this.fetch,\n `${this.url}/DeleteVectorBucket`,\n { vectorBucketName },\n { headers: this.headers }\n )\n return data || {}\n })\n }\n}\n","import VectorIndexApi, { CreateIndexOptions } from './VectorIndexApi'\nimport VectorDataApi from './VectorDataApi'\nimport { Fetch } from '../lib/common/fetch'\nimport VectorBucketApi from './VectorBucketApi'\nimport {\n ApiResponse,\n DeleteVectorsOptions,\n GetVectorsOptions,\n ListIndexesOptions,\n ListVectorsOptions,\n ListVectorBucketsOptions,\n ListVectorBucketsResponse,\n PutVectorsOptions,\n QueryVectorsOptions,\n VectorBucket,\n} from '../lib/types'\n\n/**\n *\n * @alpha\n *\n * Configuration options for the Storage Vectors client\n *\n * **Public alpha:** This API is part of a public alpha release and may not be available to your account type.\n */\nexport interface StorageVectorsClientOptions {\n /**\n * Custom headers to include in all requests\n */\n headers?: { [key: string]: string }\n /**\n * Custom fetch implementation (optional)\n * Useful for testing or custom request handling\n */\n fetch?: Fetch\n}\n\n/**\n *\n * @alpha\n *\n * Main client for interacting with S3 Vectors API\n * Provides access to bucket, index, and vector data operations\n *\n * **Public alpha:** This API is part of a public alpha release and may not be available to your account type.\n *\n * **Usage Patterns:**\n *\n * ```typescript\n * const { data, error } = await supabase\n * .storage\n * .vectors\n * .createBucket('embeddings-prod')\n *\n * // Access index operations via buckets\n * const bucket = supabase.storage.vectors.from('embeddings-prod')\n * await bucket.createIndex({\n * indexName: 'documents',\n * dataType: 'float32',\n * dimension: 1536,\n * distanceMetric: 'cosine'\n * })\n *\n * // Access vector operations via index\n * const index = bucket.index('documents')\n * await index.putVectors({\n * vectors: [\n * { key: 'doc-1', data: { float32: [...] }, metadata: { title: 'Intro' } }\n * ]\n * })\n *\n * // Query similar vectors\n * const { data } = await index.queryVectors({\n * queryVector: { float32: [...] },\n * topK: 5,\n * returnDistance: true\n * })\n * ```\n */\nexport class StorageVectorsClient extends VectorBucketApi {\n /**\n * @alpha\n *\n * Creates a StorageVectorsClient that can manage buckets, indexes, and vectors.\n *\n * **Public alpha:** This API is part of a public alpha release and may not be available to your account type.\n *\n * @category Storage\n * @subcategory Vector Buckets\n * @param url - Base URL of the Storage Vectors REST API.\n * @param options.headers - Optional headers (for example `Authorization`) applied to every request.\n * @param options.fetch - Optional custom `fetch` implementation for non-browser runtimes.\n *\n * @example Using supabase-js (recommended)\n * ```typescript\n * import { createClient } from '@supabase/supabase-js'\n *\n * const supabase = createClient('https://xyzcompany.supabase.co', 'your-publishable-key')\n * const bucket = supabase.storage.vectors.from('embeddings-prod')\n * ```\n *\n * @example Standalone import for bundle-sensitive environments\n * ```typescript\n * import { StorageVectorsClient } from '@supabase/storage-js'\n *\n * const client = new StorageVectorsClient(url, options)\n * ```\n */\n constructor(url: string, options: StorageVectorsClientOptions = {}) {\n super(url, options.headers || {}, options.fetch)\n }\n\n /**\n *\n * @alpha\n *\n * Access operations for a specific vector bucket\n * Returns a scoped client for index and vector operations within the bucket\n *\n * **Public alpha:** This API is part of a public alpha release and may not be available to your account type.\n *\n * @category Storage\n * @subcategory Vector Buckets\n * @param vectorBucketName - Name of the vector bucket\n * @returns Bucket-scoped client with index and vector operations\n *\n * @example Accessing a vector bucket\n * ```typescript\n * const bucket = supabase.storage.vectors.from('embeddings-prod')\n * ```\n */\n from(vectorBucketName: string): VectorBucketScope {\n return new VectorBucketScope(this.url, this.headers, vectorBucketName, this.fetch)\n }\n\n /**\n *\n * @alpha\n *\n * Creates a new vector bucket\n * Vector buckets are containers for vector indexes and their data\n *\n * **Public alpha:** This API is part of a public alpha release and may not be available to your account type.\n *\n * @category Storage\n * @subcategory Vector Buckets\n * @param vectorBucketName - Unique name for the vector bucket\n * @returns Promise with empty response on success or error\n *\n * @example Creating a vector bucket\n * ```typescript\n * const { data, error } = await supabase\n * .storage\n * .vectors\n * .createBucket('embeddings-prod')\n * ```\n */\n async createBucket(vectorBucketName: string): Promise> {\n return super.createBucket(vectorBucketName)\n }\n\n /**\n *\n * @alpha\n *\n * Retrieves metadata for a specific vector bucket\n *\n * **Public alpha:** This API is part of a public alpha release and may not be available to your account type.\n *\n * @category Storage\n * @subcategory Vector Buckets\n * @param vectorBucketName - Name of the vector bucket\n * @returns Promise with bucket metadata or error\n *\n * @example Get bucket metadata\n * ```typescript\n * const { data, error } = await supabase\n * .storage\n * .vectors\n * .getBucket('embeddings-prod')\n *\n * console.log('Bucket created:', data?.vectorBucket.creationTime)\n * ```\n */\n async getBucket(vectorBucketName: string): Promise> {\n return super.getBucket(vectorBucketName)\n }\n\n /**\n *\n * @alpha\n *\n * Lists all vector buckets with optional filtering and pagination\n *\n * **Public alpha:** This API is part of a public alpha release and may not be available to your account type.\n *\n * @category Storage\n * @subcategory Vector Buckets\n * @param options - Optional filters (prefix, maxResults, nextToken)\n * @returns Promise with list of buckets or error\n *\n * @example List vector buckets\n * ```typescript\n * const { data, error } = await supabase\n * .storage\n * .vectors\n * .listBuckets({ prefix: 'embeddings-' })\n *\n * data?.vectorBuckets.forEach(bucket => {\n * console.log(bucket.vectorBucketName)\n * })\n * ```\n */\n async listBuckets(\n options: ListVectorBucketsOptions = {}\n ): Promise> {\n return super.listBuckets(options)\n }\n\n /**\n *\n * @alpha\n *\n * Deletes a vector bucket (bucket must be empty)\n * All indexes must be deleted before deleting the bucket\n *\n * **Public alpha:** This API is part of a public alpha release and may not be available to your account type.\n *\n * @category Storage\n * @subcategory Vector Buckets\n * @param vectorBucketName - Name of the vector bucket to delete\n * @returns Promise with empty response on success or error\n *\n * @example Delete a vector bucket\n * ```typescript\n * const { data, error } = await supabase\n * .storage\n * .vectors\n * .deleteBucket('embeddings-old')\n * ```\n */\n async deleteBucket(vectorBucketName: string): Promise> {\n return super.deleteBucket(vectorBucketName)\n }\n}\n\n/**\n *\n * @alpha\n *\n * Scoped client for operations within a specific vector bucket\n * Provides index management and access to vector operations\n *\n * **Public alpha:** This API is part of a public alpha release and may not be available to your account type.\n */\nexport class VectorBucketScope extends VectorIndexApi {\n private vectorBucketName: string\n\n /**\n * @alpha\n *\n * Creates a helper that automatically scopes all index operations to the provided bucket.\n *\n * **Public alpha:** This API is part of a public alpha release and may not be available to your account type.\n *\n * @category Storage\n * @subcategory Vector Buckets\n * @example Creating a vector bucket scope\n * ```typescript\n * const bucket = supabase.storage.vectors.from('embeddings-prod')\n * ```\n */\n constructor(\n url: string,\n headers: { [key: string]: string },\n vectorBucketName: string,\n fetch?: Fetch\n ) {\n super(url, headers, fetch)\n this.vectorBucketName = vectorBucketName\n }\n\n /**\n *\n * @alpha\n *\n * Creates a new vector index in this bucket\n * Convenience method that automatically includes the bucket name\n *\n * **Public alpha:** This API is part of a public alpha release and may not be available to your account type.\n *\n * @category Storage\n * @subcategory Vector Buckets\n * @param options - Index configuration (vectorBucketName is automatically set)\n * @returns Promise with empty response on success or error\n *\n * @example Creating a vector index\n * ```typescript\n * const bucket = supabase.storage.vectors.from('embeddings-prod')\n * await bucket.createIndex({\n * indexName: 'documents-openai',\n * dataType: 'float32',\n * dimension: 1536,\n * distanceMetric: 'cosine',\n * metadataConfiguration: {\n * nonFilterableMetadataKeys: ['raw_text']\n * }\n * })\n * ```\n */\n override async createIndex(options: Omit) {\n return super.createIndex({\n ...options,\n vectorBucketName: this.vectorBucketName,\n })\n }\n\n /**\n *\n * @alpha\n *\n * Lists indexes in this bucket\n * Convenience method that automatically includes the bucket name\n *\n * **Public alpha:** This API is part of a public alpha release and may not be available to your account type.\n *\n * @category Storage\n * @subcategory Vector Buckets\n * @param options - Listing options (vectorBucketName is automatically set)\n * @returns Promise with response containing indexes array and pagination token or error\n *\n * @example List indexes\n * ```typescript\n * const bucket = supabase.storage.vectors.from('embeddings-prod')\n * const { data } = await bucket.listIndexes({ prefix: 'documents-' })\n * ```\n */\n override async listIndexes(options: Omit = {}) {\n return super.listIndexes({\n ...options,\n vectorBucketName: this.vectorBucketName,\n })\n }\n\n /**\n *\n * @alpha\n *\n * Retrieves metadata for a specific index in this bucket\n * Convenience method that automatically includes the bucket name\n *\n * **Public alpha:** This API is part of a public alpha release and may not be available to your account type.\n *\n * @category Storage\n * @subcategory Vector Buckets\n * @param indexName - Name of the index to retrieve\n * @returns Promise with index metadata or error\n *\n * @example Get index metadata\n * ```typescript\n * const bucket = supabase.storage.vectors.from('embeddings-prod')\n * const { data } = await bucket.getIndex('documents-openai')\n * console.log('Dimension:', data?.index.dimension)\n * ```\n */\n override async getIndex(indexName: string) {\n return super.getIndex(this.vectorBucketName, indexName)\n }\n\n /**\n *\n * @alpha\n *\n * Deletes an index from this bucket\n * Convenience method that automatically includes the bucket name\n *\n * **Public alpha:** This API is part of a public alpha release and may not be available to your account type.\n *\n * @category Storage\n * @subcategory Vector Buckets\n * @param indexName - Name of the index to delete\n * @returns Promise with empty response on success or error\n *\n * @example Delete an index\n * ```typescript\n * const bucket = supabase.storage.vectors.from('embeddings-prod')\n * await bucket.deleteIndex('old-index')\n * ```\n */\n override async deleteIndex(indexName: string) {\n return super.deleteIndex(this.vectorBucketName, indexName)\n }\n\n /**\n *\n * @alpha\n *\n * Access operations for a specific index within this bucket\n * Returns a scoped client for vector data operations\n *\n * **Public alpha:** This API is part of a public alpha release and may not be available to your account type.\n *\n * @category Storage\n * @subcategory Vector Buckets\n * @param indexName - Name of the index\n * @returns Index-scoped client with vector data operations\n *\n * @example Accessing an index\n * ```typescript\n * const index = supabase.storage.vectors.from('embeddings-prod').index('documents-openai')\n *\n * // Insert vectors\n * await index.putVectors({\n * vectors: [\n * { key: 'doc-1', data: { float32: [...] }, metadata: { title: 'Intro' } }\n * ]\n * })\n *\n * // Query similar vectors\n * const { data } = await index.queryVectors({\n * queryVector: { float32: [...] },\n * topK: 5\n * })\n * ```\n */\n index(indexName: string): VectorIndexScope {\n return new VectorIndexScope(\n this.url,\n this.headers,\n this.vectorBucketName,\n indexName,\n this.fetch\n )\n }\n}\n\n/**\n *\n * @alpha\n *\n * Scoped client for operations within a specific vector index\n * Provides vector data operations (put, get, list, query, delete)\n *\n * **Public alpha:** This API is part of a public alpha release and may not be available to your account type.\n */\nexport class VectorIndexScope extends VectorDataApi {\n private vectorBucketName: string\n private indexName: string\n\n /**\n *\n * @alpha\n *\n * Creates a helper that automatically scopes all vector operations to the provided bucket/index names.\n *\n * **Public alpha:** This API is part of a public alpha release and may not be available to your account type.\n *\n * @category Storage\n * @subcategory Vector Buckets\n * @example Creating a vector index scope\n * ```typescript\n * const index = supabase.storage.vectors.from('embeddings-prod').index('documents-openai')\n * ```\n */\n constructor(\n url: string,\n headers: { [key: string]: string },\n vectorBucketName: string,\n indexName: string,\n fetch?: Fetch\n ) {\n super(url, headers, fetch)\n this.vectorBucketName = vectorBucketName\n this.indexName = indexName\n }\n\n /**\n *\n * @alpha\n *\n * Inserts or updates vectors in this index\n * Convenience method that automatically includes bucket and index names\n *\n * **Public alpha:** This API is part of a public alpha release and may not be available to your account type.\n *\n * @category Storage\n * @subcategory Vector Buckets\n * @param options - Vector insertion options (bucket and index names automatically set)\n * @returns Promise with empty response on success or error\n *\n * @example Insert vectors into an index\n * ```typescript\n * const index = supabase.storage.vectors.from('embeddings-prod').index('documents-openai')\n * await index.putVectors({\n * vectors: [\n * {\n * key: 'doc-1',\n * data: { float32: [0.1, 0.2, ...] },\n * metadata: { title: 'Introduction', page: 1 }\n * }\n * ]\n * })\n * ```\n */\n override async putVectors(options: Omit) {\n return super.putVectors({\n ...options,\n vectorBucketName: this.vectorBucketName,\n indexName: this.indexName,\n })\n }\n\n /**\n *\n * @alpha\n *\n * Retrieves vectors by keys from this index\n * Convenience method that automatically includes bucket and index names\n *\n * **Public alpha:** This API is part of a public alpha release and may not be available to your account type.\n *\n * @category Storage\n * @subcategory Vector Buckets\n * @param options - Vector retrieval options (bucket and index names automatically set)\n * @returns Promise with response containing vectors array or error\n *\n * @example Get vectors by keys\n * ```typescript\n * const index = supabase.storage.vectors.from('embeddings-prod').index('documents-openai')\n * const { data } = await index.getVectors({\n * keys: ['doc-1', 'doc-2'],\n * returnMetadata: true\n * })\n * ```\n */\n override async getVectors(options: Omit) {\n return super.getVectors({\n ...options,\n vectorBucketName: this.vectorBucketName,\n indexName: this.indexName,\n })\n }\n\n /**\n *\n * @alpha\n *\n * Lists vectors in this index with pagination\n * Convenience method that automatically includes bucket and index names\n *\n * **Public alpha:** This API is part of a public alpha release and may not be available to your account type.\n *\n * @category Storage\n * @subcategory Vector Buckets\n * @param options - Listing options (bucket and index names automatically set)\n * @returns Promise with response containing vectors array and pagination token or error\n *\n * @example List vectors with pagination\n * ```typescript\n * const index = supabase.storage.vectors.from('embeddings-prod').index('documents-openai')\n * const { data } = await index.listVectors({\n * maxResults: 500,\n * returnMetadata: true\n * })\n * ```\n */\n override async listVectors(\n options: Omit = {}\n ) {\n return super.listVectors({\n ...options,\n vectorBucketName: this.vectorBucketName,\n indexName: this.indexName,\n })\n }\n\n /**\n *\n * @alpha\n *\n * Queries for similar vectors in this index\n * Convenience method that automatically includes bucket and index names\n *\n * **Public alpha:** This API is part of a public alpha release and may not be available to your account type.\n *\n * @category Storage\n * @subcategory Vector Buckets\n * @param options - Query options (bucket and index names automatically set)\n * @returns Promise with response containing matches array of similar vectors ordered by distance or error\n *\n * @example Query similar vectors\n * ```typescript\n * const index = supabase.storage.vectors.from('embeddings-prod').index('documents-openai')\n * const { data } = await index.queryVectors({\n * queryVector: { float32: [0.1, 0.2, ...] },\n * topK: 5,\n * filter: { category: 'technical' },\n * returnDistance: true,\n * returnMetadata: true\n * })\n * ```\n */\n override async queryVectors(\n options: Omit\n ) {\n return super.queryVectors({\n ...options,\n vectorBucketName: this.vectorBucketName,\n indexName: this.indexName,\n })\n }\n\n /**\n *\n * @alpha\n *\n * Deletes vectors by keys from this index\n * Convenience method that automatically includes bucket and index names\n *\n * **Public alpha:** This API is part of a public alpha release and may not be available to your account type.\n *\n * @category Storage\n * @subcategory Vector Buckets\n * @param options - Deletion options (bucket and index names automatically set)\n * @returns Promise with empty response on success or error\n *\n * @example Delete vectors by keys\n * ```typescript\n * const index = supabase.storage.vectors.from('embeddings-prod').index('documents-openai')\n * await index.deleteVectors({\n * keys: ['doc-1', 'doc-2', 'doc-3']\n * })\n * ```\n */\n override async deleteVectors(\n options: Omit\n ) {\n return super.deleteVectors({\n ...options,\n vectorBucketName: this.vectorBucketName,\n indexName: this.indexName,\n })\n }\n}\n","import StorageFileApi from './packages/StorageFileApi'\nimport StorageBucketApi from './packages/StorageBucketApi'\nimport StorageAnalyticsClient from './packages/StorageAnalyticsClient'\nimport { Fetch } from './lib/common/fetch'\nimport { StorageVectorsClient } from './packages/StorageVectorsClient'\n\nexport interface StorageClientOptions {\n useNewHostname?: boolean\n}\n\nexport class StorageClient extends StorageBucketApi {\n /**\n * Creates a client for Storage buckets, files, analytics, and vectors.\n *\n * @category Storage\n * @subcategory File Buckets\n *\n * @example Using supabase-js (recommended)\n * ```ts\n * import { createClient } from '@supabase/supabase-js'\n *\n * const supabase = createClient('https://xyzcompany.supabase.co', 'your-publishable-key')\n * const avatars = supabase.storage.from('avatars')\n * ```\n *\n * @example Standalone import for bundle-sensitive environments\n * ```ts\n * import { StorageClient } from '@supabase/storage-js'\n *\n * const storage = new StorageClient('https://xyzcompany.supabase.co/storage/v1', {\n * apikey: 'your-publishable-key',\n * })\n * const avatars = storage.from('avatars')\n * ```\n */\n constructor(\n url: string,\n headers: { [key: string]: string } = {},\n fetch?: Fetch,\n opts?: StorageClientOptions\n ) {\n super(url, headers, fetch, opts)\n }\n\n /**\n * Perform file operation in a bucket.\n *\n * @category Storage\n * @subcategory File Buckets\n *\n * @param id The bucket id to operate on.\n *\n * @example Accessing a bucket\n * ```typescript\n * const avatars = supabase.storage.from('avatars')\n * ```\n */\n from(id: string): StorageFileApi {\n return new StorageFileApi(this.url, this.headers, id, this.fetch)\n }\n\n /**\n *\n * @alpha\n *\n * Access vector storage operations.\n *\n * **Public alpha:** This API is part of a public alpha release and may not be available to your account type.\n *\n * @category Storage\n * @subcategory Vector Buckets\n *\n * @returns A StorageVectorsClient instance configured with the current storage settings.\n */\n get vectors(): StorageVectorsClient {\n return new StorageVectorsClient(this.url + '/vector', {\n headers: this.headers,\n fetch: this.fetch,\n })\n }\n\n /**\n *\n * @alpha\n *\n * Access analytics storage operations using Iceberg tables.\n *\n * **Public alpha:** This API is part of a public alpha release and may not be available to your account type.\n *\n * @category Storage\n * @subcategory Analytics Buckets\n *\n * @returns A StorageAnalyticsClient instance configured with the current storage settings.\n */\n get analytics(): StorageAnalyticsClient {\n return new StorageAnalyticsClient(this.url + '/iceberg', this.headers, this.fetch)\n }\n}\n"],"mappings":"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"}
\ No newline at end of file
diff --git a/node_modules/@supabase/storage-js/dist/index.d.cts b/node_modules/@supabase/storage-js/dist/index.d.cts
new file mode 100644
index 0000000000000000000000000000000000000000..2d360b134f8ae1ccadd7e5251ad3fb59c14e36ba
--- /dev/null
+++ b/node_modules/@supabase/storage-js/dist/index.d.cts
@@ -0,0 +1,3086 @@
+import { IcebergError, IcebergRestCatalog } from "iceberg-js";
+
+//#region src/lib/common/errors.d.ts
+
+/**
+ * Namespace type for error classes
+ * Determines the error class names and type guards
+ */
+type ErrorNamespace = 'storage' | 'vectors';
+/**
+ * Base error class for all Storage errors
+ * Supports both 'storage' and 'vectors' namespaces
+ */
+declare class StorageError extends Error {
+ protected __isStorageError: boolean;
+ protected namespace: ErrorNamespace;
+ status: number | undefined;
+ statusCode: string | undefined;
+ constructor(message: string, namespace?: ErrorNamespace, status?: number, statusCode?: string);
+ toJSON(): {
+ name: string;
+ message: string;
+ status: number | undefined;
+ statusCode: string | undefined;
+ };
+}
+/**
+ * Type guard to check if an error is a StorageError
+ * @param error - The error to check
+ * @returns True if the error is a StorageError
+ */
+declare function isStorageError(error: unknown): error is StorageError;
+/**
+ * API error returned from Storage service
+ * Includes HTTP status code and service-specific error code
+ */
+declare class StorageApiError extends StorageError {
+ status: number;
+ statusCode: string;
+ /**
+ * Service-specific error code from the Storage API response body, such as
+ * `NoSuchKey`, `AccessDenied` or `ResourceAlreadyExists`. Use this to branch
+ * on the specific error rather than parsing the message.
+ * @see https://supabase.com/docs/guides/storage/debugging/error-codes
+ */
+ code: string | undefined;
+ constructor(message: string, status: number, statusCode: string, namespace?: ErrorNamespace, code?: string);
+ toJSON(): {
+ name: string;
+ message: string;
+ status: number | undefined;
+ statusCode: string | undefined;
+ code: string | undefined;
+ };
+}
+/**
+ * Unknown error that doesn't match expected error patterns
+ * Wraps the original error for debugging
+ */
+declare class StorageUnknownError extends StorageError {
+ originalError: unknown;
+ constructor(message: string, originalError: unknown, namespace?: ErrorNamespace);
+}
+/**
+ * @deprecated Use StorageError with namespace='vectors' instead
+ * Alias for backward compatibility with existing vector storage code
+ */
+declare class StorageVectorsError extends StorageError {
+ constructor(message: string);
+}
+/**
+ * Type guard to check if an error is a StorageVectorsError
+ * @param error - The error to check
+ * @returns True if the error is a StorageVectorsError
+ */
+declare function isStorageVectorsError(error: unknown): error is StorageVectorsError;
+/**
+ * @deprecated Use StorageApiError with namespace='vectors' instead
+ * Alias for backward compatibility with existing vector storage code
+ */
+declare class StorageVectorsApiError extends StorageApiError {
+ constructor(message: string, status: number, statusCode: string);
+}
+/**
+ * @deprecated Use StorageUnknownError with namespace='vectors' instead
+ * Alias for backward compatibility with existing vector storage code
+ */
+declare class StorageVectorsUnknownError extends StorageUnknownError {
+ constructor(message: string, originalError: unknown);
+}
+/**
+ * Error codes specific to S3 Vectors API
+ * Maps AWS service errors to application-friendly error codes
+ */
+declare enum StorageVectorsErrorCode {
+ /** Internal server fault (HTTP 500) */
+ InternalError = "InternalError",
+ /** Resource already exists / conflict (HTTP 409) */
+ S3VectorConflictException = "S3VectorConflictException",
+ /** Resource not found (HTTP 404) */
+ S3VectorNotFoundException = "S3VectorNotFoundException",
+ /** Delete bucket while not empty (HTTP 400) */
+ S3VectorBucketNotEmpty = "S3VectorBucketNotEmpty",
+ /** Exceeds bucket quota/limit (HTTP 400) */
+ S3VectorMaxBucketsExceeded = "S3VectorMaxBucketsExceeded",
+ /** Exceeds index quota/limit (HTTP 400) */
+ S3VectorMaxIndexesExceeded = "S3VectorMaxIndexesExceeded",
+}
+//#endregion
+//#region src/lib/types.d.ts
+/**
+ * Type of storage bucket
+ * - STANDARD: Regular file storage buckets
+ * - ANALYTICS: Iceberg table-based buckets for analytical workloads
+ */
+type BucketType = 'STANDARD' | 'ANALYTICS' | (string & {});
+interface Bucket {
+ id: string;
+ type?: BucketType;
+ name: string;
+ owner: string;
+ file_size_limit?: number;
+ allowed_mime_types?: string[];
+ created_at: string;
+ updated_at: string;
+ public: boolean;
+}
+interface ListBucketOptions {
+ limit?: number;
+ offset?: number;
+ sortColumn?: 'id' | 'name' | 'created_at' | 'updated_at';
+ sortOrder?: 'asc' | 'desc';
+ search?: string;
+}
+interface PurgeCacheOptions {
+ /**
+ * If true, purges only the transformations (resized/formatted variants) for the object or bucket,
+ * leaving the original cached file intact. If omitted, purges all cached versions.
+ */
+ transformations?: true;
+}
+/**
+ * Represents an Analytics Bucket using Apache Iceberg table format.
+ * Analytics buckets are optimized for analytical queries and data processing.
+ */
+interface AnalyticBucket {
+ /** Unique identifier for the bucket */
+ name: string;
+ /** Bucket type - always 'ANALYTICS' for analytics buckets */
+ type: 'ANALYTICS';
+ /** Storage format used (e.g., 'iceberg') */
+ format: string;
+ /** ISO 8601 timestamp of bucket creation */
+ created_at: string;
+ /** ISO 8601 timestamp of last update */
+ updated_at: string;
+}
+/**
+ * Metadata object returned by the Storage API for files
+ * Contains information about file size, type, caching, and HTTP response details
+ */
+interface FileMetadata {
+ /** Entity tag for caching and conditional requests */
+ eTag: string;
+ /** File size in bytes */
+ size: number;
+ /** MIME type of the file */
+ mimetype: string;
+ /** Cache control directive (e.g., "max-age=3600") */
+ cacheControl: string;
+ /** Last modification timestamp (ISO 8601) */
+ lastModified: string;
+ /** Content length in bytes (usually same as size) */
+ contentLength: number;
+ /** HTTP status code from the storage backend */
+ httpStatusCode: number;
+ /** Any additional custom metadata stored with the file */
+ [key: string]: any;
+}
+/**
+ * File object returned by the List V1 API (list() method)
+ * Note: Folder entries will have null values for most fields except name
+ *
+ * Warning: Some fields may not be present in all API responses. Fields like
+ * bucket_id, owner, and buckets are not returned by list() operations.
+ */
+interface FileObject {
+ /** File or folder name (relative to the prefix) - always present */
+ name: string;
+ /** Unique identifier for the file (null for folders) */
+ id: string | null;
+ /** Last update timestamp (null for folders) */
+ updated_at: string | null;
+ /** Creation timestamp (null for folders) */
+ created_at: string | null;
+ /** @deprecated Last access timestamp (null for folders) */
+ last_accessed_at: string | null;
+ /** File metadata including size, mimetype, etc. (null for folders) */
+ metadata: FileMetadata | null;
+ /**
+ * @deprecated Bucket identifier - NOT returned by list() operations.
+ * May be present in remove() responses. Do not rely on this field.
+ */
+ bucket_id?: string;
+ /**
+ * @deprecated Owner identifier - NOT returned by list() or remove() operations.
+ * This field should not be relied upon.
+ */
+ owner?: string;
+ /**
+ * @deprecated Bucket object - NOT returned by list() or remove() operations.
+ * This field should not be relied upon.
+ */
+ buckets?: Bucket;
+}
+/**
+ * File object returned by the Info endpoint (info() method)
+ * Contains detailed metadata for a specific file
+ */
+interface FileObjectV2 {
+ /** Unique identifier for the file */
+ id: string;
+ /** File version identifier */
+ version: string;
+ /** File name */
+ name: string;
+ /** Bucket identifier */
+ bucket_id: string;
+ /** Creation timestamp */
+ created_at: string;
+ /** File size in bytes */
+ size?: number;
+ /** Cache control header value */
+ cache_control?: string;
+ /** MIME content type */
+ content_type?: string;
+ /** Entity tag for caching */
+ etag?: string;
+ /** Last modification timestamp (replaces updated_at) */
+ last_modified?: string;
+ /** Custom file metadata */
+ metadata?: FileMetadata;
+ /**
+ * @deprecated The API returns last_modified instead.
+ * This field may not be present in responses.
+ */
+ updated_at?: string;
+}
+interface SortBy {
+ column?: string;
+ order?: string;
+}
+interface FileOptions {
+ /**
+ * The number of seconds the asset is cached in the browser and in the Supabase CDN. This is set in the `Cache-Control: max-age=` header. Defaults to 3600 seconds.
+ */
+ cacheControl?: string;
+ /**
+ * the `Content-Type` header value. Should be specified if using a `fileBody` that is neither `Blob` nor `File` nor `FormData`, otherwise will default to `text/plain;charset=UTF-8`.
+ */
+ contentType?: string;
+ /**
+ * When upsert is set to true, the file is overwritten if it exists. When set to false, an error is thrown if the object already exists. Defaults to false.
+ */
+ upsert?: boolean;
+ /**
+ * The duplex option is a string parameter that enables or disables duplex streaming, allowing for both reading and writing data in the same stream. It can be passed as an option to the fetch() method.
+ */
+ duplex?: string;
+ /**
+ * The metadata option is an object that allows you to store additional information about the file. This information can be used to filter and search for files. The metadata object can contain any key-value pairs you want to store.
+ */
+ metadata?: Record;
+ /**
+ * Optionally add extra headers
+ */
+ headers?: Record;
+}
+interface DestinationOptions {
+ destinationBucket?: string;
+}
+interface SearchOptions {
+ /**
+ * The number of files you want to be returned.
+ * @default 100
+ */
+ limit?: number;
+ /**
+ * The starting position.
+ */
+ offset?: number;
+ /**
+ * The column to sort by. Can be any column inside a FileObject.
+ */
+ sortBy?: SortBy;
+ /**
+ * The search string to filter files by.
+ */
+ search?: string;
+}
+interface SortByV2 {
+ column: 'name' | 'updated_at' | 'created_at';
+ order?: 'asc' | 'desc';
+}
+interface SearchV2Options {
+ /**
+ * The number of files you want to be returned.
+ * @default 1000
+ */
+ limit?: number;
+ /**
+ * The prefix search string to filter files by.
+ */
+ prefix?: string;
+ /**
+ * The cursor used for pagination. Pass the value received from nextCursor of the previous request.
+ */
+ cursor?: string;
+ /**
+ * Whether to emulate a hierarchical listing of objects using delimiters.
+ *
+ * - When `false` (default), all objects are listed as flat key/value pairs.
+ * - When `true`, the response groups objects by delimiter, making it appear
+ * like a file/folder hierarchy.
+ *
+ * @default false
+ */
+ with_delimiter?: boolean;
+ /**
+ * The column and order to sort by
+ * @default 'name asc'
+ */
+ sortBy?: SortByV2;
+}
+/**
+ * File object returned by the List V2 API (listV2() method)
+ * Objects and folders are returned in separate arrays - this type represents
+ * actual files only. Use SearchV2Folder for folder entries.
+ */
+interface SearchV2Object {
+ /** File name */
+ name: string;
+ /** Full object key/path */
+ key?: string;
+ /** Unique identifier for the file */
+ id: string;
+ /** Last update timestamp */
+ updated_at: string;
+ /** Creation timestamp */
+ created_at: string;
+ /** File metadata including size, mimetype, etc. (null if not yet set) */
+ metadata: FileMetadata | null;
+ /** @deprecated Last access timestamp */
+ last_accessed_at: string;
+}
+/**
+ * Folder entry returned by the List V2 API (listV2() method) when using with_delimiter: true
+ */
+interface SearchV2Folder {
+ /** Folder name/prefix */
+ name: string;
+ /** Full folder key/path */
+ key?: string;
+}
+interface SearchV2Result {
+ hasNext: boolean;
+ folders: SearchV2Folder[];
+ objects: SearchV2Object[];
+ nextCursor?: string;
+}
+interface FetchParameters {
+ /**
+ * Pass in an AbortController's signal to cancel the request.
+ */
+ signal?: AbortSignal;
+ /**
+ * Controls how the request interacts with the browser's HTTP cache.
+ * - 'default': Use standard cache behavior
+ * - 'no-store': Bypass cache entirely (useful in Edge Functions)
+ * - 'reload': Bypass cache but update it with response
+ * - 'no-cache': Validate with server before using cached response
+ * - 'force-cache': Use cache even if stale
+ * - 'only-if-cached': Only use cache, fail if not cached
+ */
+ cache?: 'default' | 'no-store' | 'reload' | 'no-cache' | 'force-cache' | 'only-if-cached';
+}
+interface Metadata {
+ name: string;
+}
+interface TransformOptions {
+ /**
+ * The width of the image in pixels.
+ */
+ width?: number;
+ /**
+ * The height of the image in pixels.
+ */
+ height?: number;
+ /**
+ * The resize mode can be cover, contain or fill. Defaults to cover.
+ * Cover resizes the image to maintain it's aspect ratio while filling the entire width and height.
+ * Contain resizes the image to maintain it's aspect ratio while fitting the entire image within the width and height.
+ * Fill resizes the image to fill the entire width and height. If the object's aspect ratio does not match the width and height, the image will be stretched to fit.
+ */
+ resize?: 'cover' | 'contain' | 'fill';
+ /**
+ * Set the quality of the returned image.
+ * A number from 20 to 100, with 100 being the highest quality.
+ * Defaults to 80
+ */
+ quality?: number;
+ /**
+ * Specify the format of the image requested.
+ *
+ * When using 'origin' we force the format to be the same as the original image.
+ * When this option is not passed in, images are optimized to modern image formats like Webp.
+ */
+ format?: 'origin';
+}
+type CamelCase = S extends `${infer P1}_${infer P2}${infer P3}` ? `${Lowercase}${Uppercase}${CamelCase}` : S;
+type Camelize = { [K in keyof T as CamelCase>]: T[K] };
+type DownloadResult = {
+ data: T;
+ error: null;
+} | {
+ data: null;
+ error: StorageError;
+};
+/**
+ * Configuration for encryption at rest
+ * @property kmsKeyArn - ARN of the KMS key used for encryption
+ * @property sseType - Server-side encryption type (e.g., 'KMS')
+ */
+interface EncryptionConfiguration {
+ kmsKeyArn?: string;
+ sseType?: string;
+}
+/**
+ * Vector bucket metadata
+ * @property vectorBucketName - Unique name of the vector bucket
+ * @property creationTime - Unix timestamp of when the bucket was created
+ * @property encryptionConfiguration - Optional encryption settings
+ */
+interface VectorBucket {
+ vectorBucketName: string;
+ creationTime?: number;
+ encryptionConfiguration?: EncryptionConfiguration;
+}
+/**
+ * Metadata configuration for vector index
+ * Defines which metadata keys should not be indexed for filtering
+ * @property nonFilterableMetadataKeys - Array of metadata keys that cannot be used in filters
+ */
+interface MetadataConfiguration {
+ nonFilterableMetadataKeys?: string[];
+}
+/**
+ * Supported data types for vectors
+ * Currently only float32 is supported
+ */
+type VectorDataType = 'float32' | (string & {});
+/**
+ * Distance metrics for vector similarity search
+ */
+type DistanceMetric = 'cosine' | 'euclidean' | 'dotproduct' | (string & {});
+/**
+ * Vector index configuration and metadata
+ * @property indexName - Unique name of the index within the bucket
+ * @property vectorBucketName - Name of the parent vector bucket
+ * @property dataType - Data type of vector components (currently only 'float32')
+ * @property dimension - Dimensionality of vectors (e.g., 384, 768, 1536)
+ * @property distanceMetric - Similarity metric used for queries
+ * @property metadataConfiguration - Configuration for metadata filtering
+ * @property creationTime - Unix timestamp of when the index was created
+ */
+interface VectorIndex {
+ indexName: string;
+ vectorBucketName: string;
+ dataType: VectorDataType;
+ dimension: number;
+ distanceMetric: DistanceMetric;
+ metadataConfiguration?: MetadataConfiguration;
+ creationTime?: number;
+}
+/**
+ * Vector data representation
+ * Vectors must be float32 arrays with dimensions matching the index
+ * @property float32 - Array of 32-bit floating point numbers
+ */
+interface VectorData {
+ float32: number[];
+}
+/**
+ * Arbitrary JSON metadata attached to vectors
+ * Keys configured as non-filterable in the index can be stored but not queried
+ */
+type VectorMetadata = Record;
+/**
+ * Single vector object for insertion/update
+ * @property key - Unique identifier for the vector
+ * @property data - Vector embedding data
+ * @property metadata - Optional arbitrary metadata
+ */
+interface VectorObject {
+ key: string;
+ data: VectorData;
+ metadata?: VectorMetadata;
+}
+/**
+ * Vector object returned from queries with optional distance
+ * @property key - Unique identifier for the vector
+ * @property data - Vector embedding data (if requested)
+ * @property metadata - Arbitrary metadata (if requested)
+ * @property distance - Similarity distance from query vector (if requested)
+ */
+interface VectorMatch {
+ key: string;
+ data?: VectorData;
+ metadata?: VectorMetadata;
+ distance?: number;
+}
+/**
+ * Options for fetching vector buckets
+ * @property prefix - Filter buckets by name prefix
+ * @property maxResults - Maximum number of results to return (default: 100)
+ * @property nextToken - Token for pagination from previous response
+ */
+interface ListVectorBucketsOptions {
+ prefix?: string;
+ maxResults?: number;
+ nextToken?: string;
+}
+/**
+ * Response from listing vector buckets
+ * @property vectorBuckets - Array of bucket names
+ * @property nextToken - Token for fetching next page (if more results exist)
+ */
+interface ListVectorBucketsResponse {
+ vectorBuckets: {
+ vectorBucketName: string;
+ }[];
+ nextToken?: string;
+}
+/**
+ * Options for listing indexes within a bucket
+ * @property vectorBucketName - Name of the parent vector bucket
+ * @property prefix - Filter indexes by name prefix
+ * @property maxResults - Maximum number of results to return (default: 100)
+ * @property nextToken - Token for pagination from previous response
+ */
+interface ListIndexesOptions {
+ vectorBucketName: string;
+ prefix?: string;
+ maxResults?: number;
+ nextToken?: string;
+}
+/**
+ * Response from listing indexes
+ * @property indexes - Array of index names
+ * @property nextToken - Token for fetching next page (if more results exist)
+ */
+interface ListIndexesResponse {
+ indexes: {
+ indexName: string;
+ }[];
+ nextToken?: string;
+}
+/**
+ * Options for batch reading vectors
+ * @property vectorBucketName - Name of the vector bucket
+ * @property indexName - Name of the index
+ * @property keys - Array of vector keys to retrieve
+ * @property returnData - Whether to include vector data in response
+ * @property returnMetadata - Whether to include metadata in response
+ */
+interface GetVectorsOptions {
+ vectorBucketName: string;
+ indexName: string;
+ keys: string[];
+ returnData?: boolean;
+ returnMetadata?: boolean;
+}
+/**
+ * Response from getting vectors
+ * @property vectors - Array of retrieved vector objects
+ */
+interface GetVectorsResponse {
+ vectors: VectorMatch[];
+}
+/**
+ * Options for batch inserting/updating vectors
+ * @property vectorBucketName - Name of the vector bucket
+ * @property indexName - Name of the index
+ * @property vectors - Array of vectors to insert/upsert (1-500 items)
+ */
+interface PutVectorsOptions {
+ vectorBucketName: string;
+ indexName: string;
+ vectors: VectorObject[];
+}
+/**
+ * Options for batch deleting vectors
+ * @property vectorBucketName - Name of the vector bucket
+ * @property indexName - Name of the index
+ * @property keys - Array of vector keys to delete (1-500 items)
+ */
+interface DeleteVectorsOptions {
+ vectorBucketName: string;
+ indexName: string;
+ keys: string[];
+}
+/**
+ * Options for listing/scanning vectors in an index
+ * Supports parallel scanning via segment configuration
+ * @property vectorBucketName - Name of the vector bucket
+ * @property indexName - Name of the index
+ * @property maxResults - Maximum number of results to return (default: 500, max: 1000)
+ * @property nextToken - Token for pagination from previous response
+ * @property returnData - Whether to include vector data in response
+ * @property returnMetadata - Whether to include metadata in response
+ * @property segmentCount - Total number of parallel segments (1-16)
+ * @property segmentIndex - Zero-based index of this segment (0 to segmentCount-1)
+ */
+interface ListVectorsOptions {
+ vectorBucketName: string;
+ indexName: string;
+ maxResults?: number;
+ nextToken?: string;
+ returnData?: boolean;
+ returnMetadata?: boolean;
+ segmentCount?: number;
+ segmentIndex?: number;
+}
+/**
+ * Response from listing vectors
+ * @property vectors - Array of vector objects
+ * @property nextToken - Token for fetching next page (if more results exist)
+ */
+interface ListVectorsResponse {
+ vectors: VectorMatch[];
+ nextToken?: string;
+}
+/**
+ * JSON filter expression for metadata filtering
+ * Format and syntax depend on the S3 Vectors service implementation
+ */
+type VectorFilter = Record;
+/**
+ * Options for querying similar vectors (ANN search)
+ * @property vectorBucketName - Name of the vector bucket
+ * @property indexName - Name of the index
+ * @property queryVector - Query vector to find similar vectors
+ * @property topK - Number of nearest neighbors to return (default: 10)
+ * @property filter - Optional JSON filter for metadata
+ * @property returnDistance - Whether to include distance scores
+ * @property returnMetadata - Whether to include metadata in results
+ */
+interface QueryVectorsOptions {
+ vectorBucketName: string;
+ indexName: string;
+ queryVector: VectorData;
+ topK?: number;
+ filter?: VectorFilter;
+ returnDistance?: boolean;
+ returnMetadata?: boolean;
+}
+/**
+ * Response from vector similarity query
+ * @property vectors - Array of similar vectors ordered by distance
+ * @property distanceMetric - The distance metric used for the similarity search
+ */
+interface QueryVectorsResponse {
+ vectors: VectorMatch[];
+ distanceMetric?: DistanceMetric;
+}
+/**
+ * Fetch-specific parameters like abort signals
+ * @property signal - AbortSignal for cancelling requests
+ */
+interface VectorFetchParameters {
+ signal?: AbortSignal;
+}
+/**
+ * Standard response wrapper for successful operations
+ * @property data - Response data of type T
+ * @property error - Null on success
+ */
+interface SuccessResponse {
+ data: T;
+ error: null;
+}
+/**
+ * Standard response wrapper for failed operations
+ * @property data - Null on error
+ * @property error - StorageError with details (named StorageVectorsError for vector operations)
+ */
+interface ErrorResponse {
+ data: null;
+ error: StorageError;
+}
+/**
+ * Union type for all API responses
+ * Follows the pattern: { data: T, error: null } | { data: null, error: Error }
+ */
+type ApiResponse = SuccessResponse | ErrorResponse;
+//#endregion
+//#region src/lib/common/fetch.d.ts
+type Fetch = typeof fetch;
+//#endregion
+//#region src/lib/common/BaseApiClient.d.ts
+/**
+ * @ignore
+ * Base API client class for all Storage API classes
+ * Provides common infrastructure for error handling and configuration
+ *
+ * @typeParam TError - The error type (StorageError or subclass)
+ */
+declare abstract class BaseApiClient {
+ protected url: string;
+ protected headers: {
+ [key: string]: string;
+ };
+ protected fetch: Fetch;
+ protected shouldThrowOnError: boolean;
+ protected namespace: ErrorNamespace;
+ /**
+ * Creates a new BaseApiClient instance
+ * @param url - Base URL for API requests
+ * @param headers - Default headers for API requests
+ * @param fetch - Optional custom fetch implementation
+ * @param namespace - Error namespace ('storage' or 'vectors')
+ */
+ constructor(url: string, headers?: {
+ [key: string]: string;
+ }, fetch?: Fetch, namespace?: ErrorNamespace);
+ /**
+ * Enable throwing errors instead of returning them.
+ * When enabled, errors are thrown instead of returned in { data, error } format.
+ *
+ * @returns this - For method chaining
+ */
+ throwOnError(): this;
+ /**
+ * Set an HTTP header for the request.
+ * Creates a shallow copy of headers to avoid mutating shared state.
+ *
+ * @param name - Header name
+ * @param value - Header value
+ * @returns this - For method chaining
+ */
+ setHeader(name: string, value: string): this;
+ /**
+ * Handles API operation with standardized error handling
+ * Eliminates repetitive try-catch blocks across all API methods
+ *
+ * This wrapper:
+ * 1. Executes the operation
+ * 2. Returns { data, error: null } on success
+ * 3. Returns { data: null, error } on failure (if shouldThrowOnError is false)
+ * 4. Throws error on failure (if shouldThrowOnError is true)
+ *
+ * @typeParam T - The expected data type from the operation
+ * @param operation - Async function that performs the API call
+ * @returns Promise with { data, error } tuple
+ *
+ * @example Handling an operation
+ * ```typescript
+ * async listBuckets() {
+ * return this.handleOperation(async () => {
+ * return await get(this.fetch, `${this.url}/bucket`, {
+ * headers: this.headers,
+ * })
+ * })
+ * }
+ * ```
+ */
+ protected handleOperation(operation: () => Promise): Promise<{
+ data: T;
+ error: null;
+ } | {
+ data: null;
+ error: TError;
+ }>;
+}
+//#endregion
+//#region src/packages/StreamDownloadBuilder.d.ts
+declare class StreamDownloadBuilder implements Promise> {
+ private downloadFn;
+ private shouldThrowOnError;
+ readonly [Symbol.toStringTag]: string;
+ private promise;
+ constructor(downloadFn: () => Promise, shouldThrowOnError: boolean);
+ then, TResult2 = never>(onfulfilled?: ((value: DownloadResult) => TResult1 | PromiseLike) | null, onrejected?: ((reason: any) => TResult2 | PromiseLike) | null): Promise;
+ catch(onrejected?: ((reason: any) => TResult | PromiseLike) | null): Promise | TResult>;
+ finally(onfinally?: (() => void) | null): Promise>;
+ private getPromise;
+ private execute;
+}
+//#endregion
+//#region src/packages/BlobDownloadBuilder.d.ts
+declare class BlobDownloadBuilder implements Promise