@supacloud/compiler 0.39.0 → 0.40.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,2 +1,2 @@
1
1
  /** Appended to the generated SDK; browser consumers need only the platform fetch API. */
2
- export declare const GRAPHQL_CLIENT_SOURCE = "\nexport interface GraphqlClientOptions {\n /** Project base URL, not the management API URL. HTTPS is required outside loopback. */\n url: string;\n /** Public project key only. Never put a service-role or management key in a browser. */\n publishableKey?: string;\n /** Resolved on every request so session refresh and logout are observed. */\n getAccessToken?: () => string | null | undefined | Promise<string | null | undefined>;\n fetch?: (url: string, init: RequestInit) => Promise<Response>;\n}\n\nexport interface GraphqlRequestOptions {\n signal?: AbortSignal;\n}\n\nexport class GraphqlRequestError extends Error {\n constructor(\n public readonly code: \"http\" | \"graphql\" | \"invalid-response\",\n message: string,\n public readonly status?: number,\n public readonly errors?: readonly unknown[],\n ) {\n super(message);\n this.name = \"GraphqlRequestError\";\n }\n}\n\nexport function createGraphqlClient(options: GraphqlClientOptions) {\n const endpoint = new URL(options.url);\n const loopback = [\"localhost\", \"127.0.0.1\", \"[::1]\"].includes(endpoint.hostname);\n if (endpoint.protocol !== \"https:\" && !(endpoint.protocol === \"http:\" && loopback)) {\n throw new Error(\"GraphQL requires HTTPS outside loopback development.\");\n }\n if (endpoint.username || endpoint.password || endpoint.search || endpoint.hash) {\n throw new Error(\"GraphQL project URLs must not contain credentials, query parameters or fragments.\");\n }\n endpoint.pathname = endpoint.pathname.replace(/\\/$/, \"\") + \"/graphql/v1\";\n const fetcher = options.fetch ?? globalThis.fetch.bind(globalThis);\n return getSdk<GraphqlRequestOptions>(async (\n query: string,\n variables?: unknown,\n request?: GraphqlRequestOptions,\n ): Promise<unknown> => {\n const headers = new Headers({ \"Content-Type\": \"application/json\", Accept: \"application/json\" });\n if (options.publishableKey) headers.set(\"apikey\", options.publishableKey);\n const token = await options.getAccessToken?.();\n if (token) headers.set(\"Authorization\", \"Bearer \" + token);\n const response = await fetcher(endpoint.toString(), {\n method: \"POST\",\n headers,\n body: JSON.stringify({ query, variables }),\n ...(request?.signal ? { signal: request.signal } : {}),\n redirect: \"error\",\n });\n if (!response.ok) {\n throw new GraphqlRequestError(\"http\", \"GraphQL HTTP request failed (\" + response.status + \").\", response.status);\n }\n let envelope: unknown;\n try {\n envelope = await response.json();\n } catch {\n throw new GraphqlRequestError(\"invalid-response\", \"GraphQL returned invalid JSON.\", response.status);\n }\n if (!envelope || typeof envelope !== \"object\" || Array.isArray(envelope)) {\n throw new GraphqlRequestError(\"invalid-response\", \"GraphQL returned an invalid envelope.\", response.status);\n }\n if (\"errors\" in envelope) {\n if (!Array.isArray(envelope.errors)) {\n throw new GraphqlRequestError(\"invalid-response\", \"GraphQL returned invalid errors.\", response.status);\n }\n if (envelope.errors.length > 0) {\n throw new GraphqlRequestError(\"graphql\", \"GraphQL query failed.\", response.status, envelope.errors);\n }\n }\n if (!(\"data\" in envelope) || !envelope.data || typeof envelope.data !== \"object\" || Array.isArray(envelope.data)) {\n throw new GraphqlRequestError(\"invalid-response\", \"GraphQL returned no result object.\", response.status);\n }\n // The operation-specific parser in getSdk validates selected field values.\n return envelope.data;\n });\n}\n";
2
+ export declare const GRAPHQL_CLIENT_SOURCE = "\nexport interface GraphqlClientOptions {\n /** Project base URL, not the management API URL. HTTPS is required outside loopback. */\n url: string;\n /** Public project key only. Never put a service-role or management key in a browser. */\n publishableKey?: string;\n /** Resolved on every request so session refresh and logout are observed. */\n getAccessToken?: () => string | null | undefined | Promise<string | null | undefined>;\n /** Include the persisted-operation SHA while retaining the full query for pg_graphql compatibility. */\n persistedOperations?: boolean;\n fetch?: (url: string, init: RequestInit) => Promise<Response>;\n}\n\nexport interface GraphqlRequestOptions {\n signal?: AbortSignal;\n}\n\nexport interface GraphqlOperationMetadata {\n name: string;\n sha256: string;\n}\n\nexport class GraphqlRequestError extends Error {\n constructor(\n public readonly code: \"http\" | \"graphql\" | \"invalid-response\",\n message: string,\n public readonly status?: number,\n public readonly errors?: readonly unknown[],\n ) {\n super(message);\n this.name = \"GraphqlRequestError\";\n }\n}\n\nexport function createGraphqlClient(options: GraphqlClientOptions) {\n const endpoint = new URL(options.url);\n const loopback = [\"localhost\", \"127.0.0.1\", \"[::1]\"].includes(endpoint.hostname);\n if (endpoint.protocol !== \"https:\" && !(endpoint.protocol === \"http:\" && loopback)) {\n throw new Error(\"GraphQL requires HTTPS outside loopback development.\");\n }\n if (endpoint.username || endpoint.password || endpoint.search || endpoint.hash) {\n throw new Error(\"GraphQL project URLs must not contain credentials, query parameters or fragments.\");\n }\n endpoint.pathname = endpoint.pathname.replace(/\\/$/, \"\") + \"/graphql/v1\";\n const fetcher = options.fetch ?? globalThis.fetch.bind(globalThis);\n return getSdk<GraphqlRequestOptions>(async (\n query: string,\n variables?: unknown,\n request?: GraphqlRequestOptions,\n operation?: GraphqlOperationMetadata,\n ): Promise<unknown> => {\n const headers = new Headers({ \"Content-Type\": \"application/json\", Accept: \"application/json\" });\n if (options.publishableKey) headers.set(\"apikey\", options.publishableKey);\n const token = await options.getAccessToken?.();\n if (token) headers.set(\"Authorization\", \"Bearer \" + token);\n const response = await fetcher(endpoint.toString(), {\n method: \"POST\",\n headers,\n body: JSON.stringify({\n query,\n variables,\n ...(operation?.name ? { operationName: operation.name } : {}),\n ...(options.persistedOperations === false || !operation?.sha256 ? {} : {\n extensions: {\n persistedQuery: { version: 1, sha256Hash: operation.sha256 },\n },\n }),\n }),\n ...(request?.signal ? { signal: request.signal } : {}),\n redirect: \"error\",\n });\n if (!response.ok) {\n throw new GraphqlRequestError(\"http\", \"GraphQL HTTP request failed (\" + response.status + \").\", response.status);\n }\n let envelope: unknown;\n try {\n envelope = await response.json();\n } catch {\n throw new GraphqlRequestError(\"invalid-response\", \"GraphQL returned invalid JSON.\", response.status);\n }\n if (!envelope || typeof envelope !== \"object\" || Array.isArray(envelope)) {\n throw new GraphqlRequestError(\"invalid-response\", \"GraphQL returned an invalid envelope.\", response.status);\n }\n if (\"errors\" in envelope) {\n if (!Array.isArray(envelope.errors)) {\n throw new GraphqlRequestError(\"invalid-response\", \"GraphQL returned invalid errors.\", response.status);\n }\n if (envelope.errors.length > 0) {\n throw new GraphqlRequestError(\"graphql\", \"GraphQL query failed.\", response.status, envelope.errors);\n }\n }\n if (!(\"data\" in envelope) || !envelope.data || typeof envelope.data !== \"object\" || Array.isArray(envelope.data)) {\n throw new GraphqlRequestError(\"invalid-response\", \"GraphQL returned no result object.\", response.status);\n }\n // The operation-specific parser in getSdk validates selected field values.\n return envelope.data;\n });\n}\n";
@@ -0,0 +1,92 @@
1
+ import { type GraphQLSchema } from "graphql";
2
+ export type GraphqlSeverity = "error" | "warn";
3
+ export interface GraphqlGovernanceDiagnostic {
4
+ severity: GraphqlSeverity;
5
+ code: string;
6
+ message: string;
7
+ file?: string;
8
+ line?: number;
9
+ operation?: string;
10
+ }
11
+ export interface GraphqlGovernancePolicy {
12
+ /** Exact operation names or simple '*' suffix patterns. */
13
+ operations?: string[];
14
+ maxDepth?: number;
15
+ maxFields?: number;
16
+ maxComplexity?: number;
17
+ maxPageSize?: number;
18
+ }
19
+ export interface GraphqlOperationReport {
20
+ name: string;
21
+ operation: "query" | "mutation" | "subscription";
22
+ depth: number;
23
+ fields: number;
24
+ complexity: number;
25
+ pageSizes: number[];
26
+ allowed: boolean;
27
+ }
28
+ export interface GraphqlFeatureMatrix {
29
+ pgGraphql: "schema-snapshot";
30
+ query: boolean;
31
+ mutation: boolean;
32
+ subscription: boolean;
33
+ relayConnections: boolean;
34
+ filtering: boolean;
35
+ ordering: boolean;
36
+ aggregation: boolean;
37
+ byPk: boolean;
38
+ functions: boolean;
39
+ }
40
+ export interface GraphqlCompatibilityReport {
41
+ ok: boolean;
42
+ schema: {
43
+ path: string;
44
+ schemaHash: string;
45
+ schemaNormalizedHash: string;
46
+ };
47
+ features: GraphqlFeatureMatrix;
48
+ operations: GraphqlOperationReport[];
49
+ diagnostics: GraphqlGovernanceDiagnostic[];
50
+ }
51
+ export interface GraphqlSchemaChange {
52
+ severity: "breaking" | "non-breaking";
53
+ code: string;
54
+ message: string;
55
+ path: string;
56
+ }
57
+ export interface GraphqlSchemaDiff {
58
+ ok: boolean;
59
+ breaking: GraphqlSchemaChange[];
60
+ nonBreaking: GraphqlSchemaChange[];
61
+ }
62
+ export interface GraphqlRoleSnapshot {
63
+ role: string;
64
+ schema: string;
65
+ schemaHash: string;
66
+ schemaNormalizedHash: string;
67
+ }
68
+ export interface GraphqlRoleSnapshotReport {
69
+ ok: boolean;
70
+ roles: GraphqlRoleSnapshot[];
71
+ diagnostics: GraphqlGovernanceDiagnostic[];
72
+ }
73
+ export declare function schemaFromSource(source: string, path?: string): GraphQLSchema;
74
+ export declare function readGraphqlSchema(path: string): Promise<{
75
+ path: string;
76
+ source: string;
77
+ schema: GraphQLSchema;
78
+ schemaHash: string;
79
+ schemaNormalizedHash: string;
80
+ }>;
81
+ export declare function graphqlFeatureMatrix(schema: GraphQLSchema): GraphqlFeatureMatrix;
82
+ export declare function checkGraphqlCompatibility(schema: GraphQLSchema, documents: readonly {
83
+ source: string;
84
+ path?: string;
85
+ }[], policy?: GraphqlGovernancePolicy): Omit<GraphqlCompatibilityReport, "schema">;
86
+ export declare function diffGraphqlSchemas(previous: GraphQLSchema, current: GraphQLSchema): GraphqlSchemaDiff;
87
+ export declare function createRoleSnapshotReport(roles: readonly {
88
+ role: string;
89
+ path: string;
90
+ source: string;
91
+ }[]): GraphqlRoleSnapshotReport;
92
+ export declare function introspectionQuery(): string;
@@ -2,4 +2,5 @@
2
2
  * Project the standard Codegen result types, rather than independently interpreting
