8000 feat: generate types for foreign tables · f-elix/postgres-meta@1a52837 · GitHub
[go: up one dir, main page]

Skip to content

Commit 1a52837

Browse files
committed
feat: generate types for foreign tables
1 parent dd47c6d commit 1a52837

File tree

7 files changed

+141
-70
lines changed
  • server
  • 7 files changed

    +141
    -70
    lines changed

    src/lib/PostgresMetaForeignTables.ts

    Lines changed: 13 additions & 1 deletion
    Original file line numberDiff line numberDiff line change
    @@ -1,5 +1,5 @@
    11
    import { literal } from 'pg-format'
    2-
    import { coalesceRowsToArray } from './helpers.js'
    2+
    import { coalesceRowsToArray, filterByList } from './helpers.js'
    33
    import { columnsSql, foreignTablesSql } from './sql/index.js'
    44
    import { PostgresMetaResult, PostgresForeignTable } from './types.js'
    55

    @@ -11,25 +11,37 @@ export default class PostgresMetaForeignTables {
    1111
    }
    1212

    13< 8000 code>13
    async list(options: {
    14+
    includedSchemas?: string[]
    15+
    excludedSchemas?: string[]
    1416
    limit?: number
    1517
    offset?: number
    1618
    includeColumns: false
    1719
    }): Promise<PostgresMetaResult<(PostgresForeignTable & { columns: never })[]>>
    1820
    async list(options?: {
    21+
    includedSchemas?: string[]
    22+
    excludedSchemas?: string[]
    1923
    limit?: number
    2024
    offset?: number
    2125
    includeColumns?: boolean
    2226
    }): Promise<PostgresMetaResult<(PostgresForeignTable & { columns: unknown[] })[]>>
    2327
    async list({
    28+
    includedSchemas,
    29+
    excludedSchemas,
    2430
    limit,
    2531
    offset,
    2632
    includeColumns = true,
    2733
    }: {
    34+
    includedSchemas?: string[]
    35+
    excludedSchemas?: string[]
    2836
    limit?: number
    2937
    offset?: number
    3038
    includeColumns?: boolean
    3139
    } = {}): Promise<PostgresMetaResult<PostgresForeignTable[]>> {
    3240
    let sql = generateEnrichedForeignTablesSql({ includeColumns })
    41+
    const filter = filterByList(includedSchemas, excludedSchemas)
    42+
    if (filter) {
    43+
    sql += ` where schema ${filter}`
    44+
    }
    3345
    if (limit) {
    3446
    sql += ` limit ${limit}`
    3547
    }

    src/lib/generators.ts

    Lines changed: 12 additions & 0 deletions
    Original file line numberDiff line numberDiff line change
    @@ -1,6 +1,7 @@
    11
    import PostgresMeta from './PostgresMeta.js'
    22
    import {
    33
    PostgresColumn,
    4+
    PostgresForeignTable,
    45
    PostgresFunction,
    56
    PostgresMaterializedView,
    67
    PostgresRelationship,
    @@ -14,6 +15,7 @@ import { PostgresMetaResult } from './types.js'
    1415
    export type GeneratorMetadata = {
    1516
    schemas: PostgresSchema[]
    1617
    tables: Omit<PostgresTable, 'columns'>[]
    18+
    foreignTables: Omit<PostgresForeignTable, 'columns'>[]
    1719
    views: Omit<PostgresView, 'columns'>[]
    1820
    materializedViews: Omit<PostgresMaterializedView, 'columns'>[]
    1921
    columns: PostgresColumn[]
    @@ -46,6 +48,15 @@ export async function getGeneratorMetadata(
    4648
    return { data: null, error: tablesError }
    4749
    }
    4850

    51+
    const { data: foreignTables, error: foreignTablesError } = await pgMeta.foreignTables.list({
    52+
    includedSchemas: includedSchemas.length > 0 ? includedSchemas : undefined,
    53+
    excludedSchemas,
    54+
    includeColumns: false,
    55+
    })
    56+
    if (foreignTablesError) {
    57+
    return { data: null, error: foreignTablesError }
    58+
    }
    59+
    4960
    const { data: views, error: viewsError } = await pgMeta.views.list({
    5061
    includedSchemas: includedSchemas.length > 0 ? includedSchemas : undefined,
    5162
    excludedSchemas,
    @@ -104,6 +115,7 @@ export async function getGeneratorMetadata(
    104115
    (includedSchemas.length === 0 || includedSchemas.includes(name))
    105116
    ),
    106117
    tables,
    118+
    foreignTables,
    107119
    views,
    108120
    materializedViews,
    109121
    columns,

    src/server/server.ts

    Lines changed: 10 additions & 0 deletions
    Original file line numberDiff line numberDiff line change
    @@ -41,6 +41,7 @@ if (EXPORT_DOCS) {
    4141
    const [
    4242
    { data: schemas, error: schemasError },
    4343
    { data: tables, error: tablesError },
    44+
    { data: foreignTables, error: foreignTablesError },
    4445
    { data: views, error: viewsError },
    4546
    { data: materializedViews, error: materializedViewsError },
    4647
    { data: columns, error: columnsError },
    @@ -54,6 +55,11 @@ if (EXPORT_DOCS) {
    5455
    GENERATE_TYPES_INCLUDED_SCHEMAS.length > 0 ? GENERATE_TYPES_INCLUDED_SCHEMAS : undefined,
    5556
    includeColumns: false,
    5657
    }),
    58+
    pgMeta.foreignTables.list({
    59+
    includedSchemas:
    60+
    GENERATE_TYPES_INCLUDED_SCHEMAS.length > 0 ? GENERATE_TYPES_INCLUDED_SCHEMAS : undefined,
    61+
    includeColumns: false,
    62+
    }),
    5763
    pgMeta.views.list({
    5864
    includedSchemas:
    5965
    GENERATE_TYPES_INCLUDED_SCHEMAS.length > 0 ? GENERATE_TYPES_INCLUDED_SCHEMAS : undefined,
    @@ -86,6 +92,9 @@ if (EXPORT_DOCS) {
    8692
    if (tablesError) {
    8793
    throw new Error(tablesError.message)
    8894
    }
    95+
    if (foreignTablesError) {
    96+
    throw new Error(foreignTablesError.message)
    97+
    }
    8998
    if (viewsError) {
    9099
    throw new Error(viewsError.message)
    91100
    }
    @@ -113,6 +122,7 @@ if (EXPORT_DOCS) {
    113122
    GENERATE_TYPES_INCLUDED_SCHEMAS.includes(name)
    114123
    ),
    115124
    tables: tables!,
    125+
    foreignTables: foreignTables!,
    116126
    views: views!,
    117127
    materializedViews: materializedViews!,
    118128
    columns: columns!,

    src/server/templates/typescript.ts

    Lines changed: 3 additions & 2 deletions
    Original file line numberDiff line numberDiff line change
    @@ -12,6 +12,7 @@ import type { GeneratorMetadata } from '../../lib/generators.js'
    1212
    export const apply = async ({
    1313
    schemas,
    1414
    tables,
    15+
    foreignTables,
    1516
    views,
    1617
    materializedViews,
    1718
    columns,
    @@ -23,7 +24,7 @@ export const apply = async ({
    2324
    detectOneToOneRelationships: boolean
    2425
    }): Promise<string> => {
    2526
    const columnsByTableId = Object.fromEntries<PostgresColumn[]>(
    26-
    [...tables, ...views, ...materializedViews].map((t) => [t.id, []])
    27+
    [...tables, ...foreignTables, ...views, ...materializedViews].map((t) => [t.id, []])
    2728
    )
    2829
    columns
    2930
    .filter((c) => c.table_id in columnsByTableId)
    @@ -37,7 +38,7 @@ export type Database = {
    3738
    ${schemas
    3839
    .sort(({ name: a }, { name: b }) => a.localeCompare(b))
    3940
    .map((schema) => {
    40-
    const schemaTables = tables
    41+
    const schemaTables = [...tables, ...foreignTables]
    4142
    .filter((table) => table.schema === schema.name)
    4243
    .sort(({ name: a }, { name: b }) => a.localeCompare(b))
    4344
    const schemaViews = [...views, ...materializedViews]

    test/db/00-init.sql

    Lines changed: 1 addition & 1 deletion
    Original file line numberDiff line numberDiff line change
    @@ -87,7 +87,7 @@ create extension postgres_fdw;
    8787
    create server foreign_server foreign data wrapper postgres_fdw options (host 'localhost', port '5432', dbname 'postgres');
    8888
    create user mapping for postgres server foreign_server options (user 'postgres', password 'postgres');
    8989
    create foreign table foreign_table (
    90-
    id int8,
    90+
    id int8 not null,
    9191
    name text,
    9292
    status user_status
    9393
    ) server foreign_server options (schema_name 'public', table_name 'users');

    test/lib/foreign-tables.ts

    Lines changed: 66 additions & 66 deletions
    Original file line numberDiff line numberDiff line change
    @@ -22,71 +22,71 @@ test('list', async () => {
    2222
    const res = await pgMeta.foreignTables.list()
    2323
    expect(cleanNondetFromResponse(res).data?.find(({ name }) => name === 'foreign_table'))
    2424
    .toMatchInlineSnapshot(`
    25-
    {
    26-
    "columns": [
    27-
    {
    28-
    "check": null,
    29-
    "comment": null,
    30-
    "data_type": "bigint",
    31-
    "default_value": null,
    32-
    "enums": [],
    33-
    "format": "int8",
    34-
    "identity_generation": null,
    35-
    "is_generated": false,
    36-
    "is_identity": false,
    37-
    "is_nullable": true,
    38-
    "is_unique": false,
    39-
    "is_updatable": true,
    40-
    "name": "id",
    41-
    "ordinal_position": 1,
    42-
    "schema": "public",
    43-
    "table": "foreign_table",
    44-
    },
    45-
    {
    46-
    "check": null,
    47-
    "comment": null,
    48-
    "data_type": "text",
    49-
    "default_value": null,
    50-
    "enums": [],
    51-
    "format": "text",
    52-
    "identity_generation": null,
    53-
    "is_generated": false,
    54-
    "is_identity": false,
    55-
    "is_nullable": true,
    56-
    "is_unique": false,
    57-
    "is_updatable": true,
    58-
    "name": "name",
    59-
    "ordinal_position": 2,
    60-
    "schema": "public",
    61-
    "table": "foreign_table",
    62-
    },
    63-
    {
    64-
    "check": null,
    65-
    "comment": null,
    66-
    "data_type": "USER-DEFINED",
    67-
    "default_value": null,
    68-
    "enums": [
    69-
    "ACTIVE",
    70-
    "INACTIVE",
    71-
    ],
    72-
    "format": "user_status",
    73-
    "identity_generation": null,
    74-
    "is_generated": false,
    75-
    "is_identity": false,
    76-
    "is_nullable": true,
    77-
    "is_unique": false,
    78-
    "is_updatable": true,
    79-
    "name": "status",
    80-
    "ordinal_position": 3,
    81-
    "schema": "public",
    82-
    "table": "foreign_table",
    83-
    },
    84-
    ],
    85-
    "comment": null,
    86-
    "name": "foreign_table",
    87-
    "schema": "public",
    88-
    }
    89-
    `)
    25+
    {
    26+
    "columns": [
    27+
    {
    28+
    "check": null,
    29+
    "comment": null,
    30+
    "data_type": "bigint",
    31+
    "default_value": null,
    32+
    "enums": [],
    33+
    "format": "int8",
    34+
    "identity_generation": null,
    35+
    "is_generated": false,
    36+
    "is_identity": false,
    37+
    "is_nullable": false,
    38+
    "is_unique": false,
    39+
    "is_updatable": true,
    40+
    "name": "id",
    41+
    "ordinal_position": 1,
    42+
    "schema": "public",
    43+
    "table": "foreign_table",
    44+
    },
    45+
    {
    46+
    "check": null,
    47+
    "comment": null,
    48+
    "data_type": "text",
    49+
    "default_value": null,
    50+
    "enums": [],
    51+
    "format": "text",
    52+
    "identity_generation": null,
    53+
    "is_generated": false,
    54+
    "is_identity": false,
    55+
    "is_nullable": true,
    56+
    "is_unique": false,
    57+
    "is_updatable": true,
    58+
    "name": "name",
    59+
    "ordinal_position": 2,
    60+
    "schema": "public",
    61+
    "table": "foreign_table",
    62+
    },
    63+
    {
    64+
    "check": null,
    65+
    "comment": null,
    66+
    "data_type": "USER-DEFINED",
    67+
    "default_value": null,
    68+
    "enums": [
    69+
    "ACTIVE",
    70+
    "INACTIVE",
    71+
    ],
    72+
    "format": "user_status",
    73+
    "identity_generation": null,
    74+
    "is_generated": false,
    75+
    "is_identity": false,
    76+
    "is_nullable": true,
    77+
    "is_unique": false,
    78+
    "is_updatable": true,
    79+
    "name": "status",
    80+
    "ordinal_position": 3,
    81+
    "schema": "public",
    82+
    "table": "foreign_table",
    83+
    },
    84+
    ],
    85+
    "comment": null,
    86+
    "name": "foreign_table",
    87+
    "schema": "public",
    88+
    }
    89+
    `)
    9090
    })
    9191

    9292
    test('list without columns', async () => {
    @@ -117,7 +117,7 @@ test('retrieve', async () => {
    117117
    "identity_generation": null,
    118118
    "is_generated": false,
    119119
    "is_identity": false,
    120-
    "is_nullable": true,
    120+
    "is_nullable": false,
    121121
    "is_unique": false,
    122122
    "is_updatable": true,
    123123
    "name": "id",

    test/server/typegen.ts

    Lines changed: 36 additions & 0 deletions
    Original file line numberDiff line numberDiff line change
    @@ -36,6 +36,24 @@ test('typegen', async () => {
    3636
    Update: {}
    3737
    Relationships: []
    3838
    }
    39+
    foreign_table: {
    40+
    Row: {
    41+
    id: number
    42+
    name: string | null
    43+
    status: Database["public"]["Enums"]["user_status"] | null
    44+
    }
    45+
    Insert: {
    46+
    id: number
    47+
    name?: string | null
    48+
    status?: Database["public"]["Enums"]["user_status"] | null
    49+
    }
    50+
    Update: {
    51+
    id?: number
    52+
    name?: string | null
    53+
    status?: Database["public"]["Enums"]["user_status"] | null
    54+
    }
    55+
    Relationships: []
    56+
    }
    3957
    memes: {
    4058
    Row: {
    4159
    category: number | null
    @@ -519,6 +537,24 @@ test('typegen w/ one-to-one relationships', async () => {
    519537
    Update: {}
    520538
    Relationships: []
    521539
    }
    540+
    foreign_table: {
    541+
    Row: {
    542+
    id: number
    543+
    name: string | null
    544+
    status: Database["public"]["Enums"]["user_status"] | null
    545+
    }
    546+
    Insert: {
    547+
    id: number
    548+
    name?: string | null
    549+
    status?: Database["public"]["Enums"]["user_status"] | null
    550+
    }
    551+
    Update: {
    552+
    id?: number
    553+
    name?: string | null
    554+
    status?: Database["public"]["Enums"]["user_status"] | null
    555+
    }
    556+
    Relationships: []
    557+
    }
    522558
    memes: {
    523559
    Row: {
    524560
    category: number | null

    0 commit comments

    Comments
     (0)
    0