feat: add application productivity foundations
Quality / quality (ubuntu-latest) (push) Failing after 22s
Quality / quality (windows-latest) (push) Canceled after 0s

This commit is contained in:
2026-08-23 11:13:03 +05:30
parent 46195462c3
commit 64ab20cc95
42 changed files with 1533 additions and 40 deletions
+41
View File
@@ -0,0 +1,41 @@
export interface ApiRequest<Input = unknown> {
method?: string;
params?: Record<string, string | number>;
query?: Record<string, string | number | boolean | undefined>;
body?: Input;
}
export interface ApiClientOptions {
baseUrl?: string;
fetch?: (input: RequestInfo | URL, init?: RequestInit) => Promise<Response>;
}
/** Runtime used by generated API clients; throws a typed response error on non-2xx results. */
export function createApiClient(options: ApiClientOptions = {}) {
const fetcher = options.fetch ?? globalThis.fetch;
return async function call<Output, Input = unknown>(
template: string,
request: ApiRequest<Input> = {},
): Promise<Output> {
let path = template;
for (const [name, value] of Object.entries(request.params ?? {})) {
path = path.replace(`[${name}]`, encodeURIComponent(String(value)));
}
const url = new URL(path, options.baseUrl ?? globalThis.location?.origin ?? "http://localhost");
for (const [name, value] of Object.entries(request.query ?? {}))
if (value !== undefined) url.searchParams.set(name, String(value));
const response = await fetcher(url, {
method: request.method ?? (request.body === undefined ? "GET" : "POST"),
credentials: "same-origin",
headers: request.body === undefined ? undefined : { "content-type": "application/json" },
body: request.body === undefined ? undefined : JSON.stringify(request.body),
});
const data = response.status === 204 ? undefined : await response.json();
if (!response.ok)
throw Object.assign(
new Error((data as { error?: string })?.error ?? `HTTP ${response.status}`),
{ status: response.status, data },
);
return data as Output;
};
}
+2
View File
@@ -16,6 +16,8 @@ export { REACTIVE_RUNTIME } from "./reactive-runtime.ts";
export { NAV_RUNTIME } from "./nav-runtime.ts";
export { REALTIME_RUNTIME } from "./realtime-runtime.ts";
export { ACTION_RUNTIME } from "./action-runtime.ts";
export { createApiClient } from "./api-client.ts";
export type { ApiClientOptions, ApiRequest } from "./api-client.ts";
const CONTROLLER_SECTIONS = ["PRIMARY", "UI", "PIN"] as const;