3
3
  * selections, fragments and conditional fields. Unsupported wire types fail closed.
4
4
  */
5
- export declare function renderGraphqlValidators(source: string, operationNames: readonly string[]): string;
5
+ export type GraphqlOperationKind = "query" | "mutation";
6
+ export declare function renderGraphqlValidators(source: string, operationNames: readonly string[], operationKinds?: ReadonlyMap<string, GraphqlOperationKind>): string;
package/dist/index.d.ts CHANGED
@@ -56,4 +56,6 @@ export type { ApplicationGraph, AspectRefNode, CachedModuleEntry, CheckProjectRe
56
56
  export { inspectRouteContracts, validateRouteContracts } from "./route-contracts";
57
57
  export { pullGraphqlSchema } from "./graphql-schema";
58
58
  export type { PullGraphqlSchemaOptions } from "./graphql-schema";
59
+ export { checkGraphqlCompatibility, createRoleSnapshotReport, diffGraphqlSchemas, graphqlFeatureMatrix, introspectionQuery, readGraphqlSchema, schemaFromSource, } from "./graphql-governance";
60
+ export type { GraphqlCompatibilityReport, GraphqlFeatureMatrix, GraphqlGovernanceDiagnostic, GraphqlGovernancePolicy, GraphqlOperationReport, GraphqlRoleSnapshot, GraphqlRoleSnapshotReport, GraphqlSchemaChange, GraphqlSchemaDiff, } from "./graphql-governance";
59
61
  export { generateDatabaseContracts, parseDatabaseContractsOptions, runDatabaseContractsFile, type DatabaseContractsOptions } from "./database-contracts";