Skip to content

k.site.codes

Site code repository: API endpoint scripts and reusable CodeBlock additions, deletions, modifications and queries

Overview

k.site.codes manages site Code resources. In the same k.site.codes warehouse, the purpose is distinguished by codeType on the object - this is the core classification of server-side rendering and routing:

codeType (when writing)Enumeration value (common when reading)meaningTypical uses
"Api"4 or "Api"API scriptUse k.api to define the HTTP interface; with routing URL, available getByUrl / getUrl
"CodeBlock"10 or "CodeBlock"code blockReusable KScript modules (export function, etc.); no independent routing, referenced in pages/views
"PageScript"5Page scriptScript embedded in the page
"PaymentCallBack" etc.7 etc.otherSpecial types such as payment callbacks

::: Representation of info codeType Please pass the string "Api" / "CodeBlock" when add. On the object returned by get / all, codeType is often a numeric enumeration (such as 4, 10), or it may be a string. It is recommended to be compatible with both forms when filtering. :::

API behaves differently than CodeBlock's add

  • codeType: "CodeBlock": Only need name, body; Do not pass url (site routing will not be registered).
  • codeType: "Api" (or routable creation when CodeBlock is not explicitly written): name, body is required, and url (such as /api/hello) should be provided, the route will be registered, and the behavior is similar to k.site.pages / k.site.scripts.

::: The relationship between tip and k.api The API file written in the console corresponds to the Code of codeType === "Api"; k.api.get/post in the file defines the subpath under the API. k.site.codes is used to do CRUD on these Codes at runtime, rather than replacing the k.api syntax itself. :::

TypeScript Definition

ts
type CodeType =
  | 'Api'
  | 'CodeBlock'
  | 'PageScript'
  | 'PaymentCallBack'
  | 'Job'
  | /* Additional deprecated enum values exist */;

interface CodeRepository {
  add(code: CodeInput): void;
  all(): Code[];
  get(nameOrId: string): Code | null;
  getByUrl(url: string): Code | null;
  update(code: Code): void;
  updateBody(nameOrId: string, body: string): void;
  delete(nameOrId: string): void;
  getUrl(id: string): string | null;
  getAbsUrl(id: string): string | null;
  getLogs(nameOrId: string): ChangeLog[] | null;
  getByLog(logId: number): Code | null;
}

interface CodeInput {
  name: string;
  body: string;
  codeType: CodeType;
  url?: string;
  scriptType?: string;
  cors?: boolean;
}

Filter by codeType

all() returns all Codes and needs to be filtered by codeType in the script:

ts
k.api.get(() => {
    const all = k.site.codes.all()
    const isApi = (c) => c.codeType === "Api" || c.codeType === 4
    const isCodeBlock = (c) => c.codeType === "CodeBlock" || c.codeType === 10
    return {
        apiCount: all.filter(isApi).length,
        codeBlockCount: all.filter(isCodeBlock).length
    }
})

add() — CodeBlock

Create reusable code blocks (without routing).

ParameterTypeRequiredDescription
code.namestringyesCodeBlock name
code.bodystringyesKScript source code
code.codeTypestringyesMust be "CodeBlock"

Returns: void.

ts
k.api.post(() => {
    const stamp = Date.now().toString()
    const name = "ai-cb-" + stamp

    k.site.codes.add({
        name,
        codeType: "CodeBlock",
        body: `export function aiCb_${stamp}() { return "${stamp}"; }`
    })

    const block = k.site.codes.get(name)
    return {
        verified: !!block && (block.codeType === "CodeBlock" || block.codeType === 10),
        id: block?.id,
        hasRoute: block ? !!k.site.codes.getUrl(block.id) : false
    }
})

hasRoute should be false: CodeBlock does not register standalone URLs.

add() — API

Create API scripts and register routes.

ParameterTypeRequiredDescription
code.namestringyesAPI name (unique within site)
code.bodystringyesScript containing k.api.*
code.codeTypestringyesMust be "Api"
code.urlstringyesAPI root path, such as /api/demo

Returns: void.

