{"_id":"@allyourbase/js","_rev":"3-873b73f1a30ff01e6c1d3cebb630f275","name":"@allyourbase/js","dist-tags":{"latest":"0.3.0"},"versions":{"0.1.0":{"name":"@allyourbase/js","version":"0.1.0","keywords":["allyourbase","ayb","baas","postgresql","sdk","client"],"license":"MIT","_id":"@allyourbase/js@0.1.0","maintainers":[{"name":"stuartcrobinsonnpm","email":"stuart.clifford+npm@gmail.com"}],"dist":{"shasum":"10d8e87d541b59aa9f9102547bc0df67576acf8e","tarball":"https://registry.npmjs.org/@allyourbase/js/-/js-0.1.0.tgz","fileCount":8,"integrity":"sha512-Tcdwaoz1x+llIFnE5U0T9AwzN6sGMUGbt1fe4cFG17jF5FaY90OATj8u2RknTZXBBOhZPvGYfRe9jmndzphaZg==","signatures":[{"sig":"MEQCIAu6veJNMeGhUlaEX32TtRWg6ZhV9jLV9Pj12PjYX2egAiA9KTgZU/+2QnlwIFsOzLkMzSpAauZb9jzS89z9gu0RTg==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":72118},"main":"dist/index.cjs","type":"module","types":"dist/index.d.ts","module":"dist/index.js","exports":{".":{"import":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"require":{"types":"./dist/index.d.cts","default":"./dist/index.cjs"}}},"gitHead":"1f118e0acaa47cebde86036b5b2483c92f8c6f9e","scripts":{"dev":"tsup --watch","test":"vitest run","build":"tsup","typecheck":"tsc --noEmit","test:watch":"vitest","prepublishOnly":"npm run build"},"_npmUser":{"name":"stuartcrobinsonnpm","email":"stuart.clifford+npm@gmail.com"},"_npmVersion":"11.6.2","description":"JavaScript/TypeScript client SDK for AllYourBase","directories":{},"_nodeVersion":"23.9.0","_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.0.0","vitest":"^2.0.0","typescript":"^5.5.0"},"_npmOperationalInternal":{"tmp":"tmp/js_0.1.0_1770576387888_0.47586952203885313","host":"s3://npm-registry-packages-npm-production"}},"0.2.0":{"name":"@allyourbase/js","version":"0.2.0","keywords":["allyourbase","ayb","baas","postgresql","sdk","client"],"license":"MIT","_id":"@allyourbase/js@0.2.0","maintainers":[{"name":"stuartcrobinsonnpm","email":"stuart.clifford+npm@gmail.com"}],"dist":{"shasum":"f0b4aa18d7aa02c56be0db185e836e6ea493c231","tarball":"https://registry.npmjs.org/@allyourbase/js/-/js-0.2.0.tgz","fileCount":8,"integrity":"sha512-aJCs4Dfrd915heM7pfA/WYYmpnkK6IY1DlXnyViW0jLioUmUZRBg+4pGnC+1p/68/kGQG//josBU9+YNP0fKHw==","signatures":[{"sig":"MEUCIBRF7PRj3GqtetgiqBqVoAnaVHFaHRQT07gbYEbDq6G7AiEAwWzXDBvTXJi+kaVTSIFj9PePiV6V3JDqLV89H/RR9OE=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":284393},"main":"dist/index.cjs","type":"module","types":"dist/index.d.ts","module":"dist/index.js","exports":{".":{"import":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"require":{"types":"./dist/index.d.cts","default":"./dist/index.cjs"}}},"scripts":{"dev":"tsup --watch","test":"vitest run","build":"tsup","typecheck":"tsc --noEmit","test:watch":"vitest","prepublishOnly":"npm run build","test:integration":"vitest run src/integration*.test.ts --no-file-parallelism"},"_npmUser":{"name":"stuartcrobinsonnpm","email":"stuart.clifford+npm@gmail.com"},"_npmVersion":"11.12.1","description":"JavaScript/TypeScript client SDK for Allyourbase","directories":{},"_nodeVersion":"26.0.0","_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.0.0","jsdom":"^27.0.1","eslint":"^10.4.1","vitest":"^4.1.0","globals":"^17.6.0","@eslint/js":"^10.0.1","typescript":"^5.5.0","eventsource":"^3.0.7","typescript-eslint":"^8.60.1"},"_npmOperationalInternal":{"tmp":"tmp/js_0.2.0_1780602222819_0.43317371210245814","host":"s3://npm-registry-packages-npm-production"}},"0.3.0":{"name":"@allyourbase/js","version":"0.3.0","description":"JavaScript/TypeScript client SDK for Allyourbase","type":"module","packageManager":"pnpm@11.1.2","main":"dist/index.cjs","module":"dist/index.js","types":"dist/index.d.ts","exports":{".":{"import":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"require":{"types":"./dist/index.d.cts","default":"./dist/index.cjs"}},"./instantsearch":{"import":{"types":"./dist/instantsearch.d.ts","default":"./dist/instantsearch.js"},"require":{"types":"./dist/instantsearch.d.cts","default":"./dist/instantsearch.cjs"}}},"scripts":{"build":"tsup","dev":"tsup --watch","test":"vitest run","test:watch":"vitest","test:integration":"vitest run src/integration*.test.ts --no-file-parallelism","typecheck":"tsc --noEmit","prepublishOnly":"npm run build"},"keywords":["allyourbase","ayb","baas","postgresql","sdk","client"],"license":"MIT","devDependencies":{"@eslint/js":"^10.0.1","eslint":"^10.4.1","eventsource":"^3.0.7","globals":"^17.6.0","jsdom":"^27.0.1","tsup":"^8.0.0","typescript":"^5.5.0","typescript-eslint":"^8.60.1","vite":"^7.3.5","vitest":"^4.1.0"},"_id":"@allyourbase/js@0.3.0","_integrity":"sha512-nYnG+05tx946JGjyYBVCUZldH9H671w+DQ+wvoaGbvz1ApFPnxM48BJSmWL7XV9xdjNE60E7ZYJ+Hw/IvfyKDg==","_resolved":"/Users/stuart/parallel_development/allyourbase_dev/jul31_4pm_4_sdk_publish_version_truth/allyourbase_dev/sdk/dist/allyourbase-js-0.3.0.tgz","_from":"file:dist/allyourbase-js-0.3.0.tgz","_nodeVersion":"26.0.0","_npmVersion":"11.12.1","dist":{"integrity":"sha512-nYnG+05tx946JGjyYBVCUZldH9H671w+DQ+wvoaGbvz1ApFPnxM48BJSmWL7XV9xdjNE60E7ZYJ+Hw/IvfyKDg==","shasum":"fd52168412f3dc4bd620170f616ec63c117b2ebc","tarball":"https://registry.npmjs.org/@allyourbase/js/-/js-0.3.0.tgz","fileCount":16,"unpackedSize":593304,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEQCIAU95urB6Ocmc6TVjhnO25tZA3CmoImc4oZSWzww2dEeAiAuejdIhIKIlT1CnxavH985ELkWFYnOG8LpFGqOBL8WIA=="}]},"_npmUser":{"name":"stuartcrobinsonnpm","email":"stuart.clifford+npm@gmail.com"},"directories":{},"maintainers":[{"name":"stuartcrobinsonnpm","email":"stuart.clifford+npm@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/js_0.3.0_1785539121271_0.06515624168516698"},"_hasShrinkwrap":false}},"time":{"created":"2026-02-08T18:46:27.730Z","modified":"2026-07-31T23:05:21.613Z","0.1.0":"2026-02-08T18:46:28.035Z","0.2.0":"2026-06-04T19:43:43.007Z","0.3.0":"2026-07-31T23:05:21.439Z"},"license":"MIT","keywords":["allyourbase","ayb","baas","postgresql","sdk","client"],"description":"JavaScript/TypeScript client SDK for Allyourbase","maintainers":[{"name":"stuartcrobinsonnpm","email":"stuart.clifford+npm@gmail.com"}],"readme":"# @allyourbase/js\n\nJavaScript/TypeScript client SDK for [Allyourbase](https://github.com/AllyourbaseHQ/allyourbase) — the PostgreSQL Backend-as-a-Service.\n\n## Install\n\n```bash\nnpm install @allyourbase/js\n```\n\nThe SDK release candidate is version `0.3.0`.\n\n## Quick Start\n\n```ts\nimport { AYBClient, type SearchHit } from \"@allyourbase/js\";\n\nconst ayb = new AYBClient(\"http://localhost:8090\");\n\n// Create a record\nconst post = await ayb.records.create(\"posts\", {\n  title: \"Hello World\",\n  published: true,\n});\n\n// List records with filtering and sorting\nconst posts = await ayb.records.list(\"posts\", {\n  filter: \"published=true\",\n  sort: \"-created_at\",\n  perPage: 20,\n});\n\n// Search records with highlights and facet counts\nconst search = await ayb.records.list<SearchHit<{ id: string; title: string }>>(\n  \"posts\",\n  {\n    search: \"postgres\",\n    fuzzy: true,\n    typoThreshold: 0.3,\n    highlight: true,\n    facets: [\"published\"],\n  },\n);\nconsole.log(search.items[0]?._highlight, search.facets?.published);\n\n// Auth\nawait ayb.auth.login(\"user@example.com\", \"password\");\nconst me = await ayb.auth.me();\n\n// Passkey sign-in and MFA\nawait ayb.auth.signInWithPasskey(\"user@example.com\");\nawait ayb.auth.enrollPasskey(\"Primary passkey\");\n```\n\n`highlight` is a boolean toggle that asks the backend to return `_highlight`\nsnippets on matching items. `typoThreshold` is only accepted when `fuzzy: true`.\n\n## API Reference\n\n### `new AYBClient(baseURL, options?)`\n\nCreate a client instance.\n\n```ts\nconst ayb = new AYBClient(\"http://localhost:8090\");\n\n// With custom fetch (e.g. for Node.js < 18)\nconst ayb = new AYBClient(\"http://localhost:8090\", { fetch: myFetch });\n```\n\n### PostgreSQL RPC\n\nCall PostgreSQL functions with\n`client.rpc<T>(functionName, args?, options?)`. Void and empty responses resolve\nto `undefined`.\n\n```ts\nconst total = await ayb.rpc<number>(\"leaderboard_total\", {\n  club_id: \"abc123\",\n});\n```\n\n### Edge functions\n\n`client.functions.invoke(name, options?)` returns the raw response as\n`{ status, headers, rawBody }`.\n\n```ts\nconst response = await ayb.functions.invoke(\"send-digest\", {\n  body: { club_id: \"abc123\" },\n});\nconsole.log(response.status, response.headers, response.rawBody);\n```\n\nGraphQL and admin/org typed clients are JS-only scope today and live on\n`client.graphql` and `client.admin(...)`. The other SDKs intentionally do not\ndefine those typed clients yet.\n\n### Records\n\n```ts\n// List with filtering, sorting, pagination\nconst result = await ayb.records.list<Post>(\"posts\", {\n  filter: \"status='active' AND views>100\",\n  sort: \"-created_at,+title\",\n  page: 1,\n  perPage: 50,\n  fields: \"id,title,status\",\n  expand: \"author,category\",\n  skipTotal: true,\n});\n// result: { items: Post[], page, perPage, totalItems, totalPages }\n\n// Search with typo tolerance, highlights, and facets\nconst search = await ayb.records.list<SearchHit<Post>>(\"posts\", {\n  search: \"postgres database\",\n  fuzzy: true,\n  typoThreshold: 0.3,\n  highlight: true,\n  facets: [\"status\", \"category\"],\n});\n// search.items[0]._highlight is present when the backend returns a highlight.\n// search.facets is a FacetCounts envelope keyed by requested facet column.\n\n// Semantic/vector search\nawait ayb.records.list<Post>(\"posts\", {\n  semantic: true,\n  semanticQuery: \"articles about hosted Postgres\",\n  nearest: [0.12, 0.34, 0.56],\n  vectorColumn: \"embedding\",\n  distance: \"cosine\",\n});\n\n// Get by ID\nconst post = await ayb.records.get<Post>(\"posts\", \"abc123\", {\n  expand: \"author\",\n});\n\n// Create\nconst post = await ayb.records.create<Post>(\"posts\", {\n  title: \"New Post\",\n  body: \"Content here\",\n});\n\n// Update (partial)\nconst updated = await ayb.records.update<Post>(\"posts\", \"abc123\", {\n  title: \"Updated Title\",\n});\n\n// Delete\nawait ayb.records.delete(\"posts\", \"abc123\");\n```\n\n`highlight` mirrors the REST API's boolean query param: pass `true` to request\n`_highlight` snippets, and omit it otherwise. `typoThreshold` requires\n`fuzzy: true`.\n\n### InstantSearch adapter\n\n```ts\nimport { createInstantSearchClient } from \"@allyourbase/js/instantsearch\";\n\nconst searchClient = createInstantSearchClient({\n  client: ayb,\n  objectIDField: \"id\",\n  defaultIndexName: \"posts\",\n});\n```\n\n`@allyourbase/js/instantsearch` is a thin adapter over `records.list`; it does\nnot add a second search transport. `objectIDField` is required because AYB rows\nare arbitrary PostgreSQL records, and the adapter fails closed when a returned\nrow is missing that field or has a `null` value.\n\nThe adapter supports one-index `search(requests)` calls with `query`, zero-based\n`page`, `hitsPerPage`, concrete `facets`, `disjunctiveFacets`,\n`facetFilters` in `attribute:value` form, `numericFilters` range comparisons,\nand the documented `filters` comparison subset. Empty query strings are sent as\nbrowsable list calls with no `search` parameter so first-render facets and\nrange stats remain available. Set `highlight: false` in the adapter options to\nomit the backend `highlight=true` request flag.\n\n`searchClient.searchForFacetValues(requests)` is supported for searchable facet\nwidgets. It delegates each request through `client.records.searchFacetValues()`\n(see below) and returns Algolia-shaped `{ facetHits, exhaustiveFacetsCount,\nprocessingTimeMS }` per request; the backend's `<mark>` prefix wrappers are\nremapped onto the caller's `highlightPreTag`/`highlightPostTag` (default\nInstantSearch placeholders). `maxFacetHits` defaults to 10 and is capped at\n100.\n\nUnsupported cases throw before AYB is called: mixed index requests,\nwildcard facets, vector/search tuning params, `skipTotal`, negative\n`facetFilters`, nested attributes, tag filters, malformed numeric filters,\narrays, `NOT`, and unlisted Algolia request parameters.\n\n### Facet value search\n\n```ts\n// Searchable facet values: bucket-level search on a single facet column\nconst facet = await ayb.records.searchFacetValues(\"products\", \"category\", {\n  q: \"st\",\n  maxFacetHits: 10,\n});\n// facet.facetHits[0]: { value: \"Stationery\", highlighted: \"<mark>St</mark>ationery\", count: 3 }\nconsole.log(facet.exhaustiveFacetsCount);\n```\n\n`records.searchFacetValues(collection, column, params)` calls\n`GET /api/collections/{table}/facets/{column}/search`. `column` must be a text\nfacet column. `params` accepts an optional `q` prefix, `maxFacetHits`,\n`filter`, and `search` (the same scoping predicates the list endpoint accepts).\n`maxFacetHits` defaults to 10 and is capped at 100.\nThe InstantSearch adapter's\n`searchForFacetValues(requests)` uses this method as its transport.\n\n### Auth\n\n```ts\n// Register\nconst { token, refreshToken, user } = await ayb.auth.register(\n  \"user@example.com\",\n  \"password123\",\n);\n\n// Login\nawait ayb.auth.login(\"user@example.com\", \"password123\");\n\n// Current user\nconst me = await ayb.auth.me();\n\n// Refresh token\nawait ayb.auth.refresh();\n\n// Logout\nawait ayb.auth.logout();\n\n// Password reset\nawait ayb.auth.requestPasswordReset(\"user@example.com\");\nawait ayb.auth.confirmPasswordReset(token, \"newpassword\");\n\n// Email verification\nawait ayb.auth.verifyEmail(token);\nawait ayb.auth.resendVerification();\n\n// First-factor WebAuthn login\nconst challenge = await ayb.auth.beginWebAuthnLogin(\"user@example.com\");\nawait ayb.auth.finishWebAuthnLogin(challenge.challengeId, assertionResponse);\n\n// Browser passkey convenience flow\nawait ayb.auth.signInWithPasskey(\"user@example.com\");\n\n// WebAuthn MFA enrollment and verification\nawait ayb.auth.enrollPasskey(\"Work laptop\");\nawait ayb.auth.verifyPasskey(mfaToken);\n\n// Restore tokens from storage\nayb.setTokens(savedToken, savedRefreshToken);\n```\n\n### Storage\n\n```ts\n// Upload a file to a bucket\nconst file = document.querySelector(\"input[type=file]\").files[0];\nconst result = await ayb.storage.upload(\"avatars\", file);\n// result: { id, bucket, name, size, contentType, createdAt, updatedAt }\n\n// Upload with a custom filename\nawait ayb.storage.upload(\"documents\", blob, \"report.pdf\");\n\n// Get download URL\nconst url = ayb.storage.downloadURL(\"avatars\", \"photo.jpg\");\n// → \"http://localhost:8090/api/storage/avatars/photo.jpg\"\n\n// List files in a bucket\nconst files = await ayb.storage.list(\"avatars\", { prefix: \"user_\", limit: 20 });\n\n// Get a signed URL (time-limited access, default 1 hour)\nconst { url: signedUrl } = await ayb.storage.getSignedURL(\"avatars\", \"photo.jpg\", 3600);\n\n// Delete\nawait ayb.storage.delete(\"avatars\", \"photo.jpg\");\n```\n\n### Realtime\n\n```ts\n// Subscribe to table changes (Server-Sent Events)\nconst unsubscribe = ayb.realtime.subscribe(\n  [\"posts\", \"comments\"],\n  (event) => {\n    console.log(event.action, event.table, event.record);\n    // action: \"create\" | \"update\" | \"delete\"\n  },\n);\n\n// Stop listening\nunsubscribe();\n```\n\n## TypeScript\n\nAll methods accept generic type parameters for full type safety:\n\n```ts\ninterface Post {\n  id: string;\n  title: string;\n  published: boolean;\n  created_at: string;\n}\n\nconst posts = await ayb.records.list<Post>(\"posts\");\n// posts.items is Post[]\n```\n\nExported types include:\n\n`AdminAPIKey`, `AdminAPIKeyListResponse`, `App`, `AppListResponse`, `AuthPersistence`, `AuthResponse`, `AuthStateEvent`, `AuthStateListener`, `BatchOperation`, `BatchResult`, `ClientOptions`, `CreateAdminAPIKeyRequest`, `CreateAdminAPIKeyResponse`, `CreateOAuthClientRequest`, `CreateOAuthClientResponse`, `FacetCounts`, `FacetValueCount`, `FacetValueSearchHit`, `FacetValueSearchParams`, `FacetValueSearchResponse`, `GetParams`, `GraphQLErrorItem`, `GraphQLResponse`, `HealthResponse`, `ListParams`, `ListResponse`, `MagicLinkConfirmResponse`, `MagicLinkRequestResponse`, `MFAPendingAuthResponse`, `OAuthClient`, `OAuthClientListResponse`, `OAuthOptions`, `OAuthProvider`, `OAuthTokenResponse`, `PersistedAuthSession`, `PublicKeyCredentialCreationOptionsJSON`, `PublicKeyCredentialDescriptorJSON`, `PublicKeyCredentialParametersJSON`, `PublicKeyCredentialRequestOptionsJSON`, `PublicKeyCredentialRpEntityJSON`, `PublicKeyCredentialUserEntityJSON`, `RealtimeEvent`, `RotateOAuthClientSecretResponse`, `RpcNotifyOption`, `RpcOptions`, `SearchHit`, `StorageObject`, `UpdateOAuthClientRequest`, `User`, `WebAuthnEnrollBeginResponse`, `WebAuthnEnrollConfirmRequest`, `WebAuthnLoginBeginResponse`, `WebAuthnLoginFinishRequest`, `WebAuthnMFAChallengeResponse`, and `WebAuthnMFAVerifyRequest`.\n\n## Error Handling\n\nAll API errors throw `AYBError` with the HTTP status code:\n\n```ts\nimport { AYBClient, AYBError } from \"@allyourbase/js\";\n\ntry {\n  await ayb.records.get(\"posts\", \"nonexistent\");\n} catch (err) {\n  if (err instanceof AYBError) {\n    console.log(err.status);  // 404\n    console.log(err.message); // \"record not found\"\n  }\n}\n```\n\n## License\n\nMIT\n","readmeFilename":"README.md"}