feat: add module database ABI v1 adapters
CI / verify (pull_request) Successful in 58s
CI / infrastructure-smoke (pull_request) Successful in 35s
CI / migration-smoke (pull_request) Successful in 1m53s
CI / image-build (pull_request) Successful in 29s
CI / deploy-smoke (same-origin) (pull_request) Successful in 49s
CI / deploy-smoke (split) (pull_request) Successful in 1m31s
CI / verify (pull_request) Successful in 58s
CI / infrastructure-smoke (pull_request) Successful in 35s
CI / migration-smoke (pull_request) Successful in 1m53s
CI / image-build (pull_request) Successful in 29s
CI / deploy-smoke (same-origin) (pull_request) Successful in 49s
CI / deploy-smoke (split) (pull_request) Successful in 1m31s
This commit is contained in:
@@ -0,0 +1,50 @@
|
||||
import {
|
||||
isModuleDatabaseError,
|
||||
type ModuleDatabaseError,
|
||||
type ModuleDatabaseParameter,
|
||||
type ModuleDatabaseQuery,
|
||||
} from "@ekklesia/contracts";
|
||||
|
||||
/** SQL text and values ready to pass directly to a Module Database ABI v1 executor. */
|
||||
export type ModuleSqlQuery = Readonly<Required<Pick<ModuleDatabaseQuery, "text" | "values">>>;
|
||||
|
||||
/**
|
||||
* Builds one PostgreSQL statement without ever interpolating a value into its text.
|
||||
*
|
||||
* Every interpolation becomes the next positional parameter. Dynamic identifiers and trusted SQL
|
||||
* fragments are deliberately unsupported in v1: keep identifiers in the static template text.
|
||||
*/
|
||||
export function sql(
|
||||
strings: TemplateStringsArray,
|
||||
...values: readonly ModuleDatabaseParameter[]
|
||||
): ModuleSqlQuery {
|
||||
let text = strings[0] ?? "";
|
||||
for (let index = 0; index < values.length; index += 1) {
|
||||
text += `$${index + 1}${strings[index + 1] ?? ""}`;
|
||||
}
|
||||
return Object.freeze({ text, values: Object.freeze([...values]) });
|
||||
}
|
||||
|
||||
export type EkklesiaDatabaseError = Pick<
|
||||
ModuleDatabaseError,
|
||||
"code" | "message" | "name" | "sqlState"
|
||||
>;
|
||||
|
||||
/**
|
||||
* Finds a stable Ekklesia database error through wrappers such as DrizzleQueryError.
|
||||
*
|
||||
* Callers inspect the returned `code` and `sqlState`; they never need a PostgreSQL driver error,
|
||||
* `.cause.code`, or message parsing.
|
||||
*/
|
||||
export function findEkklesiaDatabaseError(value: unknown): EkklesiaDatabaseError | undefined {
|
||||
const visited = new Set<unknown>();
|
||||
let current = value;
|
||||
while (current instanceof Error && !visited.has(current)) {
|
||||
if (isModuleDatabaseError(current)) {
|
||||
return current;
|
||||
}
|
||||
visited.add(current);
|
||||
current = current.cause;
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
Reference in New Issue
Block a user