ts
k.api.post(() => {
    const stamp = Date.now().toString()
    const name = "ai-api-" + stamp
    const url = "/api/ai-code-" + stamp

    k.site.codes.add({
        name,
        url,
        codeType: "Api",
        body: `k.api.get("ping", () => ({ stamp: "${stamp}" }))`
    })

    const api = k.site.codes.getByUrl(url)
    const route = api ? k.site.codes.getUrl(api.id) : null

    return {
        verified: !!api && (api.codeType === "Api" || api.codeType === 4) && route === url,
        id: api?.id,
        route
    }
})

all()/get()

MethodParametersReturnsDescription
all()NoneCode[]Returns all Code / CodeBlock resources
get(nameOrId)nameOrId: string`Codenull`
ts
k.api.get(() => {
    const code = k.site.codes.get("my-api")
    return code
        ? { name: code.name, codeType: code.codeType }
        : null
})

getByUrl()

Only valid for Api (codeType is "Api" or 4) and Code with registered routing.

ParameterTypeRequiredDescription
urlstringyesAPI route URL

Returns: Code | null.

ts
k.api.get(() => {
    const api = k.site.codes.getByUrl("/api/hello")
    return api ? { name: api.name, codeType: api.codeType } : null
})

update() / updateBody()

MethodParametersReturnsDescription
update(code)code: CodevoidUpdates the full Code object
updateBody(nameOrId, body)nameOrId: string, body: stringvoidReplaces only the source body
ts
k.api.post(() => {
    const stamp = Date.now().toString()
    const name = "ai-api-upd-" + stamp
    const url = "/api/ai-code-upd-" + stamp

    k.site.codes.add({
        name,
        url,
        codeType: "Api",
        body: 'k.api.get(() => "v1")'
    })

    const api = k.site.codes.getByUrl(url)
    api.body = 'k.api.get(() => "v2")'
    k.site.codes.update(api)

    const after = k.site.codes.getByUrl(url)
    return { verified: after?.body?.indexOf("v2") >= 0 }
})

updateBody(nameOrId, body) only replaces body and has the same usage as styles/scripts.

delete()

Use get(name) to verify after deletion; Do not call getByUrl after deleting the API (it may be abnormal when the route remains, the same as k.site.pages).

ParameterTypeRequiredDescription
nameOrIdstringyesCode name or ID

Returns: void.

ts
k.api.post(() => {
    const stamp = Date.now().toString()
    const name = "ai-api-del-" + stamp
    const url = "/api/ai-code-del-" + stamp

    k.site.codes.add({
        name,
        url,
        codeType: "Api",
        body: 'k.api.get(() => "del")'
    })
    const before = k.site.codes.getByUrl(url)

    k.site.codes.delete(name)
    const after = k.site.codes.get(name)

    return { verified: !!before && !after }
})

getUrl() / getAbsUrl()

MethodParametersReturnsDescription
getUrl(id)id: string`stringnull`
getAbsUrl(id)id: string`stringnull`
ts
k.api.get(() => {
    const apis = k.site.codes.all().filter((c) => c.codeType === "Api" || c.codeType === 4)
    for (const api of apis) {
        const rel = k.site.codes.getUrl(api.id)
        if (!rel) continue
        const abs = k.site.codes.getAbsUrl(api.id)
        return { relative: rel, absolute: abs, name: api.name }
    }
    return null
})

getLogs() / getByLog()

Consistent with other k.site.* text repositories.

MethodParametersReturnsDescription
getLogs(nameOrId)nameOrId: string`ChangeLog[]null`
getByLog(logId)logId: number`Codenull`
ts
k.api.get(() => {
    const codes = k.site.codes.all()
    if (!codes.length) return { error: "no codes" }

    const logs = k.site.codes.getLogs(codes[0].id)
    return { logCount: logs ? logs.length : 0 }
})

Common Code Fields

FieldTypeDescription
IDstringCode ID
namestringname
bodystringSource code
codeTypeCodeTypeApi / CodeBlock etc.
scriptTypestringScript engine type (such as Module)
extensionstringUsually .js
corsbooleanWhether the API enables CORS
parametersstring[]API request parameter declaration
onlinebooleanIs it online?
versionnumberversion number