chore: server-and-serverless template

This commit is contained in:
e2e
2026-06-26 14:41:47 +02:00
commit facba843e5
202 changed files with 9060 additions and 0 deletions

View File

@@ -0,0 +1,18 @@
{
"name": "@project/functions-sdk",
"version": "0.0.1",
"private": true,
"type": "module",
"exports": {
"./pikku/api.gen": "./src/pikku/api.gen.ts",
"./pikku/pikku-fetch.gen": "./src/pikku/pikku-fetch.gen.ts",
"./pikku/pikku-rpc.gen": "./src/pikku/pikku-rpc.gen.ts",
"./pikku/rpc-map.gen": "./src/pikku/rpc-map.gen.d.ts",
"./pikku/http-map.gen": "./src/pikku/http-map.gen.d.ts",
"./pikku/*": "./src/pikku/*"
},
"dependencies": {
"@pikku/fetch": "^0.12.4",
"@pikku/react": "^0.12.4"
}
}

View File

@@ -0,0 +1,56 @@
/**
* This file was generated by @pikku/cli@0.12.48
*/
import { useQuery, useInfiniteQuery, useMutation, type UseQueryOptions, type UseInfiniteQueryOptions, type UseMutationOptions, type InfiniteData } from '@tanstack/react-query'
import { usePikkuRPC } from '@pikku/react'
import type { FlattenedRPCMap } from '../../../functions/.pikku/rpc/pikku-rpc-wirings-map.gen.d.js'
type RPCInvoke = <Name extends keyof FlattenedRPCMap>(name: Name, data: FlattenedRPCMap[Name]['input']) => Promise<FlattenedRPCMap[Name]['output']>
export const usePikkuQuery = <Name extends keyof FlattenedRPCMap>(
name: Name,
data: FlattenedRPCMap[Name]['input'],
options?: Omit<UseQueryOptions<FlattenedRPCMap[Name]['output'], Error>, 'queryKey' | 'queryFn'>
) => {
const rpc = usePikkuRPC<{ invoke: RPCInvoke }>()
return useQuery<FlattenedRPCMap[Name]['output'], Error>({
queryKey: [name, data],
queryFn: () => rpc.invoke(name, data),
...options,
})
}
export const usePikkuMutation = <Name extends keyof FlattenedRPCMap>(
name: Name,
options?: Omit<UseMutationOptions<FlattenedRPCMap[Name]['output'], Error, FlattenedRPCMap[Name]['input']>, 'mutationFn'>
) => {
const rpc = usePikkuRPC<{ invoke: RPCInvoke }>()
return useMutation<FlattenedRPCMap[Name]['output'], Error, FlattenedRPCMap[Name]['input']>({
mutationFn: (data) => rpc.invoke(name, data),
...options,
})
}
type PaginatedKeys = {
[K in keyof FlattenedRPCMap]: FlattenedRPCMap[K]['output'] extends { nextCursor?: string | null } ? K : never
}[keyof FlattenedRPCMap]
type InfiniteOpts<Name extends PaginatedKeys> = Omit<
UseInfiniteQueryOptions<FlattenedRPCMap[Name]['output'], Error, InfiniteData<FlattenedRPCMap[Name]['output'], string | undefined>, readonly unknown[], string | undefined>,
'queryKey' | 'queryFn' | 'getNextPageParam' | 'initialPageParam'
>
export const usePikkuInfiniteQuery = <Name extends PaginatedKeys>(
name: Name,
data: Omit<FlattenedRPCMap[Name]['input'], 'nextCursor'>,
options?: InfiniteOpts<Name>
) => {
const rpc = usePikkuRPC<{ invoke: RPCInvoke }>()
return useInfiniteQuery({
queryKey: [name, data] as const,
queryFn: ({ pageParam }: { pageParam: string | undefined }) => rpc.invoke(name, { ...data, nextCursor: pageParam } as unknown as FlattenedRPCMap[Name]['input']),
initialPageParam: undefined as string | undefined,
getNextPageParam: (lastPage: FlattenedRPCMap[Name]['output']) => (lastPage as { nextCursor?: string }).nextCursor ?? undefined,
...options,
})
}

View File

