Skip to content
Merged
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
1 change: 1 addition & 0 deletions src/server/templates/python.ts
Original file line number Diff line number Diff line change
Expand Up @@ -345,6 +345,7 @@ const PY_TYPE_MAP: Record<string, string> = {
timestamptz: 'datetime.datetime',
uuid: 'uuid.UUID',
vector: 'list[Any]',
interval: 'str',
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cc @o-santi @silentworks might be a better type for this in Python, mapping to str as it's the format for Typescript. WDYT ?


// JSON
json: 'Json[Any]',
Expand Down
3 changes: 2 additions & 1 deletion src/server/templates/typescript.ts
Original file line number Diff line number Diff line change
Expand Up @@ -869,7 +869,7 @@ export const Constants = {
}

// TODO: Make this more robust. Currently doesn't handle range types - returns them as unknown.
const pgTypeToTsType = (
export const pgTypeToTsType = (
schema: PostgresSchema,
pgType: string,
{
Expand Down Expand Up @@ -902,6 +902,7 @@ const pgTypeToTsType = (
'timestamptz',
'uuid',
'vector',
'interval',
].includes(pgType)
) {
return 'string'
Expand Down
37 changes: 36 additions & 1 deletion test/db/00-init.sql
Original file line number Diff line number Diff line change
Expand Up @@ -465,4 +465,39 @@ CREATE OR REPLACE FUNCTION "public"."days_since_event" ("public"."events") RETUR
SET
"search_path" TO '' AS $_$
SELECT ROUND(EXTRACT(EPOCH FROM (NOW() - $1.created_at)) / 86400);
$_$;
$_$;

-- Table with interval columns for testing interval type (nullable and not nullable)
CREATE TABLE public.interval_test (
id bigint GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
duration_required interval NOT NULL,
duration_optional interval
);

-- Insert test data with interval values
INSERT INTO public.interval_test (duration_required, duration_optional)
VALUES
('1 day 2 hours 30 minutes', '3 days 5 hours'),
('1 week', NULL),
('2 hours 15 minutes', '45 minutes');

-- Function that takes interval parameter and returns interval
CREATE OR REPLACE FUNCTION public.add_interval_to_duration(
base_duration interval,
additional_interval interval
)
RETURNS interval
LANGUAGE SQL
STABLE
AS $$
SELECT base_duration + additional_interval;
$$;

-- Function that takes a table row with interval and returns interval
CREATE OR REPLACE FUNCTION public.double_duration(interval_test_row public.interval_test)
RETURNS interval
LANGUAGE SQL
STABLE
AS $$
SELECT interval_test_row.duration_required * 2;
$$;
205 changes: 205 additions & 0 deletions test/server/typegen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,24 @@ test('typegen: typescript', async () => {
}
Relationships: []
}
interval_test: {
Row: {
duration_optional: string | null
duration_required: string
id: number
}
Insert: {
duration_optional?: string | null
duration_required: string
id?: number
}
Update: {
duration_optional?: string | null
duration_required?: string
id?: number
}
Relationships: []
}
memes: {
Row: {
category: number | null
Expand Down Expand Up @@ -525,6 +543,10 @@ test('typegen: typescript', async () => {
}
}
Functions: {
add_interval_to_duration: {
Args: { additional_interval: string; base_duration: string }
Returns: string
}
blurb: {
Args: { "": Database["public"]["Tables"]["todos"]["Row"] }
Returns: {
Expand Down Expand Up @@ -574,6 +596,12 @@ test('typegen: typescript', async () => {
error: true
} & "the function public.details_words with parameter or with a single unnamed json/jsonb parameter, but no matches were found in the schema cache"
}
double_duration: {
Args: {
interval_test_row: Database["public"]["Tables"]["interval_test"]["Row"]
}
Returns: string
}
function_returning_row: {
Args: never
Returns: {
Expand Down Expand Up @@ -1291,6 +1319,24 @@ test('typegen w/ one-to-one relationships', async () => {
}
Relationships: []
}
interval_test: {
Row: {
duration_optional: string | null
duration_required: string
id: number
}
Insert: {
duration_optional?: string | null
duration_required: string
id?: number
}
Update: {
duration_optional?: string | null
duration_required?: string
id?: number
}
Relationships: []
}
memes: {
Row: {
category: number | null
Expand Down Expand Up @@ -1722,6 +1768,10 @@ test('typegen w/ one-to-one relationships', async () => {
}
}
Functions: {
add_interval_to_duration: {
Args: { additional_interval: string; base_duration: string }
Returns: string
}
blurb: {
Args: { "": Database["public"]["Tables"]["todos"]["Row"] }
Returns: {
Expand Down Expand Up @@ -1771,6 +1821,12 @@ test('typegen w/ one-to-one relationships', async () => {
error: true
} & "the function public.details_words with parameter or with a single unnamed json/jsonb parameter, but no matches were found in the schema cache"
}
double_duration: {
Args: {
interval_test_row: Database["public"]["Tables"]["interval_test"]["Row"]
}
Returns: string
}
function_returning_row: {
Args: never
Returns: {
Expand Down Expand Up @@ -2488,6 +2544,24 @@ test('typegen: typescript w/ one-to-one relationships', async () => {
}
Relationships: []
}
interval_test: {
Row: {
duration_optional: string | null
duration_required: string
id: number
}
Insert: {
duration_optional?: string | null
duration_required: string
id?: number
}
Update: {
duration_optional?: string | null
duration_required?: string
id?: number
}
Relationships: []
}
memes: {
Row: {
category: number | null
Expand Down Expand Up @@ -2919,6 +2993,10 @@ test('typegen: typescript w/ one-to-one relationships', async () => {
}
}
Functions: {
add_interval_to_duration: {
Args: { additional_interval: string; base_duration: string }
Returns: string
}
blurb: {
Args: { "": Database["public"]["Tables"]["todos"]["Row"] }
Returns: {
Expand Down Expand Up @@ -2968,6 +3046,12 @@ test('typegen: typescript w/ one-to-one relationships', async () => {
error: true
} & "the function public.details_words with parameter or with a single unnamed json/jsonb parameter, but no matches were found in the schema cache"
}
double_duration: {
Args: {
interval_test_row: Database["public"]["Tables"]["interval_test"]["Row"]
}
Returns: string
}
function_returning_row: {
Args: never
Returns: {
Expand Down Expand Up @@ -3690,6 +3774,24 @@ test('typegen: typescript w/ postgrestVersion', async () => {
}
Relationships: []
}
interval_test: {
Row: {
duration_optional: string | null
duration_required: string
id: number
}
Insert: {
duration_optional?: string | null
duration_required: string
id?: number
}
Update: {
duration_optional?: string | null
duration_required?: string
id?: number
}
Relationships: []
}
memes: {
Row: {
category: number | null
Expand Down Expand Up @@ -4121,6 +4223,10 @@ test('typegen: typescript w/ postgrestVersion', async () => {
}
}
Functions: {
add_interval_to_duration: {
Args: { additional_interval: string; base_duration: string }
Returns: string
}
blurb: {
Args: { "": Database["public"]["Tables"]["todos"]["Row"] }
Returns: {
Expand Down Expand Up @@ -4170,6 +4276,12 @@ test('typegen: typescript w/ postgrestVersion', async () => {
error: true
} & "the function public.details_words with parameter or with a single unnamed json/jsonb parameter, but no matches were found in the schema cache"
}
double_duration: {
Args: {
interval_test_row: Database["public"]["Tables"]["interval_test"]["Row"]
}
Returns: string
}
function_returning_row: {
Args: never
Returns: {
Expand Down Expand Up @@ -5339,6 +5451,24 @@ test('typegen: go', async () => {
Id *int64 \`json:"id"\`
}

type PublicIntervalTestSelect struct {
DurationOptional interface{} \`json:"duration_optional"\`
DurationRequired interface{} \`json:"duration_required"\`
Id int64 \`json:"id"\`
}

type PublicIntervalTestInsert struct {
DurationOptional interface{} \`json:"duration_optional"\`
DurationRequired interface{} \`json:"duration_required"\`
Id *int64 \`json:"id"\`
}

type PublicIntervalTestUpdate struct {
DurationOptional interface{} \`json:"duration_optional"\`
DurationRequired interface{} \`json:"duration_required"\`
Id *int64 \`json:"id"\`
}

type PublicCategorySelect struct {
Id int32 \`json:"id"\`
Name string \`json:"name"\`
Expand Down Expand Up @@ -5614,6 +5744,36 @@ test('typegen: swift', async () => {
case status = "status"
}
}
internal struct IntervalTestSelect: Codable, Hashable, Sendable, Identifiable {
internal let durationOptional: IntervalSelect?
internal let durationRequired: IntervalSelect
internal let id: Int64
internal enum CodingKeys: String, CodingKey {
case durationOptional = "duration_optional"
case durationRequired = "duration_required"
case id = "id"
}
}
internal struct IntervalTestInsert: Codable, Hashable, Sendable, Identifiable {
internal let durationOptional: IntervalSelect?
internal let durationRequired: IntervalSelect
internal let id: Int64?
internal enum CodingKeys: String, CodingKey {
case durationOptional = "duration_optional"
case durationRequired = "duration_required"
case id = "id"
}
}
internal struct IntervalTestUpdate: Codable, Hashable, Sendable, Identifiable {
internal let durationOptional: IntervalSelect?
internal let durationRequired: IntervalSelect?
internal let id: Int64?
internal enum CodingKeys: String, CodingKey {
case durationOptional = "duration_optional"
case durationRequired = "duration_required"
case id = "id"
}
}
internal struct MemesSelect: Codable, Hashable, Sendable {
internal let category: Int32?
internal let createdAt: String
Expand Down Expand Up @@ -6115,6 +6275,36 @@ test('typegen: swift w/ public access control', async () => {
case status = "status"
}
}
public struct IntervalTestSelect: Codable, Hashable, Sendable, Identifiable {
public let durationOptional: IntervalSelect?
public let durationRequired: IntervalSelect
public let id: Int64
public enum CodingKeys: String, CodingKey {
case durationOptional = "duration_optional"
case durationRequired = "duration_required"
case id = "id"
}
}
public struct IntervalTestInsert: Codable, Hashable, Sendable, Identifiable {
public let durationOptional: IntervalSelect?
public let durationRequired: IntervalSelect
public let id: Int64?
public enum CodingKeys: String, CodingKey {
case durationOptional = "duration_optional"
case durationRequired = "duration_required"
case id = "id"
}
}
public struct IntervalTestUpdate: Codable, Hashable, Sendable, Identifiable {
public let durationOptional: IntervalSelect?
public let durationRequired: IntervalSelect?
public let id: Int64?
public enum CodingKeys: String, CodingKey {
case durationOptional = "duration_optional"
case durationRequired = "duration_required"
case id = "id"
}
}
public struct MemesSelect: Codable, Hashable, Sendable {
public let category: Int32?
public let createdAt: String
Expand Down Expand Up @@ -6609,6 +6799,21 @@ test('typegen: python', async () => {
event_type: NotRequired[Annotated[str, Field(alias="event_type")]]
id: NotRequired[Annotated[int, Field(alias="id")]]

class PublicIntervalTest(BaseModel):
duration_optional: Optional[str] = Field(alias="duration_optional")
duration_required: str = Field(alias="duration_required")
id: int = Field(alias="id")

class PublicIntervalTestInsert(TypedDict):
duration_optional: NotRequired[Annotated[str, Field(alias="duration_optional")]]
duration_required: Annotated[str, Field(alias="duration_required")]
id: NotRequired[Annotated[int, Field(alias="id")]]

class PublicIntervalTestUpdate(TypedDict):
duration_optional: NotRequired[Annotated[str, Field(alias="duration_optional")]]
duration_required: NotRequired[Annotated[str, Field(alias="duration_required")]]
id: NotRequired[Annotated[int, Field(alias="id")]]

class PublicCategory(BaseModel):
id: int = Field(alias="id")
name: str = Field(alias="name")
Expand Down
Loading