orchid-graphql 0.0.1 → 0.0.2

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/README.md CHANGED
@@ -64,10 +64,10 @@ const db = orchidORM(
64
64
  )
65
65
 
66
66
  await db.$adapter.query(`
67
- create table post (
68
- id serial primary key,
69
- text text not null
70
- );
67
+ create table post (
68
+ id serial primary key,
69
+ text text not null
70
+ );
71
71
  `)
72
72
 
73
73
  // Define GraphQL schema
package/dist/index.cjs CHANGED
@@ -44,12 +44,13 @@ function set_query_page_result(query, get_page) {
44
44
  }
45
45
  return get_page(data);
46
46
  }
47
- const { handleResult } = query.query;
48
- query.query.handleResult = (...args) => {
49
- const data = handleResult(...args);
50
- return _get_page(data);
47
+ const _query = query.query;
48
+ const { handleResult } = _query;
49
+ _query.handleResult = (q, result, s2) => {
50
+ const data = handleResult(q, result, s2);
51
+ return s2 ? data : _get_page(data);
51
52
  };
52
- query.query[s] = _get_page;
53
+ _query[s] = _get_page;
53
54
  return query;
54
55
  }
55
56
  function get_query_pagination_handler(query) {
@@ -81,7 +82,6 @@ var CursorPaginator = class {
81
82
  paginate(query, args = {}) {
82
83
  const take = args.take ?? this.options.take;
83
84
  const { cursor } = args;
84
- console.log("paginating query", query);
85
85
  query = query.clear("order");
86
86
  for (const field of this.fields) {
87
87
  query = query.select(field.name).order({ [field.name]: field.desc ? "DESC" : "ASC" });
@@ -234,19 +234,27 @@ var import_pqb = require("pqb");
234
234
  function definePageResolver(paginator, options = {}) {
235
235
  const { tableField, filters, modify } = options;
236
236
  return defineFieldResolver({
237
- modify: (query, { field, tree, graph }) => query.select({
238
- [field]: (q) => {
239
- const page_query = graph._resolve_page({
240
- tree,
241
- query: q[tableField || field],
242
- paginator,
243
- filters
244
- });
245
- const get_page = get_query_pagination_handler(page_query);
246
- (0, import_pqb.addParserToQuery)(page_query.query, field, get_page);
247
- return modify ? modify(page_query, tree) : page_query;
248
- }
249
- })
237
+ modify: (query, { field, tree, graph }) => {
238
+ let get_page;
239
+ query = query.select({
240
+ [field]: (q) => {
241
+ q = graph._resolve_page({
242
+ tree,
243
+ query: q[tableField || field],
244
+ paginator,
245
+ filters
246
+ });
247
+ get_page = get_query_pagination_handler(q);
248
+ return modify ? modify(q, tree) : q;
249
+ }
250
+ });
251
+ const parser = query.query.parsers?.[field];
252
+ (0, import_pqb.addParserToQuery)(query.query, field, (nodes) => {
253
+ nodes = parser ? parser(nodes) : nodes;
254
+ return get_page(nodes);
255
+ });
256
+ return query;
257
+ }
250
258
  });
251
259
  }
252
260
 
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/paginators/base.ts","../src/paginators/cursor.ts","../src/utils/query-context.ts","../src/utils/run-after.ts","../src/resolvers/field.ts","../src/resolvers/graph.ts","../src/resolvers/page.ts","../src/resolvers/relation.ts","../src/utils/is-plain-object.ts","../src/filters/filters.ts","../src/resolvers/table.ts"],"sourcesContent":["export {\n\tdefineCursorPaginator as cursor,\n\tdefineCursorPaginator,\n} from \"./paginators/cursor\"\nexport {\n\tdefineFieldResolver,\n\tdefineFieldResolver as field,\n} from \"./resolvers/field\"\nexport {\n\tcreateGraphResolver,\n\tcreateGraphResolver as graph,\n} from \"./resolvers/graph\"\nexport {\n\tdefinePageResolver,\n\tdefinePageResolver as page,\n} from \"./resolvers/page\"\nexport {\n\tdefineRelationResolver,\n\tdefineRelationResolver as relation,\n} from \"./resolvers/relation\"\nexport {\n\tdefineTableResolver,\n\tdefineTableResolver as table,\n} from \"./resolvers/table\"\n","import { Query } from \"pqb\"\n\nexport interface Paginator {\n\t/** GraphQL path, for example: `[\"nodes\"]` */\n\treadonly path: string[]\n\tpaginate(query: Query, ...args: any[]): Query\n}\n\ntype GetPageFn<P> = (nodes: any[]) => P\n\nconst s = Symbol()\n\n// FIXME use proper orchid methods, set result type\nexport function set_query_page_result<P>(query: Query, get_page: GetPageFn<P>) {\n\tfunction _get_page(data: any) {\n\t\tif (!Array.isArray(data)) {\n\t\t\tthrow new Error(`Paginator called for single result query.`)\n\t\t}\n\t\treturn get_page(data)\n\t}\n\n\t// For root query\n\tconst { handleResult } = query.query as any\n\t;(query.query as any).handleResult = (...args: any[]) => {\n\t\tconst data = handleResult(...args)\n\t\treturn _get_page(data)\n\t}\n\n\t// For nested query\n\t;(query.query as any)[s] = _get_page\n\n\treturn query\n}\n\nexport function get_query_pagination_handler(query: Query) {\n\treturn (query.query as any)[s]\n}\n","import { Query } from \"pqb\"\n\nimport { Paginator, set_query_page_result } from \"./base\"\n\nexport function defineCursorPaginator(\n\toptions: Partial<CursorPaginatorOptions> = {}\n) {\n\treturn new CursorPaginator(options)\n}\n\nexport interface CursorPaginatorOptions {\n\tfields: string[]\n\ttake: number\n}\n\nexport interface CursorPaginatorArgs {\n\tcursor?: string\n\ttake?: number\n}\n\nexport interface CursorPaginatorPage<M> {\n\tnodes: M[]\n\tcursor?: string\n}\n\nclass CursorPaginator implements Paginator {\n\treadonly path = [\"nodes\"]\n\treadonly options: CursorPaginatorOptions\n\n\treadonly fields: Array<{\n\t\tname: string\n\t\tdesc: boolean\n\t}>\n\n\tconstructor(options: Partial<CursorPaginatorOptions> = {}) {\n\t\tthis.options = {\n\t\t\tfields: [\"id\"],\n\t\t\ttake: 10,\n\t\t\t...options,\n\t\t}\n\t\tthis.fields = this.options.fields.map((field) => {\n\t\t\tif (field.startsWith(\"-\")) {\n\t\t\t\treturn { name: field.slice(1), desc: true }\n\t\t\t} else {\n\t\t\t\treturn { name: field, desc: false }\n\t\t\t}\n\t\t})\n\t}\n\n\tpaginate(query: Query, args: CursorPaginatorArgs = {}) {\n\t\tconst take = args.take ?? this.options.take\n\t\tconst { cursor } = args\n\t\tconsole.log(\"paginating query\", query)\n\n\t\t// Set query order\n\t\tquery = query.clear(\"order\")\n\t\tfor (const field of this.fields) {\n\t\t\t// TODO: prevent potential name clash with aliases like .as(`_${table_ref}_order_key_0`)\n\t\t\tquery = query\n\t\t\t\t.select(field.name)\n\t\t\t\t.order({ [field.name]: field.desc ? \"DESC\" : \"ASC\" })\n\t\t}\n\n\t\tif (cursor) {\n\t\t\tquery = this._set_query_cursor(query, cursor)\n\t\t}\n\t\tquery = query.limit(take + 1)\n\n\t\tquery = set_query_page_result(query, (nodes) => {\n\t\t\tlet cursor: string | undefined\n\t\t\tif (nodes.length > take) {\n\t\t\t\tcursor = this._create_cursor(nodes[take - 1])\n\t\t\t\tnodes = nodes.slice(0, take)\n\t\t\t}\n\t\t\treturn { nodes, cursor }\n\t\t})\n\n\t\treturn query\n\t}\n\n\t_create_cursor(instance: any) {\n\t\treturn JSON.stringify(\n\t\t\tthis.fields.map((field) => {\n\t\t\t\tconst value = instance[field.name]\n\t\t\t\tif (value === undefined) {\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t`Unable to create cursor: undefined field ${field.name}`\n\t\t\t\t\t)\n\t\t\t\t}\n\t\t\t\treturn String(value)\n\t\t\t})\n\t\t)\n\t}\n\n\t_set_query_cursor(query: Query, cursor: string) {\n\t\tconst values = JSON.parse(cursor)\n\t\tconst left: string[] = []\n\t\tconst right: string[] = []\n\t\tconst expr_values: Record<string, any> = {}\n\t\t// TODO: refactor\n\t\tfor (let i = 0; i < this.fields.length; ++i) {\n\t\t\tconst field = this.fields[i]\n\t\t\tconst expressions = field.desc ? right : left\n\t\t\tconst placeholders = field.desc ? left : right\n\t\t\texpressions.push(`\"${field.name}\"`)\n\t\t\tconst placeholder = `value${i}`\n\t\t\tplaceholders.push(\"$\" + placeholder)\n\t\t\texpr_values[placeholder] = values[i]\n\t\t}\n\t\treturn query.where(\n\t\t\tquery.raw(`(${left.join(\",\")}) > (${right.join(\",\")})`, expr_values)\n\t\t)\n\t}\n}\n","import { Query } from \"pqb\"\n\nconst graphql = Symbol(\"graphql\")\n\nexport function set_query_context(query: Query, context: any) {\n\t;(query.query as any)[graphql] = context\n}\n\nexport function get_query_context(query: Query) {\n\treturn (query.query as any)[graphql]\n}\n","import { Query } from \"pqb\"\n\nexport function run_after_query(\n\tquery: Query,\n\ttransform: (instance: any) => any\n) {\n\treturn query.afterQuery(async (_, result) => {\n\t\t// FIXME: returning is ignored in orchid (unlike objection). Add some hacks instead.\n\t\tif (Array.isArray(result)) {\n\t\t\tconst result1 = await Promise.all(result.map(transform))\n\t\t\treturn result1.filter(Boolean) // Skip empty objects\n\t\t} else if (result) {\n\t\t\treturn transform(result)\n\t\t} else {\n\t\t\t// Supposedly, single query builder returning NULL\n\t\t\treturn result\n\t\t}\n\t})\n}\n","import { ResolveTree } from \"graphql-parse-resolve-info\"\nimport { Query } from \"pqb\"\n\nimport { get_query_context } from \"../utils/query-context\"\nimport { run_after_query } from \"../utils/run-after\"\nimport type { GraphResolver } from \"./graph\"\n\n/* A function that modifies the query to select a field. */\nexport type FieldResolverFn = (\n\tquery: Query,\n\toptions: {\n\t\t/** GraphQL field */\n\t\tfield: string\n\t\t/** GraphQL resolve tree */\n\t\ttree: ResolveTree\n\t\t/** Current graph resolver */\n\t\tgraph: GraphResolver\n\t}\n) => Query\n\nexport interface FieldResolverOptions {\n\t/** Table field (if different from GraphQL field) */\n\ttableField?: string\n\t/** Custom query modifier (if different than simply selecting a field). */\n\tmodify?: FieldResolverFn\n\t/** Post-process selected value. Return a new value or a promise. */\n\ttransform?(value: any, instance: any, context: any): any\n}\n\nexport function defineFieldResolver(\n\toptions: FieldResolverOptions = {}\n): FieldResolverFn {\n\tconst { tableField, modify, transform } = options\n\n\treturn function resolve(query, options) {\n\t\tconst { field } = options\n\t\tif (modify) {\n\t\t\treturn modify(query, options)\n\t\t} else {\n\t\t\tquery = query.select({ [field]: tableField || field })\n\t\t}\n\t\tif (transform) {\n\t\t\tconst context = get_query_context(query)\n\t\t\tquery = run_after_query(query, async (instance) => {\n\t\t\t\tinstance[field] = await transform(instance[field], instance, context)\n\t\t\t\treturn instance\n\t\t\t})\n\t\t}\n\t\treturn query\n\t}\n}\n","import { GraphQLResolveInfo } from \"graphql\"\nimport { parseResolveInfo, ResolveTree } from \"graphql-parse-resolve-info\"\nimport { Query } from \"pqb\"\n\nimport { FiltersDef } from \"../filters/filters\"\nimport { Paginator } from \"../paginators/base\"\nimport { set_query_context } from \"../utils/query-context\"\nimport type { TableResolverFn, TableResolverOptions } from \"./table\"\n\nexport type GraphResolverOptions = Pick<\n\tTableResolverOptions,\n\t\"allowAllFields\" | \"allowAllFilters\"\n>\n\nexport function createGraphResolver(\n\ttypes: Record<string, TableResolverFn>,\n\toptions?: GraphResolverOptions\n) {\n\treturn new GraphResolver(types, options)\n}\n\nexport interface GraphResolveOptions {\n\tinfo: GraphQLResolveInfo\n\tcontext: any\n\tfilters?: FiltersDef\n}\n\nexport class GraphResolver {\n\tconstructor(\n\t\tpublic readonly tables: Record<string, TableResolverFn>,\n\t\tpublic readonly options: GraphResolverOptions = {}\n\t) {}\n\n\tresolve(query: Query, { info, context, filters }: GraphResolveOptions) {\n\t\tset_query_context(query, context)\n\t\tconst tree = this._get_resolve_tree(info)\n\t\treturn this._resolve_type({ query, tree, filters })\n\t}\n\n\tresolvePage(\n\t\tquery: Query,\n\t\tpaginator: Paginator,\n\t\t{ info, context, filters }: GraphResolveOptions\n\t) {\n\t\tset_query_context(query, context)\n\t\tconst tree = this._get_resolve_tree(info)\n\t\treturn this._resolve_page({ query, tree, paginator, filters })\n\t}\n\n\t_get_resolve_tree(info: GraphQLResolveInfo) {\n\t\treturn parseResolveInfo(info) as ResolveTree\n\t}\n\n\t_resolve_type({\n\t\ttree,\n\t\tquery,\n\t\tfilters,\n\t}: {\n\t\tquery: Query\n\t\ttree: ResolveTree\n\t\tfilters?: FiltersDef\n\t}) {\n\t\tconst type = Object.keys(tree.fieldsByTypeName)[0]\n\t\tconst table_resolver = this.tables[type]\n\t\tif (!table_resolver) {\n\t\t\tthrow new Error(`Table resolver not found for type ${type}.`)\n\t\t}\n\t\treturn table_resolver({ tree, type, query, filters, graph: this })\n\t}\n\n\t_resolve_page({\n\t\ttree,\n\t\tquery,\n\t\tpaginator,\n\t\tfilters,\n\t}: {\n\t\tquery: Query\n\t\ttree: ResolveTree\n\t\tpaginator: Paginator\n\t\tfilters?: FiltersDef\n\t}) {\n\t\tconst { args } = tree\n\t\t// Skip page subtree(s)\n\t\tfor (const field of paginator.path) {\n\t\t\tconst type = Object.keys(tree.fieldsByTypeName)[0]\n\t\t\ttree = tree.fieldsByTypeName[type][field]\n\t\t\t// TODO: raise exception if not found\n\t\t}\n\t\tquery = this._resolve_type({ query, tree, filters })\n\t\treturn paginator.paginate(query, args)\n\t}\n}\n","import { addParserToQuery } from \"pqb\"\n\nimport { get_query_pagination_handler, Paginator } from \"../paginators/base\"\nimport { defineFieldResolver } from \"./field\"\nimport { RelationResolverOptions } from \"./relation\"\n\nexport function definePageResolver(\n\tpaginator: Paginator,\n\toptions: RelationResolverOptions = {}\n) {\n\tconst { tableField, filters, modify } = options\n\n\treturn defineFieldResolver({\n\t\tmodify: (query, { field, tree, graph }) =>\n\t\t\tquery.select({\n\t\t\t\t[field]: (q) => {\n\t\t\t\t\tconst page_query = graph._resolve_page({\n\t\t\t\t\t\ttree,\n\t\t\t\t\t\tquery: (q as any)[tableField || field],\n\t\t\t\t\t\tpaginator,\n\t\t\t\t\t\tfilters,\n\t\t\t\t\t})\n\t\t\t\t\tconst get_page = get_query_pagination_handler(page_query)\n\t\t\t\t\taddParserToQuery(page_query.query, field, get_page as any)\n\t\t\t\t\treturn modify ? modify(page_query, tree) : page_query\n\t\t\t\t},\n\t\t\t}),\n\t})\n}\n","import { FiltersDef } from \"../filters/filters\"\nimport { defineFieldResolver, FieldResolverOptions } from \"./field\"\nimport { QueryTreeModifier } from \"./table\"\n\nexport interface RelationResolverOptions\n\textends Omit<FieldResolverOptions, \"modify\"> {\n\tfilters?: FiltersDef\n\tmodify?: QueryTreeModifier\n}\n\nexport function defineRelationResolver(options: RelationResolverOptions = {}) {\n\tconst { tableField, filters, modify } = options\n\n\treturn defineFieldResolver({\n\t\tmodify: (query, { field, tree, graph }) =>\n\t\t\tquery.select({\n\t\t\t\t[field]: (q) => {\n\t\t\t\t\tconst relation_query = graph._resolve_type({\n\t\t\t\t\t\ttree,\n\t\t\t\t\t\tquery: (q as any)[tableField || field],\n\t\t\t\t\t\tfilters,\n\t\t\t\t\t})\n\t\t\t\t\treturn modify ? modify(relation_query, tree) : relation_query\n\t\t\t\t},\n\t\t\t}),\n\t})\n}\n","export function is_plain_object(obj: any): obj is Record<string, any> {\n\treturn typeof obj === \"object\" && !Array.isArray(obj)\n}\n","import { Query } from \"pqb\"\n\nimport { is_plain_object } from \"../utils/is-plain-object\"\nimport { Modifier } from \"../utils/modifier\"\n\n// TODO: per-field definitions\nexport type FiltersDef = boolean\n\nexport type FilterScalarValue = null | string | number | boolean\nexport type FilterValue = FilterScalarValue | Exclude<FilterScalarValue, null>[]\nexport type Filter = { [property: string]: FilterValue }\n\nfunction is_scalar(value: any) {\n\treturn (\n\t\tvalue === null ||\n\t\ttypeof value === \"string\" ||\n\t\ttypeof value === \"number\" ||\n\t\ttypeof value === \"boolean\"\n\t)\n}\n\nexport function apply_filters({\n\tquery,\n\tfilters,\n\targs,\n\tmodifiers,\n}: {\n\tquery: Query\n\tfilters: FiltersDef\n\targs?: Record<string, any>\n\tmodifiers?: Record<string, Modifier>\n}) {\n\tif (!filters) {\n\t\treturn query\n\t}\n\tconst filter_obj = args?.filter\n\tif (!filter_obj) {\n\t\treturn query\n\t}\n\tif (!is_plain_object(filter_obj)) {\n\t\tthrow new Error(`Invalid filter: ${filter_obj}, must be object.`)\n\t}\n\tfor (const [field, value] of Object.entries(filter_obj)) {\n\t\tif (value === undefined) {\n\t\t\t// Support optional GraphQL arguments in filter\n\t\t\tcontinue\n\t\t}\n\t\tif (modifiers?.[field]) {\n\t\t\tquery = modifiers[field](query, value)\n\t\t} else {\n\t\t\t// Normal filter\n\t\t\tconst [dbfield, op0] = field.split(\"__\")\n\t\t\tconst op = op0?.toLowerCase() || \"exact\"\n\t\t\tif (\n\t\t\t\t// TODO: add the rest of orchid ops (or allow all of them?)\n\t\t\t\t[\n\t\t\t\t\t\"exact\",\n\t\t\t\t\t\"lt\",\n\t\t\t\t\t\"lte\",\n\t\t\t\t\t\"gt\",\n\t\t\t\t\t\"gte\",\n\t\t\t\t\t\"like\",\n\t\t\t\t\t\"ilike\",\n\t\t\t\t\t\"contains\",\n\t\t\t\t].includes(op)\n\t\t\t) {\n\t\t\t\tif (!is_scalar(value)) {\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t`Unsupported filter value for ${query.table}.${field}: must be scalar.`\n\t\t\t\t\t)\n\t\t\t\t}\n\t\t\t\tif (op === \"exact\") {\n\t\t\t\t\tquery = query.where({ [dbfield]: value })\n\t\t\t\t} else {\n\t\t\t\t\tconst query_op = { like: \"contains\" }[op] || op\n\t\t\t\t\tquery = query.where({ [dbfield]: { [query_op]: value } })\n\t\t\t\t}\n\t\t\t} else if (op === \"in\") {\n\t\t\t\tif (!(Array.isArray(value) && value.every(is_scalar))) {\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t`Invalid filter value for ${query.table}.${field}: must be an array of scalars.`\n\t\t\t\t\t)\n\t\t\t\t}\n\t\t\t\tquery = query.whereIn(dbfield, value)\n\t\t\t} else {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Invalid filter ${query.table}.${field}: unsupported operator ${op}.`\n\t\t\t\t)\n\t\t\t}\n\t\t}\n\t}\n\treturn query\n}\n","import { ResolveTree } from \"graphql-parse-resolve-info\"\nimport { DbTable, TableClass } from \"orchid-orm\"\nimport { Query } from \"pqb\"\n\nimport { apply_filters, FiltersDef } from \"../filters/filters\"\nimport { Modifier } from \"../utils/modifier\"\nimport { get_query_context } from \"../utils/query-context\"\nimport { run_after_query } from \"../utils/run-after\"\nimport { defineFieldResolver, FieldResolverFn } from \"./field\"\nimport type { GraphResolver } from \"./graph\"\nimport { defineRelationResolver } from \"./relation\"\n\n/** A function that modifies the query to select fields/relations and filter the result set. */\nexport type TableResolverFn = (args: {\n\ttree: ResolveTree\n\t/** GraphQL type */\n\ttype: string\n\tquery: Query\n\tfilters?: FiltersDef\n\tgraph: GraphResolver\n}) => Query\n\nexport interface TableResolverOptions {\n\t/** allow to resolve all table fields without explicitly listing them */\n\tallowAllFields?: boolean\n\t/** allow to filter all table fields without explicitly listing them */\n\tallowAllFilters?: boolean\n\tfields?: Record<string, SimpleFieldResolver>\n\tmodifiers?: Record<string, Modifier>\n\tmodify?: QueryTreeModifier\n\ttransform?(instance: any, context: any): void | PromiseLike<void>\n}\n\nexport type SimpleFieldResolver = true | string | FieldResolverFn\n\nexport type QueryTreeModifier = (query: Query, tree: ResolveTree) => Query\n\nexport function defineTableResolver<T extends TableClass>(\n\ttable: DbTable<T>,\n\toptions: TableResolverOptions = {}\n): TableResolverFn {\n\t/**\n\t * Create a field resolver which will modify the query to resolve a GraphQL field.\n\t */\n\tconst get_default_field_resolver = (\n\t\tfield: string,\n\t\ttableField?: string\n\t): FieldResolverFn | undefined => {\n\t\tconst table_field_lookup = tableField || field\n\t\tif (options.modifiers?.[table_field_lookup]) {\n\t\t\t// Keep query as is.\n\t\t\treturn (query) => query\n\t\t} else if ((table.relations as any)?.[table_field_lookup]) {\n\t\t\treturn defineRelationResolver({ tableField })\n\t\t} else {\n\t\t\treturn defineFieldResolver({ tableField })\n\t\t}\n\t}\n\n\t// Pre-create field resolvers\n\tconst { fields } = options\n\tconst table_field_resolvers = fields\n\t\t? Object.keys(fields).reduce<Record<string, FieldResolverFn>>(\n\t\t\t\t(resolvers, field) => {\n\t\t\t\t\tconst r0 = fields[field]\n\t\t\t\t\tconst r: FieldResolverFn | undefined =\n\t\t\t\t\t\ttypeof r0 === \"function\"\n\t\t\t\t\t\t\t? r0\n\t\t\t\t\t\t\t: r0 === true\n\t\t\t\t\t\t\t? get_default_field_resolver(field)\n\t\t\t\t\t\t\t: typeof r0 === \"string\"\n\t\t\t\t\t\t\t? get_default_field_resolver(field, r0)\n\t\t\t\t\t\t\t: undefined\n\t\t\t\t\tif (r === undefined) {\n\t\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t\t`Field resolver must be a function, string, or true; found ${r0}`\n\t\t\t\t\t\t)\n\t\t\t\t\t}\n\t\t\t\t\tresolvers[field] = r\n\t\t\t\t\treturn resolvers\n\t\t\t\t},\n\t\t\t\t{}\n\t\t )\n\t\t: undefined\n\n\tconst { modify, transform } = options\n\n\treturn function resolve({ tree, type, query, filters, graph }) {\n\t\tif (query.table !== table.table) {\n\t\t\tthrow new Error(\n\t\t\t\t`Mismatching query type (expected ${table.table}, found ${query.table}).`\n\t\t\t)\n\t\t}\n\n\t\tconst allow_all_fields =\n\t\t\toptions.allowAllFields ??\n\t\t\tgraph.options.allowAllFields ??\n\t\t\ttable_field_resolvers === undefined\n\n\t\tif (!allow_all_fields && !table_field_resolvers) {\n\t\t\tthrow new Error(\n\t\t\t\t`Table resolver for ${type} must either allow all fields or specify options.fields`\n\t\t\t)\n\t\t}\n\n\t\tif (modify) {\n\t\t\tquery = modify(query, tree)\n\t\t}\n\n\t\tfor (const subtree of Object.values(tree.fieldsByTypeName[type])) {\n\t\t\tconst field = subtree.name\n\t\t\tconst r =\n\t\t\t\ttable_field_resolvers?.[field] ||\n\t\t\t\t(allow_all_fields ? get_default_field_resolver(field) : undefined)\n\t\t\tif (!r) {\n\t\t\t\tthrow new Error(`No field resolver defined for field ${type}.${field}`)\n\t\t\t}\n\t\t\tif (r) {\n\t\t\t\tquery = r(query, { field, tree: subtree, graph })\n\t\t\t}\n\t\t}\n\n\t\tconst allow_all_filters =\n\t\t\toptions.allowAllFilters ?? graph.options.allowAllFilters\n\n\t\tconst effective_filters = allow_all_filters ? true : filters\n\n\t\tif (effective_filters) {\n\t\t\tquery = apply_filters({\n\t\t\t\tquery,\n\t\t\t\tfilters: effective_filters,\n\t\t\t\targs: tree.args,\n\t\t\t\tmodifiers: options.modifiers,\n\t\t\t})\n\t\t}\n\n\t\tif (transform) {\n\t\t\tconst context = get_query_context(query)\n\t\t\tquery = run_after_query(query, (instance) => {\n\t\t\t\treturn transform(instance, context)\n\t\t\t})\n\t\t}\n\n\t\treturn query\n\t}\n}\n"],"mappings":"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","names":["cursor","options"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/paginators/base.ts","../src/paginators/cursor.ts","../src/utils/query-context.ts","../src/utils/run-after.ts","../src/resolvers/field.ts","../src/resolvers/graph.ts","../src/resolvers/page.ts","../src/resolvers/relation.ts","../src/utils/is-plain-object.ts","../src/filters/filters.ts","../src/resolvers/table.ts"],"sourcesContent":["export {\n\tdefineCursorPaginator as cursor,\n\tdefineCursorPaginator,\n} from \"./paginators/cursor\"\nexport {\n\tdefineFieldResolver,\n\tdefineFieldResolver as field,\n} from \"./resolvers/field\"\nexport {\n\tcreateGraphResolver,\n\tcreateGraphResolver as graph,\n} from \"./resolvers/graph\"\nexport {\n\tdefinePageResolver,\n\tdefinePageResolver as page,\n} from \"./resolvers/page\"\nexport {\n\tdefineRelationResolver,\n\tdefineRelationResolver as relation,\n} from \"./resolvers/relation\"\nexport {\n\tdefineTableResolver,\n\tdefineTableResolver as table,\n} from \"./resolvers/table\"\n","import { Query } from \"pqb\"\n\nexport interface Paginator {\n\t/** GraphQL path, for example: `[\"nodes\"]` */\n\treadonly path: string[]\n\tpaginate(query: Query, ...args: any[]): Query\n}\n\ntype GetPageFn<P> = (nodes: any[]) => P\n\nconst s = Symbol()\n\n// FIXME use proper orchid methods, set result type\nexport function set_query_page_result<P>(query: Query, get_page: GetPageFn<P>) {\n\tfunction _get_page(data: any) {\n\t\tif (!Array.isArray(data)) {\n\t\t\tthrow new Error(`Paginator called for single result query.`)\n\t\t}\n\t\treturn get_page(data)\n\t}\n\n\t// For root query\n\tconst _query = query.query\n\tconst { handleResult } = _query\n\t_query.handleResult = (q, result, s) => {\n\t\tconst data = handleResult(q, result, s)\n\t\t// Sometimes this is called for subqueries, sometimes not.\n\t\t// TODO: investigate and use always.\n\t\treturn s ? data : _get_page(data)\n\t}\n\n\t// For subqueries\n\t;(_query as any)[s] = _get_page\n\n\treturn query\n}\n\nexport function get_query_pagination_handler(query: Query) {\n\treturn (query.query as any)[s]\n}\n","import { Query } from \"pqb\"\n\nimport { Paginator, set_query_page_result } from \"./base\"\n\nexport function defineCursorPaginator(\n\toptions: Partial<CursorPaginatorOptions> = {}\n) {\n\treturn new CursorPaginator(options)\n}\n\nexport interface CursorPaginatorOptions {\n\tfields: string[]\n\ttake: number\n}\n\nexport interface CursorPaginatorArgs {\n\tcursor?: string\n\ttake?: number\n}\n\nexport interface CursorPaginatorPage<M> {\n\tnodes: M[]\n\tcursor?: string\n}\n\nclass CursorPaginator implements Paginator {\n\treadonly path = [\"nodes\"]\n\treadonly options: CursorPaginatorOptions\n\n\treadonly fields: Array<{\n\t\tname: string\n\t\tdesc: boolean\n\t}>\n\n\tconstructor(options: Partial<CursorPaginatorOptions> = {}) {\n\t\tthis.options = {\n\t\t\tfields: [\"id\"],\n\t\t\ttake: 10,\n\t\t\t...options,\n\t\t}\n\t\tthis.fields = this.options.fields.map((field) => {\n\t\t\tif (field.startsWith(\"-\")) {\n\t\t\t\treturn { name: field.slice(1), desc: true }\n\t\t\t} else {\n\t\t\t\treturn { name: field, desc: false }\n\t\t\t}\n\t\t})\n\t}\n\n\tpaginate(query: Query, args: CursorPaginatorArgs = {}) {\n\t\tconst take = args.take ?? this.options.take\n\t\tconst { cursor } = args\n\n\t\t// Set query order\n\t\tquery = query.clear(\"order\")\n\t\tfor (const field of this.fields) {\n\t\t\t// TODO: prevent potential name clash with aliases like .as(`_${table_ref}_order_key_0`)\n\t\t\tquery = query\n\t\t\t\t.select(field.name)\n\t\t\t\t.order({ [field.name]: field.desc ? \"DESC\" : \"ASC\" })\n\t\t}\n\n\t\tif (cursor) {\n\t\t\tquery = this._set_query_cursor(query, cursor)\n\t\t}\n\t\tquery = query.limit(take + 1)\n\n\t\tquery = set_query_page_result(query, (nodes) => {\n\t\t\tlet cursor: string | undefined\n\t\t\tif (nodes.length > take) {\n\t\t\t\tcursor = this._create_cursor(nodes[take - 1])\n\t\t\t\tnodes = nodes.slice(0, take)\n\t\t\t}\n\t\t\treturn { nodes, cursor }\n\t\t})\n\n\t\treturn query\n\t}\n\n\t_create_cursor(instance: any) {\n\t\treturn JSON.stringify(\n\t\t\tthis.fields.map((field) => {\n\t\t\t\tconst value = instance[field.name]\n\t\t\t\tif (value === undefined) {\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t`Unable to create cursor: undefined field ${field.name}`\n\t\t\t\t\t)\n\t\t\t\t}\n\t\t\t\treturn String(value)\n\t\t\t})\n\t\t)\n\t}\n\n\t_set_query_cursor(query: Query, cursor: string) {\n\t\tconst values = JSON.parse(cursor)\n\t\tconst left: string[] = []\n\t\tconst right: string[] = []\n\t\tconst expr_values: Record<string, any> = {}\n\t\t// TODO: refactor\n\t\tfor (let i = 0; i < this.fields.length; ++i) {\n\t\t\tconst field = this.fields[i]\n\t\t\tconst expressions = field.desc ? right : left\n\t\t\tconst placeholders = field.desc ? left : right\n\t\t\texpressions.push(`\"${field.name}\"`)\n\t\t\tconst placeholder = `value${i}`\n\t\t\tplaceholders.push(\"$\" + placeholder)\n\t\t\texpr_values[placeholder] = values[i]\n\t\t}\n\t\treturn query.where(\n\t\t\tquery.raw(`(${left.join(\",\")}) > (${right.join(\",\")})`, expr_values)\n\t\t)\n\t}\n}\n","import { Query } from \"pqb\"\n\nconst graphql = Symbol(\"graphql\")\n\nexport function set_query_context(query: Query, context: any) {\n\t;(query.query as any)[graphql] = context\n}\n\nexport function get_query_context(query: Query) {\n\treturn (query.query as any)[graphql]\n}\n","import { Query } from \"pqb\"\n\nexport function run_after_query(\n\tquery: Query,\n\ttransform: (instance: any) => any\n) {\n\treturn query.afterQuery(async (_, result) => {\n\t\t// FIXME: returning is ignored in orchid (unlike objection). Add some hacks instead.\n\t\tif (Array.isArray(result)) {\n\t\t\tconst result1 = await Promise.all(result.map(transform))\n\t\t\treturn result1.filter(Boolean) // Skip empty objects\n\t\t} else if (result) {\n\t\t\treturn transform(result)\n\t\t} else {\n\t\t\t// Supposedly, single query builder returning NULL\n\t\t\treturn result\n\t\t}\n\t})\n}\n","import { ResolveTree } from \"graphql-parse-resolve-info\"\nimport { Query } from \"pqb\"\n\nimport { get_query_context } from \"../utils/query-context\"\nimport { run_after_query } from \"../utils/run-after\"\nimport type { GraphResolver } from \"./graph\"\n\n/* A function that modifies the query to select a field. */\nexport type FieldResolverFn = (\n\tquery: Query,\n\toptions: {\n\t\t/** GraphQL field */\n\t\tfield: string\n\t\t/** GraphQL resolve tree */\n\t\ttree: ResolveTree\n\t\t/** Current graph resolver */\n\t\tgraph: GraphResolver\n\t}\n) => Query\n\nexport interface FieldResolverOptions {\n\t/** Table field (if different from GraphQL field) */\n\ttableField?: string\n\t/** Custom query modifier (if different than simply selecting a field). */\n\tmodify?: FieldResolverFn\n\t/** Post-process selected value. Return a new value or a promise. */\n\ttransform?(value: any, instance: any, context: any): any\n}\n\nexport function defineFieldResolver(\n\toptions: FieldResolverOptions = {}\n): FieldResolverFn {\n\tconst { tableField, modify, transform } = options\n\n\treturn function resolve(query, options) {\n\t\tconst { field } = options\n\t\tif (modify) {\n\t\t\treturn modify(query, options)\n\t\t} else {\n\t\t\tquery = query.select({ [field]: tableField || field })\n\t\t}\n\t\tif (transform) {\n\t\t\tconst context = get_query_context(query)\n\t\t\tquery = run_after_query(query, async (instance) => {\n\t\t\t\tinstance[field] = await transform(instance[field], instance, context)\n\t\t\t\treturn instance\n\t\t\t})\n\t\t}\n\t\treturn query\n\t}\n}\n","import { GraphQLResolveInfo } from \"graphql\"\nimport { parseResolveInfo, ResolveTree } from \"graphql-parse-resolve-info\"\nimport { Query } from \"pqb\"\n\nimport { FiltersDef } from \"../filters/filters\"\nimport { Paginator } from \"../paginators/base\"\nimport { set_query_context } from \"../utils/query-context\"\nimport type { TableResolverFn, TableResolverOptions } from \"./table\"\n\nexport type GraphResolverOptions = Pick<\n\tTableResolverOptions,\n\t\"allowAllFields\" | \"allowAllFilters\"\n>\n\nexport function createGraphResolver(\n\ttypes: Record<string, TableResolverFn>,\n\toptions?: GraphResolverOptions\n) {\n\treturn new GraphResolver(types, options)\n}\n\nexport interface GraphResolveOptions {\n\tinfo: GraphQLResolveInfo\n\tcontext: any\n\tfilters?: FiltersDef\n}\n\nexport class GraphResolver {\n\tconstructor(\n\t\tpublic readonly tables: Record<string, TableResolverFn>,\n\t\tpublic readonly options: GraphResolverOptions = {}\n\t) {}\n\n\tresolve(query: Query, { info, context, filters }: GraphResolveOptions) {\n\t\tset_query_context(query, context)\n\t\tconst tree = this._get_resolve_tree(info)\n\t\treturn this._resolve_type({ query, tree, filters })\n\t}\n\n\tresolvePage(\n\t\tquery: Query,\n\t\tpaginator: Paginator,\n\t\t{ info, context, filters }: GraphResolveOptions\n\t) {\n\t\tset_query_context(query, context)\n\t\tconst tree = this._get_resolve_tree(info)\n\t\treturn this._resolve_page({ query, tree, paginator, filters })\n\t}\n\n\t_get_resolve_tree(info: GraphQLResolveInfo) {\n\t\treturn parseResolveInfo(info) as ResolveTree\n\t}\n\n\t_resolve_type({\n\t\ttree,\n\t\tquery,\n\t\tfilters,\n\t}: {\n\t\tquery: Query\n\t\ttree: ResolveTree\n\t\tfilters?: FiltersDef\n\t}) {\n\t\tconst type = Object.keys(tree.fieldsByTypeName)[0]\n\t\tconst table_resolver = this.tables[type]\n\t\tif (!table_resolver) {\n\t\t\tthrow new Error(`Table resolver not found for type ${type}.`)\n\t\t}\n\t\treturn table_resolver({ tree, type, query, filters, graph: this })\n\t}\n\n\t_resolve_page({\n\t\ttree,\n\t\tquery,\n\t\tpaginator,\n\t\tfilters,\n\t}: {\n\t\tquery: Query\n\t\ttree: ResolveTree\n\t\tpaginator: Paginator\n\t\tfilters?: FiltersDef\n\t}) {\n\t\tconst { args } = tree\n\t\t// Skip page subtree(s)\n\t\tfor (const field of paginator.path) {\n\t\t\tconst type = Object.keys(tree.fieldsByTypeName)[0]\n\t\t\ttree = tree.fieldsByTypeName[type][field]\n\t\t\t// TODO: raise exception if not found\n\t\t}\n\t\tquery = this._resolve_type({ query, tree, filters })\n\t\treturn paginator.paginate(query, args)\n\t}\n}\n","import { addParserToQuery } from \"pqb\"\n\nimport { get_query_pagination_handler, Paginator } from \"../paginators/base\"\nimport { defineFieldResolver } from \"./field\"\nimport { RelationResolverOptions } from \"./relation\"\n\nexport function definePageResolver(\n\tpaginator: Paginator,\n\toptions: RelationResolverOptions = {}\n) {\n\tconst { tableField, filters, modify } = options\n\n\treturn defineFieldResolver({\n\t\tmodify: (query, { field, tree, graph }) => {\n\t\t\t// FIXME: refactor, add types\n\t\t\tlet get_page: any\n\t\t\tquery = query.select({\n\t\t\t\t[field]: (q) => {\n\t\t\t\t\tq = graph._resolve_page({\n\t\t\t\t\t\ttree,\n\t\t\t\t\t\tquery: (q as any)[tableField || field],\n\t\t\t\t\t\tpaginator,\n\t\t\t\t\t\tfilters,\n\t\t\t\t\t})\n\t\t\t\t\t// Calling addParserToQuery here doesn't work, save the paginator for later.\n\t\t\t\t\tget_page = get_query_pagination_handler(q)\n\t\t\t\t\treturn modify ? modify(q, tree) : q\n\t\t\t\t},\n\t\t\t})\n\t\t\tconst parser = query.query.parsers?.[field]\n\t\t\taddParserToQuery(query.query, field, (nodes) => {\n\t\t\t\tnodes = parser ? parser(nodes) : nodes\n\t\t\t\treturn get_page(nodes)\n\t\t\t})\n\t\t\treturn query\n\t\t},\n\t})\n}\n","import { FiltersDef } from \"../filters/filters\"\nimport { defineFieldResolver, FieldResolverOptions } from \"./field\"\nimport { QueryTreeModifier } from \"./table\"\n\nexport interface RelationResolverOptions\n\textends Omit<FieldResolverOptions, \"modify\"> {\n\tfilters?: FiltersDef\n\tmodify?: QueryTreeModifier\n}\n\nexport function defineRelationResolver(options: RelationResolverOptions = {}) {\n\tconst { tableField, filters, modify } = options\n\n\treturn defineFieldResolver({\n\t\tmodify: (query, { field, tree, graph }) =>\n\t\t\tquery.select({\n\t\t\t\t[field]: (q) => {\n\t\t\t\t\tconst relation_query = graph._resolve_type({\n\t\t\t\t\t\ttree,\n\t\t\t\t\t\tquery: (q as any)[tableField || field],\n\t\t\t\t\t\tfilters,\n\t\t\t\t\t})\n\t\t\t\t\treturn modify ? modify(relation_query, tree) : relation_query\n\t\t\t\t},\n\t\t\t}),\n\t})\n}\n","export function is_plain_object(obj: any): obj is Record<string, any> {\n\treturn typeof obj === \"object\" && !Array.isArray(obj)\n}\n","import { Query } from \"pqb\"\n\nimport { is_plain_object } from \"../utils/is-plain-object\"\nimport { Modifier } from \"../utils/modifier\"\n\n// TODO: per-field definitions\nexport type FiltersDef = boolean\n\nexport type FilterScalarValue = null | string | number | boolean\nexport type FilterValue = FilterScalarValue | Exclude<FilterScalarValue, null>[]\nexport type Filter = { [property: string]: FilterValue }\n\nfunction is_scalar(value: any) {\n\treturn (\n\t\tvalue === null ||\n\t\ttypeof value === \"string\" ||\n\t\ttypeof value === \"number\" ||\n\t\ttypeof value === \"boolean\"\n\t)\n}\n\nexport function apply_filters({\n\tquery,\n\tfilters,\n\targs,\n\tmodifiers,\n}: {\n\tquery: Query\n\tfilters: FiltersDef\n\targs?: Record<string, any>\n\tmodifiers?: Record<string, Modifier>\n}) {\n\tif (!filters) {\n\t\treturn query\n\t}\n\tconst filter_obj = args?.filter\n\tif (!filter_obj) {\n\t\treturn query\n\t}\n\tif (!is_plain_object(filter_obj)) {\n\t\tthrow new Error(`Invalid filter: ${filter_obj}, must be object.`)\n\t}\n\tfor (const [field, value] of Object.entries(filter_obj)) {\n\t\tif (value === undefined) {\n\t\t\t// Support optional GraphQL arguments in filter\n\t\t\tcontinue\n\t\t}\n\t\tif (modifiers?.[field]) {\n\t\t\tquery = modifiers[field](query, value)\n\t\t} else {\n\t\t\t// Normal filter\n\t\t\tconst [dbfield, op0] = field.split(\"__\")\n\t\t\tconst op = op0?.toLowerCase() || \"exact\"\n\t\t\tif (\n\t\t\t\t// TODO: add the rest of orchid ops (or allow all of them?)\n\t\t\t\t[\n\t\t\t\t\t\"exact\",\n\t\t\t\t\t\"lt\",\n\t\t\t\t\t\"lte\",\n\t\t\t\t\t\"gt\",\n\t\t\t\t\t\"gte\",\n\t\t\t\t\t\"like\",\n\t\t\t\t\t\"ilike\",\n\t\t\t\t\t\"contains\",\n\t\t\t\t].includes(op)\n\t\t\t) {\n\t\t\t\tif (!is_scalar(value)) {\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t`Unsupported filter value for ${query.table}.${field}: must be scalar.`\n\t\t\t\t\t)\n\t\t\t\t}\n\t\t\t\tif (op === \"exact\") {\n\t\t\t\t\tquery = query.where({ [dbfield]: value })\n\t\t\t\t} else {\n\t\t\t\t\tconst query_op = { like: \"contains\" }[op] || op\n\t\t\t\t\tquery = query.where({ [dbfield]: { [query_op]: value } })\n\t\t\t\t}\n\t\t\t} else if (op === \"in\") {\n\t\t\t\tif (!(Array.isArray(value) && value.every(is_scalar))) {\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t`Invalid filter value for ${query.table}.${field}: must be an array of scalars.`\n\t\t\t\t\t)\n\t\t\t\t}\n\t\t\t\tquery = query.whereIn(dbfield, value)\n\t\t\t} else {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Invalid filter ${query.table}.${field}: unsupported operator ${op}.`\n\t\t\t\t)\n\t\t\t}\n\t\t}\n\t}\n\treturn query\n}\n","import { ResolveTree } from \"graphql-parse-resolve-info\"\nimport { DbTable, TableClass } from \"orchid-orm\"\nimport { Query } from \"pqb\"\n\nimport { apply_filters, FiltersDef } from \"../filters/filters\"\nimport { Modifier } from \"../utils/modifier\"\nimport { get_query_context } from \"../utils/query-context\"\nimport { run_after_query } from \"../utils/run-after\"\nimport { defineFieldResolver, FieldResolverFn } from \"./field\"\nimport type { GraphResolver } from \"./graph\"\nimport { defineRelationResolver } from \"./relation\"\n\n/** A function that modifies the query to select fields/relations and filter the result set. */\nexport type TableResolverFn = (args: {\n\ttree: ResolveTree\n\t/** GraphQL type */\n\ttype: string\n\tquery: Query\n\tfilters?: FiltersDef\n\tgraph: GraphResolver\n}) => Query\n\nexport interface TableResolverOptions {\n\t/** allow to resolve all table fields without explicitly listing them */\n\tallowAllFields?: boolean\n\t/** allow to filter all table fields without explicitly listing them */\n\tallowAllFilters?: boolean\n\tfields?: Record<string, SimpleFieldResolver>\n\tmodifiers?: Record<string, Modifier>\n\tmodify?: QueryTreeModifier\n\ttransform?(instance: any, context: any): void | PromiseLike<void>\n}\n\nexport type SimpleFieldResolver = true | string | FieldResolverFn\n\nexport type QueryTreeModifier = (query: Query, tree: ResolveTree) => Query\n\nexport function defineTableResolver<T extends TableClass>(\n\ttable: DbTable<T>,\n\toptions: TableResolverOptions = {}\n): TableResolverFn {\n\t/**\n\t * Create a field resolver which will modify the query to resolve a GraphQL field.\n\t */\n\tconst get_default_field_resolver = (\n\t\tfield: string,\n\t\ttableField?: string\n\t): FieldResolverFn | undefined => {\n\t\tconst table_field_lookup = tableField || field\n\t\tif (options.modifiers?.[table_field_lookup]) {\n\t\t\t// Keep query as is.\n\t\t\treturn (query) => query\n\t\t} else if ((table.relations as any)?.[table_field_lookup]) {\n\t\t\treturn defineRelationResolver({ tableField })\n\t\t} else {\n\t\t\treturn defineFieldResolver({ tableField })\n\t\t}\n\t}\n\n\t// Pre-create field resolvers\n\tconst { fields } = options\n\tconst table_field_resolvers = fields\n\t\t? Object.keys(fields).reduce<Record<string, FieldResolverFn>>(\n\t\t\t\t(resolvers, field) => {\n\t\t\t\t\tconst r0 = fields[field]\n\t\t\t\t\tconst r: FieldResolverFn | undefined =\n\t\t\t\t\t\ttypeof r0 === \"function\"\n\t\t\t\t\t\t\t? r0\n\t\t\t\t\t\t\t: r0 === true\n\t\t\t\t\t\t\t? get_default_field_resolver(field)\n\t\t\t\t\t\t\t: typeof r0 === \"string\"\n\t\t\t\t\t\t\t? get_default_field_resolver(field, r0)\n\t\t\t\t\t\t\t: undefined\n\t\t\t\t\tif (r === undefined) {\n\t\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t\t`Field resolver must be a function, string, or true; found ${r0}`\n\t\t\t\t\t\t)\n\t\t\t\t\t}\n\t\t\t\t\tresolvers[field] = r\n\t\t\t\t\treturn resolvers\n\t\t\t\t},\n\t\t\t\t{}\n\t\t )\n\t\t: undefined\n\n\tconst { modify, transform } = options\n\n\treturn function resolve({ tree, type, query, filters, graph }) {\n\t\tif (query.table !== table.table) {\n\t\t\tthrow new Error(\n\t\t\t\t`Mismatching query type (expected ${table.table}, found ${query.table}).`\n\t\t\t)\n\t\t}\n\n\t\tconst allow_all_fields =\n\t\t\toptions.allowAllFields ??\n\t\t\tgraph.options.allowAllFields ??\n\t\t\ttable_field_resolvers === undefined\n\n\t\tif (!allow_all_fields && !table_field_resolvers) {\n\t\t\tthrow new Error(\n\t\t\t\t`Table resolver for ${type} must either allow all fields or specify options.fields`\n\t\t\t)\n\t\t}\n\n\t\tif (modify) {\n\t\t\tquery = modify(query, tree)\n\t\t}\n\n\t\tfor (const subtree of Object.values(tree.fieldsByTypeName[type])) {\n\t\t\tconst field = subtree.name\n\t\t\tconst r =\n\t\t\t\ttable_field_resolvers?.[field] ||\n\t\t\t\t(allow_all_fields ? get_default_field_resolver(field) : undefined)\n\t\t\tif (!r) {\n\t\t\t\tthrow new Error(`No field resolver defined for field ${type}.${field}`)\n\t\t\t}\n\t\t\tif (r) {\n\t\t\t\tquery = r(query, { field, tree: subtree, graph })\n\t\t\t}\n\t\t}\n\n\t\tconst allow_all_filters =\n\t\t\toptions.allowAllFilters ?? graph.options.allowAllFilters\n\n\t\tconst effective_filters = allow_all_filters ? true : filters\n\n\t\tif (effective_filters) {\n\t\t\tquery = apply_filters({\n\t\t\t\tquery,\n\t\t\t\tfilters: effective_filters,\n\t\t\t\targs: tree.args,\n\t\t\t\tmodifiers: options.modifiers,\n\t\t\t})\n\t\t}\n\n\t\tif (transform) {\n\t\t\tconst context = get_query_context(query)\n\t\t\tquery = run_after_query(query, (instance) => {\n\t\t\t\treturn transform(instance, context)\n\t\t\t})\n\t\t}\n\n\t\treturn query\n\t}\n}\n"],"mappings":"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","names":["s","cursor","options"]}
package/dist/index.js CHANGED
@@ -7,12 +7,13 @@ function set_query_page_result(query, get_page) {
7
7
  }
8
8
  return get_page(data);
9
9
  }
10
- const { handleResult } = query.query;
11
- query.query.handleResult = (...args) => {
12
- const data = handleResult(...args);
13
- return _get_page(data);
10
+ const _query = query.query;
11
+ const { handleResult } = _query;
12
+ _query.handleResult = (q, result, s2) => {
13
+ const data = handleResult(q, result, s2);
14
+ return s2 ? data : _get_page(data);
14
15
  };
15
- query.query[s] = _get_page;
16
+ _query[s] = _get_page;
16
17
  return query;
17
18
  }
18
19
  function get_query_pagination_handler(query) {
@@ -44,7 +45,6 @@ var CursorPaginator = class {
44
45
  paginate(query, args = {}) {
45
46
  const take = args.take ?? this.options.take;
46
47
  const { cursor } = args;
47
- console.log("paginating query", query);
48
48
  query = query.clear("order");
49
49
  for (const field of this.fields) {
50
50
  query = query.select(field.name).order({ [field.name]: field.desc ? "DESC" : "ASC" });
@@ -197,19 +197,27 @@ import { addParserToQuery } from "pqb";
197
197
  function definePageResolver(paginator, options = {}) {
198
198
  const { tableField, filters, modify } = options;
199
199
  return defineFieldResolver({
200
- modify: (query, { field, tree, graph }) => query.select({
201
- [field]: (q) => {
202
- const page_query = graph._resolve_page({
203
- tree,
204
- query: q[tableField || field],
205
- paginator,
206
- filters
207
- });
208
- const get_page = get_query_pagination_handler(page_query);
209
- addParserToQuery(page_query.query, field, get_page);
210
- return modify ? modify(page_query, tree) : page_query;
211
- }
212
- })
200
+ modify: (query, { field, tree, graph }) => {
201
+ let get_page;
202
+ query = query.select({
203
+ [field]: (q) => {
204
+ q = graph._resolve_page({
205
+ tree,
206
+ query: q[tableField || field],
207
+ paginator,
208
+ filters
209
+ });
210
+ get_page = get_query_pagination_handler(q);
211
+ return modify ? modify(q, tree) : q;
212
+ }
213
+ });
214
+ const parser = query.query.parsers?.[field];
215
+ addParserToQuery(query.query, field, (nodes) => {
216
+ nodes = parser ? parser(nodes) : nodes;
217
+ return get_page(nodes);
218
+ });
219
+ return query;
220
+ }
213
221
  });
214
222
  }
215
223
 
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/paginators/base.ts","../src/paginators/cursor.ts","../src/utils/query-context.ts","../src/utils/run-after.ts","../src/resolvers/field.ts","../src/resolvers/graph.ts","../src/resolvers/page.ts","../src/resolvers/relation.ts","../src/utils/is-plain-object.ts","../src/filters/filters.ts","../src/resolvers/table.ts"],"sourcesContent":["import { Query } from \"pqb\"\n\nexport interface Paginator {\n\t/** GraphQL path, for example: `[\"nodes\"]` */\n\treadonly path: string[]\n\tpaginate(query: Query, ...args: any[]): Query\n}\n\ntype GetPageFn<P> = (nodes: any[]) => P\n\nconst s = Symbol()\n\n// FIXME use proper orchid methods, set result type\nexport function set_query_page_result<P>(query: Query, get_page: GetPageFn<P>) {\n\tfunction _get_page(data: any) {\n\t\tif (!Array.isArray(data)) {\n\t\t\tthrow new Error(`Paginator called for single result query.`)\n\t\t}\n\t\treturn get_page(data)\n\t}\n\n\t// For root query\n\tconst { handleResult } = query.query as any\n\t;(query.query as any).handleResult = (...args: any[]) => {\n\t\tconst data = handleResult(...args)\n\t\treturn _get_page(data)\n\t}\n\n\t// For nested query\n\t;(query.query as any)[s] = _get_page\n\n\treturn query\n}\n\nexport function get_query_pagination_handler(query: Query) {\n\treturn (query.query as any)[s]\n}\n","import { Query } from \"pqb\"\n\nimport { Paginator, set_query_page_result } from \"./base\"\n\nexport function defineCursorPaginator(\n\toptions: Partial<CursorPaginatorOptions> = {}\n) {\n\treturn new CursorPaginator(options)\n}\n\nexport interface CursorPaginatorOptions {\n\tfields: string[]\n\ttake: number\n}\n\nexport interface CursorPaginatorArgs {\n\tcursor?: string\n\ttake?: number\n}\n\nexport interface CursorPaginatorPage<M> {\n\tnodes: M[]\n\tcursor?: string\n}\n\nclass CursorPaginator implements Paginator {\n\treadonly path = [\"nodes\"]\n\treadonly options: CursorPaginatorOptions\n\n\treadonly fields: Array<{\n\t\tname: string\n\t\tdesc: boolean\n\t}>\n\n\tconstructor(options: Partial<CursorPaginatorOptions> = {}) {\n\t\tthis.options = {\n\t\t\tfields: [\"id\"],\n\t\t\ttake: 10,\n\t\t\t...options,\n\t\t}\n\t\tthis.fields = this.options.fields.map((field) => {\n\t\t\tif (field.startsWith(\"-\")) {\n\t\t\t\treturn { name: field.slice(1), desc: true }\n\t\t\t} else {\n\t\t\t\treturn { name: field, desc: false }\n\t\t\t}\n\t\t})\n\t}\n\n\tpaginate(query: Query, args: CursorPaginatorArgs = {}) {\n\t\tconst take = args.take ?? this.options.take\n\t\tconst { cursor } = args\n\t\tconsole.log(\"paginating query\", query)\n\n\t\t// Set query order\n\t\tquery = query.clear(\"order\")\n\t\tfor (const field of this.fields) {\n\t\t\t// TODO: prevent potential name clash with aliases like .as(`_${table_ref}_order_key_0`)\n\t\t\tquery = query\n\t\t\t\t.select(field.name)\n\t\t\t\t.order({ [field.name]: field.desc ? \"DESC\" : \"ASC\" })\n\t\t}\n\n\t\tif (cursor) {\n\t\t\tquery = this._set_query_cursor(query, cursor)\n\t\t}\n\t\tquery = query.limit(take + 1)\n\n\t\tquery = set_query_page_result(query, (nodes) => {\n\t\t\tlet cursor: string | undefined\n\t\t\tif (nodes.length > take) {\n\t\t\t\tcursor = this._create_cursor(nodes[take - 1])\n\t\t\t\tnodes = nodes.slice(0, take)\n\t\t\t}\n\t\t\treturn { nodes, cursor }\n\t\t})\n\n\t\treturn query\n\t}\n\n\t_create_cursor(instance: any) {\n\t\treturn JSON.stringify(\n\t\t\tthis.fields.map((field) => {\n\t\t\t\tconst value = instance[field.name]\n\t\t\t\tif (value === undefined) {\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t`Unable to create cursor: undefined field ${field.name}`\n\t\t\t\t\t)\n\t\t\t\t}\n\t\t\t\treturn String(value)\n\t\t\t})\n\t\t)\n\t}\n\n\t_set_query_cursor(query: Query, cursor: string) {\n\t\tconst values = JSON.parse(cursor)\n\t\tconst left: string[] = []\n\t\tconst right: string[] = []\n\t\tconst expr_values: Record<string, any> = {}\n\t\t// TODO: refactor\n\t\tfor (let i = 0; i < this.fields.length; ++i) {\n\t\t\tconst field = this.fields[i]\n\t\t\tconst expressions = field.desc ? right : left\n\t\t\tconst placeholders = field.desc ? left : right\n\t\t\texpressions.push(`\"${field.name}\"`)\n\t\t\tconst placeholder = `value${i}`\n\t\t\tplaceholders.push(\"$\" + placeholder)\n\t\t\texpr_values[placeholder] = values[i]\n\t\t}\n\t\treturn query.where(\n\t\t\tquery.raw(`(${left.join(\",\")}) > (${right.join(\",\")})`, expr_values)\n\t\t)\n\t}\n}\n","import { Query } from \"pqb\"\n\nconst graphql = Symbol(\"graphql\")\n\nexport function set_query_context(query: Query, context: any) {\n\t;(query.query as any)[graphql] = context\n}\n\nexport function get_query_context(query: Query) {\n\treturn (query.query as any)[graphql]\n}\n","import { Query } from \"pqb\"\n\nexport function run_after_query(\n\tquery: Query,\n\ttransform: (instance: any) => any\n) {\n\treturn query.afterQuery(async (_, result) => {\n\t\t// FIXME: returning is ignored in orchid (unlike objection). Add some hacks instead.\n\t\tif (Array.isArray(result)) {\n\t\t\tconst result1 = await Promise.all(result.map(transform))\n\t\t\treturn result1.filter(Boolean) // Skip empty objects\n\t\t} else if (result) {\n\t\t\treturn transform(result)\n\t\t} else {\n\t\t\t// Supposedly, single query builder returning NULL\n\t\t\treturn result\n\t\t}\n\t})\n}\n","import { ResolveTree } from \"graphql-parse-resolve-info\"\nimport { Query } from \"pqb\"\n\nimport { get_query_context } from \"../utils/query-context\"\nimport { run_after_query } from \"../utils/run-after\"\nimport type { GraphResolver } from \"./graph\"\n\n/* A function that modifies the query to select a field. */\nexport type FieldResolverFn = (\n\tquery: Query,\n\toptions: {\n\t\t/** GraphQL field */\n\t\tfield: string\n\t\t/** GraphQL resolve tree */\n\t\ttree: ResolveTree\n\t\t/** Current graph resolver */\n\t\tgraph: GraphResolver\n\t}\n) => Query\n\nexport interface FieldResolverOptions {\n\t/** Table field (if different from GraphQL field) */\n\ttableField?: string\n\t/** Custom query modifier (if different than simply selecting a field). */\n\tmodify?: FieldResolverFn\n\t/** Post-process selected value. Return a new value or a promise. */\n\ttransform?(value: any, instance: any, context: any): any\n}\n\nexport function defineFieldResolver(\n\toptions: FieldResolverOptions = {}\n): FieldResolverFn {\n\tconst { tableField, modify, transform } = options\n\n\treturn function resolve(query, options) {\n\t\tconst { field } = options\n\t\tif (modify) {\n\t\t\treturn modify(query, options)\n\t\t} else {\n\t\t\tquery = query.select({ [field]: tableField || field })\n\t\t}\n\t\tif (transform) {\n\t\t\tconst context = get_query_context(query)\n\t\t\tquery = run_after_query(query, async (instance) => {\n\t\t\t\tinstance[field] = await transform(instance[field], instance, context)\n\t\t\t\treturn instance\n\t\t\t})\n\t\t}\n\t\treturn query\n\t}\n}\n","import { GraphQLResolveInfo } from \"graphql\"\nimport { parseResolveInfo, ResolveTree } from \"graphql-parse-resolve-info\"\nimport { Query } from \"pqb\"\n\nimport { FiltersDef } from \"../filters/filters\"\nimport { Paginator } from \"../paginators/base\"\nimport { set_query_context } from \"../utils/query-context\"\nimport type { TableResolverFn, TableResolverOptions } from \"./table\"\n\nexport type GraphResolverOptions = Pick<\n\tTableResolverOptions,\n\t\"allowAllFields\" | \"allowAllFilters\"\n>\n\nexport function createGraphResolver(\n\ttypes: Record<string, TableResolverFn>,\n\toptions?: GraphResolverOptions\n) {\n\treturn new GraphResolver(types, options)\n}\n\nexport interface GraphResolveOptions {\n\tinfo: GraphQLResolveInfo\n\tcontext: any\n\tfilters?: FiltersDef\n}\n\nexport class GraphResolver {\n\tconstructor(\n\t\tpublic readonly tables: Record<string, TableResolverFn>,\n\t\tpublic readonly options: GraphResolverOptions = {}\n\t) {}\n\n\tresolve(query: Query, { info, context, filters }: GraphResolveOptions) {\n\t\tset_query_context(query, context)\n\t\tconst tree = this._get_resolve_tree(info)\n\t\treturn this._resolve_type({ query, tree, filters })\n\t}\n\n\tresolvePage(\n\t\tquery: Query,\n\t\tpaginator: Paginator,\n\t\t{ info, context, filters }: GraphResolveOptions\n\t) {\n\t\tset_query_context(query, context)\n\t\tconst tree = this._get_resolve_tree(info)\n\t\treturn this._resolve_page({ query, tree, paginator, filters })\n\t}\n\n\t_get_resolve_tree(info: GraphQLResolveInfo) {\n\t\treturn parseResolveInfo(info) as ResolveTree\n\t}\n\n\t_resolve_type({\n\t\ttree,\n\t\tquery,\n\t\tfilters,\n\t}: {\n\t\tquery: Query\n\t\ttree: ResolveTree\n\t\tfilters?: FiltersDef\n\t}) {\n\t\tconst type = Object.keys(tree.fieldsByTypeName)[0]\n\t\tconst table_resolver = this.tables[type]\n\t\tif (!table_resolver) {\n\t\t\tthrow new Error(`Table resolver not found for type ${type}.`)\n\t\t}\n\t\treturn table_resolver({ tree, type, query, filters, graph: this })\n\t}\n\n\t_resolve_page({\n\t\ttree,\n\t\tquery,\n\t\tpaginator,\n\t\tfilters,\n\t}: {\n\t\tquery: Query\n\t\ttree: ResolveTree\n\t\tpaginator: Paginator\n\t\tfilters?: FiltersDef\n\t}) {\n\t\tconst { args } = tree\n\t\t// Skip page subtree(s)\n\t\tfor (const field of paginator.path) {\n\t\t\tconst type = Object.keys(tree.fieldsByTypeName)[0]\n\t\t\ttree = tree.fieldsByTypeName[type][field]\n\t\t\t// TODO: raise exception if not found\n\t\t}\n\t\tquery = this._resolve_type({ query, tree, filters })\n\t\treturn paginator.paginate(query, args)\n\t}\n}\n","import { addParserToQuery } from \"pqb\"\n\nimport { get_query_pagination_handler, Paginator } from \"../paginators/base\"\nimport { defineFieldResolver } from \"./field\"\nimport { RelationResolverOptions } from \"./relation\"\n\nexport function definePageResolver(\n\tpaginator: Paginator,\n\toptions: RelationResolverOptions = {}\n) {\n\tconst { tableField, filters, modify } = options\n\n\treturn defineFieldResolver({\n\t\tmodify: (query, { field, tree, graph }) =>\n\t\t\tquery.select({\n\t\t\t\t[field]: (q) => {\n\t\t\t\t\tconst page_query = graph._resolve_page({\n\t\t\t\t\t\ttree,\n\t\t\t\t\t\tquery: (q as any)[tableField || field],\n\t\t\t\t\t\tpaginator,\n\t\t\t\t\t\tfilters,\n\t\t\t\t\t})\n\t\t\t\t\tconst get_page = get_query_pagination_handler(page_query)\n\t\t\t\t\taddParserToQuery(page_query.query, field, get_page as any)\n\t\t\t\t\treturn modify ? modify(page_query, tree) : page_query\n\t\t\t\t},\n\t\t\t}),\n\t})\n}\n","import { FiltersDef } from \"../filters/filters\"\nimport { defineFieldResolver, FieldResolverOptions } from \"./field\"\nimport { QueryTreeModifier } from \"./table\"\n\nexport interface RelationResolverOptions\n\textends Omit<FieldResolverOptions, \"modify\"> {\n\tfilters?: FiltersDef\n\tmodify?: QueryTreeModifier\n}\n\nexport function defineRelationResolver(options: RelationResolverOptions = {}) {\n\tconst { tableField, filters, modify } = options\n\n\treturn defineFieldResolver({\n\t\tmodify: (query, { field, tree, graph }) =>\n\t\t\tquery.select({\n\t\t\t\t[field]: (q) => {\n\t\t\t\t\tconst relation_query = graph._resolve_type({\n\t\t\t\t\t\ttree,\n\t\t\t\t\t\tquery: (q as any)[tableField || field],\n\t\t\t\t\t\tfilters,\n\t\t\t\t\t})\n\t\t\t\t\treturn modify ? modify(relation_query, tree) : relation_query\n\t\t\t\t},\n\t\t\t}),\n\t})\n}\n","export function is_plain_object(obj: any): obj is Record<string, any> {\n\treturn typeof obj === \"object\" && !Array.isArray(obj)\n}\n","import { Query } from \"pqb\"\n\nimport { is_plain_object } from \"../utils/is-plain-object\"\nimport { Modifier } from \"../utils/modifier\"\n\n// TODO: per-field definitions\nexport type FiltersDef = boolean\n\nexport type FilterScalarValue = null | string | number | boolean\nexport type FilterValue = FilterScalarValue | Exclude<FilterScalarValue, null>[]\nexport type Filter = { [property: string]: FilterValue }\n\nfunction is_scalar(value: any) {\n\treturn (\n\t\tvalue === null ||\n\t\ttypeof value === \"string\" ||\n\t\ttypeof value === \"number\" ||\n\t\ttypeof value === \"boolean\"\n\t)\n}\n\nexport function apply_filters({\n\tquery,\n\tfilters,\n\targs,\n\tmodifiers,\n}: {\n\tquery: Query\n\tfilters: FiltersDef\n\targs?: Record<string, any>\n\tmodifiers?: Record<string, Modifier>\n}) {\n\tif (!filters) {\n\t\treturn query\n\t}\n\tconst filter_obj = args?.filter\n\tif (!filter_obj) {\n\t\treturn query\n\t}\n\tif (!is_plain_object(filter_obj)) {\n\t\tthrow new Error(`Invalid filter: ${filter_obj}, must be object.`)\n\t}\n\tfor (const [field, value] of Object.entries(filter_obj)) {\n\t\tif (value === undefined) {\n\t\t\t// Support optional GraphQL arguments in filter\n\t\t\tcontinue\n\t\t}\n\t\tif (modifiers?.[field]) {\n\t\t\tquery = modifiers[field](query, value)\n\t\t} else {\n\t\t\t// Normal filter\n\t\t\tconst [dbfield, op0] = field.split(\"__\")\n\t\t\tconst op = op0?.toLowerCase() || \"exact\"\n\t\t\tif (\n\t\t\t\t// TODO: add the rest of orchid ops (or allow all of them?)\n\t\t\t\t[\n\t\t\t\t\t\"exact\",\n\t\t\t\t\t\"lt\",\n\t\t\t\t\t\"lte\",\n\t\t\t\t\t\"gt\",\n\t\t\t\t\t\"gte\",\n\t\t\t\t\t\"like\",\n\t\t\t\t\t\"ilike\",\n\t\t\t\t\t\"contains\",\n\t\t\t\t].includes(op)\n\t\t\t) {\n\t\t\t\tif (!is_scalar(value)) {\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t`Unsupported filter value for ${query.table}.${field}: must be scalar.`\n\t\t\t\t\t)\n\t\t\t\t}\n\t\t\t\tif (op === \"exact\") {\n\t\t\t\t\tquery = query.where({ [dbfield]: value })\n\t\t\t\t} else {\n\t\t\t\t\tconst query_op = { like: \"contains\" }[op] || op\n\t\t\t\t\tquery = query.where({ [dbfield]: { [query_op]: value } })\n\t\t\t\t}\n\t\t\t} else if (op === \"in\") {\n\t\t\t\tif (!(Array.isArray(value) && value.every(is_scalar))) {\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t`Invalid filter value for ${query.table}.${field}: must be an array of scalars.`\n\t\t\t\t\t)\n\t\t\t\t}\n\t\t\t\tquery = query.whereIn(dbfield, value)\n\t\t\t} else {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Invalid filter ${query.table}.${field}: unsupported operator ${op}.`\n\t\t\t\t)\n\t\t\t}\n\t\t}\n\t}\n\treturn query\n}\n","import { ResolveTree } from \"graphql-parse-resolve-info\"\nimport { DbTable, TableClass } from \"orchid-orm\"\nimport { Query } from \"pqb\"\n\nimport { apply_filters, FiltersDef } from \"../filters/filters\"\nimport { Modifier } from \"../utils/modifier\"\nimport { get_query_context } from \"../utils/query-context\"\nimport { run_after_query } from \"../utils/run-after\"\nimport { defineFieldResolver, FieldResolverFn } from \"./field\"\nimport type { GraphResolver } from \"./graph\"\nimport { defineRelationResolver } from \"./relation\"\n\n/** A function that modifies the query to select fields/relations and filter the result set. */\nexport type TableResolverFn = (args: {\n\ttree: ResolveTree\n\t/** GraphQL type */\n\ttype: string\n\tquery: Query\n\tfilters?: FiltersDef\n\tgraph: GraphResolver\n}) => Query\n\nexport interface TableResolverOptions {\n\t/** allow to resolve all table fields without explicitly listing them */\n\tallowAllFields?: boolean\n\t/** allow to filter all table fields without explicitly listing them */\n\tallowAllFilters?: boolean\n\tfields?: Record<string, SimpleFieldResolver>\n\tmodifiers?: Record<string, Modifier>\n\tmodify?: QueryTreeModifier\n\ttransform?(instance: any, context: any): void | PromiseLike<void>\n}\n\nexport type SimpleFieldResolver = true | string | FieldResolverFn\n\nexport type QueryTreeModifier = (query: Query, tree: ResolveTree) => Query\n\nexport function defineTableResolver<T extends TableClass>(\n\ttable: DbTable<T>,\n\toptions: TableResolverOptions = {}\n): TableResolverFn {\n\t/**\n\t * Create a field resolver which will modify the query to resolve a GraphQL field.\n\t */\n\tconst get_default_field_resolver = (\n\t\tfield: string,\n\t\ttableField?: string\n\t): FieldResolverFn | undefined => {\n\t\tconst table_field_lookup = tableField || field\n\t\tif (options.modifiers?.[table_field_lookup]) {\n\t\t\t// Keep query as is.\n\t\t\treturn (query) => query\n\t\t} else if ((table.relations as any)?.[table_field_lookup]) {\n\t\t\treturn defineRelationResolver({ tableField })\n\t\t} else {\n\t\t\treturn defineFieldResolver({ tableField })\n\t\t}\n\t}\n\n\t// Pre-create field resolvers\n\tconst { fields } = options\n\tconst table_field_resolvers = fields\n\t\t? Object.keys(fields).reduce<Record<string, FieldResolverFn>>(\n\t\t\t\t(resolvers, field) => {\n\t\t\t\t\tconst r0 = fields[field]\n\t\t\t\t\tconst r: FieldResolverFn | undefined =\n\t\t\t\t\t\ttypeof r0 === \"function\"\n\t\t\t\t\t\t\t? r0\n\t\t\t\t\t\t\t: r0 === true\n\t\t\t\t\t\t\t? get_default_field_resolver(field)\n\t\t\t\t\t\t\t: typeof r0 === \"string\"\n\t\t\t\t\t\t\t? get_default_field_resolver(field, r0)\n\t\t\t\t\t\t\t: undefined\n\t\t\t\t\tif (r === undefined) {\n\t\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t\t`Field resolver must be a function, string, or true; found ${r0}`\n\t\t\t\t\t\t)\n\t\t\t\t\t}\n\t\t\t\t\tresolvers[field] = r\n\t\t\t\t\treturn resolvers\n\t\t\t\t},\n\t\t\t\t{}\n\t\t )\n\t\t: undefined\n\n\tconst { modify, transform } = options\n\n\treturn function resolve({ tree, type, query, filters, graph }) {\n\t\tif (query.table !== table.table) {\n\t\t\tthrow new Error(\n\t\t\t\t`Mismatching query type (expected ${table.table}, found ${query.table}).`\n\t\t\t)\n\t\t}\n\n\t\tconst allow_all_fields =\n\t\t\toptions.allowAllFields ??\n\t\t\tgraph.options.allowAllFields ??\n\t\t\ttable_field_resolvers === undefined\n\n\t\tif (!allow_all_fields && !table_field_resolvers) {\n\t\t\tthrow new Error(\n\t\t\t\t`Table resolver for ${type} must either allow all fields or specify options.fields`\n\t\t\t)\n\t\t}\n\n\t\tif (modify) {\n\t\t\tquery = modify(query, tree)\n\t\t}\n\n\t\tfor (const subtree of Object.values(tree.fieldsByTypeName[type])) {\n\t\t\tconst field = subtree.name\n\t\t\tconst r =\n\t\t\t\ttable_field_resolvers?.[field] ||\n\t\t\t\t(allow_all_fields ? get_default_field_resolver(field) : undefined)\n\t\t\tif (!r) {\n\t\t\t\tthrow new Error(`No field resolver defined for field ${type}.${field}`)\n\t\t\t}\n\t\t\tif (r) {\n\t\t\t\tquery = r(query, { field, tree: subtree, graph })\n\t\t\t}\n\t\t}\n\n\t\tconst allow_all_filters =\n\t\t\toptions.allowAllFilters ?? graph.options.allowAllFilters\n\n\t\tconst effective_filters = allow_all_filters ? true : filters\n\n\t\tif (effective_filters) {\n\t\t\tquery = apply_filters({\n\t\t\t\tquery,\n\t\t\t\tfilters: effective_filters,\n\t\t\t\targs: tree.args,\n\t\t\t\tmodifiers: options.modifiers,\n\t\t\t})\n\t\t}\n\n\t\tif (transform) {\n\t\t\tconst context = get_query_context(query)\n\t\t\tquery = run_after_query(query, (instance) => {\n\t\t\t\treturn transform(instance, context)\n\t\t\t})\n\t\t}\n\n\t\treturn query\n\t}\n}\n"],"mappings":"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","names":["cursor","options"]}
1
+ {"version":3,"sources":["../src/paginators/base.ts","../src/paginators/cursor.ts","../src/utils/query-context.ts","../src/utils/run-after.ts","../src/resolvers/field.ts","../src/resolvers/graph.ts","../src/resolvers/page.ts","../src/resolvers/relation.ts","../src/utils/is-plain-object.ts","../src/filters/filters.ts","../src/resolvers/table.ts"],"sourcesContent":["import { Query } from \"pqb\"\n\nexport interface Paginator {\n\t/** GraphQL path, for example: `[\"nodes\"]` */\n\treadonly path: string[]\n\tpaginate(query: Query, ...args: any[]): Query\n}\n\ntype GetPageFn<P> = (nodes: any[]) => P\n\nconst s = Symbol()\n\n// FIXME use proper orchid methods, set result type\nexport function set_query_page_result<P>(query: Query, get_page: GetPageFn<P>) {\n\tfunction _get_page(data: any) {\n\t\tif (!Array.isArray(data)) {\n\t\t\tthrow new Error(`Paginator called for single result query.`)\n\t\t}\n\t\treturn get_page(data)\n\t}\n\n\t// For root query\n\tconst _query = query.query\n\tconst { handleResult } = _query\n\t_query.handleResult = (q, result, s) => {\n\t\tconst data = handleResult(q, result, s)\n\t\t// Sometimes this is called for subqueries, sometimes not.\n\t\t// TODO: investigate and use always.\n\t\treturn s ? data : _get_page(data)\n\t}\n\n\t// For subqueries\n\t;(_query as any)[s] = _get_page\n\n\treturn query\n}\n\nexport function get_query_pagination_handler(query: Query) {\n\treturn (query.query as any)[s]\n}\n","import { Query } from \"pqb\"\n\nimport { Paginator, set_query_page_result } from \"./base\"\n\nexport function defineCursorPaginator(\n\toptions: Partial<CursorPaginatorOptions> = {}\n) {\n\treturn new CursorPaginator(options)\n}\n\nexport interface CursorPaginatorOptions {\n\tfields: string[]\n\ttake: number\n}\n\nexport interface CursorPaginatorArgs {\n\tcursor?: string\n\ttake?: number\n}\n\nexport interface CursorPaginatorPage<M> {\n\tnodes: M[]\n\tcursor?: string\n}\n\nclass CursorPaginator implements Paginator {\n\treadonly path = [\"nodes\"]\n\treadonly options: CursorPaginatorOptions\n\n\treadonly fields: Array<{\n\t\tname: string\n\t\tdesc: boolean\n\t}>\n\n\tconstructor(options: Partial<CursorPaginatorOptions> = {}) {\n\t\tthis.options = {\n\t\t\tfields: [\"id\"],\n\t\t\ttake: 10,\n\t\t\t...options,\n\t\t}\n\t\tthis.fields = this.options.fields.map((field) => {\n\t\t\tif (field.startsWith(\"-\")) {\n\t\t\t\treturn { name: field.slice(1), desc: true }\n\t\t\t} else {\n\t\t\t\treturn { name: field, desc: false }\n\t\t\t}\n\t\t})\n\t}\n\n\tpaginate(query: Query, args: CursorPaginatorArgs = {}) {\n\t\tconst take = args.take ?? this.options.take\n\t\tconst { cursor } = args\n\n\t\t// Set query order\n\t\tquery = query.clear(\"order\")\n\t\tfor (const field of this.fields) {\n\t\t\t// TODO: prevent potential name clash with aliases like .as(`_${table_ref}_order_key_0`)\n\t\t\tquery = query\n\t\t\t\t.select(field.name)\n\t\t\t\t.order({ [field.name]: field.desc ? \"DESC\" : \"ASC\" })\n\t\t}\n\n\t\tif (cursor) {\n\t\t\tquery = this._set_query_cursor(query, cursor)\n\t\t}\n\t\tquery = query.limit(take + 1)\n\n\t\tquery = set_query_page_result(query, (nodes) => {\n\t\t\tlet cursor: string | undefined\n\t\t\tif (nodes.length > take) {\n\t\t\t\tcursor = this._create_cursor(nodes[take - 1])\n\t\t\t\tnodes = nodes.slice(0, take)\n\t\t\t}\n\t\t\treturn { nodes, cursor }\n\t\t})\n\n\t\treturn query\n\t}\n\n\t_create_cursor(instance: any) {\n\t\treturn JSON.stringify(\n\t\t\tthis.fields.map((field) => {\n\t\t\t\tconst value = instance[field.name]\n\t\t\t\tif (value === undefined) {\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t`Unable to create cursor: undefined field ${field.name}`\n\t\t\t\t\t)\n\t\t\t\t}\n\t\t\t\treturn String(value)\n\t\t\t})\n\t\t)\n\t}\n\n\t_set_query_cursor(query: Query, cursor: string) {\n\t\tconst values = JSON.parse(cursor)\n\t\tconst left: string[] = []\n\t\tconst right: string[] = []\n\t\tconst expr_values: Record<string, any> = {}\n\t\t// TODO: refactor\n\t\tfor (let i = 0; i < this.fields.length; ++i) {\n\t\t\tconst field = this.fields[i]\n\t\t\tconst expressions = field.desc ? right : left\n\t\t\tconst placeholders = field.desc ? left : right\n\t\t\texpressions.push(`\"${field.name}\"`)\n\t\t\tconst placeholder = `value${i}`\n\t\t\tplaceholders.push(\"$\" + placeholder)\n\t\t\texpr_values[placeholder] = values[i]\n\t\t}\n\t\treturn query.where(\n\t\t\tquery.raw(`(${left.join(\",\")}) > (${right.join(\",\")})`, expr_values)\n\t\t)\n\t}\n}\n","import { Query } from \"pqb\"\n\nconst graphql = Symbol(\"graphql\")\n\nexport function set_query_context(query: Query, context: any) {\n\t;(query.query as any)[graphql] = context\n}\n\nexport function get_query_context(query: Query) {\n\treturn (query.query as any)[graphql]\n}\n","import { Query } from \"pqb\"\n\nexport function run_after_query(\n\tquery: Query,\n\ttransform: (instance: any) => any\n) {\n\treturn query.afterQuery(async (_, result) => {\n\t\t// FIXME: returning is ignored in orchid (unlike objection). Add some hacks instead.\n\t\tif (Array.isArray(result)) {\n\t\t\tconst result1 = await Promise.all(result.map(transform))\n\t\t\treturn result1.filter(Boolean) // Skip empty objects\n\t\t} else if (result) {\n\t\t\treturn transform(result)\n\t\t} else {\n\t\t\t// Supposedly, single query builder returning NULL\n\t\t\treturn result\n\t\t}\n\t})\n}\n","import { ResolveTree } from \"graphql-parse-resolve-info\"\nimport { Query } from \"pqb\"\n\nimport { get_query_context } from \"../utils/query-context\"\nimport { run_after_query } from \"../utils/run-after\"\nimport type { GraphResolver } from \"./graph\"\n\n/* A function that modifies the query to select a field. */\nexport type FieldResolverFn = (\n\tquery: Query,\n\toptions: {\n\t\t/** GraphQL field */\n\t\tfield: string\n\t\t/** GraphQL resolve tree */\n\t\ttree: ResolveTree\n\t\t/** Current graph resolver */\n\t\tgraph: GraphResolver\n\t}\n) => Query\n\nexport interface FieldResolverOptions {\n\t/** Table field (if different from GraphQL field) */\n\ttableField?: string\n\t/** Custom query modifier (if different than simply selecting a field). */\n\tmodify?: FieldResolverFn\n\t/** Post-process selected value. Return a new value or a promise. */\n\ttransform?(value: any, instance: any, context: any): any\n}\n\nexport function defineFieldResolver(\n\toptions: FieldResolverOptions = {}\n): FieldResolverFn {\n\tconst { tableField, modify, transform } = options\n\n\treturn function resolve(query, options) {\n\t\tconst { field } = options\n\t\tif (modify) {\n\t\t\treturn modify(query, options)\n\t\t} else {\n\t\t\tquery = query.select({ [field]: tableField || field })\n\t\t}\n\t\tif (transform) {\n\t\t\tconst context = get_query_context(query)\n\t\t\tquery = run_after_query(query, async (instance) => {\n\t\t\t\tinstance[field] = await transform(instance[field], instance, context)\n\t\t\t\treturn instance\n\t\t\t})\n\t\t}\n\t\treturn query\n\t}\n}\n","import { GraphQLResolveInfo } from \"graphql\"\nimport { parseResolveInfo, ResolveTree } from \"graphql-parse-resolve-info\"\nimport { Query } from \"pqb\"\n\nimport { FiltersDef } from \"../filters/filters\"\nimport { Paginator } from \"../paginators/base\"\nimport { set_query_context } from \"../utils/query-context\"\nimport type { TableResolverFn, TableResolverOptions } from \"./table\"\n\nexport type GraphResolverOptions = Pick<\n\tTableResolverOptions,\n\t\"allowAllFields\" | \"allowAllFilters\"\n>\n\nexport function createGraphResolver(\n\ttypes: Record<string, TableResolverFn>,\n\toptions?: GraphResolverOptions\n) {\n\treturn new GraphResolver(types, options)\n}\n\nexport interface GraphResolveOptions {\n\tinfo: GraphQLResolveInfo\n\tcontext: any\n\tfilters?: FiltersDef\n}\n\nexport class GraphResolver {\n\tconstructor(\n\t\tpublic readonly tables: Record<string, TableResolverFn>,\n\t\tpublic readonly options: GraphResolverOptions = {}\n\t) {}\n\n\tresolve(query: Query, { info, context, filters }: GraphResolveOptions) {\n\t\tset_query_context(query, context)\n\t\tconst tree = this._get_resolve_tree(info)\n\t\treturn this._resolve_type({ query, tree, filters })\n\t}\n\n\tresolvePage(\n\t\tquery: Query,\n\t\tpaginator: Paginator,\n\t\t{ info, context, filters }: GraphResolveOptions\n\t) {\n\t\tset_query_context(query, context)\n\t\tconst tree = this._get_resolve_tree(info)\n\t\treturn this._resolve_page({ query, tree, paginator, filters })\n\t}\n\n\t_get_resolve_tree(info: GraphQLResolveInfo) {\n\t\treturn parseResolveInfo(info) as ResolveTree\n\t}\n\n\t_resolve_type({\n\t\ttree,\n\t\tquery,\n\t\tfilters,\n\t}: {\n\t\tquery: Query\n\t\ttree: ResolveTree\n\t\tfilters?: FiltersDef\n\t}) {\n\t\tconst type = Object.keys(tree.fieldsByTypeName)[0]\n\t\tconst table_resolver = this.tables[type]\n\t\tif (!table_resolver) {\n\t\t\tthrow new Error(`Table resolver not found for type ${type}.`)\n\t\t}\n\t\treturn table_resolver({ tree, type, query, filters, graph: this })\n\t}\n\n\t_resolve_page({\n\t\ttree,\n\t\tquery,\n\t\tpaginator,\n\t\tfilters,\n\t}: {\n\t\tquery: Query\n\t\ttree: ResolveTree\n\t\tpaginator: Paginator\n\t\tfilters?: FiltersDef\n\t}) {\n\t\tconst { args } = tree\n\t\t// Skip page subtree(s)\n\t\tfor (const field of paginator.path) {\n\t\t\tconst type = Object.keys(tree.fieldsByTypeName)[0]\n\t\t\ttree = tree.fieldsByTypeName[type][field]\n\t\t\t// TODO: raise exception if not found\n\t\t}\n\t\tquery = this._resolve_type({ query, tree, filters })\n\t\treturn paginator.paginate(query, args)\n\t}\n}\n","import { addParserToQuery } from \"pqb\"\n\nimport { get_query_pagination_handler, Paginator } from \"../paginators/base\"\nimport { defineFieldResolver } from \"./field\"\nimport { RelationResolverOptions } from \"./relation\"\n\nexport function definePageResolver(\n\tpaginator: Paginator,\n\toptions: RelationResolverOptions = {}\n) {\n\tconst { tableField, filters, modify } = options\n\n\treturn defineFieldResolver({\n\t\tmodify: (query, { field, tree, graph }) => {\n\t\t\t// FIXME: refactor, add types\n\t\t\tlet get_page: any\n\t\t\tquery = query.select({\n\t\t\t\t[field]: (q) => {\n\t\t\t\t\tq = graph._resolve_page({\n\t\t\t\t\t\ttree,\n\t\t\t\t\t\tquery: (q as any)[tableField || field],\n\t\t\t\t\t\tpaginator,\n\t\t\t\t\t\tfilters,\n\t\t\t\t\t})\n\t\t\t\t\t// Calling addParserToQuery here doesn't work, save the paginator for later.\n\t\t\t\t\tget_page = get_query_pagination_handler(q)\n\t\t\t\t\treturn modify ? modify(q, tree) : q\n\t\t\t\t},\n\t\t\t})\n\t\t\tconst parser = query.query.parsers?.[field]\n\t\t\taddParserToQuery(query.query, field, (nodes) => {\n\t\t\t\tnodes = parser ? parser(nodes) : nodes\n\t\t\t\treturn get_page(nodes)\n\t\t\t})\n\t\t\treturn query\n\t\t},\n\t})\n}\n","import { FiltersDef } from \"../filters/filters\"\nimport { defineFieldResolver, FieldResolverOptions } from \"./field\"\nimport { QueryTreeModifier } from \"./table\"\n\nexport interface RelationResolverOptions\n\textends Omit<FieldResolverOptions, \"modify\"> {\n\tfilters?: FiltersDef\n\tmodify?: QueryTreeModifier\n}\n\nexport function defineRelationResolver(options: RelationResolverOptions = {}) {\n\tconst { tableField, filters, modify } = options\n\n\treturn defineFieldResolver({\n\t\tmodify: (query, { field, tree, graph }) =>\n\t\t\tquery.select({\n\t\t\t\t[field]: (q) => {\n\t\t\t\t\tconst relation_query = graph._resolve_type({\n\t\t\t\t\t\ttree,\n\t\t\t\t\t\tquery: (q as any)[tableField || field],\n\t\t\t\t\t\tfilters,\n\t\t\t\t\t})\n\t\t\t\t\treturn modify ? modify(relation_query, tree) : relation_query\n\t\t\t\t},\n\t\t\t}),\n\t})\n}\n","export function is_plain_object(obj: any): obj is Record<string, any> {\n\treturn typeof obj === \"object\" && !Array.isArray(obj)\n}\n","import { Query } from \"pqb\"\n\nimport { is_plain_object } from \"../utils/is-plain-object\"\nimport { Modifier } from \"../utils/modifier\"\n\n// TODO: per-field definitions\nexport type FiltersDef = boolean\n\nexport type FilterScalarValue = null | string | number | boolean\nexport type FilterValue = FilterScalarValue | Exclude<FilterScalarValue, null>[]\nexport type Filter = { [property: string]: FilterValue }\n\nfunction is_scalar(value: any) {\n\treturn (\n\t\tvalue === null ||\n\t\ttypeof value === \"string\" ||\n\t\ttypeof value === \"number\" ||\n\t\ttypeof value === \"boolean\"\n\t)\n}\n\nexport function apply_filters({\n\tquery,\n\tfilters,\n\targs,\n\tmodifiers,\n}: {\n\tquery: Query\n\tfilters: FiltersDef\n\targs?: Record<string, any>\n\tmodifiers?: Record<string, Modifier>\n}) {\n\tif (!filters) {\n\t\treturn query\n\t}\n\tconst filter_obj = args?.filter\n\tif (!filter_obj) {\n\t\treturn query\n\t}\n\tif (!is_plain_object(filter_obj)) {\n\t\tthrow new Error(`Invalid filter: ${filter_obj}, must be object.`)\n\t}\n\tfor (const [field, value] of Object.entries(filter_obj)) {\n\t\tif (value === undefined) {\n\t\t\t// Support optional GraphQL arguments in filter\n\t\t\tcontinue\n\t\t}\n\t\tif (modifiers?.[field]) {\n\t\t\tquery = modifiers[field](query, value)\n\t\t} else {\n\t\t\t// Normal filter\n\t\t\tconst [dbfield, op0] = field.split(\"__\")\n\t\t\tconst op = op0?.toLowerCase() || \"exact\"\n\t\t\tif (\n\t\t\t\t// TODO: add the rest of orchid ops (or allow all of them?)\n\t\t\t\t[\n\t\t\t\t\t\"exact\",\n\t\t\t\t\t\"lt\",\n\t\t\t\t\t\"lte\",\n\t\t\t\t\t\"gt\",\n\t\t\t\t\t\"gte\",\n\t\t\t\t\t\"like\",\n\t\t\t\t\t\"ilike\",\n\t\t\t\t\t\"contains\",\n\t\t\t\t].includes(op)\n\t\t\t) {\n\t\t\t\tif (!is_scalar(value)) {\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t`Unsupported filter value for ${query.table}.${field}: must be scalar.`\n\t\t\t\t\t)\n\t\t\t\t}\n\t\t\t\tif (op === \"exact\") {\n\t\t\t\t\tquery = query.where({ [dbfield]: value })\n\t\t\t\t} else {\n\t\t\t\t\tconst query_op = { like: \"contains\" }[op] || op\n\t\t\t\t\tquery = query.where({ [dbfield]: { [query_op]: value } })\n\t\t\t\t}\n\t\t\t} else if (op === \"in\") {\n\t\t\t\tif (!(Array.isArray(value) && value.every(is_scalar))) {\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t`Invalid filter value for ${query.table}.${field}: must be an array of scalars.`\n\t\t\t\t\t)\n\t\t\t\t}\n\t\t\t\tquery = query.whereIn(dbfield, value)\n\t\t\t} else {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Invalid filter ${query.table}.${field}: unsupported operator ${op}.`\n\t\t\t\t)\n\t\t\t}\n\t\t}\n\t}\n\treturn query\n}\n","import { ResolveTree } from \"graphql-parse-resolve-info\"\nimport { DbTable, TableClass } from \"orchid-orm\"\nimport { Query } from \"pqb\"\n\nimport { apply_filters, FiltersDef } from \"../filters/filters\"\nimport { Modifier } from \"../utils/modifier\"\nimport { get_query_context } from \"../utils/query-context\"\nimport { run_after_query } from \"../utils/run-after\"\nimport { defineFieldResolver, FieldResolverFn } from \"./field\"\nimport type { GraphResolver } from \"./graph\"\nimport { defineRelationResolver } from \"./relation\"\n\n/** A function that modifies the query to select fields/relations and filter the result set. */\nexport type TableResolverFn = (args: {\n\ttree: ResolveTree\n\t/** GraphQL type */\n\ttype: string\n\tquery: Query\n\tfilters?: FiltersDef\n\tgraph: GraphResolver\n}) => Query\n\nexport interface TableResolverOptions {\n\t/** allow to resolve all table fields without explicitly listing them */\n\tallowAllFields?: boolean\n\t/** allow to filter all table fields without explicitly listing them */\n\tallowAllFilters?: boolean\n\tfields?: Record<string, SimpleFieldResolver>\n\tmodifiers?: Record<string, Modifier>\n\tmodify?: QueryTreeModifier\n\ttransform?(instance: any, context: any): void | PromiseLike<void>\n}\n\nexport type SimpleFieldResolver = true | string | FieldResolverFn\n\nexport type QueryTreeModifier = (query: Query, tree: ResolveTree) => Query\n\nexport function defineTableResolver<T extends TableClass>(\n\ttable: DbTable<T>,\n\toptions: TableResolverOptions = {}\n): TableResolverFn {\n\t/**\n\t * Create a field resolver which will modify the query to resolve a GraphQL field.\n\t */\n\tconst get_default_field_resolver = (\n\t\tfield: string,\n\t\ttableField?: string\n\t): FieldResolverFn | undefined => {\n\t\tconst table_field_lookup = tableField || field\n\t\tif (options.modifiers?.[table_field_lookup]) {\n\t\t\t// Keep query as is.\n\t\t\treturn (query) => query\n\t\t} else if ((table.relations as any)?.[table_field_lookup]) {\n\t\t\treturn defineRelationResolver({ tableField })\n\t\t} else {\n\t\t\treturn defineFieldResolver({ tableField })\n\t\t}\n\t}\n\n\t// Pre-create field resolvers\n\tconst { fields } = options\n\tconst table_field_resolvers = fields\n\t\t? Object.keys(fields).reduce<Record<string, FieldResolverFn>>(\n\t\t\t\t(resolvers, field) => {\n\t\t\t\t\tconst r0 = fields[field]\n\t\t\t\t\tconst r: FieldResolverFn | undefined =\n\t\t\t\t\t\ttypeof r0 === \"function\"\n\t\t\t\t\t\t\t? r0\n\t\t\t\t\t\t\t: r0 === true\n\t\t\t\t\t\t\t? get_default_field_resolver(field)\n\t\t\t\t\t\t\t: typeof r0 === \"string\"\n\t\t\t\t\t\t\t? get_default_field_resolver(field, r0)\n\t\t\t\t\t\t\t: undefined\n\t\t\t\t\tif (r === undefined) {\n\t\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t\t`Field resolver must be a function, string, or true; found ${r0}`\n\t\t\t\t\t\t)\n\t\t\t\t\t}\n\t\t\t\t\tresolvers[field] = r\n\t\t\t\t\treturn resolvers\n\t\t\t\t},\n\t\t\t\t{}\n\t\t )\n\t\t: undefined\n\n\tconst { modify, transform } = options\n\n\treturn function resolve({ tree, type, query, filters, graph }) {\n\t\tif (query.table !== table.table) {\n\t\t\tthrow new Error(\n\t\t\t\t`Mismatching query type (expected ${table.table}, found ${query.table}).`\n\t\t\t)\n\t\t}\n\n\t\tconst allow_all_fields =\n\t\t\toptions.allowAllFields ??\n\t\t\tgraph.options.allowAllFields ??\n\t\t\ttable_field_resolvers === undefined\n\n\t\tif (!allow_all_fields && !table_field_resolvers) {\n\t\t\tthrow new Error(\n\t\t\t\t`Table resolver for ${type} must either allow all fields or specify options.fields`\n\t\t\t)\n\t\t}\n\n\t\tif (modify) {\n\t\t\tquery = modify(query, tree)\n\t\t}\n\n\t\tfor (const subtree of Object.values(tree.fieldsByTypeName[type])) {\n\t\t\tconst field = subtree.name\n\t\t\tconst r =\n\t\t\t\ttable_field_resolvers?.[field] ||\n\t\t\t\t(allow_all_fields ? get_default_field_resolver(field) : undefined)\n\t\t\tif (!r) {\n\t\t\t\tthrow new Error(`No field resolver defined for field ${type}.${field}`)\n\t\t\t}\n\t\t\tif (r) {\n\t\t\t\tquery = r(query, { field, tree: subtree, graph })\n\t\t\t}\n\t\t}\n\n\t\tconst allow_all_filters =\n\t\t\toptions.allowAllFilters ?? graph.options.allowAllFilters\n\n\t\tconst effective_filters = allow_all_filters ? true : filters\n\n\t\tif (effective_filters) {\n\t\t\tquery = apply_filters({\n\t\t\t\tquery,\n\t\t\t\tfilters: effective_filters,\n\t\t\t\targs: tree.args,\n\t\t\t\tmodifiers: options.modifiers,\n\t\t\t})\n\t\t}\n\n\t\tif (transform) {\n\t\t\tconst context = get_query_context(query)\n\t\t\tquery = run_after_query(query, (instance) => {\n\t\t\t\treturn transform(instance, context)\n\t\t\t})\n\t\t}\n\n\t\treturn query\n\t}\n}\n"],"mappings":"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","names":["s","cursor","options"]}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "orchid-graphql",
3
3
  "description": "orchid-orm plugin: resolve GraphQL query with Orchid ORM",
4
- "version": "0.0.1",
4
+ "version": "0.0.2",
5
5
  "repository": {
6
6
  "type": "git",
7
7
  "url": "https://github.com/IlyaSemenov/orchid-graphql"
@@ -20,14 +20,17 @@ export function set_query_page_result<P>(query: Query, get_page: GetPageFn<P>) {
20
20
  }
21
21
 
22
22
  // For root query
23
- const { handleResult } = query.query as any
24
- ;(query.query as any).handleResult = (...args: any[]) => {
25
- const data = handleResult(...args)
26
- return _get_page(data)
23
+ const _query = query.query
24
+ const { handleResult } = _query
25
+ _query.handleResult = (q, result, s) => {
26
+ const data = handleResult(q, result, s)
27
+ // Sometimes this is called for subqueries, sometimes not.
28
+ // TODO: investigate and use always.
29
+ return s ? data : _get_page(data)
27
30
  }
28
31
 
29
- // For nested query
30
- ;(query.query as any)[s] = _get_page
32
+ // For subqueries
33
+ ;(_query as any)[s] = _get_page
31
34
 
32
35
  return query
33
36
  }
@@ -50,7 +50,6 @@ class CursorPaginator implements Paginator {
50
50
  paginate(query: Query, args: CursorPaginatorArgs = {}) {
51
51
  const take = args.take ?? this.options.take
52
52
  const { cursor } = args
53
- console.log("paginating query", query)
54
53
 
55
54
  // Set query order
56
55
  query = query.clear("order")
@@ -11,19 +11,28 @@ export function definePageResolver(
11
11
  const { tableField, filters, modify } = options
12
12
 
13
13
  return defineFieldResolver({
14
- modify: (query, { field, tree, graph }) =>
15
- query.select({
14
+ modify: (query, { field, tree, graph }) => {
15
+ // FIXME: refactor, add types
16
+ let get_page: any
17
+ query = query.select({
16
18
  [field]: (q) => {
17
- const page_query = graph._resolve_page({
19
+ q = graph._resolve_page({
18
20
  tree,
19
21
  query: (q as any)[tableField || field],
20
22
  paginator,
21
23
  filters,
22
24
  })
23
- const get_page = get_query_pagination_handler(page_query)
24
- addParserToQuery(page_query.query, field, get_page as any)
25
- return modify ? modify(page_query, tree) : page_query
25
+ // Calling addParserToQuery here doesn't work, save the paginator for later.
26
+ get_page = get_query_pagination_handler(q)
27
+ return modify ? modify(q, tree) : q
26
28
  },
27
- }),
29
+ })
30
+ const parser = query.query.parsers?.[field]
31
+ addParserToQuery(query.query, field, (nodes) => {
32
+ nodes = parser ? parser(nodes) : nodes
33
+ return get_page(nodes)
34
+ })
35
+ return query
36
+ },
28
37
  })
29
38
  }