一键导入
huuma-ui-remote-functions
Adding server-side mutations and form handling to a Huuma UI app with type-safe .remote.ts functions.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
Adding server-side mutations and form handling to a Huuma UI app with type-safe .remote.ts functions.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
| name | huuma-ui-remote-functions |
| description | Adding server-side mutations and form handling to a Huuma UI app with type-safe .remote.ts functions. |
Use this skill when the agent is adding server-side mutations, form submissions, or backend calls in a Huuma UI app.
.remote.ts files.export async function name(...) (lint async-remote-functions).default remote function.export const foo = ... and export { foo } are not reliably recognized by the current bundler stub; prefer named export async function..remote.ts file into an island (.client.tsx).fetch to POST /_huuma/remote/<hash>/<name>.void / undefined resolves to undefined on the client (the server responds 204 No Content). This is the correct way to express "fire and forget" or "acknowledged mutation" — do not return undefined accidentally.Error carrying name and message from the server. Wrap calls in try/catch.The server (packRemoteFunctions in src/platform/server/pack/pack.ts) normalizes the return before sending:
| Return value | Server response | Client receives |
|---|---|---|
undefined (or void) | 204 No Content | undefined |
null | 200 body null | null |
| Any JSON-serializable value | 200 body JSON.stringify(res) | the deserialized value |
function, Symbol, Symbol-keyed-only object | 500 RemoteFunctionSerializationError | rejected Error |
BigInt, circular reference (throws in JSON.stringify) | 500 RemoteFunctionSerializationError | rejected Error |
The void/null distinction is preserved end-to-end: void → undefined, explicit null → null.
Current behavior (the success path is raw JSON; the error path uses HTTP status + a small JSON body):
2xx): the client stub parses the body as JSON and resolves. The success body shape is not enveloped — JSON.stringify(res) is sent directly. Backward compatible.204: the client stub resolves undefined without parsing.2xx (including 500 from a thrown remote function or an unserializable return): the client stub reads the JSON body and throws a reconstructed Error with:
err.name ← body.name (e.g. "RemoteFunctionSerializationError"), falling back to "RemoteFunctionError".err.message ← body.message, falling back to "Remote function \"<name>\" failed (HTTP <status>)".502, HTML error page), the fallback message still carries the status code.name only survives for serialization errors. The only server path that emits a name field is the unserializable-return 500 produced inside executeRemoteFunction. Every other error — a user-thrown error inside the remote function, NotFoundException (function not found), and @huuma/validate body-schema failures — propagates to the framework's global handleException (@huuma/route), which emits { status, message, error? } with no name. So for all real application errors the client's err.name falls back to the generic "RemoteFunctionError"; only err.message carries useful information. Closing this gap (wrapping user-thrown errors with a structured { name, message, ... } body before they reach handleException) is the first Round 1 work item.TypeError: Failed to fetch and are not wrapped into a RemoteFunctionError yet. This is a known gap.The error body today carries only { name, message }. Fields like stack, cause, code, or validation fields are not yet transported. Treat the body shape as provisional.
@huuma/validate inside the remote-handler shipped by @huuma/ui/server/pack.{ remoteFunction: string, args?: unknown[] }.remoteFunction on the imported module and invokes it with the args.remoteFunctionsSchema.parse(body) throws and is handled by the framework's global error handler — not yet by the structured error path above. The same applies to NotFoundException ("Remote function not found"). Both are open improvements; do not rely on a structured body for these yet.Error — its name and message will reach the client.PUBLIC_ env vars are shimmed to the client.name asymmetry: the only server path that emits a name field is the unserializable-return 500 from executeRemoteFunction. Every other error (user-thrown, NotFoundException, @huuma/validate schema failure) goes through the framework's global handleException in @huuma/route, which emits { status, message, error? } with no name. So all real application errors collapse to the generic "RemoteFunctionError" on the client; only message survives. Wrapping user-thrown errors with { name, message, ... } is the first Round 1 work item.TypeError: Failed to fetch) into RemoteFunctionError; callers see the raw browser error.name and message (and only name on the serialization-error path). stack, cause, custom subclass properties, and validation fields are not yet transported. Dev/prod redaction policy for stack is not yet defined.Error with name/message set — there is no instanceof-checkable RemoteFunctionError class exported from @huuma/ui yet.improvements.md.export async function.void/undefined intentionally. Watch for accidental BigInt, function, Symbol, or circular references — they produce a 500 RemoteFunctionSerializationError..remote.ts file is imported only from islands (or server-safe code), not from server components that will ship to the client.try/catch that handles the reconstructed Error (use error.name to distinguish RemoteFunctionSerializationError from your own thrown errors).undefined for void returns, not null.Diagnosing and fixing Huuma UI lint violations and runtime errors after they occur.
Editing root.tsx, entry points, dev/prod workflow, environment variables, and the Huuma UI build pipeline.
Building or navigating a Huuma UI app — file conventions, server/client boundary rules, dev workflow, and where to look for authoritative answers.
Adding translations and multilingual routing to a Huuma UI app with setupI18n, useI18n middleware, and the T component.
Adding client interactivity to a Huuma UI app with `.client.tsx` islands, on-* events, refs, and hydration boundaries.
Adding Huuma UI pages, layouts, routes, dynamic params, data loading with resolvers, metadata, and middleware.