@@ -0,0 +1,67 @@
/**
* This file was generated by @pikku/cli@0.12.48
*/
import { CorePikkuFetch, HTTPMethod } from '@pikku/fetch'
import type { HTTPWiringsMap, HTTPWiringHandlerOf, HTTPWiringsWithMethod } from '../../../functions/.pikku/http/pikku-http-wirings-map.gen.d.js'
export class PikkuFetch extends CorePikkuFetch {
public async post<Route extends HTTPWiringsWithMethod<'POST'>>(
route: Route,
...args: null extends HTTPWiringHandlerOf<Route, 'POST'>['input']
? [data?: Exclude<HTTPWiringHandlerOf<Route, 'POST'>['input'], null>, options?: Omit<RequestInit, 'body'>]
: [data: HTTPWiringHandlerOf<Route, 'POST'>['input'], options?: Omit<RequestInit, 'body'>]
): Promise<HTTPWiringHandlerOf<Route, 'POST'>['output']> {
const [data, options] = args;
return super.api(route, 'POST', data, options);
}
public async get<Route extends HTTPWiringsWithMethod<'GET'>>(
route: Route,
...args: null extends HTTPWiringHandlerOf<Route, 'GET'>['input']
? [data?: Exclude<HTTPWiringHandlerOf<Route, 'GET'>['input'], null>, options?: Omit<RequestInit, 'body'>]
: [data: HTTPWiringHandlerOf<Route, 'GET'>['input'], options?: Omit<RequestInit, 'body'>]
): Promise<HTTPWiringHandlerOf<Route, 'GET'>['output']> {
const [data, options] = args;
return super.api(route, 'GET', data, options);
}
public async patch<Route extends HTTPWiringsWithMethod<'PATCH'>>(
route: Route,
...args: null extends HTTPWiringHandlerOf<Route, 'PATCH'>['input']
? [data?: Exclude<HTTPWiringHandlerOf<Route, 'PATCH'>['input'], null>, options?: Omit<RequestInit, 'body'>]
: [data: HTTPWiringHandlerOf<Route, 'PATCH'>['input'], options?: Omit<RequestInit, 'body'>]
): Promise<HTTPWiringHandlerOf<Route, 'PATCH'>['output']> {
const [data, options] = args;
return super.api(route, 'PATCH', data, options);
}
public async head<Route extends HTTPWiringsWithMethod<'HEAD'>>(
route: Route,
...args: null extends HTTPWiringHandlerOf<Route, 'HEAD'>['input']
? [data?: Exclude<HTTPWiringHandlerOf<Route, 'HEAD'>['input'], null>, options?: Omit<RequestInit, 'body'>]
: [data: HTTPWiringHandlerOf<Route, 'HEAD'>['input'], options?: Omit<RequestInit, 'body'>]
): Promise<HTTPWiringHandlerOf<Route, 'HEAD'>['output']> {
const [data, options] = args;
return super.api(route, 'HEAD', data, options);
}
public async delete<Route extends HTTPWiringsWithMethod<'DELETE'>>(
route: Route,
...args: null extends HTTPWiringHandlerOf<Route, 'DELETE'>['input']
? [data?: Exclude<HTTPWiringHandlerOf<Route, 'DELETE'>['input'], null>, options?: Omit<RequestInit, 'body'>]
: [data: HTTPWiringHandlerOf<Route, 'DELETE'>['input'], options?: Omit<RequestInit, 'body'>]
): Promise<HTTPWiringHandlerOf<Route, 'DELETE'>['output']> {
const [data, options] = args;
return super.api(route, 'DELETE', data, options);
}
public async fetch<
Route extends keyof HTTPWiringsMap,
Method extends keyof HTTPWiringsMap[Route]
>(route: Route, method: Method, data: HTTPWiringHandlerOf<Route, Method>['input'], options?: Omit<RequestInit, 'body'>): Promise<Response> {
return await super.fetch(route, method as HTTPMethod, data, options);
}
}
export const pikkuFetch = new PikkuFetch();

View File

