@constructive-io/graphql-query 2.8.0 → 3.0.0

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.
package/ast.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import type { DocumentNode, FieldNode } from 'graphql';
1
+ import { type DocumentNode, type FieldNode } from 'graphql';
2
2
  import type { ASTFunctionParams, FieldSelection, MutationASTParams } from './types';
3
3
  export declare const getAll: ({ queryName, operationName, query: _query, selection, }: ASTFunctionParams) => DocumentNode;
4
4
  export declare const getCount: ({ queryName, operationName, query, }: Omit<ASTFunctionParams, "selection">) => DocumentNode;
package/ast.js CHANGED
@@ -36,6 +36,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
36
36
  exports.deleteOne = exports.patchOne = exports.createOne = exports.getOne = exports.getMany = exports.getCount = exports.getAll = void 0;
37
37
  exports.getSelections = getSelections;
38
38
  const t = __importStar(require("gql-ast"));
39
+ const graphql_1 = require("graphql");
39
40
  const inflection_1 = require("inflection");
40
41
  const custom_ast_1 = require("./custom-ast");
41
42
  const NON_MUTABLE_PROPS = ['createdAt', 'createdBy', 'updatedAt', 'updatedBy'];
@@ -76,7 +77,7 @@ const createGqlMutation = ({ operationName, mutationName, selectArgs, selections
76
77
  return t.document({
77
78
  definitions: [
78
79
  t.operationDefinition({
79
- operation: 'mutation',
80
+ operation: graphql_1.OperationTypeNode.MUTATION,
80
81
  name: mutationName,
81
82
  variableDefinitions,
82
83
  selectionSet: t.selectionSet({ selections: opSel }),
@@ -105,7 +106,7 @@ const getAll = ({ queryName, operationName, query: _query, selection, }) => {
105
106
  const ast = t.document({
106
107
  definitions: [
107
108
  t.operationDefinition({
108
- operation: 'query',
109
+ operation: graphql_1.OperationTypeNode.QUERY,
109
110
  name: queryName,
110
111
  selectionSet: t.selectionSet({ selections: opSel }),
111
112
  }),
@@ -149,7 +150,7 @@ const getCount = ({ queryName, operationName, query, }) => {
149
150
  const ast = t.document({
150
151
  definitions: [
151
152
  t.operationDefinition({
152
- operation: 'query',
153
+ operation: graphql_1.OperationTypeNode.QUERY,
153
154
  name: queryName,
154
155
  variableDefinitions,
155
156
  selectionSet: t.selectionSet({ selections: opSel }),
@@ -246,7 +247,7 @@ const getMany = ({ builder, queryName, operationName, query, selection, }) => {
246
247
  const ast = t.document({
247
248
  definitions: [
248
249
  t.operationDefinition({
249
- operation: 'query',
250
+ operation: graphql_1.OperationTypeNode.QUERY,
250
251
  name: queryName,
251
252
  variableDefinitions,
252
253
  selectionSet: t.selectionSet({
@@ -303,7 +304,7 @@ const getOne = ({ queryName, operationName, query, selection, }) => {
303
304
  const ast = t.document({
304
305
  definitions: [
305
306
  t.operationDefinition({
306
- operation: 'query',
307
+ operation: graphql_1.OperationTypeNode.QUERY,
307
308
  name: queryName,
308
309
  variableDefinitions,
309
310
  selectionSet: t.selectionSet({ selections: opSel }),
package/custom-ast.js CHANGED
@@ -42,6 +42,7 @@ exports.geometryAst = geometryAst;
42
42
  exports.intervalAst = intervalAst;
43
43
  exports.isIntervalType = isIntervalType;
44
44
  const t = __importStar(require("gql-ast"));
45
+ const graphql_1 = require("graphql");
45
46
  function getCustomAst(fieldDefn) {
46
47
  if (!fieldDefn) {
47
48
  return null;
@@ -116,28 +117,28 @@ function geometryPointAst(name) {
116
117
  function geometryCollectionAst(name) {
117
118
  // Manually create inline fragment since gql-ast doesn't support it
118
119
  const inlineFragment = {
119
- kind: 'InlineFragment',
120
+ kind: graphql_1.Kind.INLINE_FRAGMENT,
120
121
  typeCondition: {
121
- kind: 'NamedType',
122
+ kind: graphql_1.Kind.NAMED_TYPE,
122
123
  name: {
123
- kind: 'Name',
124
+ kind: graphql_1.Kind.NAME,
124
125
  value: 'GeometryPoint',
125
126
  },
126
127
  },
127
128
  selectionSet: {
128
- kind: 'SelectionSet',
129
+ kind: graphql_1.Kind.SELECTION_SET,
129
130
  selections: [
130
131
  {
131
- kind: 'Field',
132
+ kind: graphql_1.Kind.FIELD,
132
133
  name: {
133
- kind: 'Name',
134
+ kind: graphql_1.Kind.NAME,
134
135
  value: 'x',
135
136
  },
136
137
  },
137
138
  {
138
- kind: 'Field',
139
+ kind: graphql_1.Kind.FIELD,
139
140
  name: {
140
- kind: 'Name',
141
+ kind: graphql_1.Kind.NAME,
141
142
  value: 'y',
142
143
  },
143
144
  },
package/esm/ast.js CHANGED
@@ -1,4 +1,5 @@
1
1
  import * as t from 'gql-ast';
2
+ import { OperationTypeNode, } from 'graphql';
2
3
  import { camelize, singularize } from 'inflection';
3
4
  import { getCustomAst } from './custom-ast';
4
5
  const NON_MUTABLE_PROPS = ['createdAt', 'createdBy', 'updatedAt', 'updatedBy'];
@@ -39,7 +40,7 @@ const createGqlMutation = ({ operationName, mutationName, selectArgs, selections
39
40
  return t.document({
40
41
  definitions: [
41
42
  t.operationDefinition({
42
- operation: 'mutation',
43
+ operation: OperationTypeNode.MUTATION,
43
44
  name: mutationName,
44
45
  variableDefinitions,
45
46
  selectionSet: t.selectionSet({ selections: opSel }),
@@ -68,7 +69,7 @@ export const getAll = ({ queryName, operationName, query: _query, selection, })
68
69
  const ast = t.document({
69
70
  definitions: [
70
71
  t.operationDefinition({
71
- operation: 'query',
72
+ operation: OperationTypeNode.QUERY,
72
73
  name: queryName,
73
74
  selectionSet: t.selectionSet({ selections: opSel }),
74
75
  }),
@@ -111,7 +112,7 @@ export const getCount = ({ queryName, operationName, query, }) => {
111
112
  const ast = t.document({
112
113
  definitions: [
113
114
  t.operationDefinition({
114
- operation: 'query',
115
+ operation: OperationTypeNode.QUERY,
115
116
  name: queryName,
116
117
  variableDefinitions,
117
118
  selectionSet: t.selectionSet({ selections: opSel }),
@@ -207,7 +208,7 @@ export const getMany = ({ builder, queryName, operationName, query, selection, }
207
208
  const ast = t.document({
208
209
  definitions: [
209
210
  t.operationDefinition({
210
- operation: 'query',
211
+ operation: OperationTypeNode.QUERY,
211
212
  name: queryName,
212
213
  variableDefinitions,
213
214
  selectionSet: t.selectionSet({
@@ -263,7 +264,7 @@ export const getOne = ({ queryName, operationName, query, selection, }) => {
263
264
  const ast = t.document({
264
265
  definitions: [
265
266
  t.operationDefinition({
266
- operation: 'query',
267
+ operation: OperationTypeNode.QUERY,
267
268
  name: queryName,
268
269
  variableDefinitions,
269
270
  selectionSet: t.selectionSet({ selections: opSel }),
package/esm/custom-ast.js CHANGED
@@ -1,4 +1,5 @@
1
1
  import * as t from 'gql-ast';
2
+ import { Kind } from 'graphql';
2
3
  export function getCustomAst(fieldDefn) {
3
4
  if (!fieldDefn) {
4
5
  return null;
@@ -73,28 +74,28 @@ export function geometryPointAst(name) {
73
74
  export function geometryCollectionAst(name) {
74
75
  // Manually create inline fragment since gql-ast doesn't support it
75
76
  const inlineFragment = {
76
- kind: 'InlineFragment',
77
+ kind: Kind.INLINE_FRAGMENT,
77
78
  typeCondition: {
78
- kind: 'NamedType',
79
+ kind: Kind.NAMED_TYPE,
79
80
  name: {
80
- kind: 'Name',
81
+ kind: Kind.NAME,
81
82
  value: 'GeometryPoint',
82
83
  },
83
84
  },
84
85
  selectionSet: {
85
- kind: 'SelectionSet',
86
+ kind: Kind.SELECTION_SET,
86
87
  selections: [
87
88
  {
88
- kind: 'Field',
89
+ kind: Kind.FIELD,
89
90
  name: {
90
- kind: 'Name',
91
+ kind: Kind.NAME,
91
92
  value: 'x',
92
93
  },
93
94
  },
94
95
  {
95
- kind: 'Field',
96
+ kind: Kind.FIELD,
96
97
  name: {
97
- kind: 'Name',
98
+ kind: Kind.NAME,
98
99
  value: 'y',
99
100
  },
100
101
  },
@@ -0,0 +1,176 @@
1
+ /**
2
+ * QueryExecutor - Execute GraphQL queries using Grafast/PostGraphile v5
3
+ *
4
+ * This module provides a high-level interface for executing GraphQL queries
5
+ * against a PostgreSQL database using PostGraphile v5's Grafast execution engine.
6
+ */
7
+ import { execute } from 'grafast';
8
+ import { postgraphile } from 'postgraphile';
9
+ import { ConstructivePreset, makePgService } from 'graphile-settings';
10
+ import { withPgClientFromPgService } from 'graphile-build-pg';
11
+ import { LRUCache } from 'lru-cache';
12
+ /**
13
+ * Global cache for executor instances, keyed by connection string + schemas
14
+ */
15
+ const executorCache = new LRUCache({
16
+ max: 10,
17
+ dispose: async (entry) => {
18
+ try {
19
+ await entry.pgl.release();
20
+ }
21
+ catch {
22
+ // Ignore disposal errors
23
+ }
24
+ },
25
+ });
26
+ /**
27
+ * Build a cache key from connection string and schemas
28
+ */
29
+ const buildCacheKey = (connectionString, schemas) => {
30
+ return `${connectionString}:${schemas.sort().join(',')}`;
31
+ };
32
+ /**
33
+ * QueryExecutor - Execute GraphQL queries using Grafast
34
+ *
35
+ * Example usage:
36
+ * ```typescript
37
+ * const executor = new QueryExecutor({
38
+ * connectionString: 'postgres://user:pass@localhost/db',
39
+ * schemas: ['public'],
40
+ * pgSettings: { role: 'authenticated' },
41
+ * });
42
+ *
43
+ * await executor.initialize();
44
+ *
45
+ * const result = await executor.execute<{ allUsers: { nodes: User[] } }>(
46
+ * parse('query { allUsers { nodes { id name } } }')
47
+ * );
48
+ * ```
49
+ */
50
+ export class QueryExecutor {
51
+ options;
52
+ executor = null;
53
+ cacheKey;
54
+ constructor(options) {
55
+ this.options = options;
56
+ this.cacheKey = buildCacheKey(options.connectionString, options.schemas);
57
+ }
58
+ /**
59
+ * Initialize the executor by building or retrieving the PostGraphile schema
60
+ *
61
+ * This method is called automatically by execute() if not already initialized,
62
+ * but can be called explicitly for eager initialization.
63
+ */
64
+ async initialize() {
65
+ // Check cache first
66
+ const cached = executorCache.get(this.cacheKey);
67
+ if (cached) {
68
+ this.executor = cached;
69
+ return;
70
+ }
71
+ // Create new PostGraphile instance
72
+ const pgService = makePgService({
73
+ connectionString: this.options.connectionString,
74
+ schemas: this.options.schemas,
75
+ });
76
+ // Note: Using 'as unknown as' to bypass strict type checking
77
+ // because GraphileConfig.Preset doesn't include pgServices in its type definition
78
+ // but postgraphile() accepts it at runtime
79
+ const preset = {
80
+ extends: [ConstructivePreset],
81
+ pgServices: [pgService],
82
+ grafast: {
83
+ context: () => ({
84
+ pgSettings: this.options.pgSettings || {},
85
+ }),
86
+ },
87
+ };
88
+ const pgl = postgraphile(preset);
89
+ const schema = await pgl.getSchema();
90
+ const resolvedPreset = pgl.getResolvedPreset();
91
+ this.executor = {
92
+ pgl,
93
+ schema,
94
+ resolvedPreset,
95
+ pgService,
96
+ createdAt: Date.now(),
97
+ };
98
+ executorCache.set(this.cacheKey, this.executor);
99
+ }
100
+ /**
101
+ * Execute a GraphQL document against the schema
102
+ *
103
+ * @param document - Parsed GraphQL document (DocumentNode)
104
+ * @param variables - Optional variables for the query
105
+ * @param pgSettings - Optional per-request PostgreSQL settings (overrides constructor settings)
106
+ * @returns ExecutionResult with data and/or errors
107
+ */
108
+ async execute(document, variables, pgSettings) {
109
+ if (!this.executor) {
110
+ await this.initialize();
111
+ }
112
+ const { schema, resolvedPreset, pgService } = this.executor;
113
+ // Build context with pgSettings and withPgClient
114
+ const contextValue = {
115
+ pgSettings: pgSettings || this.options.pgSettings || {},
116
+ };
117
+ // Add withPgClient function using the pgService's configured key
118
+ const withPgClientKey = pgService.withPgClientKey ?? 'withPgClient';
119
+ contextValue[withPgClientKey] = withPgClientFromPgService.bind(null, pgService);
120
+ return execute({
121
+ schema,
122
+ document,
123
+ variableValues: variables,
124
+ contextValue,
125
+ resolvedPreset,
126
+ });
127
+ }
128
+ /**
129
+ * Get the GraphQL schema for introspection purposes
130
+ */
131
+ async getSchema() {
132
+ if (!this.executor) {
133
+ await this.initialize();
134
+ }
135
+ return this.executor.schema;
136
+ }
137
+ /**
138
+ * Get cache statistics
139
+ */
140
+ static getCacheStats() {
141
+ return {
142
+ size: executorCache.size,
143
+ maxSize: executorCache.max,
144
+ };
145
+ }
146
+ /**
147
+ * Clear all cached executors
148
+ */
149
+ static async clearCache() {
150
+ executorCache.clear();
151
+ }
152
+ /**
153
+ * Clear a specific executor from the cache
154
+ */
155
+ static async clearCacheEntry(connectionString, schemas) {
156
+ const key = buildCacheKey(connectionString, schemas);
157
+ return executorCache.delete(key);
158
+ }
159
+ }
160
+ /**
161
+ * Create a QueryExecutor instance with simplified options
162
+ *
163
+ * @param connectionString - PostgreSQL connection string
164
+ * @param schemas - Database schemas to expose
165
+ * @param pgSettings - Optional PostgreSQL settings
166
+ * @returns Initialized QueryExecutor
167
+ */
168
+ export const createExecutor = async (connectionString, schemas, pgSettings) => {
169
+ const executor = new QueryExecutor({
170
+ connectionString,
171
+ schemas,
172
+ pgSettings,
173
+ });
174
+ await executor.initialize();
175
+ return executor;
176
+ };
package/esm/index.js CHANGED
@@ -1,3 +1,4 @@
1
1
  export { QueryBuilder } from './query-builder';
2
+ export { QueryExecutor, createExecutor } from './executor';
2
3
  export * from './types';
3
4
  export * as MetaObject from './meta-object';
package/executor.d.ts ADDED
@@ -0,0 +1,88 @@
1
+ /**
2
+ * QueryExecutor - Execute GraphQL queries using Grafast/PostGraphile v5
3
+ *
4
+ * This module provides a high-level interface for executing GraphQL queries
5
+ * against a PostgreSQL database using PostGraphile v5's Grafast execution engine.
6
+ */
7
+ import type { DocumentNode, ExecutionResult, GraphQLSchema } from 'graphql';
8
+ /**
9
+ * Configuration options for QueryExecutor
10
+ */
11
+ export interface ExecutorOptions {
12
+ /** PostgreSQL connection string */
13
+ connectionString: string;
14
+ /** Database schemas to expose in the GraphQL schema */
15
+ schemas: string[];
16
+ /** PostgreSQL settings to apply (e.g., { role: 'authenticated' }) */
17
+ pgSettings?: Record<string, string>;
18
+ /** Maximum number of cached executor instances (default: 10) */
19
+ maxCacheSize?: number;
20
+ }
21
+ /**
22
+ * QueryExecutor - Execute GraphQL queries using Grafast
23
+ *
24
+ * Example usage:
25
+ * ```typescript
26
+ * const executor = new QueryExecutor({
27
+ * connectionString: 'postgres://user:pass@localhost/db',
28
+ * schemas: ['public'],
29
+ * pgSettings: { role: 'authenticated' },
30
+ * });
31
+ *
32
+ * await executor.initialize();
33
+ *
34
+ * const result = await executor.execute<{ allUsers: { nodes: User[] } }>(
35
+ * parse('query { allUsers { nodes { id name } } }')
36
+ * );
37
+ * ```
38
+ */
39
+ export declare class QueryExecutor {
40
+ private options;
41
+ private executor;
42
+ private cacheKey;
43
+ constructor(options: ExecutorOptions);
44
+ /**
45
+ * Initialize the executor by building or retrieving the PostGraphile schema
46
+ *
47
+ * This method is called automatically by execute() if not already initialized,
48
+ * but can be called explicitly for eager initialization.
49
+ */
50
+ initialize(): Promise<void>;
51
+ /**
52
+ * Execute a GraphQL document against the schema
53
+ *
54
+ * @param document - Parsed GraphQL document (DocumentNode)
55
+ * @param variables - Optional variables for the query
56
+ * @param pgSettings - Optional per-request PostgreSQL settings (overrides constructor settings)
57
+ * @returns ExecutionResult with data and/or errors
58
+ */
59
+ execute<T = unknown>(document: DocumentNode, variables?: Record<string, unknown>, pgSettings?: Record<string, string>): Promise<ExecutionResult<T>>;
60
+ /**
61
+ * Get the GraphQL schema for introspection purposes
62
+ */
63
+ getSchema(): Promise<GraphQLSchema>;
64
+ /**
65
+ * Get cache statistics
66
+ */
67
+ static getCacheStats(): {
68
+ size: number;
69
+ maxSize: number;
70
+ };
71
+ /**
72
+ * Clear all cached executors
73
+ */
74
+ static clearCache(): Promise<void>;
75
+ /**
76
+ * Clear a specific executor from the cache
77
+ */
78
+ static clearCacheEntry(connectionString: string, schemas: string[]): Promise<boolean>;
79
+ }
80
+ /**
81
+ * Create a QueryExecutor instance with simplified options
82
+ *
83
+ * @param connectionString - PostgreSQL connection string
84
+ * @param schemas - Database schemas to expose
85
+ * @param pgSettings - Optional PostgreSQL settings
86
+ * @returns Initialized QueryExecutor
87
+ */
88
+ export declare const createExecutor: (connectionString: string, schemas: string[], pgSettings?: Record<string, string>) => Promise<QueryExecutor>;
package/executor.js ADDED
@@ -0,0 +1,181 @@
1
+ "use strict";
2
+ /**
3
+ * QueryExecutor - Execute GraphQL queries using Grafast/PostGraphile v5
4
+ *
5
+ * This module provides a high-level interface for executing GraphQL queries
6
+ * against a PostgreSQL database using PostGraphile v5's Grafast execution engine.
7
+ */
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.createExecutor = exports.QueryExecutor = void 0;
10
+ const grafast_1 = require("grafast");
11
+ const postgraphile_1 = require("postgraphile");
12
+ const graphile_settings_1 = require("graphile-settings");
13
+ const graphile_build_pg_1 = require("graphile-build-pg");
14
+ const lru_cache_1 = require("lru-cache");
15
+ /**
16
+ * Global cache for executor instances, keyed by connection string + schemas
17
+ */
18
+ const executorCache = new lru_cache_1.LRUCache({
19
+ max: 10,
20
+ dispose: async (entry) => {
21
+ try {
22
+ await entry.pgl.release();
23
+ }
24
+ catch {
25
+ // Ignore disposal errors
26
+ }
27
+ },
28
+ });
29
+ /**
30
+ * Build a cache key from connection string and schemas
31
+ */
32
+ const buildCacheKey = (connectionString, schemas) => {
33
+ return `${connectionString}:${schemas.sort().join(',')}`;
34
+ };
35
+ /**
36
+ * QueryExecutor - Execute GraphQL queries using Grafast
37
+ *
38
+ * Example usage:
39
+ * ```typescript
40
+ * const executor = new QueryExecutor({
41
+ * connectionString: 'postgres://user:pass@localhost/db',
42
+ * schemas: ['public'],
43
+ * pgSettings: { role: 'authenticated' },
44
+ * });
45
+ *
46
+ * await executor.initialize();
47
+ *
48
+ * const result = await executor.execute<{ allUsers: { nodes: User[] } }>(
49
+ * parse('query { allUsers { nodes { id name } } }')
50
+ * );
51
+ * ```
52
+ */
53
+ class QueryExecutor {
54
+ options;
55
+ executor = null;
56
+ cacheKey;
57
+ constructor(options) {
58
+ this.options = options;
59
+ this.cacheKey = buildCacheKey(options.connectionString, options.schemas);
60
+ }
61
+ /**
62
+ * Initialize the executor by building or retrieving the PostGraphile schema
63
+ *
64
+ * This method is called automatically by execute() if not already initialized,
65
+ * but can be called explicitly for eager initialization.
66
+ */
67
+ async initialize() {
68
+ // Check cache first
69
+ const cached = executorCache.get(this.cacheKey);
70
+ if (cached) {
71
+ this.executor = cached;
72
+ return;
73
+ }
74
+ // Create new PostGraphile instance
75
+ const pgService = (0, graphile_settings_1.makePgService)({
76
+ connectionString: this.options.connectionString,
77
+ schemas: this.options.schemas,
78
+ });
79
+ // Note: Using 'as unknown as' to bypass strict type checking
80
+ // because GraphileConfig.Preset doesn't include pgServices in its type definition
81
+ // but postgraphile() accepts it at runtime
82
+ const preset = {
83
+ extends: [graphile_settings_1.ConstructivePreset],
84
+ pgServices: [pgService],
85
+ grafast: {
86
+ context: () => ({
87
+ pgSettings: this.options.pgSettings || {},
88
+ }),
89
+ },
90
+ };
91
+ const pgl = (0, postgraphile_1.postgraphile)(preset);
92
+ const schema = await pgl.getSchema();
93
+ const resolvedPreset = pgl.getResolvedPreset();
94
+ this.executor = {
95
+ pgl,
96
+ schema,
97
+ resolvedPreset,
98
+ pgService,
99
+ createdAt: Date.now(),
100
+ };
101
+ executorCache.set(this.cacheKey, this.executor);
102
+ }
103
+ /**
104
+ * Execute a GraphQL document against the schema
105
+ *
106
+ * @param document - Parsed GraphQL document (DocumentNode)
107
+ * @param variables - Optional variables for the query
108
+ * @param pgSettings - Optional per-request PostgreSQL settings (overrides constructor settings)
109
+ * @returns ExecutionResult with data and/or errors
110
+ */
111
+ async execute(document, variables, pgSettings) {
112
+ if (!this.executor) {
113
+ await this.initialize();
114
+ }
115
+ const { schema, resolvedPreset, pgService } = this.executor;
116
+ // Build context with pgSettings and withPgClient
117
+ const contextValue = {
118
+ pgSettings: pgSettings || this.options.pgSettings || {},
119
+ };
120
+ // Add withPgClient function using the pgService's configured key
121
+ const withPgClientKey = pgService.withPgClientKey ?? 'withPgClient';
122
+ contextValue[withPgClientKey] = graphile_build_pg_1.withPgClientFromPgService.bind(null, pgService);
123
+ return (0, grafast_1.execute)({
124
+ schema,
125
+ document,
126
+ variableValues: variables,
127
+ contextValue,
128
+ resolvedPreset,
129
+ });
130
+ }
131
+ /**
132
+ * Get the GraphQL schema for introspection purposes
133
+ */
134
+ async getSchema() {
135
+ if (!this.executor) {
136
+ await this.initialize();
137
+ }
138
+ return this.executor.schema;
139
+ }
140
+ /**
141
+ * Get cache statistics
142
+ */
143
+ static getCacheStats() {
144
+ return {
145
+ size: executorCache.size,
146
+ maxSize: executorCache.max,
147
+ };
148
+ }
149
+ /**
150
+ * Clear all cached executors
151
+ */
152
+ static async clearCache() {
153
+ executorCache.clear();
154
+ }
155
+ /**
156
+ * Clear a specific executor from the cache
157
+ */
158
+ static async clearCacheEntry(connectionString, schemas) {
159
+ const key = buildCacheKey(connectionString, schemas);
160
+ return executorCache.delete(key);
161
+ }
162
+ }
163
+ exports.QueryExecutor = QueryExecutor;
164
+ /**
165
+ * Create a QueryExecutor instance with simplified options
166
+ *
167
+ * @param connectionString - PostgreSQL connection string
168
+ * @param schemas - Database schemas to expose
169
+ * @param pgSettings - Optional PostgreSQL settings
170
+ * @returns Initialized QueryExecutor
171
+ */
172
+ const createExecutor = async (connectionString, schemas, pgSettings) => {
173
+ const executor = new QueryExecutor({
174
+ connectionString,
175
+ schemas,
176
+ pgSettings,
177
+ });
178
+ await executor.initialize();
179
+ return executor;
180
+ };
181
+ exports.createExecutor = createExecutor;
package/index.d.ts CHANGED
@@ -1,3 +1,4 @@
1
1
  export { QueryBuilder } from './query-builder';
2
+ export { QueryExecutor, createExecutor } from './executor';
2
3
  export * from './types';
3
4
  export * as MetaObject from './meta-object';
package/index.js CHANGED
@@ -36,8 +36,11 @@ var __importStar = (this && this.__importStar) || (function () {
36
36
  };
37
37
  })();
38
38
  Object.defineProperty(exports, "__esModule", { value: true });
39
- exports.MetaObject = exports.QueryBuilder = void 0;
39
+ exports.MetaObject = exports.createExecutor = exports.QueryExecutor = exports.QueryBuilder = void 0;
40
40
  var query_builder_1 = require("./query-builder");
41
41
  Object.defineProperty(exports, "QueryBuilder", { enumerable: true, get: function () { return query_builder_1.QueryBuilder; } });
42
+ var executor_1 = require("./executor");
43
+ Object.defineProperty(exports, "QueryExecutor", { enumerable: true, get: function () { return executor_1.QueryExecutor; } });
44
+ Object.defineProperty(exports, "createExecutor", { enumerable: true, get: function () { return executor_1.createExecutor; } });
42
45
  __exportStar(require("./types"), exports);
43
46
  exports.MetaObject = __importStar(require("./meta-object"));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@constructive-io/graphql-query",
3
- "version": "2.8.0",
3
+ "version": "3.0.0",
4
4
  "description": "Constructive GraphQL Query",
5
5
  "author": "Constructive <developers@constructive.io>",
6
6
  "main": "index.js",
@@ -30,9 +30,15 @@
30
30
  },
31
31
  "dependencies": {
32
32
  "ajv": "^7.0.4",
33
- "gql-ast": "^2.7.0",
34
- "graphql": "15.10.1",
35
- "inflection": "^3.0.2"
33
+ "gql-ast": "^3.0.0",
34
+ "grafast": "^1.0.0-rc.4",
35
+ "graphile-build-pg": "^5.0.0-rc.3",
36
+ "graphile-config": "1.0.0-rc.3",
37
+ "graphile-settings": "^4.0.0",
38
+ "graphql": "^16.9.0",
39
+ "inflection": "^3.0.0",
40
+ "lru-cache": "^10.4.3",
41
+ "postgraphile": "^5.0.0-rc.4"
36
42
  },
37
43
  "keywords": [
38
44
  "query",
@@ -42,7 +48,7 @@
42
48
  "database"
43
49
  ],
44
50
  "devDependencies": {
45
- "makage": "^0.1.12"
51
+ "makage": "^0.1.10"
46
52
  },
47
- "gitHead": "048188f6b43ffaa6146e7694b2b0d35d34cb2945"
53
+ "gitHead": "b2daeefe49cdefb3d01ea63cf778fb9b847ab5fe"
48
54
  }
package/types.d.ts CHANGED
@@ -137,3 +137,27 @@ export declare function isGraphQLVariables(obj: unknown): obj is GraphQLVariable
137
137
  export type StrictRecord<K extends PropertyKey, V> = Record<K, V> & {
138
138
  [P in PropertyKey]: P extends K ? V : never;
139
139
  };
140
+ /**
141
+ * Configuration options for QueryExecutor
142
+ */
143
+ export interface ExecutorOptions {
144
+ /** PostgreSQL connection string */
145
+ connectionString: string;
146
+ /** Database schemas to expose in the GraphQL schema */
147
+ schemas: string[];
148
+ /** PostgreSQL settings to apply (e.g., { role: 'authenticated' }) */
149
+ pgSettings?: Record<string, string>;
150
+ /** Maximum number of cached executor instances (default: 10) */
151
+ maxCacheSize?: number;
152
+ }
153
+ /**
154
+ * Cache statistics for QueryExecutor
155
+ */
156
+ export interface ExecutorCacheStats {
157
+ size: number;
158
+ maxSize: number;
159
+ }
160
+ /**
161
+ * Re-export GraphQL execution types for convenience
162
+ */
163
+ export type { ExecutionResult, GraphQLError, GraphQLSchema, } from 'graphql';