Initial Dever 0.0.1

This commit is contained in:
Codex committed 2026-11-03 03:32:07 +00:00
commit 81233d098c
1479 files changed
+163782

No files matched your search

+42
View File
@@ -0,0 +1,42 @@
# 标准库
提供文本、数值、网络、数据库和并发能力,直接按包名调用,无需 import。签名从源码读取,主题说明解释用途和特殊规则。
- [十进制](doc/decimal.md)
- [Cookie](doc/dever-api-cookie.md)
- [请求信息](doc/dever-api-request.md)
- [API 错误](doc/dever-api.md)
- [业务权限](doc/dever-auth-capability.md)
- [角色与权限](doc/dever-auth-roles.md)
- [当前身份](doc/dever-auth-session.md)
- [身份声明](doc/dever-auth-values.md)
- [字节](doc/dever-bytes.md)
- [密码与摘要](doc/dever-crypto.md)
- [数据库错误](doc/dever-database.md)
- [HTTP 调用](doc/dever-http-call.md)
- [流式响应](doc/dever-http-live.md)
- [HTTP 连接池](doc/dever-http-pool.md)
- [流式请求](doc/dever-http-stream.md)
- [HTTP 数据结构](doc/dever-http-value.md)
- [文本标识](doc/dever-id.md)
- [文件与标准输出](doc/dever-io.md)
- [JSON 文档](doc/dever-json-value.md)
- [JSON](doc/dever-json.md)
- [TCP 监听](doc/dever-net-listener.md)
- [TCP 连接](doc/dever-net-socket.md)
- [进程与命令](doc/dever-process.md)
- [当前站点](doc/dever-site.md)
- [SSE](doc/dever-sse.md)
- [上传存储](doc/dever-storage.md)
- [异步等待](doc/dever-task.md)
- [日历结果](doc/dever-time-calendar.md)
- [时钟](doc/dever-time-clock.md)
- [日期与时长](doc/dever-time-operations.md)
- [同步等待](doc/dever-time.md)
- [TLS](doc/dever-tls.md)
- [WebSocket](doc/dever-websocket.md)
- [浮点数](doc/float.md)
- [整数](doc/int.md)
- [数学](doc/math.md)
- [文本](doc/text.md)
- [UUID](doc/uuid.md)
+15
View File
@@ -0,0 +1,15 @@
public round(value: Decimal, places: Int) (result: Decimal) {
result = dever.system.decimalRound(value, places)
}
public parse(value: Text) (result: Decimal?) {
result = dever.system.decimalParse(value)
}
public toText(value: Decimal) (result: Text) {
result = dever.system.decimalToText(value)
}
public fromInt(value: Int) (result: Decimal) {
result = dever.system.decimalFromInt(value)
}
+14
View File
@@ -0,0 +1,14 @@
public type Error {
error Invalid
error Unauthorized
error Forbidden
error NotFound
error Conflict
error TooManyRequests
}
public require(condition: true, error: Error) () pure recover("条件成立时不触发指定失败") {}
public require(condition: false, error: Error) () pure recover("条件成立时不触发指定失败") {
fail(error)
}
+26
View File
@@ -0,0 +1,26 @@
public type SameSite {
Strict
Lax
None
}
public type CookieOptions {
path: Text
domain: Text?
same_site: SameSite
secure: Bool
http_only: Bool
max_age: Int?
}
public secureCookieOptions() (options: CookieOptions) pure {
options = CookieOptions { path = "/", domain = null, same_site = SameSite.Lax, secure = true, http_only = true, max_age = null }
}
public cookie(name: Text) (value: Text?) { value = dever.system.apiCookie(name) }
public secretCookie(name: Text) (value: Secret?) { value = dever.system.apiSecretCookie(name) }
public setCookie(name: Text, value: Text, options: CookieOptions) () { dever.system.apiSetCookie(name, value, options) }
public setSecretCookie(name: Text, value: Secret, options: CookieOptions) () { dever.system.apiSetSecretCookie(name, value, options) }
+11
View File
@@ -0,0 +1,11 @@
public requestId() (value: Text) { value = dever.system.apiRequestId() }
public method() (value: Text) { value = dever.system.apiMethod() }
public path() (value: Text) { value = dever.system.apiPath() }
public clientAddress() (value: Text) { value = dever.system.apiClientAddress() }
public header(name: Text) (value: Text?) { value = dever.system.apiHeader(name) }
public setHeader(name: Text, value: Text) () { dever.system.apiSetHeader(name, value) }
+11
View File
@@ -0,0 +1,11 @@
public hasProtectedRoles(user_id: Int) (value: Bool) {
value = dever.system.authHasProtectedRoles(user_id)
}
public registerCapability(id: Uuid) (key: Text) {
key = dever.system.authRegisterCapability(id)
}
public removeCapability(id: Uuid) () {
dever.system.authRemoveCapability(id)
}
+43
View File
@@ -0,0 +1,43 @@
public type Permission {
key: Text
component: Text
domain: Text
site: Text
action: Text
method: Text
kind: Text
}
public type Role {
id: Text
site: Text
name: Text
all_permissions: Bool
enabled: Bool
protected: Bool
permission_keys: List<Text>
}
public permissions() (values: List<Permission>) { values = dever.system.authPermissions() }
public currentPermissions() (values: List<Permission>) { values = dever.system.authCurrentPermissions() }
public roles() (values: List<Role>) { values = dever.system.authRoles() }
public role(id: Text) (value: Role?) { value = first(dever.system.authRole(id)) }
public userRoles(user_id: Int) (values: List<Role>) { values = dever.system.authUserRoles(user_id) }
public isOwner(user_id: Int) (value: Bool) { value = reduce(owner, userRoles(user_id), false) }
public saveRole(id: Text, name: Text, all_permissions: Bool, permission_keys: List<Text>) () { dever.system.authSaveRole(id, name, all_permissions, permission_keys) }
public grantRole(user_id: Int, role_id: Text) () { dever.system.authGrantRole(user_id, role_id) }
public revokeRole(user_id: Int, role_id: Text) () { dever.system.authRevokeRole(user_id, role_id) }
public disableRole(role_id: Text) () { dever.system.authDisableRole(role_id) }
public deleteRole(role_id: Text) () { dever.system.authDeleteRole(role_id) }
owner(role: Role, found: Bool) (value: Bool) pure { value = found or role.protected }
+13
View File
@@ -0,0 +1,13 @@
public id() (value: Text) { value = dever.system.authId() }
public session() (value: Text) { value = dever.system.authSession() }
public userId() (value: Int?) { value = dever.system.authUserId() }
public tenantId() (value: Int?) { value = dever.system.authTenantId() }
public issue(subject: Text, session: Text, tenant: Text?) (value: Secret) { value = dever.system.authIssue(subject, session, tenant) }
public issueCookie(subject: Text, session: Text, tenant: Text?) () { dever.system.authIssueCookie(subject, session, tenant) }
public clearCookie() () { dever.system.authClearCookie() }
+6
View File
@@ -0,0 +1,6 @@
public type Claims {
subject: Text
session: Text
tenant: Text?
site: Text
}
+51
View File
@@ -0,0 +1,51 @@
public type DecodeResult {
Decoded(text: Text)
error Failed(message: Text)
}
public type BufferResult {
Ready(bytes: Bytes)
error Failed(message: Text)
}
public fromText(text: Text) (bytes: Bytes) {
bytes = dever.system.bytesFromText(text)
}
public toText(bytes: Bytes) (text: Text) {
text = decoded(dever.system.bytesToText(bytes))
}
decoded(result: DecodeResult.Decoded(value)) (text: Text) {
text = value
}
decoded(result: DecodeResult.Failed(message)) (text: Text) {
fail(DecodeResult.Failed(message))
}
public fromInts(values: List<Int>) (bytes: Bytes) {
bytes = ready(dever.system.bytesFromInts(values))
}
public length(bytes: Bytes) (length: Int) {
length = dever.system.bytesLength(bytes)
}
public at(bytes: Bytes, index: Int) (value: Int?) {
value = dever.system.bytesAt(bytes, index)
}
public slice(bytes: Bytes, start: Int, end: Int) (result: Bytes) {
result = ready(dever.system.bytesSlice(bytes, start, end))
}
ready(result: BufferResult.Ready(bytes)) (value: Bytes) {
value = bytes
}
ready(result: BufferResult.Failed(message)) (value: Bytes) {
fail(BufferResult.Failed(message))
}
public concat(left: Bytes, right: Bytes) (bytes: Bytes) {
bytes = dever.system.bytesConcat(left, right)
}
+29
View File
@@ -0,0 +1,29 @@
public type TokenResult { Ready(value: Secret)
error Failed(message: Text) }
public type HashResult { Ready(value: Text)
error Failed(message: Text) }
public type VerifyResult { Ready(value: Bool)
error Failed(message: Text) }
public token(bytes: Int) (value: Secret) { value = tokenValue(dever.system.cryptoToken(bytes)) }
public passwordHash(password: Secret) (value: Text) { value = hashValue(dever.system.cryptoPasswordHash(password)) }
public passwordVerify(password: Secret, hash: Text) (value: Bool) { value = verifyValue(dever.system.cryptoPasswordVerify(password, hash)) }
public sha256(bytes: Bytes) (value: Bytes) pure { value = dever.system.cryptoSha256(bytes) }
public hmacSha256(key: Secret, bytes: Bytes) (value: Bytes) pure { value = dever.system.cryptoHmacSha256(key, bytes) }
public constantTimeEq(left: Bytes, right: Bytes) (equal: Bool) pure { equal = dever.system.cryptoConstantTimeEq(left, right) }
tokenValue(result: TokenResult.Ready(value)) (secret: Secret) { secret = value }
tokenValue(result: TokenResult.Failed(message)) (secret: Secret) { fail(TokenResult.Failed(message)) }
hashValue(result: HashResult.Ready(value)) (hash: Text) { hash = value }
hashValue(result: HashResult.Failed(message)) (hash: Text) { fail(HashResult.Failed(message)) }
verifyValue(result: VerifyResult.Ready(value)) (valid: Bool) { valid = value }
verifyValue(result: VerifyResult.Failed(message)) (valid: Bool) { fail(VerifyResult.Failed(message)) }
+12
View File
@@ -0,0 +1,12 @@
public type Error {
error Pool(message: Text)
error PoolExhausted(message: Text)
error Connection(message: Text)
error Timeout(message: Text)
error Cancelled(message: Text)
error Database(message: Text)
error Constraint(message: Text)
error NotFound(message: Text)
error InvalidData(message: Text)
error Migration(message: Text)
}
+29
View File
@@ -0,0 +1,29 @@
public header(name: Text, value: Text) (result: Header) {
result = Header { name = text.lower(name), value = dever.bytes.fromText(value) }
}
public headerValue(headers: List<Header>, name: Text) (value: Bytes?) {
value = foundHeader(find(namedHeader, headers, text.lower(name)))
}
namedHeader(header: Header, name: Text) (matches: Bool) {
matches = text.lower(header.name) == name
}
foundHeader(header: null) (value: Bytes?) { value = null }
foundHeader(header: Header) (value: Bytes?) { value = header.value }
public serve(route: handler(request: Request) (response: Response), listener: dever.system.Listener, limits: Limits) () {
dever.system.httpServe(route, listener, limits)
}
public send(address: Text, port: Int, request: Request, limits: Limits) (response: Response) {
response = readResponse(dever.system.httpSend(address, port, request, limits))
}
public serveTls(route: handler(request: Request) (response: Response), listener: dever.system.Listener, limits: Limits, tls: dever.system.ServerTls) () {
dever.system.httpServeTls(route, listener, limits, tls)
}
readResponse(result: ResponseResult.Read(response)) (value: Response) { value = response }
readResponse(result: ResponseResult.Failed(message)) (value: Response) { fail(ResponseResult.Failed(message)) }
+39
View File
@@ -0,0 +1,39 @@
public type LiveLimits {
chunk_bytes: Int
idle_ms: Int
heartbeat_ms: Int
}
public defaultLiveLimits() (result: LiveLimits) {
result = LiveLimits { chunk_bytes = 65536, idle_ms = 60000, heartbeat_ms = 15000 }
}
public serveLive(route: handler(request: Request, reply: dever.system.HttpReply) (), listener: dever.system.Listener, limits: Limits, live: LiveLimits) () {
dever.system.httpServeLive(route, listener, limits, live)
}
public serveLiveTls(route: handler(request: Request, reply: dever.system.HttpReply) (), listener: dever.system.Listener, limits: Limits, live: LiveLimits, tls: dever.system.ServerTls) () {
dever.system.httpServeLiveTls(route, listener, limits, live, tls)
}
public respond(reply: dever.system.HttpReply, response: Response) () {
wroteLive(dever.system.httpRespond(reply, response))
}
public start(reply: dever.system.HttpReply, status: Int, headers: List<Header>) () {
wroteLive(dever.system.httpStart(reply, status, headers))
}
public write(reply: dever.system.HttpReply, bytes: Bytes) () {
wroteLive(dever.system.httpWrite(reply, bytes))
}
public finish(reply: dever.system.HttpReply) () {
closedLive(dever.system.httpFinish(reply))
}
wroteLive(result: dever.io.WriteResult.Done) () {}
wroteLive(result: dever.io.WriteResult.Failed(message)) () { fail(dever.io.WriteResult.Failed(message)) }
closedLive(result: dever.io.CloseResult.Closed) () {}
closedLive(result: dever.io.CloseResult.Failed(message)) () { fail(dever.io.CloseResult.Failed(message)) }
+32
View File
@@ -0,0 +1,32 @@
public type PoolLimits {
idle_ms: Int
chunk_bytes: Int
read_ms: Int
}
public type ClientResult {
Ready(client: dever.system.HttpClient)
error Failed(message: Text)
}
public defaultPoolLimits() (limits: PoolLimits) {
limits = PoolLimits { idle_ms = 10000, chunk_bytes = 65536, read_ms = 60000 }
}
public client(origin: Text, tls: dever.system.ClientTls, limits: Limits, pool: PoolLimits) (client: dever.system.HttpClient) {
client = readClient(dever.system.httpClient(origin, tls, limits, pool))
}
public request(client: dever.system.HttpClient, request: Request) (response: Response) {
response = readResponse(dever.system.httpRequest(client, request))
}
public closeClient(client: dever.system.HttpClient) () {
closedClient(dever.system.httpCloseClient(client))
}
readClient(result: ClientResult.Ready(value)) (client: dever.system.HttpClient) { client = value }
readClient(result: ClientResult.Failed(message)) (client: dever.system.HttpClient) { fail(ClientResult.Failed(message)) }
closedClient(result: dever.io.CloseResult.Closed) () {}
closedClient(result: dever.io.CloseResult.Failed(message)) () { fail(dever.io.CloseResult.Failed(message)) }
+28
View File
@@ -0,0 +1,28 @@
public type StreamRequest {
method: Text
target: Text
headers: List<Header>
body: AsyncStream<dever.io.ReadEvent>
}
public type StreamResponse {
status: Int
headers: List<Header>
body: AsyncStream<dever.io.ReadEvent>
}
public type StreamResponseResult {
Read(response: StreamResponse)
error Failed(message: Text)
}
public open(client: dever.system.HttpClient, request: Request) (response: StreamResponse) {
response = readStreamResponse(dever.system.httpOpen(client, request))
}
public openStream(client: dever.system.HttpClient, request: StreamRequest) (response: StreamResponse) {
response = readStreamResponse(dever.system.httpOpenStream(client, request))
}
readStreamResponse(result: StreamResponseResult.Read(value)) (response: StreamResponse) { response = value }
readStreamResponse(result: StreamResponseResult.Failed(message)) (response: StreamResponse) { fail(StreamResponseResult.Failed(message)) }
+44
View File
@@ -0,0 +1,44 @@
public type Header {
name: Text
value: Bytes
}
public type Request {
method: Text
target: Text
headers: List<Header>
body: Bytes
}
public type Response {
status: Int
headers: List<Header>
body: Bytes
}
public type Limits {
header_bytes: Int
body_bytes: Int
timeout_ms: Int
connections: Int
http2: Http2Limits?
}
public type Http2Limits {
streams: Int
stream_window_bytes: Int
connection_window_bytes: Int
}
public type ResponseResult {
Read(response: Response)
error Failed(message: Text)
}
public defaultLimits() (result: Limits) {
result = Limits { header_bytes = 8192, body_bytes = 1048576, timeout_ms = 5000, connections = 32, http2 = null }
}
public defaultHttp2Limits() (result: Http2Limits) {
result = Http2Limits { streams = 16, stream_window_bytes = 65535, connection_window_bytes = 262144 }
}
+7
View File
@@ -0,0 +1,7 @@
public fromText(text: Text) (id: Id) {
id = dever.system.idFromText(text)
}
public toText(id: Id) (text: Text) {
text = dever.system.idToText(id)
}
+102
View File
@@ -0,0 +1,102 @@
public type OpenResult {
Opened(file: dever.system.File)
error Failed(message: Text)
}
public type ReadState {
Read(bytes: Bytes)
End
}
public type ReadResult {
Done(state: ReadState)
error Failed(message: Text)
}
type SystemReadResult {
Read(bytes: Bytes)
End
error Failed(message: Text)
}
public type WriteResult {
Done
error Failed(message: Text)
}
public type CloseResult {
Closed
error Failed(message: Text)
}
public type ReadEvent {
Chunk(bytes: Bytes)
error Failed(message: Text)
}
public type ReadStreamResult {
Streaming(stream: Stream<ReadEvent>)
error Failed(message: Text)
}
public println(text: Text) () {
dever.system.stdoutWrite(text + "\n")
}
public open(path: Text) (file: dever.system.File) {
file = opened(dever.system.fileOpen(path))
}
public create(path: Text) (file: dever.system.File) {
file = opened(dever.system.fileCreate(path))
}
opened(result: OpenResult.Opened(file)) (value: dever.system.File) {
value = file
}
opened(result: OpenResult.Failed(message)) (value: dever.system.File) {
fail(OpenResult.Failed(message))
}
public read(file: dever.system.File, limit: Int) (state: ReadState) {
state = readState(dever.system.fileRead(file, limit))
}
readState(result: SystemReadResult.Read(bytes)) (state: ReadState) {
state = ReadState.Read(bytes)
}
readState(result: SystemReadResult.End) (state: ReadState) {
state = ReadState.End
}
readState(result: SystemReadResult.Failed(message)) (state: ReadState) {
fail(ReadResult.Failed(message))
}
public write(file: dever.system.File, bytes: Bytes) () {
wrote(dever.system.fileWrite(file, bytes))
}
wrote(result: WriteResult.Done) () {}
wrote(result: WriteResult.Failed(message)) () {
fail(WriteResult.Failed(message))
}
public close(file: dever.system.File) () {
closed(dever.system.fileClose(file))
}
closed(result: CloseResult.Closed) () {}
closed(result: CloseResult.Failed(message)) () {
fail(CloseResult.Failed(message))
}
public chunks(file: dever.system.File, limit: Int) (stream: Stream<ReadEvent>) {
stream = readStream(dever.system.fileChunks(file, limit))
}
readStream(result: ReadStreamResult.Streaming(stream)) (value: Stream<ReadEvent>) {
value = stream
}
readStream(result: ReadStreamResult.Failed(message)) (value: Stream<ReadEvent>) {
fail(ReadStreamResult.Failed(message))
}
+97
View File
@@ -0,0 +1,97 @@
public type JsonResult {
Parsed(value: Json)
error Failed(message: Text)
}
public type TextResult {
Read(value: Text)
error Failed(message: Text)
}
public type IntResult {
Read(value: Int)
error Failed(message: Text)
}
public fromText(source: Text) (value: Json) {
value = parsed(dever.system.jsonFromText(source))
}
public toText(value: Json) (source: Text) {
source = dever.system.jsonToText(value)
}
public setProperty(value: Json, name: Text, child: Json) (result: Json) {
result = parsed(dever.system.jsonSetProperty(value, name, child))
}
public propertyValue(value: Json, name: Text) (result: Json?) {
result = propertyResult(dever.system.jsonProperty(value, name))
}
public asText(value: Json) (source: Text) {
source = textValue(dever.system.jsonAsText(value))
}
public asInteger(value: Json) (number: Int) {
number = intValue(dever.system.jsonAsInteger(value))
}
public encode(value: JsonResult) (result: Json) {
result = parsed(value)
}
parsed(result: JsonResult.Parsed(value)) (json: Json) { json = value }
parsed(result: JsonResult.Failed(message)) (json: Json) { fail(JsonResult.Failed(message)) }
public parse(source: Text) (document: dever.json.value.Document) {
document = parsedDocument(dever.system.jsonParse(source))
}
public stringify(document: dever.json.value.Document) (text: Text) {
text = written(dever.system.jsonStringify(document))
}
public node(document: dever.json.value.Document, id: Int) (value: dever.json.value.Value?) {
value = dever.system.jsonNode(document, id)
}
public property(document: dever.json.value.Document, id: Int, name: Text) (value: Int?) {
value = dever.system.jsonDocumentProperty(document, id, name)
}
public element(document: dever.json.value.Document, id: Int, index: Int) (value: Int?) {
value = dever.system.jsonElement(document, id, index)
}
parsedDocument(result: dever.json.value.ParseResult.Parsed(document)) (value: dever.json.value.Document) { value = document }
parsedDocument(result: dever.json.value.ParseResult.Failed(position, message)) (value: dever.json.value.Document) { fail(dever.json.value.ParseResult.Failed(position, message)) }
written(result: dever.json.value.WriteResult.Written(text)) (value: Text) { value = text }
written(result: dever.json.value.WriteResult.Failed(node, message)) (value: Text) { fail(dever.json.value.WriteResult.Failed(node, message)) }
textValue(result: TextResult.Read(value)) (text: Text) { text = value }
textValue(result: TextResult.Failed(message)) (text: Text) { fail(TextResult.Failed(message)) }
intValue(result: IntResult.Read(value)) (number: Int) { number = value }
intValue(result: IntResult.Failed(message)) (number: Int) { fail(IntResult.Failed(message)) }
public type PropertyResult {
Found(value: Json?)
error Failed(message: Text)
}
propertyResult(result: PropertyResult.Found(child)) (value: Json?) { value = child }
propertyResult(result: PropertyResult.Failed(message)) (value: Json?) { fail(PropertyResult.Failed(message)) }
public object(fields: Map<Text, Json>) (value: Json) { value = parsed(dever.system.jsonObject(fields)) }
public array(values: List<Json>) (value: Json) { value = dever.json.encode(values) }
public string(source: Text) (value: Json) { value = dever.json.encode(source) }
public integer(source: Int) (value: Json) { value = dever.json.encode(source) }
public boolean(source: Bool) (value: Json) { value = dever.json.encode(source) }
public nullValue() (value: Json) { value = fromText("null") }
+23
View File
@@ -0,0 +1,23 @@
public type Value {
Null
Boolean(value: Bool)
Number(raw: Text)
String(text: Text)
Array(children: List<Int>)
Object(members: Map<Text, Int>)
}
public type Document {
root: Int
nodes: List<Value>
}
public type ParseResult {
Parsed(document: Document)
error Failed(position: Int, message: Text)
}
public type WriteResult {
Written(text: Text)
error Failed(node: Int, message: Text)
}
+35
View File
@@ -0,0 +1,35 @@
public type ListenResult {
Listening(listener: dever.system.Listener)
error Failed(message: Text)
}
public type PortResult {
Bound(port: Int)
error Failed(message: Text)
}
public listen(host: Text, port: Int) (listener: dever.system.Listener) {
listener = listening(dever.system.tcpListen(host, port))
}
listening(result: ListenResult.Listening(listener)) (value: dever.system.Listener) { value = listener }
listening(result: ListenResult.Failed(message)) (value: dever.system.Listener) { fail(ListenResult.Failed(message)) }
public accept(listener: dever.system.Listener) (socket: dever.system.Socket) {
socket = connected(dever.system.tcpAccept(listener))
}
public port(listener: dever.system.Listener) (port: Int) {
port = bound(dever.system.tcpPort(listener))
}
bound(result: PortResult.Bound(port)) (value: Int) { value = port }
bound(result: PortResult.Failed(message)) (value: Int) { fail(PortResult.Failed(message)) }
public closeListener(listener: dever.system.Listener) () {
closed(dever.system.tcpCloseListener(listener))
}
public connections(listener: dever.system.Listener) (result: AsyncStream<ConnectResult>) {
result = dever.system.tcpConnections(listener)
}
+59
View File
@@ -0,0 +1,59 @@
public type ConnectResult {
Connected(socket: dever.system.Socket)
error Failed(message: Text)
}
public type ReadStreamResult {
Streaming(stream: AsyncStream<dever.io.ReadEvent>)
error Failed(message: Text)
}
type SystemReadResult {
Read(bytes: Bytes)
End
error Failed(message: Text)
}
public connect(host: Text, port: Int) (socket: dever.system.Socket) {
socket = connected(dever.system.tcpConnect(host, port))
}
public connectTimeout(address: Text, port: Int, milliseconds: Int) (socket: dever.system.Socket) {
socket = connected(dever.system.tcpConnectTimeout(address, port, milliseconds))
}
connected(result: ConnectResult.Connected(socket)) (value: dever.system.Socket) { value = socket }
connected(result: ConnectResult.Failed(message)) (value: dever.system.Socket) { fail(ConnectResult.Failed(message)) }
public read(socket: dever.system.Socket, limit: Int) (state: dever.io.ReadState) {
state = readState(dever.system.tcpRead(socket, limit))
}
readState(result: SystemReadResult.Read(bytes)) (state: dever.io.ReadState) { state = dever.io.ReadState.Read(bytes) }
readState(result: SystemReadResult.End) (state: dever.io.ReadState) { state = dever.io.ReadState.End }
readState(result: SystemReadResult.Failed(message)) (state: dever.io.ReadState) { fail(dever.io.ReadResult.Failed(message)) }
public write(socket: dever.system.Socket, bytes: Bytes) () {
wrote(dever.system.tcpWrite(socket, bytes))
}
public timeout(socket: dever.system.Socket, milliseconds: Int) () {
wrote(dever.system.tcpTimeout(socket, milliseconds))
}
wrote(result: dever.io.WriteResult.Done) () {}
wrote(result: dever.io.WriteResult.Failed(message)) () { fail(dever.io.WriteResult.Failed(message)) }
public close(socket: dever.system.Socket) () {
closed(dever.system.tcpClose(socket))
}
closed(result: dever.io.CloseResult.Closed) () {}
closed(result: dever.io.CloseResult.Failed(message)) () { fail(dever.io.CloseResult.Failed(message)) }
public chunks(socket: dever.system.Socket, limit: Int) (stream: AsyncStream<dever.io.ReadEvent>) {
stream = readStream(dever.system.tcpChunks(socket, limit))
}
readStream(result: ReadStreamResult.Streaming(stream)) (value: AsyncStream<dever.io.ReadEvent>) { value = stream }
readStream(result: ReadStreamResult.Failed(message)) (value: AsyncStream<dever.io.ReadEvent>) { fail(ReadStreamResult.Failed(message)) }
+26
View File
@@ -0,0 +1,26 @@
public type Output {
code: Int
stdout: Bytes
stderr: Bytes
}
public type Error {
error Failed(message: Text)
}
public type ArgumentsResult {
Read(values: List<Text>)
error Failed(message: Text)
}
public arguments() (values: List<Text>) {
values = argumentsValue(dever.system.processArguments())
}
argumentsValue(result: ArgumentsResult.Read(values)) (value: List<Text>) {
value = values
}
argumentsValue(result: ArgumentsResult.Failed(message)) (value: List<Text>) {
fail(ArgumentsResult.Failed(message))
}
+1
View File
@@ -0,0 +1 @@
public key() (value: Text) { value = dever.system.siteKey() }
+17
View File
@@ -0,0 +1,17 @@
public type Event {
event: Text
data: Text
id: Text?
retry_ms: Int?
}
public start(reply: dever.system.HttpReply, headers: List<dever.http.Header>) () {
wrote(dever.system.sseStart(reply, headers))
}
public send(reply: dever.system.HttpReply, event: Event) () {
wrote(dever.system.sseSend(reply, event))
}
wrote(result: dever.io.WriteResult.Done) () {}
wrote(result: dever.io.WriteResult.Failed(message)) () { fail(dever.io.WriteResult.Failed(message)) }
+11
View File
@@ -0,0 +1,11 @@
public type PutResult {
Stored(key: Uuid)
error Failed(message: Text)
}
public put(upload: Upload) (key: Uuid) {
key = stored(dever.system.uploadPut(upload))
}
stored(result: PutResult.Stored(value)) (key: Uuid) { key = value }
stored(result: PutResult.Failed(message)) (key: Uuid) { fail(PutResult.Failed(message)) }
+12
View File
@@ -0,0 +1,12 @@
public sleep(millis: Int) () {
slept(dever.system.taskSleep(millis))
}
slept(result: dever.time.SleepResult.Done) () {}
slept(result: dever.time.SleepResult.Failed(message)) () {
fail(dever.time.SleepResult.Failed(message))
}
public ticks(millis: Int) (values: AsyncStream<Int>) {
values = dever.system.taskTicks(millis)
}
+13
View File
@@ -0,0 +1,13 @@
public type SleepResult {
Done
error Failed(message: Text)
}
public sleep(millis: Int) () {
slept(dever.system.timeSleep(millis))
}
slept(result: SleepResult.Done) () {}
slept(result: SleepResult.Failed(message)) () {
fail(SleepResult.Failed(message))
}
+29
View File
@@ -0,0 +1,29 @@
public type DateTimeResult { Read(value: DateTime)
error Failed(message: Text) }
datetimeValue(result: DateTimeResult.Read(value)) (output: DateTime) pure { output = value }
datetimeValue(result: DateTimeResult.Failed(message)) (output: DateTime) pure { fail(DateTimeResult.Failed(message)) }
public type DateResult { Read(value: Date)
error Failed(message: Text) }
dateValue(result: DateResult.Read(value)) (output: Date) pure { output = value }
dateValue(result: DateResult.Failed(message)) (output: Date) pure { fail(DateResult.Failed(message)) }
public type TimeResult { Read(value: Time)
error Failed(message: Text) }
timeValue(result: TimeResult.Read(value)) (output: Time) pure { output = value }
timeValue(result: TimeResult.Failed(message)) (output: Time) pure { fail(TimeResult.Failed(message)) }
public type DurationResult { Read(value: Duration)
error Failed(message: Text) }
durationValue(result: DurationResult.Read(value)) (output: Duration) pure { output = value }
durationValue(result: DurationResult.Failed(message)) (output: Duration) pure { fail(DurationResult.Failed(message)) }
public type TextResult { Read(value: Text)
error Failed(message: Text) }
textValue(result: TextResult.Read(value)) (output: Text) pure { output = value }
textValue(result: TextResult.Failed(message)) (output: Text) pure { fail(TextResult.Failed(message)) }
+9
View File
@@ -0,0 +1,9 @@
public type ClockResult { Read(value: Int)
error Failed(message: Text) }
public unixMillis() (value: Int) { value = clockValue(dever.system.timeUnixMillis()) }
public monotonicNanos() (value: Int) { value = clockValue(dever.system.timeMonotonicNanos()) }
clockValue(result: ClockResult.Read(value)) (clock: Int) { clock = value }
clockValue(result: ClockResult.Failed(message)) (clock: Int) { fail(ClockResult.Failed(message)) }
+21
View File
@@ -0,0 +1,21 @@
public now() (output: DateTime) { output = datetimeValue(dever.system.timeNow()) }
public parseDatetime(text: Text) (output: DateTime) pure { output = datetimeValue(dever.system.timeParseDatetime(text)) }
public formatDatetime(value: DateTime) (output: Text) pure { output = textValue(dever.system.timeFormatDatetime(value)) }
public parseDate(text: Text) (output: Date) pure { output = dateValue(dever.system.timeParseDate(text)) }
public formatDate(value: Date) (output: Text) pure { output = textValue(dever.system.timeFormatDate(value)) }
public parseTime(text: Text) (output: Time) pure { output = timeValue(dever.system.timeParseTime(text)) }
public formatTime(value: Time) (output: Text) pure { output = textValue(dever.system.timeFormatTime(value)) }
public duration(millis: Int) (output: Duration) pure { output = dever.system.timeDuration(millis) }
public add(value: DateTime, duration: Duration) (output: DateTime) pure { output = datetimeValue(dever.system.timeAdd(value, duration)) }
public subtract(value: DateTime, duration: Duration) (output: DateTime) pure { output = datetimeValue(dever.system.timeSubtract(value, duration)) }
public difference(later: DateTime, earlier: DateTime) (output: Duration) pure { output = durationValue(dever.system.timeDifference(later, earlier)) }
+27
View File
@@ -0,0 +1,27 @@
public type ClientResult {
Ready(config: dever.system.ClientTls)
error Failed(message: Text)
}
public type ServerResult {
Ready(config: dever.system.ServerTls)
error Failed(message: Text)
}
public system() (config: dever.system.ClientTls) {
config = dever.system.tlsSystem()
}
public client(ca_pem: Bytes) (config: dever.system.ClientTls) {
config = clientConfig(dever.system.tlsClient(ca_pem))
}
clientConfig(result: ClientResult.Ready(config)) (value: dever.system.ClientTls) { value = config }
clientConfig(result: ClientResult.Failed(message)) (value: dever.system.ClientTls) { fail(ClientResult.Failed(message)) }
public server(cert_pem: Bytes, key_pem: Bytes) (config: dever.system.ServerTls) {
config = serverConfig(dever.system.tlsServer(cert_pem, key_pem))
}
serverConfig(result: ServerResult.Ready(config)) (value: dever.system.ServerTls) { value = config }
serverConfig(result: ServerResult.Failed(message)) (value: dever.system.ServerTls) { fail(ServerResult.Failed(message)) }
+106
View File
@@ -0,0 +1,106 @@
public type Limits {
message_bytes: Int
idle_ms: Int
write_ms: Int
}
public type Message {
Text(value: Text)
Binary(value: Bytes)
Ping(value: Bytes)
Pong(value: Bytes)
}
public type ConnectResult {
Connected(socket: dever.system.WebSocket)
error Failed(message: Text)
}
public type ReceiveState {
Read(message: Message)
End
}
public type ReceiveResult {
Done(state: ReceiveState)
error Failed(message: Text)
}
type SystemReceiveResult {
Read(message: Message)
End
error Failed(message: Text)
}
public type MessageEvent {
Read(message: Message)
error Failed(message: Text)
}
public defaultLimits() (result: Limits) {
result = Limits {
message_bytes = 1048576
idle_ms = 60000
write_ms = 5000
}
}
public accept(reply: dever.system.HttpReply, limits: Limits) (socket: dever.system.WebSocket) {
socket = connected(dever.system.wsAccept(reply, limits))
}
public connect(address: Text, port: Int, target: Text, limits: Limits) (socket: dever.system.WebSocket) {
socket = connected(dever.system.wsConnect(address, port, target, limits))
}
public open(url: Text, tls: dever.system.ClientTls, limits: Limits) (socket: dever.system.WebSocket) {
socket = connected(dever.system.wsOpen(url, tls, limits))
}
connected(result: ConnectResult.Connected(socket)) (value: dever.system.WebSocket) {
value = socket
}
connected(result: ConnectResult.Failed(message)) (value: dever.system.WebSocket) {
fail(ConnectResult.Failed(message))
}
public send(socket: dever.system.WebSocket, message: Message) () {
wrote(dever.system.wsSend(socket, message))
}
wrote(result: dever.io.WriteResult.Done) () {}
wrote(result: dever.io.WriteResult.Failed(message)) () {
fail(dever.io.WriteResult.Failed(message))
}
public receive(socket: dever.system.WebSocket) (state: ReceiveState) {
state = receiveState(dever.system.wsReceive(socket))
}
receiveState(result: SystemReceiveResult.Read(message)) (state: ReceiveState) {
state = ReceiveState.Read(message)
}
receiveState(result: SystemReceiveResult.End) (state: ReceiveState) {
state = ReceiveState.End
}
receiveState(result: SystemReceiveResult.Failed(message)) (state: ReceiveState) {
fail(ReceiveResult.Failed(message))
}
public messages(socket: dever.system.WebSocket) (result: AsyncStream<MessageEvent>) {
result = dever.system.wsMessages(socket)
}
public close(socket: dever.system.WebSocket, code: Int, reason: Text) () {
closed(dever.system.wsClose(socket, code, reason))
}
closed(result: dever.io.CloseResult.Closed) () {}
closed(result: dever.io.CloseResult.Failed(message)) () {
fail(dever.io.CloseResult.Failed(message))
}
+19
View File
@@ -0,0 +1,19 @@
# 十进制
decimal128 数值的解析、格式化和舍入。
## decimal.round
就近舍入,中点取偶数;places 为负时舍入到十、百等位。精度或结果无法表示时产生数值故障。
## decimal.parse
解析有限且精确可表示的 Decimal128;格式非法或需要舍入时返回 null。
## decimal.toText
输出规范化 Decimal 文本,去除多余尾零,零统一写为 0。
## decimal.fromInt
把 Int 精确转换为 Decimal。
+44
View File
@@ -0,0 +1,44 @@
# Cookie
Cookie 写入会检查外部 Origin;Secret Cookie 使用带版本的字节编码。
## dever.api.SameSite
限定浏览器跨站发送 Cookie 的策略。
分支:
- `Strict`:仅同站发送
- `Lax`:同站请求和安全的顶层导航
- `None`:允许跨站,必须同时启用 Secure
## dever.api.CookieOptions
属性控制浏览器发送范围,不用于服务端授权。
字段:
- `path`:路径
- `domain`:可选域
- `same_site`:浏览器跨站发送策略
- `secure`:只通过 HTTPS 发送
- `http_only`:禁止脚本读取
- `max_age`:可选秒数,零表示删除
## dever.api.secureCookieOptions
默认使用路径 /、SameSite=Lax、Secure 和 HttpOnly,不指定域和有效期。
## dever.api.cookie
读取普通文本 Cookie,认证 Cookie 或 Secret 编码不能读为 Text。
## dever.api.secretCookie
读取带 v1 前缀的无填充 base64url 字节;其他格式视为缺席。
## dever.api.setCookie
暂存普通 Cookie,业务或编码失败时不发布。
## dever.api.setSecretCookie
秘密 Cookie 必须保留 Secure 和 HttpOnly。
+27
View File
@@ -0,0 +1,27 @@
# 请求信息
读取当前 HTTP 请求的信息,客户端地址不信任转发头。
## dever.api.requestId
读取服务端为当前请求生成的标识。
## dever.api.method
读取实际请求方法。
## dever.api.path
读取不含查询参数的路径。
## dever.api.clientAddress
读取直接连接的客户端 IP,不采用 Forwarded 或 X-Forwarded-For。
## dever.api.header
读取首个非敏感请求头,缺席时返回 null。
## dever.api.setHeader
成功响应时发布,不能覆盖协议和 Cookie 字段。
+19
View File
@@ -0,0 +1,19 @@
# API 错误
Error 映射为固定 HTTP 状态;内部故障和敏感消息不进入响应。
## dever.api.require
条件为 true 时继续,false 时传播指定的 Error。用于已有业务条件的检查,不替代身份认证、对象权限、数据库约束或状态分支。不要在各领域重复定义仅负责 true/false 失败的一对函数。
## dever.api.Error
业务可以显式返回安全错误;其他失败统一返回内部错误。
分支:
- `error Invalid`:请求无效
- `error Unauthorized`:未认证
- `error Forbidden`:无权访问
- `error NotFound`:资源不存在
- `error Conflict`:资源冲突
- `error TooManyRequests`:请求过多
+15
View File
@@ -0,0 +1,15 @@
# 业务权限
业务权限属于当前认证租户和入口命名空间。注册与撤销使用当前写事务,授权数据保存在租户库;缺少租户或组件未启用时失败。
## dever.auth.hasProtectedRoles
检查指定用户在当前可信租户任意站点是否拥有受保护角色;缺少可信租户时失败。
## dever.auth.registerCapability
注册当前入口命名空间内的业务权限,重复注册返回同一键。只允许受保护写 API,显示名称和层级由业务维护。
## dever.auth.removeCapability
在同一事务内撤销当前入口命名空间中的业务权限及其角色授权,重新注册不会恢复旧授权。
+59
View File
@@ -0,0 +1,59 @@
# 角色与权限
角色操作作用于当前认证租户和站点,不能用参数切换授权库。
## dever.auth.Permission
一个接口或业务权限的名称、所属组件、领域、站点及操作信息。
## dever.auth.Role
角色及其权限设置。protected 标识保留角色,permission_keys 是分配的权限键。
## dever.auth.permissions
读取当前站点的有效权限目录。
## dever.auth.currentPermissions
读取当前用户启用角色的有效权限并集。
## dever.auth.roles
读取当前站点角色,包含禁用与受保护角色。
## dever.auth.role
读取当前站点单个角色,不存在时返回 null。
## dever.auth.userRoles
读取当前站点指定用户的角色。
## dever.auth.isOwner
根据受保护角色判断 Owner,不依赖特殊用户编号。
## dever.auth.saveRole
原子保存角色与权限,仅允许受保护写 API。
## dever.auth.grantRole
授予普通角色,保留 Owner 由运维入口建立。
## dever.auth.revokeRole
撤销普通角色。
## dever.auth.disableRole
禁用普通角色,保留关系用于管理回显。
## dever.auth.deleteRole
原子删除普通角色及授权关系。
## dever.auth.owner
只检查受保护标记,角色是否启用不改变保留身份。
+31
View File
@@ -0,0 +1,31 @@
# 当前身份
读取已认证 HTTP 请求的身份。CMD、后台和并发子任务不能借用请求上下文。
## dever.auth.id
读取 verify 建立的可信身份标识。
## dever.auth.session
读取已验证的当前会话标识。
## dever.auth.userId
读取当前认证用户的 Model ID;类型由 Provider 的 verify 输出确定。
## dever.auth.tenantId
读取当前租户的 Model ID;类型由 Provider 的 verify 输出确定。
## dever.auth.issue
签发当前站点会话,结果保持不透明 Secret。
## dever.auth.issueCookie
检查同源后暂存 Cookie,入口提交并编码成功才发布。
## dever.auth.clearCookie
检查同源后暂存清除 Cookie,失败响应不发布。
+13
View File
@@ -0,0 +1,13 @@
# 身份声明
签名有效的 Claims 仍须由配置的 App verify 校验账号和会话。
## dever.auth.Claims
传给 Provider verify 的认证声明。subject 是认证主体,session 是会话标识;site 由当前 HTTP 入口确定。
字段:
- `subject`:签发对象
- `session`:会话标识
- `tenant`:租户声明
- `site`:当前站点
+55
View File
@@ -0,0 +1,55 @@
# 字节
Bytes 保存原始字节,按 UTF-8 与 Text 显式转换。
## dever.bytes.DecodeResult
UTF-8 解码结果:Decoded 保存文本,Failed 保存错误原因。
分支:
- `Decoded(text: Text)`:成功结果
- `error Failed(message: Text)`:失败原因
## dever.bytes.BufferResult
字节构造结果:Ready 保存字节,Failed 保存错误原因。
分支:
- `Ready(bytes: Bytes)`:成功结果
- `error Failed(message: Text)`:失败原因
## dever.bytes.fromText
按 UTF-8 编码复制文本字节。
## dever.bytes.toText
完整校验 UTF-8;无效字节不会替换或忽略。
## dever.bytes.decoded
成功时返回文本,失败时保持原错误身份。
## dever.bytes.fromInts
按顺序转换 0–255 的 Int;超范围失败。
## dever.bytes.length
返回字节数。
## dever.bytes.at
使用从零开始的索引,越界返回 null。
## dever.bytes.slice
截取左闭右开区间,负数、倒置或越界范围失败。
## dever.bytes.ready
成功时返回字节,失败时保持原错误身份。
## dever.bytes.concat
顺序连接两段字节,保留两个输入的值。
+63
View File
@@ -0,0 +1,63 @@
# 密码与摘要
密码哈希和校验会阻塞,异步流程用 blocking 调用;摘要和 HMAC 是纯计算。Secret 不可打印。
## dever.crypto.TokenResult
随机 Secret 的生成结果,失败包含原因。
分支:
- `Ready(value: Secret)`:成功值
- `error Failed(message: Text)`:失败原因
## dever.crypto.HashResult
密码哈希的生成结果,成功包含 PHC 文本。
分支:
- `Ready(value: Text)`:成功值
- `error Failed(message: Text)`:失败原因
## dever.crypto.VerifyResult
密码校验结果;成功值表示密码是否匹配,失败表示哈希无效或校验无法完成。
分支:
- `Ready(value: Bool)`:成功值
- `error Failed(message: Text)`:失败原因
## dever.crypto.token
生成指定字节数的随机 Secret,允许 16–1024 字节。随机源不可用时失败。
## dever.crypto.passwordHash
用 Argon2id v19 生成密码哈希。参数为 19456 KiB、2 轮、1 lane 和 32 字节结果。
## dever.crypto.passwordVerify
校验密码与 PHC 哈希。密码不匹配返回 false;哈希损坏或资源参数超限时失败。
## dever.crypto.sha256
计算 SHA-256,返回 32 字节摘要。
## dever.crypto.hmacSha256
用 Secret 密钥计算 HMAC-SHA256,返回 32 字节结果。
## dever.crypto.constantTimeEq
对相同长度的内容使用常量时间比较,长度不同时返回 false。
## dever.crypto.tokenValue
取出随机 Secret;生成失败时继续传播错误。
## dever.crypto.hashValue
取出密码哈希;生成失败时继续传播错误。
## dever.crypto.verifyValue
取出密码是否匹配的结果;校验失败时继续传播错误。
+19
View File
@@ -0,0 +1,19 @@
# 数据库错误
数据库错误不暴露 SQL、绑定值或连接凭据。
## dever.database.Error
数据库的连接、约束、超时和解码错误。
分支:
- `error Pool(message: Text)`:连接池不可用
- `error PoolExhausted(message: Text)`:等待连接超过期限
- `error Connection(message: Text)`:连接失败
- `error Timeout(message: Text)`:操作超时
- `error Cancelled(message: Text)`:操作取消
- `error Database(message: Text)`:数据库执行失败
- `error Constraint(message: Text)`:违反约束
- `error NotFound(message: Text)`:记录不存在
- `error InvalidData(message: Text)`:存储值不符合类型
- `error Migration(message: Text)`:schema 与迁移失败
+35
View File
@@ -0,0 +1,35 @@
# HTTP 调用
发送请求或处理完整响应,正文一次读入内存。
## dever.http.header
构造 HTTP 头:名称转为小写,值按 UTF-8 编码。
## dever.http.headerValue
按名称忽略大小写查找首个 HTTP 头,找不到返回 null。
## dever.http.namedHeader
供 headerValue 匹配 HTTP 头名称。
## dever.http.foundHeader
取出匹配头的原始字节值;没有匹配项时返回 null。
## dever.http.serve
在给定监听器上处理 HTTP 请求,由 route 返回完整响应。
## dever.http.send
向给定地址和端口发送 HTTP 请求,读取完整响应。
## dever.http.serveTls
使用证书配置处理 HTTPS 请求。启用 HTTP/2 时须成功协商 h2。
## dever.http.readResponse
取出 HTTP 响应;请求失败时继续传播错误。
+48
View File
@@ -0,0 +1,48 @@
# 流式响应
在请求处理函数中按块发送响应,结束时释放会话资源。
## dever.http.LiveLimits
逐块限额及空闲期限,心跳期限必须短于空闲期限。
字段:
- `chunk_bytes`:单块上限
- `idle_ms`:普通流空闲期限
- `heartbeat_ms`:SSE 心跳周期
## dever.http.defaultLiveLimits
默认每块 64 KiB、空闲期限 60 秒、心跳间隔 15 秒。
## dever.http.serveLive
处理可分块回复的 HTTP 请求,route 通过 reply 写入响应。
## dever.http.serveLiveTls
使用 TLS 处理可分块回复的 HTTP 请求。
## dever.http.respond
通过 reply 一次发送完整响应。
## dever.http.start
发送流式响应的状态码和响应头。
## dever.http.write
向已开始的流式响应写入一块正文。
## dever.http.finish
结束流式响应。
## dever.http.wroteLive
写入成功时继续执行,失败时传播错误。
## dever.http.closedLive
结束响应成功时继续执行,失败时传播错误。
+45
View File
@@ -0,0 +1,45 @@
# HTTP 连接池
连接池固定使用一个 origin,在创建它的任务作用域结束时关闭。
## dever.http.PoolLimits
空闲保活和流读取限额。
字段:
- `idle_ms`:空闲连接期限
- `chunk_bytes`:流分块上限
- `read_ms`:流读取期限
## dever.http.ClientResult
HTTP 连接池的创建结果。
分支:
- `Ready(client: dever.system.HttpClient)`:共享资源
- `error Failed(message: Text)`:配置或资源失败
## dever.http.defaultPoolLimits
使用有限的默认保活与读取配置。
## dever.http.client
创建共享资源;第一次请求才连接。HTTPS 校验 CA 和主机名。
未声明端口时使用协议默认端口;显式端口非法时立即报错。
## dever.http.request
在固定 origin 发送独立请求;所有排队和 I/O 共用本次期限。
## dever.http.closeClient
关闭所有连接并等待驱动释放;其他别名随后请求失败。
## dever.http.readClient
取出连接池;创建失败时继续传播错误。
## dever.http.closedClient
关闭成功时继续执行,失败时传播错误。
+42
View File
@@ -0,0 +1,42 @@
# 流式请求
通过连接池按需上传或下载正文。
## dever.http.StreamRequest
流式上传总量不受 body_bytes 限制;每块受 chunk_bytes 限制,取块受 read_ms 限制。
字段:
- `method`:请求方法
- `target`:路径及查询
- `headers`:不含协议引擎拥有的长度或分块头
- `body`:按背压取块的正文
## dever.http.StreamResponse
响应头到达即返回;正文按需取块,EOF 无事件,终止错误最多交付一次。
字段:
- `status`:响应状态
- `headers`:保留重复头
- `body`:消费或关闭前占用请求名额
## dever.http.StreamResponseResult
显式捕获响应头之前的配置、排队、传输或协议失败。
分支:
- `Read(response: StreamResponse)`:响应头与正文源
- `error Failed(message: Text)`:打开失败
## dever.http.open
发送普通 Request,返回流式响应。排队到响应头共用 timeout_ms,随后逐次读取用 read_ms。
## dever.http.openStream
按需发送异步正文;取消消费或提前关闭时,HTTP/1 关闭连接,HTTP/2 仅取消当前流。
## dever.http.readStreamResponse
把打开失败沿原选择类型传播;正文中的失败由消费函数处理。
+66
View File
@@ -0,0 +1,66 @@
# HTTP 数据结构
请求、响应、HTTP 头及协议限额。
## dever.http.Header
HTTP 头的名称和原始字节值。
字段:
- `name`:HTTP 头名称
- `value`:未经文本转换的头部字节
## dever.http.Request
HTTP 请求的方法、目标路径、头和完整正文。
字段:
- `method`:请求方法,例如 GET
- `target`:路径及查询字符串
- `headers`:请求头,保留同名字段
- `body`:完整请求正文字节
## dever.http.Response
HTTP 响应的状态码、头和完整正文。
字段:
- `status`:HTTP 状态码
- `headers`:响应头,保留同名字段
- `body`:完整响应正文字节
## dever.http.Limits
请求头、正文、请求期限和并发连接限制;http2=null 表示不启用 HTTP/2。
字段:
- `header_bytes`:请求头的字节上限
- `body_bytes`:请求正文的字节上限
- `timeout_ms`:请求期限;HTTP/2 服务连接在没有活动请求或响应流时,也按此期限回收。关闭握手最多再等待一个相同期限。
- `connections`:并发连接上限
- `http2`:HTTP/2 配置,null 表示关闭
## dever.http.Http2Limits
HTTP/2 的并发流数、单流窗口和连接窗口配置。
字段:
- `streams`:单连接的并发流上限
- `stream_window_bytes`:单流接收窗口,单位为字节
- `connection_window_bytes`:连接接收窗口,单位为字节
## dever.http.ResponseResult
完整响应或请求失败原因。
分支:
- `Read(response: Response)`:成功响应
- `error Failed(message: Text)`:失败原因
## dever.http.defaultLimits
默认限制:8 KiB 请求头、1 MiB 正文、5 秒期限、32 个连接,不启用 HTTP/2。
## dever.http.defaultHttp2Limits
默认 HTTP/2 配置:16 个流,单流窗口 65535 字节,连接窗口 262144 字节。
+11
View File
@@ -0,0 +1,11 @@
# 文本标识
Id 保存原始文本,与普通 Text 区分;不生成随机值或清洗内容。
## dever.id.fromText
从文本构造稳定标识,保留空文本、大小写和 Unicode 内容。
## dever.id.toText
还原标识的原始文本。
+116
View File
@@ -0,0 +1,116 @@
# 文件与标准输出
File 副本共用游标和关闭状态。文件操作同步执行;异步流程用 blocking,不能在 pure 函数中调用。
## dever.io.OpenResult
打开或新建文件的结果。
分支:
- `Opened(file: dever.system.File)`:成功状态
- `error Failed(message: Text)`:失败原因
## dever.io.ReadState
一次读取可短于请求长度;End 表示文件结束。
分支:
- `Read(bytes: Bytes)`:成功状态
- `End`:成功状态
## dever.io.ReadResult
显式捕获读取失败时保留 ReadState。
分支:
- `Done(state: ReadState)`:成功状态
- `error Failed(message: Text)`:失败原因
## dever.io.SystemReadResult
底层文件读取结果,在库内转换为 ReadState。
分支:
- `Read(bytes: Bytes)`:成功状态
- `End`:成功状态
- `error Failed(message: Text)`:失败原因
## dever.io.WriteResult
写入全部字节或返回失败。
分支:
- `Done`:成功状态
- `error Failed(message: Text)`:失败原因
## dever.io.CloseResult
关闭共享文件句柄或返回失败。关闭不承诺数据已落盘。
分支:
- `Closed`:成功状态
- `error Failed(message: Text)`:失败原因
## dever.io.ReadEvent
流每次产生一个数据块;终止错误只产生一次,然后结束。
分支:
- `Chunk(bytes: Bytes)`:读取的数据
- `error Failed(message: Text)`:读取失败
## dever.io.ReadStreamResult
捕获流创建失败,已创建的流仍按需读取。
分支:
- `Streaming(stream: Stream<ReadEvent>)`:共享游标的同步流
- `error Failed(message: Text)`:创建失败
## dever.io.println
写入文本及换行;标准输出失败为带源码位置的 Fault。
## dever.io.open
以只读方式打开现有文件。失败默认沿调用链传播。
## dever.io.create
新建可读写文件;路径已经存在则失败,绝不截断现有文件。
## dever.io.opened
成功时取得共享文件资源,失败时保留 OpenResult 错误身份。
## dever.io.read
读取最多 limit 字节并推进共享游标;limit 必须为正,EOF 返回 End。
## dever.io.readState
把底层读取结果转换为 ReadState;失败时传播 ReadResult.Failed。
## dever.io.write
写入全部字节;失败使用 WriteResult 传播,空字节同样验证文件是否已关闭。
## dever.io.wrote
成功时无输出,失败时保留 WriteResult 身份。
## dever.io.close
关闭底层文件使所有别名失效;重复关闭失败。最后一个别名离开作用域也会释放文件。
## dever.io.closed
成功时无输出,失败时保留 CloseResult 身份。
## dever.io.chunks
先验证正数 limit 和文件未关闭,再创建按需读取的同步流。close(stream) 幂等,释放源别名但不关闭外部文件别名。
## dever.io.readStream
成功时返回共享流,失败时保留创建错误身份。
+39
View File
@@ -0,0 +1,39 @@
# JSON 文档
Document 用节点列表表示 JSON 树,子节点排在父节点之前。
## dever.json.value.Value
JSON 节点的六种值:null、布尔、数字、字符串、数组和对象。数字保留原始文本。
分支:
- `Null`:空值
- `Boolean(value: Bool)`:布尔值
- `Number(raw: Text)`:原始数字
- `String(text: Text)`:字符串
- `Array(children: List<Int>)`:子节点 ID
- `Object(members: Map<Text, Int>)`:字段到子节点 ID
## dever.json.value.Document
由根节点 ID 和节点列表组成的文档;节点 ID 是列表下标。
字段:
- `root`:根节点 ID
- `nodes`:按节点 ID 排列的节点列表
## dever.json.value.ParseResult
文档解析结果。失败位置从零开始,按 Unicode 码点计数。
分支:
- `Parsed(document: Document)`:解析成功
- `error Failed(position: Int, message: Text)`:解析失败
## dever.json.value.WriteResult
文档编码结果。失败包含节点 ID 和原因。
分支:
- `Written(text: Text)`:编码成功
- `error Failed(node: Int, message: Text)`:编码失败
+137
View File
@@ -0,0 +1,137 @@
# JSON
Json 保留已验证的 JSON 内容和数字原文,支持直接解码为具体类型;Document 用于显式遍历节点。
## dever.json.JsonResult
解析成功返回不透明 Json,失败保留错误文本。
分支:
- `Parsed(value: Json)`:解析成功
- `error Failed(message: Text)`:解析失败
## dever.json.TextResult
读取 JSON 字符串或返回类型错误。
分支:
- `Read(value: Text)`:字符串值
- `error Failed(message: Text)`:类型错误
## dever.json.IntResult
读取精确 Int 数字或返回类型错误。
分支:
- `Read(value: Int)`:整数值
- `error Failed(message: Text)`:类型错误
## dever.json.fromText
从文本解析 JSON,应用 16 MiB、64 层和 65536 值限制。
## dever.json.toText
返回已经验证的 JSON 原文。
## dever.json.setProperty
按对象字段名替换或追加一个 JSON 子值。
## dever.json.propertyValue
读取对象字段;缺失字段返回 null,非对象输入传播 PropertyResult.Failed。
## dever.json.asText
读取 JSON 字符串值。
## dever.json.asInteger
读取不带小数和指数的 i64 JSON 数字。
## dever.json.encode
把标量、公开 record、List 或可空值编码为 Json,无需手工构造 JSON 节点。
## dever.json.decode
把 Json 解码为接收位置指定的类型,例如 `input: CreateInput = dever.json.decode(value)`。字段或类型不符时失败。
不复制 JSON 文本、不建立 Document,不自动清洗 Text。普通 API 参数已有具体类型时无需再调用;未知结构才使用动态 Json/Document。
## dever.json.parsed
取出解析后的 Json;解析失败时继续传播错误。
## dever.json.parse
把 JSON 文本解析为扁平 dever.json.value.Document。
## dever.json.stringify
验证并编码手工构造的 dever.json.value.Document。
## dever.json.node
读取节点;缺失节点返回 null。
## dever.json.property
读取对象字段的节点 ID。
## dever.json.element
读取数组元素的节点 ID。
## dever.json.parsedDocument
取出文档;解析失败时保留位置和原因并传播错误。
## dever.json.written
取出编码文本;编码失败时继续传播错误。
## dever.json.textValue
取出 JSON 字符串;类型不匹配时传播错误。
## dever.json.intValue
取出 JSON 整数;类型不匹配时传播错误。
## dever.json.PropertyResult
区分缺失字段和非对象输入;JSON null 是存在的 Json 值。
分支:
- `Found(value: Json?)`:字段值或缺失
- `error Failed(message: Text)`:非对象输入
## dever.json.propertyResult
取出字段值;缺失字段返回 null,读取失败时传播错误。
## dever.json.object
按 Map 插入顺序构造对象,写入时限制大小。
## dever.json.array
按列表顺序构造 JSON 数组。
## dever.json.string
转义并编码字符串。
## dever.json.integer
编码精确 i64 整数。
## dever.json.boolean
编码布尔值。
## dever.json.nullValue
构造存在的 JSON null。
+47
View File
@@ -0,0 +1,47 @@
# TCP 监听
监听器副本共用关闭状态,网络等待使用异步运行时。
## dever.net.ListenResult
TCP 监听结果,成功包含监听器。
分支:
- `Listening(listener: dever.system.Listener)`:监听成功
- `error Failed(message: Text)`:监听失败
## dever.net.PortResult
读取监听端口的结果。
分支:
- `Bound(port: Int)`:绑定端口
- `error Failed(message: Text)`:资源失败
## dever.net.listen
在给定 host 和 port 创建 TCP 监听器。
## dever.net.listening
取出监听器;监听失败时继续传播错误。
## dever.net.accept
等待并接收一个 TCP 连接。
## dever.net.port
读取监听器实际绑定的端口。
## dever.net.bound
取出已绑定端口;读取失败时继续传播错误。
## dever.net.closeListener
关闭监听器,停止接收新连接。
## dever.net.connections
按需接收 TCP 连接,返回异步连接流。
+76
View File
@@ -0,0 +1,76 @@
# TCP 连接
连接副本共用读写和关闭状态,网络等待使用异步运行时。
## dever.net.ConnectResult
TCP 连接结果,成功包含 socket。
分支:
- `Connected(socket: dever.system.Socket)`:连接成功
- `error Failed(message: Text)`:连接失败
## dever.net.ReadStreamResult
TCP 读取流的创建结果。
分支:
- `Streaming(stream: AsyncStream<dever.io.ReadEvent>)`:读取流
- `error Failed(message: Text)`:创建失败
## dever.net.SystemReadResult
底层 TCP 读取结果,在库内转换为 ReadState。
分支:
- `Read(bytes: Bytes)`:读取数据
- `End`:数据结束
- `error Failed(message: Text)`:读取失败
## dever.net.connect
连接给定主机和端口,支持 IP 地址或主机名。
## dever.net.connectTimeout
在指定毫秒期限内连接 IP 地址和端口;此入口不解析主机名。
## dever.net.connected
取出 socket;连接失败时继续传播错误。
## dever.net.read
读取最多 limit 字节,连接结束时返回 End。
## dever.net.readState
转换 TCP 读取状态;失败时传播 dever.io.ReadResult.Failed。
## dever.net.write
向 TCP 连接写入全部字节。
## dever.net.timeout
设置后续 TCP 读写的毫秒期限。
## dever.net.wrote
写入成功时继续执行,失败时传播错误。
## dever.net.close
关闭 TCP 连接及其共享别名。
## dever.net.closed
关闭成功时继续执行,失败时传播错误。
## dever.net.chunks
按需读取 TCP 数据块,返回异步字节事件流。
## dever.net.readStream
取出读取流;创建失败时继续传播错误。
+35
View File
@@ -0,0 +1,35 @@
# 进程与命令
读取当前进程参数和受管命令结果,参数不通过 shell 执行。
## dever.process.Output
已启动命令的退出码与原始输出字节,非零退出码也是正常结果。
字段:
- `code`:退出码
- `stdout`:标准输出
- `stderr`:标准错误
## dever.process.Error
外部命令 Port 可声明的执行错误。
分支:
- `error Failed(message: Text)`:失败原因
## dever.process.ArgumentsResult
读取当前进程参数的具体结果,无法表示为 UTF-8 的参数明确失败。
分支:
- `Read(values: List<Text>)`:参数列表
- `error Failed(message: Text)`:读取失败
## dever.process.arguments
跳过程序路径 argv[0],保留之后所有参数的顺序和内容。
## dever.process.argumentsValue
取出进程参数;读取失败时继续传播错误。
+7
View File
@@ -0,0 +1,7 @@
# 当前站点
站点由服务配置和入口确定,不能用业务参数切换。
## dever.site.key
读取当前入口匹配的站点标识。
+25
View File
@@ -0,0 +1,25 @@
# SSE
在 HTTP 流式响应中发送事件和心跳。
## dever.sse.Event
数据保留换行与空 id;重连历史由应用维护。
字段:
- `event`:事件名称
- `data`:事件正文
- `id`:可空事件编号
- `retry_ms`:可空重试间隔
## dever.sse.start
提交 SSE 头并启用空闲心跳。
## dever.sse.send
编码完整事件并受单块限额约束。
## dever.sse.wrote
传播 SSE 写入失败。
+19
View File
@@ -0,0 +1,19 @@
# 上传存储
同领域 Adapter 用 storage.put 接收一次性 Upload,不暴露临时文件路径。
## dever.storage.PutResult
上传持久化的结果,成功包含文件的 Uuid。
分支:
- `Stored(key: Uuid)`:持久化后的文件标识。
- `error Failed(message: Text)`:文件写入或同步失败。
## dever.storage.put
在 Adapter 中持久化请求上传,成功返回文件 Uuid;失败时传播错误。
## dever.storage.stored
取出已存文件的 Uuid;保存失败时继续传播错误。
+15
View File
@@ -0,0 +1,15 @@
# 异步等待
挂起当前任务,不占用线程等待。
## dever.task.sleep
等待指定毫秒数,错误使用 dever.time.SleepResult 传播。所在函数自动推导为异步。
## dever.task.slept
异步等待成功时继续执行,时长无效时传播错误。
## dever.task.ticks
按需等待周期信号,首个序号为 1,跳过落后的周期;关闭释放定时器。
+63
View File
@@ -0,0 +1,63 @@
# 日历结果
日期时间、日期、时间和时长操作的结果类型。
## dever.time.DateTimeResult
日期时间操作的结果,失败包含原因。
分支:
- `Read(value: DateTime)`:成功值
- `error Failed(message: Text)`:失败原因
## dever.time.datetimeValue
取出日期时间;操作失败时继续传播错误。
## dever.time.DateResult
日期操作的结果,失败包含原因。
分支:
- `Read(value: Date)`:成功值
- `error Failed(message: Text)`:失败原因
## dever.time.dateValue
取出日期;操作失败时继续传播错误。
## dever.time.TimeResult
日内时间操作的结果,失败包含原因。
分支:
- `Read(value: Time)`:成功值
- `error Failed(message: Text)`:失败原因
## dever.time.timeValue
取出日内时间;操作失败时继续传播错误。
## dever.time.DurationResult
时长操作的结果,失败包含原因。
分支:
- `Read(value: Duration)`:成功值
- `error Failed(message: Text)`:失败原因
## dever.time.durationValue
取出时长;操作失败时继续传播错误。
## dever.time.TextResult
格式化文本操作的结果,失败包含原因。
分支:
- `Read(value: Text)`:成功值
- `error Failed(message: Text)`:失败原因
## dever.time.textValue
取出格式化文本;操作失败时继续传播错误。
+23
View File
@@ -0,0 +1,23 @@
# 时钟
提供系统毫秒时钟和进程内单调纳秒时钟。
## dever.time.ClockResult
时钟读数或读取失败原因。
分支:
- `Read(value: Int)`:成功值
- `error Failed(message: Text)`:失败原因
## dever.time.unixMillis
读取 Unix epoch 起的系统时钟毫秒数。
## dever.time.monotonicNanos
读取从本进程首次调用起经过的单调纳秒数。
## dever.time.clockValue
取出时钟读数;读取失败时继续传播错误。
+47
View File
@@ -0,0 +1,47 @@
# 日期与时长
使用 UTC 日期时间和毫秒时长。
## dever.time.now
读取当前 UTC 日期时间,精度为毫秒。
## dever.time.parseDatetime
解析 RFC3339 和明确偏移,最多三位小数;拒绝闰秒及转换后超出四位 UTC 年份的值。
## dever.time.formatDatetime
输出 UTC YYYY-MM-DDTHH:MM:SS[.sss]Z;零毫秒省略小数。
## dever.time.parseDate
解析严格的 YYYY-MM-DD,验证实际日历日期。
## dever.time.formatDate
输出 YYYY-MM-DD,Date 表示 UTC 午夜毫秒。
## dever.time.parseTime
解析 HH:MM:SS 或 HH:MM:SS.sss;拒绝闰秒和无效钟点。
## dever.time.formatTime
输出 HH:MM:SS[.sss],零毫秒省略小数。
## dever.time.duration
构造有符号毫秒时长,保留完整 Int 范围。
## dever.time.add
相加并检查 i64 溢出;结果是否能格式化由格式化操作判断。
## dever.time.subtract
相减并检查 i64 溢出;结果是否能格式化由格式化操作判断。
## dever.time.difference
计算有符号毫秒差,溢出时传播 DurationResult.Failed。
+19
View File
@@ -0,0 +1,19 @@
# 同步等待
等待占用当前线程;异步流程使用 dever.task.sleep。
## dever.time.SleepResult
等待成功或无法表示的时长;零毫秒合法,负数失败。
分支:
- `Done`:等待完成
- `error Failed(message: Text)`:时长错误
## dever.time.sleep
阻塞当前线程直到指定毫秒数过去。
## dever.time.slept
等待成功时继续执行,时长无效时传播错误。
+39
View File
@@ -0,0 +1,39 @@
# TLS
构造可共享的 TLS 配置,连接时验证证书和目标名称,不提供跳过校验的模式。
## dever.tls.ClientResult
显式捕获客户端 TLS 配置的输入失败。
分支:
- `Ready(config: dever.system.ClientTls)`:配置成功
- `error Failed(message: Text)`:配置错误
## dever.tls.ServerResult
显式捕获服务端证书或私钥的输入失败。
分支:
- `Ready(config: dever.system.ServerTls)`:配置成功
- `error Failed(message: Text)`:配置错误
## dever.tls.system
使用随二进制提供的公共 CA,不读取机器上的可变证书配置。
## dever.tls.client
仅信任指定 PEM CA;无证书或非法 PEM 默认传播失败。
## dever.tls.clientConfig
取出客户端 TLS 配置;创建失败时继续传播错误。
## dever.tls.server
读取证书链及匹配的单个私钥,返回共享服务端配置。
## dever.tls.serverConfig
取出服务端 TLS 配置;创建失败时继续传播错误。
+112
View File
@@ -0,0 +1,112 @@
# WebSocket
使用 HTTP/1 升级,连接随创建任务或服务 handler 结束而关闭。不支持 HTTP/2 升级、子协议或压缩。
## dever.websocket.Limits
限制完整消息、接收等待和写入期限。
字段:
- `message_bytes`:完整消息字节上限
- `idle_ms`:一次接收的毫秒期限
- `write_ms`:写入和握手的毫秒期限
## dever.websocket.Message
协议引擎交付完整消息;Ping 和 Pong 最多 125 字节。
分支:
- `Text(value: Text)`:文本
- `Binary(value: Bytes)`:二进制
- `Ping(value: Bytes)`:保活请求
- `Pong(value: Bytes)`:保活响应
## dever.websocket.ConnectResult
WebSocket 连接或协议升级的结果。
分支:
- `Connected(socket: dever.system.WebSocket)`:已连接
- `error Failed(message: Text)`:连接失败
## dever.websocket.ReceiveState
区分完整消息与正常关闭。
分支:
- `Read(message: Message)`:完整消息
- `End`:正常关闭
## dever.websocket.ReceiveResult
接收操作的显式捕获结果。
分支:
- `Done(state: ReceiveState)`:接收状态
- `error Failed(message: Text)`:接收失败
## dever.websocket.SystemReceiveResult
系统边界结果在库内转换为公开接收状态。
分支:
- `Read(message: Message)`:完整消息
- `End`:正常关闭
- `error Failed(message: Text)`:接收失败
## dever.websocket.MessageEvent
流在故障时产生一次失败后结束。
分支:
- `Read(message: Message)`:完整消息
- `error Failed(message: Text)`:终止失败
## dever.websocket.defaultLimits
默认消息 1 MiB、接收 60 秒、写入与握手 5 秒。
## dever.websocket.accept
只升级当前 HTTP/1.1 请求。失败时仍可回复普通 HTTP 响应;handler 退出关闭所有 socket 别名。
## dever.websocket.connect
连接数字 IP 和 origin-form 路径,不自动重试。
## dever.websocket.open
支持 ws/wss 和 DNS;WSS 校验证书和目标名称,拒绝用户信息及 fragment。
未声明端口时使用协议默认端口;显式端口非法时在连接前报错。
## dever.websocket.connected
取出 WebSocket;连接失败时继续传播错误。
## dever.websocket.send
发送一次完整消息;方向锁与写入共用期限,已开始写帧的取消会关闭连接。
## dever.websocket.wrote
消息发送成功时继续执行,失败时传播错误。
## dever.websocket.receive
按需读取协议帧,先回复 Ping 再交付应用;接收超时关闭资源。
## dever.websocket.receiveState
正常关闭映射为 End,协议失败保持 ReceiveResult 身份。
## dever.websocket.messages
惰性消费消息;正常关闭结束,终止故障只产生一次 Failed;关闭流释放源别名。
## dever.websocket.close
校验关闭码和至多 123 UTF-8 字节原因,并在写期限内等待对端关闭。
## dever.websocket.closed
关闭成功时继续执行,失败时传播错误。
+15
View File
@@ -0,0 +1,15 @@
# 浮点数
Float 文本使用 NaN、inf 和 -inf 表示非有限值。
## float.fromInt
把 Int 转换为 Float;超过 Float 有效整数精度时按浮点规则舍入。
## float.parse
接受十进制、科学计数法和精确拼写 NaN、inf、-inf;格式非法时返回 null。
## float.toText
输出 Float 文本,包括 NaN、inf 和 -inf。
+11
View File
@@ -0,0 +1,11 @@
# 整数
64 位有符号整数与十进制文本转换。
## int.parse
解析有符号十进制 Int;格式非法或超出 i64 范围时返回 null。
## int.toText
把 Int 转换为十进制文本。
+35
View File
@@ -0,0 +1,35 @@
# 数学
Float 数学函数,角度单位为弧度。
## math.sqrt
计算平方根;负数产生 NaN。
## math.sin
计算以弧度表示的正弦值。
## math.cos
计算以弧度表示的余弦值。
## math.log
计算自然对数,遵循 Float 的非有限值规则。
## math.pow
计算 value 的 exponent 次幂,遵循 Float 规则。
## math.isNan
判断 Float 是否为 NaN。
## math.isFinite
判断 Float 是否为有限值。
## math.isInfinite
判断 Float 是否为正无穷或负无穷。
+63
View File
@@ -0,0 +1,63 @@
# 文本
Text 使用 UTF-8;位置和长度按 Unicode 码点计算。
## text.trim
移除文本两端的 Unicode 空白。
## text.lower
按 Unicode 规则转换为小写。
## text.upper
按 Unicode 规则转换为大写,转换结果可以包含更多字符。
## text.codepoint
文本恰好包含一个 Unicode 标量时返回其整数值,否则返回 null。
## text.fromCodepoint
把有效 Unicode 标量值转换为文本;负数、代理区和超出范围的值返回 null。
## text.at
按从 0 开始的 Unicode 标量位置取单个字符;越界返回 null。
## text.slice
按 Unicode 标量位置返回半开区间 [start, end);负数、倒序或越界返回 null。
## text.indexOf
返回首个匹配子串的 Unicode 标量位置;未匹配返回 null,空 pattern 返回 0。
## text.contains
判断文本是否包含给定子串。
## text.startsWith
判断文本是否以给定前缀开头。
## text.endsWith
判断文本是否以给定后缀结尾。
## text.split
按给定分隔文本拆分;空分隔符按 Unicode 标量拆分,不产生首尾空项。
## text.replace
替换所有匹配子串;空 pattern 会在字符边界及首尾插入 replacement。
## text.isEmpty
判断文本是否为空。
## text.join
按列表顺序拼接,在相邻元素之间插入 separator;空列表产生空文本。
+11
View File
@@ -0,0 +1,11 @@
# UUID
独立的 128 位标识类型,可作 Map 键;解析标准 8-4-4-4-12 形式,输出小写。
## uuid.parse
解析恰好 36 字符的标准形式;输入无效时返回 null。
## uuid.toText
输出小写的标准连字符形式。
+11
View File
@@ -0,0 +1,11 @@
public fromInt(value: Int) (result: Float) {
result = dever.system.floatFromInt(value)
}
public parse(value: Text) (result: Float?) {
result = dever.system.floatParse(value)
}
public toText(value: Float) (result: Text) {
result = dever.system.floatToText(value)
}
+7
View File
@@ -0,0 +1,7 @@
public parse(value: Text) (result: Int?) {
result = dever.system.intParse(value)
}
public toText(value: Int) (result: Text) {
result = dever.system.intToText(value)
}
+31
View File
@@ -0,0 +1,31 @@
public sqrt(value: Float) (result: Float) {
result = dever.system.floatSqrt(value)
}
public sin(value: Float) (result: Float) {
result = dever.system.floatSin(value)
}
public cos(value: Float) (result: Float) {
result = dever.system.floatCos(value)
}
public log(value: Float) (result: Float) {
result = dever.system.floatLog(value)
}
public pow(value: Float, exponent: Float) (result: Float) {
result = dever.system.floatPow(value, exponent)
}
public isNan(value: Float) (result: Bool) {
result = dever.system.floatIsNan(value)
}
public isFinite(value: Float) (result: Bool) {
result = dever.system.floatIsFinite(value)
}
public isInfinite(value: Float) (result: Bool) {
result = dever.system.floatIsInfinite(value)
}
+59
View File
@@ -0,0 +1,59 @@
public trim(value: Text) (result: Text) {
result = dever.system.textTrim(value)
}
public lower(value: Text) (result: Text) {
result = dever.system.textLower(value)
}
public upper(value: Text) (result: Text) {
result = dever.system.textUpper(value)
}
public codepoint(value: Text) (result: Int?) {
result = dever.system.textCodepoint(value)
}
public fromCodepoint(value: Int) (result: Text?) {
result = dever.system.textFromCodepoint(value)
}
public at(value: Text, index: Int) (result: Text?) {
result = dever.system.textAt(value, index)
}
public slice(value: Text, start: Int, end: Int) (result: Text?) {
result = dever.system.textSlice(value, start, end)
}
public indexOf(value: Text, pattern: Text) (result: Int?) {
result = dever.system.textIndexOf(value, pattern)
}
public contains(value: Text, pattern: Text) (result: Bool) {
result = dever.system.textContains(value, pattern)
}
public startsWith(value: Text, prefix: Text) (result: Bool) {
result = dever.system.textStartsWith(value, prefix)
}
public endsWith(value: Text, suffix: Text) (result: Bool) {
result = dever.system.textEndsWith(value, suffix)
}
public split(value: Text, separator: Text) (result: List<Text>) {
result = dever.system.textSplit(value, separator)
}
public replace(value: Text, pattern: Text, replacement: Text) (result: Text) {
result = dever.system.textReplace(value, pattern, replacement)
}
public isEmpty(value: Text) (result: Bool) {
result = dever.system.textIsEmpty(value)
}
public join(values: List<Text>, separator: Text) (result: Text) {
result = dever.system.textJoin(values, separator)
}
+7
View File
@@ -0,0 +1,7 @@
public parse(value: Text) (result: Uuid?) {
result = dever.system.uuidParse(value)
}
public toText(value: Uuid) (result: Text) {
result = dever.system.uuidToText(value)
}