@@ -0,0 +1,148 @@
/**
* This file was generated by @pikku/cli@0.12.48
*/
import { PikkuFetch } from "./pikku-fetch.gen.js"
import type { RPCInvoke, TypedAgentRun, TypedStartWorkflow, TypedRunWorkflow, TypedWorkflowStatus } from '../../../functions/.pikku/rpc/pikku-rpc-wirings-map.gen.d.js'
import type { WorkflowRunStatus } from '@pikku/core/workflow'
/**
* PikkuRPC provides a type-safe client for making Remote Procedure Calls (RPC)
* to your Pikku server. It wraps the underlying HTTP client and provides a
* simple interface for invoking server-side functions.
*/
export class PikkuRPC {
/** The underlying HTTP client used for making RPC calls */
pikkuFetch = new PikkuFetch()
/**
* Sets a custom PikkuFetch instance to use for RPC calls.
* This allows you to configure custom settings or use a shared client instance.
*
* @param pikkuFetch - The PikkuFetch instance to use
*/
setPikkuFetch(pikkuFetch: PikkuFetch): void {
this.pikkuFetch = pikkuFetch
}
/**
* Sets the base server URL for all RPC calls.
*
* @param serverUrl - The base URL of your Pikku server (e.g., 'https://api.example.com')
*/
setServerUrl(serverUrl: string): void {
this.pikkuFetch.setServerUrl(serverUrl)
}
/**
* Sets the JWT token for authorization on all RPC calls.
*
* @param jwt - The JWT token to use for authorization, or null to remove authorization
*/
setAuthorizationJWT(jwt: string | null): void {
this.pikkuFetch.setAuthorizationJWT(jwt)
}
/**
* Sets the API key for authorization on all RPC calls.
*
* @param apiKey - The API key to use for authorization, or null to remove the API key
*/
setAPIKey(apiKey: string | null): void {
this.pikkuFetch.setAPIKey(apiKey)
}
/**
* Invokes a remote procedure call on the server.
* This is a generic method that routes to the appropriate server function
* based on the function name and passes the provided data.
*
* @param rpcName - The name of the server function to invoke
* @param data - The data to pass to the server function
* @returns A promise that resolves with the function's return value
*/
invoke = ((rpcName: string, data?: unknown) => {
return this.pikkuFetch.post(`/rpc/${String(rpcName)}` as never, { rpcName: String(rpcName), data }) as any
}) as RPCInvoke
/**
* Starts a workflow by name with the given input.
* Posts to \`/workflow/:workflowName/start\`.
*
* @param workflowName - The registered workflow name
* @param input - The workflow input data
* @returns A promise that resolves with the new run ID
*/
startWorkflow: TypedStartWorkflow = async (workflowName, input) => {
return await this.pikkuFetch.post(`/workflow/${String(workflowName)}/start` as never, { data: input }) as any
}
/**
* Runs a workflow to completion and returns the output.
* Posts to \`/workflow/:workflowName/run\`.
*
* @param workflowName - The registered workflow name
* @param input - The workflow input data
* @returns A promise that resolves with the workflow output
*/
runWorkflow: TypedRunWorkflow = async (workflowName, input) => {
return await this.pikkuFetch.post(`/workflow/${String(workflowName)}/run` as never, { data: input }) as any
}
/**
* Gets the current status of a workflow run.
* GET \`/workflow/:workflowName/status/:runId\`.
*
* @param workflowName - The registered workflow name
* @param runId - The workflow run ID
* @returns A promise with the minimal run status
*/
workflowStatus: TypedWorkflowStatus = async (workflowName, runId) => {
return await this.pikkuFetch.get(`/workflow/${String(workflowName)}/status/${runId}` as never) as unknown as WorkflowRunStatus
}
/**
* Agent namespace — methods for running, streaming, and approving AI agents.
* All methods post to \`/rpc/agent/:agentName/*\`.
*/
agent = {
/**
* Runs an agent to completion and returns the result.
*
* @param agentName - The registered agent name
* @param input - The agent input (message, threadId, resourceId)
* @returns A promise with runId, result, and token usage
*/
run: (async (agentName, input) => {
return await this.pikkuFetch.post(`/rpc/agent/${String(agentName)}` as never, input) as any
}) as TypedAgentRun,
/**
* Streams agent responses via SSE. Used for real-time chat interfaces.
*
* @param agentName - The registered agent name
* @param input - The agent input (message, threadId, resourceId)
*/
stream: async (agentName: string, input: Record<string, unknown>) => {
return await this.pikkuFetch.post(`/rpc/agent/${String(agentName)}/stream` as never, input) as any
},
/**
* Approves or denies pending tool calls for an agent run.
*
* @param agentName - The registered agent name
* @param input - The approval payload (runId, approvals array)
*/
approve: async (agentName: string, input: Record<string, unknown>) => {
return await this.pikkuFetch.post(`/rpc/agent/${String(agentName)}/approve` as never, input) as any
},
}
subscribeToSSE<T = unknown>(
path: string,
handler: (event: T) => void,
onError?: (err: unknown) => void
): { close: () => void } {
return this.pikkuFetch.subscribeToSSE(path, handler, onError)
}
}
export const pikkuRPC = new PikkuRPC();