技能创建器
skill-creator
创建、改进和评估自定义技能,把专业流程转化为可重复使用的 AI 能力。
nhost【数据与研究】Nhost is an open-source backend platform built on PostgreSQL, the Hasura GraphQL engine, an auth service, S3-compatible file storage and serverless functions. Use this skill when asked to set up Nhost, run it locally with the Nhost CLI, sign users in with the JavaScript SDK, query the auto-generated GraphQL API, upload files, write Nhost functions or…
独立 GitHub 快照 · 自动分类 · 以原作者文档为准
Nhost bundles Postgres, Hasura (GraphQL), Auth, Storage and Functions behind one project. Develop locally with the Nhost CLI (Docker based), keep configuration, migrations and Hasura metadata in the nhost/ folder in Git, and deploy to Nhost Cloud or self-host.
The JavaScript SDK is @nhost/nhost-js v4 (rewritten in 2025 from OpenAPI specs). The older packages @nhost/react, @nhost/react-apollo, @nhost/nextjs and the v2/v3 NhostClient({ ... }) style (nhost.auth.signIn, nhost.auth.onAuthStateChanged, { session, error } return values) are deprecated; do not use them in new code. The npm package called nhost (0.1.x) is unrelated and abandoned.
Docker must be running. Install the CLI with one of:
npm install -D @nhost/cli # pinned per project, run with npx nhost
brew install nhost/tap/nhost # macOS / Linux with Homebrew
npx nhost init # creates nhost/ (config, migrations, metadata) and functions/
npx nhost up # starts Postgres, Hasura, Auth, Storage, Functions
npx nhost logs # follow logs
npx nhost down # stop the stack
Local endpoints (HTTPS on the local.nhost.run domain, which resolves to your machine): dashboard https://local.dashboard.local.nhost.run, GraphQL https://local.graphql.local.nhost.run, auth https://local.auth.local.nhost.run, storage https://local.storage.local.nhost.run, functions https://local.functions.local.nhost.run, Postgres postgres://postgres:postgres@localhost:5432/local. nhost login is only needed to pull from or deploy to a Cloud project (nhost init --remote).
npm install @nhost/nhost-js
// src/lib/nhost.ts
import { createClient } from "@nhost/nhost-js";
export const nhost = createClient({
subdomain: process.env.NEXT_PUBLIC_NHOST_SUBDOMAIN ?? "local", // "local" for the CLI stack
region: process.env.NEXT_PUBLIC_NHOST_REGION ?? "local",
});
Every call returns { body, status, headers } and throws a FetchError (with .status and .body) on a non-2xx response, so wrap calls in try/catch instead of checking an error field. Sessions are stored and refreshed automatically by the client.
export async function signUp(email: string, password: string) {
const res = await nhost.auth.signUpEmailPassword({
email,
password,
options: { displayName: "Maria Lopez", metadata: { plan: "free" } },
});
return res.body.session; // may be undefined if email verification is required
}
export async function signIn(email: string, password: string) {
const res = await nhost.auth.signInEmailPassword({ email, password });
return res.body.session; // res.body.mfa is set when MFA is required
}
// OAuth: the SDK builds the URL, you redirect the browser
export function signInWithGoogle() {
window.location.href = nhost.auth.signInProviderURL("google");
}
// Magic link
export const sendMagicLink = (email: string) =>
nhost.auth.signInPasswordlessEmail({ email });
// Current user and changes
const session = nhost.getUserSession(); // StoredSession | null
const unsubscribe = nhost.sessionStorage.onChange((s) => console.log(s?.user?.email));
export async function signOut() {
const s = nhost.getUserSession();
if (s) await nhost.auth.signOut({ refreshToken: s.refreshToken });
}
Create a table (for example posts) in the dashboard or with a migration and Hasura exposes posts, posts_by_pk, posts_aggregate, insert_posts_one, and so on. The SDK sends the user's access token, so Hasura applies that user's role permissions.
const GET_POSTS = /* GraphQL */ `
query GetPosts($limit: Int!, $offset: Int!) {
posts(limit: $limit, offset: $offset, order_by: { created_at: desc },
where: { published: { _eq: true } }) {
id title created_at
}
posts_aggregate(where: { published: { _eq: true } }) { aggregate { count } }
}
`;
export async function getPosts(page = 1, pageSize = 20) {
const res = await nhost.graphql.request<{ posts: { id: string; title: string }[] }>({
query: GET_POSTS,
variables: { limit: pageSize, offset: (page - 1) * pageSize },
});
if (res.body.errors) throw new Error(res.body.errors[0].message); // GraphQL errors arrive with HTTP 200
return res.body.data;
}
nhost.graphql.request covers queries and mutations only. For subscriptions use a GraphQL WebSocket client such as graphql-ws (or Apollo/urql) pointed at nhost.graphql.url, passing the access token from nhost.getUserSession()?.accessToken.
export async function uploadAvatar(file: File) {
const res = await nhost.storage.uploadFiles({ "bucket-id": "default", "file[]": [file] });
return res.body.processedFiles[0]; // { id, name, size, ... }
}
export async function privateDownloadUrl(fileId: string) {
const res = await nhost.storage.getFilePresignedURL(fileId);
return res.body.url; // time-limited URL
}
Buckets (default exists out of the box) and their permissions are set in the dashboard or nhost/config; Storage permissions come from Hasura rules on storage.files.
Every .js/.ts file under functions/ is an HTTP endpoint that exports a default Express-style handler; all HTTP methods hit the same handler. functions/send-welcome-email.ts is served at https://<subdomain>.functions.<region>.nhost.run/v1/send-welcome-email (locally https://local.functions.local.nhost.run/v1/send-welcome-email). From the SDK: nhost.functions.fetch("/send-welcome-email", { method: "POST", body: JSON.stringify({ ... }) }).
Tables are inaccessible to user until permissions exist. Metadata lives in nhost/metadata/databases/default/tables/public_posts.yaml:
table: { name: posts, schema: public }
select_permissions:
- role: user
permission:
columns: [id, title, content, created_at, published, author_id]
filter:
_or:
- published: { _eq: true }
- author_id: { _eq: X-Hasura-User-Id }
insert_permissions:
- role: user
permission:
columns: [title, content, published]
set: { author_id: X-Hasura-User-Id }
update_permissions:
- role: user
permission:
columns: [title, content, published]
filter: { author_id: { _eq: X-Hasura-User-Id } }
Request: "Set up Nhost locally and show me a signed-in user's posts."
npm install -D @nhost/cli && npm install @nhost/nhost-js
npx nhost init && npx nhost up
Then create src/lib/nhost.ts as above with the local defaults, sign in with signIn("maria@northwind.dev", "correct-horse-battery") and call getPosts(). npx nhost up prints the service URLs; if the table has no user select permission, getPosts fails with a Hasura "field 'posts' not found in type: 'query_root'" error, which means the permission is missing, not the table.
Request: "Let users upload a PDF and give them a temporary download link."
Upload with nhost.storage.uploadFiles({ "bucket-id": "default", "file[]": [pdfFile] }), store processedFiles[0].id in a documents table through insert_documents_one, and later call nhost.storage.getFilePresignedURL(id). The returned url expires; request a new one instead of storing it.
@nhost/cli (not nhost) or Homebrew; avoid curl | bash installers.withAdminSession in the SDK) or functions.user and public roles, not as admin.nhost/ (migrations, metadata, nhost.toml) so CI and teammates get the same schema; secrets go in .secrets, which must stay out of Git.createServerClient with a cookie-backed session storage, not the browser client.