bazis 0.117.0 → 0.117.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/core/http/HttpContext/responseLifetime.ts +3 -1
- package/core/infra/connectors/codex/CodexAppServerClient.ts +1 -1
- package/core/kernel/startupFailure.ts +4 -1
- package/library/orm/DatabaseFacade.ts +2 -2
- package/library/orm/Providers/PostgresDialect.ts +7 -5
- package/library/orm/Schema/ExpectedSchema.ts +3 -3
- package/library/orm/Schema/tableKey.ts +10 -0
- package/package.json +1 -1
|
@@ -31,7 +31,9 @@ export function holdResponseScope(
|
|
|
31
31
|
if (signal.aborted && !body.locked) void body.cancel(signal.reason).catch(() => undefined);
|
|
32
32
|
void Promise.resolve().then(dispose).then(complete, reject);
|
|
33
33
|
};
|
|
34
|
-
|
|
34
|
+
// Types only: with the DOM lib (TypeScript's default) Response.body is the
|
|
35
|
+
// DOM ReadableStream, which node:stream's typings do not list.
|
|
36
|
+
cleanup = finished(body as unknown as Parameters<typeof finished>[0], { signal }, finish);
|
|
35
37
|
|
|
36
38
|
// Qualified Bun 1.4 consumes native Blob/file bodies directly: bodyUsed is
|
|
37
39
|
// true, but no JS reader is acquired and its stream never emits finished.
|
|
@@ -232,7 +232,7 @@ export class CodexAppServerClient implements CodexClient {
|
|
|
232
232
|
if (method === "account/updated") this.modelCache = undefined;
|
|
233
233
|
}, () => { this.clearLogin(); this.modelCache = undefined; });
|
|
234
234
|
const initialized = await client.request("initialize", {
|
|
235
|
-
clientInfo: { name: "bazis", title: "Bazis", version: "0.117.
|
|
235
|
+
clientInfo: { name: "bazis", title: "Bazis", version: "0.117.1" }, capabilities: { experimentalApi: true },
|
|
236
236
|
}, 15_000, signal);
|
|
237
237
|
if (resolve(text(initialized.codexHome, 4096)) !== this.paths.home) throw new CodexError("PROTOCOL_ERROR");
|
|
238
238
|
client.notify("initialized");
|
|
@@ -5,6 +5,8 @@ import { ShutdownTimeoutError, StartupFailuresError, StartupTimeoutError } from
|
|
|
5
5
|
const MAX_CAUSES = 5;
|
|
6
6
|
/** Properties already printed in the header, the frames or the cause chain. */
|
|
7
7
|
const SHOWN = new Set(["name", "message", "stack", "cause", "code", "errno", "errors", "failures"]);
|
|
8
|
+
/** Where in PostgreSQL's own sources the error was raised: nothing to act on. Hint, detail and the object names stay. */
|
|
9
|
+
const POSTGRES_INTERNALS = new Set(["file", "line", "routine", "severity", "severity_local"]);
|
|
8
10
|
const INSPECT = { depth: null, colors: false, customInspect: false, getters: false, maxArrayLength: null, maxStringLength: null } as const;
|
|
9
11
|
|
|
10
12
|
/**
|
|
@@ -34,7 +36,8 @@ export function formatStartupFailure(error: unknown): string {
|
|
|
34
36
|
if (!(current instanceof StartupFailuresError)) lines.push(...(current.stack ?? "").split("\n").filter((line) => /^\s+at /.test(line)));
|
|
35
37
|
// Timeouts already say their limit and what was pending in the message.
|
|
36
38
|
const restated = current instanceof StartupTimeoutError || current instanceof ShutdownTimeoutError;
|
|
37
|
-
const
|
|
39
|
+
const internals = current.name === "PostgresError" ? POSTGRES_INTERNALS : undefined;
|
|
40
|
+
const details = restated ? {} : Object.fromEntries(Object.entries(current).filter(([name]) => !SHOWN.has(name) && !internals?.has(name)));
|
|
38
41
|
if (Object.keys(details).length > 0) lines.push(inspect(redactSensitive(details), INSPECT));
|
|
39
42
|
current = current.cause;
|
|
40
43
|
}
|
|
@@ -5,7 +5,7 @@ import { Migrator, type MigrationResult } from "./Schema/Migrator";
|
|
|
5
5
|
import { MigrationRunner, type Migration, type VersionedMigrationResult } from "./Schema/MigrationRunner";
|
|
6
6
|
import { SchemaDiffer } from "./Schema/SchemaDiffer";
|
|
7
7
|
import { SchemaAdmissionEngine, type EnsureCreatedResult } from "./Schema/SchemaAdmission";
|
|
8
|
-
import { entityStorageKey } from "./Schema/tableKey";
|
|
8
|
+
import { entityStorageKey, foreignKeyName } from "./Schema/tableKey";
|
|
9
9
|
|
|
10
10
|
/** Result of `ensureCreated` together with versioned migrations. */
|
|
11
11
|
export interface EnsureCreatedWithMigrationsResult extends EnsureCreatedResult {
|
|
@@ -166,7 +166,7 @@ export class DatabaseFacade {
|
|
|
166
166
|
const constraint: ForeignKeyConstraint = {
|
|
167
167
|
column: columns[0]!.columnName,
|
|
168
168
|
columns: columns.map((column) => column!.columnName),
|
|
169
|
-
name: fk
|
|
169
|
+
name: foreignKeyName(model, fk),
|
|
170
170
|
referencedTable: this.referencedTableName(target),
|
|
171
171
|
referencedColumn: target.key[0].columnName,
|
|
172
172
|
referencedColumns: target.key.map((property) => property.columnName),
|
|
@@ -2,7 +2,7 @@ import type { ColumnType, EntityModel, IndexModel, PropertyModel } from "../Meta
|
|
|
2
2
|
import type { ForeignKeyConstraint, RowLockMode, SqlDialect, SqlParam } from "./types";
|
|
3
3
|
import { projectCheckAstIdentifiers, renderCheck } from "../Schema/CheckExpression";
|
|
4
4
|
import { resolvedForeignKey } from "./resolvedForeignKey";
|
|
5
|
-
import { physicalTableIdentity } from "../Schema/tableKey";
|
|
5
|
+
import { physicalTableIdentity, primaryKeyName } from "../Schema/tableKey";
|
|
6
6
|
import { decimalParameter } from "./decimalValue";
|
|
7
7
|
|
|
8
8
|
const jsonScalarParameters = new WeakSet<object>();
|
|
@@ -132,17 +132,19 @@ export class PostgresDialect implements SqlDialect {
|
|
|
132
132
|
}
|
|
133
133
|
|
|
134
134
|
createTableSql(model: EntityModel, foreignKeys: readonly ForeignKeyConstraint[]): string {
|
|
135
|
+
// The same name ensureCreated expects, not PostgreSQL's "<table>_pkey".
|
|
136
|
+
const primaryKey = `CONSTRAINT ${this.quoteId(primaryKeyName(model))} PRIMARY KEY`;
|
|
135
137
|
const columns = model.properties.map((property) => {
|
|
136
138
|
if (model.key.length === 1 && property.isKey && property.generation === "identity") {
|
|
137
139
|
// BY DEFAULT allows inserting an explicit key when needed.
|
|
138
|
-
return `${this.quoteId(property.columnName)} bigint GENERATED BY DEFAULT AS IDENTITY
|
|
140
|
+
return `${this.quoteId(property.columnName)} bigint GENERATED BY DEFAULT AS IDENTITY ${primaryKey}`;
|
|
139
141
|
}
|
|
140
142
|
if (model.key.length === 1 && property.isKey && property.generation === "uuid") {
|
|
141
|
-
return `${this.quoteId(property.columnName)} uuid NOT NULL DEFAULT gen_random_uuid()
|
|
143
|
+
return `${this.quoteId(property.columnName)} uuid NOT NULL DEFAULT gen_random_uuid() ${primaryKey}`;
|
|
142
144
|
}
|
|
143
145
|
if (model.key.length === 1 && property.isKey && property.generation === "uuidV7") {
|
|
144
146
|
// The ORM assigns the v7 value before INSERT, so the column has no default.
|
|
145
|
-
return `${this.quoteId(property.columnName)} uuid NOT NULL
|
|
147
|
+
return `${this.quoteId(property.columnName)} uuid NOT NULL ${primaryKey}`;
|
|
146
148
|
}
|
|
147
149
|
const foreignKey = foreignKeys.find((candidate) => (candidate.columns ?? [candidate.column]).includes(property.columnName));
|
|
148
150
|
const parts = [this.quoteId(property.columnName), this.ddlColumnType(this.foreignKeyColumnType(foreignKey, property), property)];
|
|
@@ -152,7 +154,7 @@ export class PostgresDialect implements SqlDialect {
|
|
|
152
154
|
return parts.join(" ");
|
|
153
155
|
});
|
|
154
156
|
if (model.key.length > 1 || model.key[0].generation === "none") {
|
|
155
|
-
columns.push(
|
|
157
|
+
columns.push(`${primaryKey} (${model.key.map((key) => this.quoteId(key.columnName)).join(", ")})`);
|
|
156
158
|
}
|
|
157
159
|
for (const check of model.checks) columns.push(`CONSTRAINT ${this.quoteId(check.name)} CHECK (${renderCheck(projectCheckAstIdentifiers(check.expression, (name) => model.propertyByName(name)!.columnName), (name) => this.quoteId(name))})`);
|
|
158
160
|
for (const fk of foreignKeys) {
|
|
@@ -4,7 +4,7 @@ import type { CanonicalDefault, GenerationStrategy } from "./introspection";
|
|
|
4
4
|
import { projectCheckAstIdentifiers, type CheckAst } from "./CheckExpression";
|
|
5
5
|
import { crossUnitForeignKey, physicalColumnTypes } from "./physicalColumnTypes";
|
|
6
6
|
import { SchemaAdmissionError } from "../errors";
|
|
7
|
-
import { physicalTableIdentity } from "./tableKey";
|
|
7
|
+
import { foreignKeyName, physicalTableIdentity, primaryKeyName } from "./tableKey";
|
|
8
8
|
|
|
9
9
|
export interface ExpectedColumn { readonly property: string; readonly column: string; readonly physicalType: string; readonly nullable: boolean; readonly default: CanonicalDefault; readonly generation: GenerationStrategy }
|
|
10
10
|
export interface ExpectedTable { readonly schema: string; readonly table: string; readonly columns: readonly ExpectedColumn[]; readonly primaryKey: { readonly name: string; readonly columns: readonly string[] }; readonly indexes: readonly { readonly name: string; readonly columns: readonly string[]; readonly unique: boolean; readonly method: "btree"; readonly predicate?: CheckAst }[]; readonly foreignKeys: readonly { readonly name: string; readonly columns: readonly string[]; readonly target: { readonly schema: string; readonly table: string }; readonly targetColumns: readonly string[]; readonly onDelete: string; readonly onUpdate: string }[]; readonly checks: readonly { readonly name: string; readonly expression: unknown }[] }
|
|
@@ -39,9 +39,9 @@ function compileTable(model: EntityModel, byCtor: ReadonlyMap<EntityModel["ctor"
|
|
|
39
39
|
const foreignKeys = model.foreignKeys.map((foreignKey) => {
|
|
40
40
|
const target = byCtor.get(foreignKey.target());
|
|
41
41
|
if (!target) throw crossUnitForeignKey(model, foreignKey.properties, foreignKey.target());
|
|
42
|
-
return { name:
|
|
42
|
+
return { name: foreignKeyName(model, foreignKey), columns: foreignKey.properties.map((name) => model.propertyByName(name)!.columnName), target: { schema: schemaOf(target), table: physicalTableIdentity(target).table }, targetColumns: target.key.map((property) => property.columnName), onDelete: foreignKey.onDelete, onUpdate: foreignKey.onUpdate };
|
|
43
43
|
});
|
|
44
|
-
return Object.freeze({ schema, table, columns: Object.freeze(columns), primaryKey: Object.freeze({ name: model
|
|
44
|
+
return Object.freeze({ schema, table, columns: Object.freeze(columns), primaryKey: Object.freeze({ name: primaryKeyName(model), columns: Object.freeze(model.key.map((property) => property.columnName)) }), indexes: Object.freeze(model.indexes.map((index) => Object.freeze({ name: index.name, columns: Object.freeze([...index.columns]), unique: index.unique, method: "btree" as const, ...(index.where === undefined ? {} : { predicate: projectCheckAstIdentifiers(index.where, (name) => model.propertyByName(name)!.columnName) }) }))), foreignKeys: Object.freeze(foreignKeys), checks: Object.freeze(model.checks.map((check) => Object.freeze({ name: check.name, expression: projectCheckAstIdentifiers(check.expression, (name) => model.propertyByName(name)!.columnName) }))) });
|
|
45
45
|
}
|
|
46
46
|
|
|
47
47
|
/** `decimal(12,2)` for numeric(12, 2), `decimal` for an unbounded numeric: the catalog reports the same label. */
|
|
@@ -24,3 +24,13 @@ export function entityStorageKey(model: EntityModel): string {
|
|
|
24
24
|
export function introspectedTableKey(schema: string, table: string): string {
|
|
25
25
|
return schema === "public" ? table : `${schema}.${table}`;
|
|
26
26
|
}
|
|
27
|
+
|
|
28
|
+
/** `pk_<table>` unless the key is named; ensureCreated and migrate() name the primary key the same way. */
|
|
29
|
+
export function primaryKeyName(model: EntityModel): string {
|
|
30
|
+
return model.keyName ?? `pk_${physicalTableIdentity(model).table}`;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/** `fk_<table>_<properties>` unless the foreign key is named, for every way a table is created. */
|
|
34
|
+
export function foreignKeyName(model: EntityModel, foreignKey: { readonly name?: string; readonly properties: readonly string[] }): string {
|
|
35
|
+
return foreignKey.name ?? `fk_${physicalTableIdentity(model).table}_${foreignKey.properties.join("_")}`;
|
|
36
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "bazis",
|
|
3
|
-
"version": "0.117.
|
|
3
|
+
"version": "0.117.1",
|
|
4
4
|
"description": "Modular backend framework for Bun in TypeScript: DI wired by codegen, HTTP, a PostgreSQL ORM, JWT, WebSocket, agents and a CLI.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Alexander Alenin",
|