createNaru
함수createNaru(options?: { site?: string }): NaruClientCreates a client bound to one site.
Admin
인터페이스interface Admin extends SiteCode, LiveQueriesThe owner signed in on this page. Its queries and mutations see ctx.member null and ctx.owner true, whatever collections this sign-in approved, and are not counted against the site's budget.
media: { upload( file: Blob | File, options?: { onProgress?: ( progress: | { phase: "preparing" } | { loaded: number; phase: "uploading"; total: number } | { phase: "finishing" }, ) => void; signal?: AbortSignal; }, ): Promise<{ contentType: string; id: string; name: string; size: number; url: string; }>; }batch( writes: readonly ( | { collection: string; set: { condition?: WriteCondition; data: unknown; id: string }; } | { collection: string; delete: { condition?: { revision: Revision }; id: string }; } )[], options?: { signal?: AbortSignal }, ): Promise< ({ createdAt: string; id: string; revision: Revision; updatedAt: string; } | null)[] >Commits every write or none. Conditions guard individual documents. Does not retry. Resolves, in the order written, with what each
setstored andnullfor eachdelete.collection<T = Json>(name: string): AdminCollection<T>signOut(): Promise<void>This handle stops working at once, even if the revoke request fails.
AdminCollection
인터페이스interface AdminCollection<T = Json> extends PublicCollection<T>delete( id: string, options?: { condition?: { revision: Revision }; signal?: AbortSignal }, ): Promise<void>Deleting a missing document succeeds unless a condition was supplied.
set( id: string, data: T, options?: { condition?: WriteCondition; signal?: AbortSignal }, ): Promise<Document<T>>Replaces the whole document or creates it.
Document
인터페이스interface Document<T = Json>A read or successful write: user data stays separate from server metadata.
createdAt: stringdata: Tid: stringrevision: RevisionupdatedAt: string
ListOptions
인터페이스interface ListOptionsafter?: string | nullOpaque cursor returned by the preceding page.
filter?: FilterincludeTotal?: booleansignal?: AbortSignalsize?: numberDefault 50; maximum 100.
sort?: Sort
Live
인터페이스interface LiveA live query, kept current until closed.
close(): void
LiveQueries
인터페이스interface LiveQueriesLive queries: a query's answer, kept current.
subscribe<R = Json>( name: string, args: Json | undefined, onResult: (result: R) => void, options?: { onError(error: NaruError): void }, ): LiveRuns
"<module/path>:<query>"from the site's_naru/queries/asquery()does, callsonResultwith its answer, and again whenever a write changes a table it read and the answer with it, until closed. After the connection drops it is asked again, so the latest answer arrives once it is back. A failure, now or later, goes toonError. A connection holds at most 20.argsleftundefinedisnull, asquery()'s are.
Member
인터페이스interface Member extends SiteCode, LiveQueriesA visitor signed in to this site with their Naru account.
id: stringThis member's ID on this site, the same on every visit:
ctx.member.idin the site's queries and mutations. It is not their Naru account name.media: { upload( file: Blob | File, options?: { onProgress?: ( progress: | { phase: "preparing" } | { loaded: number; phase: "uploading"; total: number } | { phase: "finishing" }, ) => void; signal?: AbortSignal; }, ): Promise<{ contentType: string; id: string; name: string; size: number; url: string; }>; }signOut(): Promise<void>Signs out on every page of this site. This handle stops working at once, even if the revoke request fails.
NaruClient
인터페이스interface NaruClient extends SiteCode, LiveQueriesA page's client. Its queries and mutations run as a visitor, signed in to nothing: they see ctx.member null and ctx.owner false, are limited per visitor address, and count against the site's budget.
auth: { session(): Promise<Admin | null>; signIn(options?: { collections?: readonly string[] }): Promise<void>; }members: { session(): Promise<Member | null>; signIn(): Promise<void> }collection<T = Json>(name: string): PublicCollection<T>Visitor access, even when signed in.
Page
인터페이스interface Page<T = Json>documents: Document<T>[]nextCursor: string | nulltotalCount?: number
PublicCollection
인터페이스interface PublicCollection<T = Json>add(data: T, options?: { signal?: AbortSignal }): Promise<Document<T>>count(options?: { filter?: Filter; signal?: AbortSignal; }): Promise<number>How many documents match
filter, or the whole collection.get(id: string, options?: { signal?: AbortSignal }): Promise<Document<T>>list(options?: ListOptions): Promise<Page<T>>pages(options?: ListOptions): AsyncIterable<Page<T>>Every page of a query in turn, following
nextCursorfromafter(or the start). Not a snapshot: writes in between can shift later pages.
SiteCode
인터페이스interface SiteCodeThe site's queries and mutations: its own code over its own tables, which its _naru/migrations/ create. Anyone may call them, signed in or not; the code decides what each caller may see and do from ctx.member and ctx.owner.
mutate<R = Json>( name: string, args?: Json, options?: { signal?: AbortSignal }, ): Promise<R>Runs an export of
_naru/mutations/<module/path>.jsin one transaction: what it wrote is kept only if it returns, and a throw,ctx.failor a limit changes nothing.query<R = Json>( name: string, args?: Json, options?: { signal?: AbortSignal }, ): Promise<R>Runs
"<module/path>:<name>", an export of the site's_naru/queries/<module/path>.js, and resolves with what it returned. A query only reads (ctx.sql), so it counts against the caller's read budget.
NaruError
클래스class NaruError extends ErrorA Naru operation that could not be completed. Check it with instanceof.
message is a short Korean sentence a visitor can read, so a page may show it as is (status.textContent = error.message): a query's or mutation's own ctx.fail message, or Naru's wording for code. Naru's English account of what went wrong, for developers, is error.cause.message.
code: NaruErrorCodedetails?: JsonThe JSON a query or mutation passed as
ctx.fail(code, message, details), such as{ reason: "sold_out" }; or, when a member's request is refused because the site has not approved them,{ membership: "pending" }or{ membership: "banned" }; or, for aCONFLICTbecause another document already holds a value of one of the collection's unique fields,{ unique: "<field>" }. Undefined for every other failure.
Filter
타입type Filter = Record<
string,
| string
| number
| boolean
| null
| {
gt?: string | number;
gte?: string | number;
lt?: string | number;
lte?: string | number;
}
>Top-level user fields, combined with AND.
Json
타입type Json =
null | boolean | number | string | Json[] | { [key: string]: Json }NaruErrorCode
타입type NaruErrorCode =
| "CONFLICT"
| "QUOTA_EXCEEDED"
| "AUTH_REQUIRED"
| "ACCESS_DENIED"
| "NOT_FOUND"
| "RATE_LIMITED"
| "INVALID_REQUEST"
| "UNAVAILABLE"Why an operation failed. The list is closed for v1: a code a later server adds reaches this version as the nearest code here.
Revision
타입type Revision = string & { [revisionBrand]: true }An opaque concurrency token. Store and return it unchanged.
Sort
타입type Sort =
| readonly [
readonly [
string | { metadata: "id" | "createdAt" | "updatedAt" },
"asc" | "desc",
],
]
| readonly [
readonly [
string | { metadata: "id" | "createdAt" | "updatedAt" },
"asc" | "desc",
],
readonly [
string | { metadata: "id" | "createdAt" | "updatedAt" },
"asc" | "desc",
],
]One or two keys: a user field by name, or document metadata.
WriteCondition
타입type WriteCondition = { revision: Revision } | { absent: true }Write only at this revision, or only if the document does not exist yet.