Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions src/server/templates/typescript.ts
Original file line number Diff line number Diff line change
Expand Up @@ -485,6 +485,11 @@ export const apply = async ({
function generateNullableUnionTsType(tsType: string, isNullable: boolean) {
// Only add the null union if the type is not unknown as unknown already includes null
if (tsType === 'unknown' || tsType === 'any' || !isNullable) {
// The Json type includes null in its definition, so for non-nullable Json columns
// we need to explicitly exclude null using NonNullable<Json>
if (!isNullable && tsType === 'Json') {
return 'NonNullable<Json>'
}
return tsType
}
return `${tsType} | null`
Expand Down
3 changes: 2 additions & 1 deletion test/db/00-init.sql
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,8 @@ create table public.users_audit (
id BIGINT generated by DEFAULT as identity,
created_at timestamptz DEFAULT now(),
user_id bigint,
previous_value jsonb
previous_value jsonb,
new_value jsonb NOT NULL DEFAULT '{}'::jsonb
);

create function public.audit_action()
Expand Down
34 changes: 34 additions & 0 deletions test/server/typegen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -355,19 +355,22 @@ test('typegen: typescript', async () => {
Row: {
created_at: string | null
id: number
new_value: NonNullable<Json>
previous_value: Json | null
user_id: number | null
created_ago: number | null
}
Insert: {
created_at?: string | null
id?: number
new_value?: NonNullable<Json>
previous_value?: Json | null
user_id?: number | null
}
Update: {
created_at?: string | null
id?: number
new_value?: NonNullable<Json>
previous_value?: Json | null
user_id?: number | null
}
Expand Down Expand Up @@ -846,6 +849,7 @@ test('typegen: typescript', async () => {
Returns: {
created_at: string | null
id: number
new_value: NonNullable<Json>
previous_value: Json | null
user_id: number | null
}
Expand Down Expand Up @@ -1568,19 +1572,22 @@ test('typegen w/ one-to-one relationships', async () => {
Row: {
created_at: string | null
id: number
new_value: NonNullable<Json>
previous_value: Json | null
user_id: number | null
created_ago: number | null
}
Insert: {
created_at?: string | null
id?: number
new_value?: NonNullable<Json>
previous_value?: Json | null
user_id?: number | null
}
Update: {
created_at?: string | null
id?: number
new_value?: NonNullable<Json>
previous_value?: Json | null
user_id?: number | null
}
Expand Down Expand Up @@ -2071,6 +2078,7 @@ test('typegen w/ one-to-one relationships', async () => {
Returns: {
created_at: string | null
id: number
new_value: NonNullable<Json>
previous_value: Json | null
user_id: number | null
}
Expand Down Expand Up @@ -2793,19 +2801,22 @@ test('typegen: typescript w/ one-to-one relationships', async () => {
Row: {
created_at: string | null
id: number
new_value: NonNullable<Json>
previous_value: Json | null
user_id: number | null
created_ago: number | null
}
Insert: {
created_at?: string | null
id?: number
new_value?: NonNullable<Json>
previous_value?: Json | null
user_id?: number | null
}
Update: {
created_at?: string | null
id?: number
new_value?: NonNullable<Json>
previous_value?: Json | null
user_id?: number | null
}
Expand Down Expand Up @@ -3296,6 +3307,7 @@ test('typegen: typescript w/ one-to-one relationships', async () => {
Returns: {
created_at: string | null
id: number
new_value: NonNullable<Json>
previous_value: Json | null
user_id: number | null
}
Expand Down Expand Up @@ -4023,19 +4035,22 @@ test('typegen: typescript w/ postgrestVersion', async () => {
Row: {
created_at: string | null
id: number
new_value: NonNullable<Json>
previous_value: Json | null
user_id: number | null
created_ago: number | null
}
Insert: {
created_at?: string | null
id?: number
new_value?: NonNullable<Json>
previous_value?: Json | null
user_id?: number | null
}
Update: {
created_at?: string | null
id?: number
new_value?: NonNullable<Json>
previous_value?: Json | null
user_id?: number | null
}
Expand Down Expand Up @@ -4526,6 +4541,7 @@ test('typegen: typescript w/ postgrestVersion', async () => {
Returns: {
created_at: string | null
id: number
new_value: NonNullable<Json>
previous_value: Json | null
user_id: number | null
}
Expand Down Expand Up @@ -5313,20 +5329,23 @@ test('typegen: go', async () => {
type PublicUsersAuditSelect struct {
CreatedAt *string \`json:"created_at"\`
Id int64 \`json:"id"\`
NewValue interface{} \`json:"new_value"\`
PreviousValue interface{} \`json:"previous_value"\`
UserId *int64 \`json:"user_id"\`
}

type PublicUsersAuditInsert struct {
CreatedAt *string \`json:"created_at"\`
Id *int64 \`json:"id"\`
NewValue interface{} \`json:"new_value"\`
PreviousValue interface{} \`json:"previous_value"\`
UserId *int64 \`json:"user_id"\`
}

type PublicUsersAuditUpdate struct {
CreatedAt *string \`json:"created_at"\`
Id *int64 \`json:"id"\`
NewValue interface{} \`json:"new_value"\`
PreviousValue interface{} \`json:"previous_value"\`
UserId *int64 \`json:"user_id"\`
}
Expand Down Expand Up @@ -5972,35 +5991,41 @@ test('typegen: swift', async () => {
internal struct UsersAuditSelect: Codable, Hashable, Sendable, Identifiable {
internal let createdAt: String?
internal let id: Int64
internal let newValue: AnyJSON
internal let previousValue: AnyJSON?
internal let userId: Int64?
internal enum CodingKeys: String, CodingKey {
case createdAt = "created_at"
case id = "id"
case newValue = "new_value"
case previousValue = "previous_value"
case userId = "user_id"
}
}
internal struct UsersAuditInsert: Codable, Hashable, Sendable, Identifiable {
internal let createdAt: String?
internal let id: Int64?
internal let newValue: AnyJSON?
internal let previousValue: AnyJSON?
internal let userId: Int64?
internal enum CodingKeys: String, CodingKey {
case createdAt = "created_at"
case id = "id"
case newValue = "new_value"
case previousValue = "previous_value"
case userId = "user_id"
}
}
internal struct UsersAuditUpdate: Codable, Hashable, Sendable, Identifiable {
internal let createdAt: String?
internal let id: Int64?
internal let newValue: AnyJSON?
internal let previousValue: AnyJSON?
internal let userId: Int64?
internal enum CodingKeys: String, CodingKey {
case createdAt = "created_at"
case id = "id"
case newValue = "new_value"
case previousValue = "previous_value"
case userId = "user_id"
}
Expand Down Expand Up @@ -6503,35 +6528,41 @@ test('typegen: swift w/ public access control', async () => {
public struct UsersAuditSelect: Codable, Hashable, Sendable, Identifiable {
public let createdAt: String?
public let id: Int64
public let newValue: AnyJSON
public let previousValue: AnyJSON?
public let userId: Int64?
public enum CodingKeys: String, CodingKey {
case createdAt = "created_at"
case id = "id"
case newValue = "new_value"
case previousValue = "previous_value"
case userId = "user_id"
}
}
public struct UsersAuditInsert: Codable, Hashable, Sendable, Identifiable {
public let createdAt: String?
public let id: Int64?
public let newValue: AnyJSON?
public let previousValue: AnyJSON?
public let userId: Int64?
public enum CodingKeys: String, CodingKey {
case createdAt = "created_at"
case id = "id"
case newValue = "new_value"
case previousValue = "previous_value"
case userId = "user_id"
}
}
public struct UsersAuditUpdate: Codable, Hashable, Sendable, Identifiable {
public let createdAt: String?
public let id: Int64?
public let newValue: AnyJSON?
public let previousValue: AnyJSON?
public let userId: Int64?
public enum CodingKeys: String, CodingKey {
case createdAt = "created_at"
case id = "id"
case newValue = "new_value"
case previousValue = "previous_value"
case userId = "user_id"
}
Expand Down Expand Up @@ -6685,18 +6716,21 @@ test('typegen: python', async () => {
class PublicUsersAudit(BaseModel):
created_at: Optional[datetime.datetime] = Field(alias="created_at")
id: int = Field(alias="id")
new_value: Json[Any] = Field(alias="new_value")
previous_value: Optional[Json[Any]] = Field(alias="previous_value")
user_id: Optional[int] = Field(alias="user_id")

class PublicUsersAuditInsert(TypedDict):
created_at: NotRequired[Annotated[Optional[datetime.datetime], Field(alias="created_at")]]
id: NotRequired[Annotated[int, Field(alias="id")]]
new_value: NotRequired[Annotated[Json[Any], Field(alias="new_value")]]
previous_value: NotRequired[Annotated[Optional[Json[Any]], Field(alias="previous_value")]]
user_id: NotRequired[Annotated[Optional[int], Field(alias="user_id")]]

class PublicUsersAuditUpdate(TypedDict):
created_at: NotRequired[Annotated[Optional[datetime.datetime], Field(alias="created_at")]]
id: NotRequired[Annotated[int, Field(alias="id")]]
new_value: NotRequired[Annotated[Json[Any], Field(alias="new_value")]]
previous_value: NotRequired[Annotated[Optional[Json[Any]], Field(alias="previous_value")]]
user_id: NotRequired[Annotated[Optional[int], Field(alias="user_id")]]

Expand Down