@settlemint/sdk-hasura
Version:
Hasura and PostgreSQL integration module for SettleMint SDK, enabling database operations and GraphQL queries
1 lines • 11.7 kB
Source Map (JSON)
{"version":3,"file":"hasura.cjs","names":["databaseName: string","client: ReturnType<typeof createHasuraMetadataClient>","tableOptions: {\n includeSchemas?: string[];\n excludeSchemas?: string[];\n }","messages: string[]","UrlOrPathSchema","options: ClientOptions","clientOptions?: RequestConfig","logger?: Logger","GraphQLClient","query: object"],"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":"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"}