UNPKG

@settlemint/sdk-hasura

Version:

Hasura and PostgreSQL integration module for SettleMint SDK, enabling database operations and GraphQL queries

1 lines 11.4 kB
{"version":3,"file":"hasura.cjs","names":["messages: string[]","z","UrlOrPathSchema","ApplicationAccessTokenSchema","GraphQLClient"],"sources":["../src/utils/track-all-tables.ts","../src/hasura.ts"],"sourcesContent":["import type { createHasuraMetadataClient } from \"../hasura.js\";\n\n/**\n * Track all tables in a database\n *\n * @param databaseName - The name of the database to track tables for\n * @param client - The client options to use for the Hasura client\n * @param tableOptions - The options to use for the table tracking\n * @param tableOptions.includeSchemas - The schemas to include in the tracking\n * @param tableOptions.excludeSchemas - The schemas to exclude from the tracking\n * @returns A promise that resolves to an object with a result property indicating success or failure\n * @example\n * import { trackAllTables } from \"@settlemint/sdk-hasura/utils/track-all-tables\";\n *\n * const client = createHasuraMetadataClient({\n * instance: \"http://localhost:8080\",\n * accessToken: \"test\",\n * adminSecret: \"test\",\n * });\n *\n * const result = await trackAllTables(\"default\", client, {\n * excludeSchemas: [\"drizzle\"],\n * });\n * if (result.result === \"success\") {\n * console.log(\"Tables tracked successfully\");\n * } else {\n * console.error(\"Failed to track tables\");\n * }\n */\nexport async function trackAllTables(\n databaseName: string,\n client: ReturnType<typeof createHasuraMetadataClient>,\n tableOptions: {\n includeSchemas?: string[];\n excludeSchemas?: string[];\n } = {\n includeSchemas: undefined,\n excludeSchemas: undefined,\n },\n): Promise<{ result: \"success\" | \"no-tables\"; messages: string[] }> {\n const messages: string[] = [];\n\n const { includeSchemas, excludeSchemas } = tableOptions;\n\n // Get all tables using pg_get_source_tables\n const getTablesResult = await client<\n Array<{\n name: string;\n schema: string;\n }>\n >({\n type: \"pg_get_source_tables\",\n args: {\n source: databaseName,\n },\n });\n\n if (!getTablesResult.ok) {\n throw new Error(`Failed to get tables: ${JSON.stringify(getTablesResult.data)}`);\n }\n\n const tables = getTablesResult.data;\n\n if (tables.length === 0) {\n return { result: \"no-tables\" as const, messages };\n }\n\n messages.push(`Found ${tables.length} tables in database \"${databaseName}\"`);\n\n // Incase a table is already tracked, untrack it first\n await client<{ code?: string }>({\n type: \"pg_untrack_tables\",\n args: {\n tables: tables.map((table) => ({\n table: table,\n })),\n allow_warnings: true,\n },\n });\n\n const tablesToTrack = tables.filter((table) => {\n if (Array.isArray(includeSchemas)) {\n return includeSchemas.includes(table.schema);\n }\n if (Array.isArray(excludeSchemas)) {\n return !excludeSchemas.includes(table.schema);\n }\n return true;\n });\n\n // Track all tables\n const trackResult = await client<{ code?: string }>({\n type: \"pg_track_tables\",\n args: {\n tables: tablesToTrack.map((table) => ({\n table: table,\n })),\n allow_warnings: true,\n },\n });\n\n if (!trackResult.ok) {\n throw new Error(`Failed to track tables: ${JSON.stringify(trackResult.data)}`);\n }\n\n messages.push(`Successfully tracked ${tablesToTrack.length} tables`);\n\n return { result: \"success\" as const, messages };\n}\n","import { extractBaseUrlBeforeSegment } from \"@settlemint/sdk-utils\";\nimport { appendHeaders } from \"@settlemint/sdk-utils/http\";\nimport { type Logger, requestLogger } from \"@settlemint/sdk-utils/logging\";\nimport { ensureServer } from \"@settlemint/sdk-utils/runtime\";\nimport { ApplicationAccessTokenSchema, UrlOrPathSchema, validate } from \"@settlemint/sdk-utils/validation\";\nimport { type AbstractSetupSchema, initGraphQLTada } from \"gql.tada\";\nimport { GraphQLClient } from \"graphql-request\";\nimport { z } from \"zod\";\n\n/**\n * Type definition for GraphQL client configuration options\n */\nexport type RequestConfig = ConstructorParameters<typeof GraphQLClient>[1];\n\n/**\n * Schema for validating client options for the Hasura client.\n */\nexport const ClientOptionsSchema = z.object({\n instance: UrlOrPathSchema,\n accessToken: ApplicationAccessTokenSchema.optional(),\n adminSecret: z.string(),\n cache: z.enum([\"default\", \"force-cache\", \"no-cache\", \"no-store\", \"only-if-cached\", \"reload\"]).optional(),\n});\n\n/**\n * Type definition for client options derived from the ClientOptionsSchema.\n */\nexport type ClientOptions = z.infer<typeof ClientOptionsSchema>;\n\n/**\n * Creates a Hasura GraphQL client with proper type safety using gql.tada\n *\n * @param options - Configuration options for the client\n * @param clientOptions - Optional GraphQL client configuration options\n * @param logger - Optional logger to use for logging the requests\n * @returns An object containing:\n * - client: The configured GraphQL client instance\n * - graphql: The initialized gql.tada function for type-safe queries\n * @throws Will throw an error if the options fail validation against ClientOptionsSchema\n * @example\n * import { createHasuraClient } from '@settlemint/sdk-hasura';\n * import type { introspection } from \"@schemas/hasura-env\";\n * import { createLogger, requestLogger } from \"@settlemint/sdk-utils/logging\";\n *\n * const logger = createLogger();\n *\n * const { client, graphql } = createHasuraClient<{\n * introspection: introspection;\n * disableMasking: true;\n * scalars: {\n * timestamp: string;\n * timestampz: string;\n * uuid: string;\n * date: string;\n * time: string;\n * jsonb: string;\n * numeric: string;\n * interval: string;\n * geometry: string;\n * geography: string;\n * };\n * }>({\n * instance: process.env.SETTLEMINT_HASURA_ENDPOINT,\n * accessToken: process.env.SETTLEMINT_ACCESS_TOKEN,\n * adminSecret: process.env.SETTLEMINT_HASURA_ADMIN_SECRET,\n * }, {\n * fetch: requestLogger(logger, \"hasura\", fetch) as typeof fetch,\n * });\n *\n * // Making GraphQL queries\n * const query = graphql(`\n * query GetUsers {\n * users {\n * id\n * name\n * email\n * }\n * }\n * `);\n *\n * const result = await client.request(query);\n */\nexport function createHasuraClient<const Setup extends AbstractSetupSchema>(\n options: ClientOptions,\n clientOptions?: RequestConfig,\n logger?: Logger,\n): {\n client: GraphQLClient;\n graphql: initGraphQLTada<Setup>;\n} {\n ensureServer();\n const validatedOptions = validate(ClientOptionsSchema, options);\n const graphql = initGraphQLTada<Setup>();\n const fullUrl = new URL(validatedOptions.instance).toString();\n\n return {\n client: new GraphQLClient(fullUrl, {\n ...clientOptions,\n headers: appendHeaders(clientOptions?.headers, {\n \"x-auth-token\": validatedOptions.accessToken,\n \"x-hasura-admin-secret\": validatedOptions.adminSecret,\n }),\n fetch: (logger ? requestLogger(logger, \"hasura\", fetch) : fetch) as typeof fetch,\n }),\n graphql,\n };\n}\n\n/**\n * Creates a Hasura Metadata client\n *\n * @param options - Configuration options for the client\n * @param logger - Optional logger to use for logging the requests\n * @returns A function that can be used to make requests to the Hasura Metadata API\n * @throws Will throw an error if the options fail validation against ClientOptionsSchema\n * @example\n * import { createHasuraMetadataClient } from '@settlemint/sdk-hasura';\n *\n * const client = createHasuraMetadataClient({\n * instance: process.env.SETTLEMINT_HASURA_ENDPOINT,\n * accessToken: process.env.SETTLEMINT_ACCESS_TOKEN,\n * adminSecret: process.env.SETTLEMINT_HASURA_ADMIN_SECRET,\n * });\n *\n * const result = await client({\n * type: \"pg_get_source_tables\",\n * args: {\n * source: \"default\",\n * },\n * });\n */\nexport function createHasuraMetadataClient(options: ClientOptions, logger?: Logger) {\n ensureServer();\n const validatedOptions = validate(ClientOptionsSchema, options);\n const baseUrl = extractBaseUrlBeforeSegment(options.instance, \"/v1/graphql\");\n const queryEndpoint = new URL(`${baseUrl}/v1/metadata`).toString();\n const fetchInstance = logger ? requestLogger(logger, \"hasura\", fetch) : fetch;\n\n return async <T>(query: object): Promise<{ ok: boolean; data: T }> => {\n const response = await fetchInstance(queryEndpoint, {\n method: \"POST\",\n headers: appendHeaders(\n { \"Content-Type\": \"application/json\" },\n {\n \"x-auth-token\": validatedOptions.accessToken,\n \"x-hasura-admin-secret\": validatedOptions.adminSecret,\n },\n ),\n body: JSON.stringify(query),\n });\n\n if (!response.ok) {\n return { ok: false, data: (await response.json()) as T };\n }\n\n return { ok: true, data: (await response.json()) as T };\n };\n}\n\nexport type { FragmentOf, ResultOf, VariablesOf } from \"gql.tada\";\nexport { readFragment } from \"gql.tada\";\nexport { trackAllTables } from \"./utils/track-all-tables.js\";\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA6BA,eAAsB,eACpB,cACA,QACA,eAGI;CACF,gBAAgB;CAChB,gBAAgB;CACjB,EACiE;CAClE,MAAMA,WAAqB,EAAE;CAE7B,MAAM,EAAE,gBAAgB,mBAAmB;CAG3C,MAAM,kBAAkB,MAAM,OAK5B;EACA,MAAM;EACN,MAAM,EACJ,QAAQ,cACT;EACF,CAAC;AAEF,KAAI,CAAC,gBAAgB,IAAI;AACvB,QAAM,IAAI,MAAM,yBAAyB,KAAK,UAAU,gBAAgB,KAAK,GAAG;;CAGlF,MAAM,SAAS,gBAAgB;AAE/B,KAAI,OAAO,WAAW,GAAG;AACvB,SAAO;GAAE,QAAQ;GAAsB;GAAU;;AAGnD,UAAS,KAAK,SAAS,OAAO,OAAO,uBAAuB,aAAa,GAAG;AAG5E,OAAM,OAA0B;EAC9B,MAAM;EACN,MAAM;GACJ,QAAQ,OAAO,KAAK,WAAW,EACtB,OACR,EAAE;GACH,gBAAgB;GACjB;EACF,CAAC;CAEF,MAAM,gBAAgB,OAAO,QAAQ,UAAU;AAC7C,MAAI,MAAM,QAAQ,eAAe,EAAE;AACjC,UAAO,eAAe,SAAS,MAAM,OAAO;;AAE9C,MAAI,MAAM,QAAQ,eAAe,EAAE;AACjC,UAAO,CAAC,eAAe,SAAS,MAAM,OAAO;;AAE/C,SAAO;GACP;CAGF,MAAM,cAAc,MAAM,OAA0B;EAClD,MAAM;EACN,MAAM;GACJ,QAAQ,cAAc,KAAK,WAAW,EAC7B,OACR,EAAE;GACH,gBAAgB;GACjB;EACF,CAAC;AAEF,KAAI,CAAC,YAAY,IAAI;AACnB,QAAM,IAAI,MAAM,2BAA2B,KAAK,UAAU,YAAY,KAAK,GAAG;;AAGhF,UAAS,KAAK,wBAAwB,cAAc,OAAO,SAAS;AAEpE,QAAO;EAAE,QAAQ;EAAoB;EAAU;;;;;;;;AC1FjD,MAAa,sBAAsBC,MAAE,OAAO;CAC1C,UAAUC;CACV,aAAaC,+DAA6B,UAAU;CACpD,aAAaF,MAAE,QAAQ;CACvB,OAAOA,MAAE,KAAK;EAAC;EAAW;EAAe;EAAY;EAAY;EAAkB;EAAS,CAAC,CAAC,UAAU;CACzG,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA4DF,SAAgB,mBACd,SACA,eACA,QAIA;AACA,mDAAc;CACd,MAAM,mEAA4B,qBAAqB,QAAQ;CAC/D,MAAM,yCAAkC;CACxC,MAAM,UAAU,IAAI,IAAI,iBAAiB,SAAS,CAAC,UAAU;AAE7D,QAAO;EACL,QAAQ,IAAIG,8BAAc,SAAS;GACjC,GAAG;GACH,wDAAuB,eAAe,SAAS;IAC7C,gBAAgB,iBAAiB;IACjC,yBAAyB,iBAAiB;IAC3C,CAAC;GACF,OAAQ,2DAAuB,QAAQ,UAAU,MAAM,GAAG;GAC3D,CAAC;EACF;EACD;;;;;;;;;;;;;;;;;;;;;;;;;AA0BH,SAAgB,2BAA2B,SAAwB,QAAiB;AAClF,mDAAc;CACd,MAAM,mEAA4B,qBAAqB,QAAQ;CAC/D,MAAM,kEAAsC,QAAQ,UAAU,cAAc;CAC5E,MAAM,gBAAgB,IAAI,IAAI,GAAG,QAAQ,cAAc,CAAC,UAAU;CAClE,MAAM,gBAAgB,2DAAuB,QAAQ,UAAU,MAAM,GAAG;AAExE,QAAO,OAAU,UAAqD;EACpE,MAAM,WAAW,MAAM,cAAc,eAAe;GAClD,QAAQ;GACR,wDACE,EAAE,gBAAgB,oBAAoB,EACtC;IACE,gBAAgB,iBAAiB;IACjC,yBAAyB,iBAAiB;IAC3C,CACF;GACD,MAAM,KAAK,UAAU,MAAM;GAC5B,CAAC;AAEF,MAAI,CAAC,SAAS,IAAI;AAChB,UAAO;IAAE,IAAI;IAAO,MAAO,MAAM,SAAS,MAAM;IAAQ;;AAG1D,SAAO;GAAE,IAAI;GAAM,MAAO,MAAM,SAAS,MAAM;GAAQ"}