orchid-graphql 0.0.3 → 1.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/README.md +13 -11
- package/dist/index.cjs +249 -216
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +127 -83
- package/dist/index.js +249 -216
- package/dist/index.js.map +1 -1
- package/package.json +13 -27
- package/src/index.ts +12 -12
- package/src/orm/orm.ts +112 -0
- package/src/resolvers/graph.ts +9 -86
- package/src/resolvers/table.ts +5 -139
- package/src/filters/filters.ts +0 -93
- package/src/paginators/base.ts +0 -40
- package/src/paginators/cursor.ts +0 -113
- package/src/resolvers/field.ts +0 -51
- package/src/resolvers/page.ts +0 -34
- package/src/resolvers/relation.ts +0 -27
- package/src/utils/is-plain-object.ts +0 -3
- package/src/utils/modifier.ts +0 -3
- package/src/utils/query-context.ts +0 -11
- package/src/utils/run-after.ts +0 -19
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 _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 { overrideParserInQuery } from \"orchid-core\"\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\toverrideParserInQuery(query.query, field, get_page)\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"]}
|
|
1
|
+
{"version":3,"sources":["../../graphql-orm-resolver/src/paginators/cursor.ts","../../graphql-orm-resolver/src/utils/run-after.ts","../../graphql-orm-resolver/src/resolvers/field.ts","../../graphql-orm-resolver/src/resolvers/graph.ts","../../graphql-orm-resolver/src/resolvers/page.ts","../../graphql-orm-resolver/src/resolvers/relation.ts","../../graphql-orm-resolver/src/utils/is-plain-object.ts","../../graphql-orm-resolver/src/filters/filters.ts","../../graphql-orm-resolver/src/resolvers/table.ts","../src/orm/orm.ts","../src/resolvers/graph.ts","../src/resolvers/table.ts"],"sourcesContent":["import { PaginateContext, Paginator } 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: unknown, context: PaginateContext) {\n\t\tconst { orm } = context.graph\n\t\tconst { args } = context.tree\n\n\t\tconst take = (args.take as number | undefined) ?? this.options.take\n\t\tconst cursor = args.cursor as string | undefined\n\n\t\t// Set query order\n\t\tquery = orm.reset_query_order(query)\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 = orm.select_field(query, { field: field.name, as: field.name })\n\t\t\tquery = orm.add_query_order(query, field.name, field.desc)\n\t\t}\n\n\t\tif (cursor) {\n\t\t\tconst { expression, bindings } = this._parse_cursor(cursor)\n\t\t\tquery = orm.where_raw(query, expression, bindings)\n\t\t}\n\t\tquery = orm.set_query_limit(query, take + 1)\n\n\t\tquery = orm.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_parse_cursor(cursor: string) {\n\t\tconst values = JSON.parse(cursor)\n\t\tconst left: string[] = []\n\t\tconst right: string[] = []\n\t\tconst bindings: Record<string, any> = {}\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\tplaceholders.push(\"$\" + field.name)\n\t\t\tbindings[field.name] = values[i]\n\t\t}\n\t\treturn {\n\t\t\texpression: `(${left.join(\",\")}) > (${right.join(\",\")})`,\n\t\t\tbindings,\n\t\t}\n\t}\n}\n","import { OrmAdapter } from \"../orm/orm\"\n\nexport function run_after_query(\n\torm: OrmAdapter<any, any>,\n\tquery: unknown,\n\ttransform: (instance: any) => any\n) {\n\treturn orm.run_after_query(query, async (result) => {\n\t\t// FIXME: returning result 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 returning NULL\n\t\t\treturn result\n\t\t}\n\t})\n}\n","import { run_after_query } from \"../utils/run-after\"\nimport { TableResolveContext } from \"./table\"\n\nexport interface FieldResolverOptions<Query = unknown> {\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?: FieldResolveModifier<Query>\n\t/** Post-process selected value. Return a new value or a promise. */\n\ttransform?(\n\t\tvalue: any,\n\t\tinstance: any,\n\t\tcontext: FieldResolveContext<Query>\n\t): any\n}\n\nexport type FieldResolveModifier<Query = unknown> = (\n\tquery: Query,\n\tcontext: FieldResolveContext<Query>\n) => Query\n\nexport interface FieldResolveContext<Query = unknown>\n\textends TableResolveContext<Query> {\n\t/** GraphQL field */\n\tfield: string\n}\n\n// That is a coincidence for now.\nexport type FieldResolver<Query = unknown> = FieldResolveModifier<Query>\n\nexport function defineFieldResolver<Query = unknown>(\n\toptions: FieldResolverOptions<Query> = {}\n): FieldResolver<Query> {\n\tconst { tableField, modify, transform } = options\n\n\treturn function resolve(query, context) {\n\t\tconst { field } = context\n\t\tif (modify) {\n\t\t\tquery = modify(query, context)\n\t\t} else {\n\t\t\tquery = context.graph.orm.select_field(query, {\n\t\t\t\tfield: tableField || field,\n\t\t\t\tas: field,\n\t\t\t})\n\t\t}\n\t\tif (transform) {\n\t\t\tquery = run_after_query(context.graph.orm, 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 type { GraphQLResolveInfo } from \"graphql\"\nimport { parseResolveInfo, ResolveTree } from \"graphql-parse-resolve-info\"\n\nimport { FiltersDef } from \"../filters/filters\"\nimport { OrmAdapter } from \"../orm/orm\"\nimport { Paginator } from \"../paginators/base\"\nimport type { TableResolver, TableResolverOptions } from \"./table\"\n\nexport type GraphResolverOptions<Query = unknown> = Pick<\n\tTableResolverOptions<Query>,\n\t\"allowAllFields\" | \"allowAllFilters\"\n>\n\nexport interface GraphResolveOptions {\n\tinfo: GraphQLResolveInfo\n\tcontext: any\n\tfilters?: FiltersDef\n}\n\nexport interface GraphResolveContext {\n\ttree: ResolveTree\n\tfilters?: FiltersDef\n\tcontext: any\n}\n\nexport class GraphResolver<Query = unknown> {\n\tconstructor(\n\t\treadonly orm: OrmAdapter<any, Query>,\n\t\treadonly type_resolvers: Record<string, TableResolver<Query>>,\n\t\treadonly options: GraphResolverOptions<Query> = {}\n\t) {}\n\n\tresolve(\n\t\tquery: Query,\n\t\t{ info, context, filters }: GraphResolveOptions\n\t): Query {\n\t\tconst tree = this._get_resolve_tree(info)\n\t\treturn this._resolve_type(query, { tree, filters, context })\n\t}\n\n\tresolvePage(\n\t\tquery: Query,\n\t\tpaginator: Paginator,\n\t\t{ info, context, filters }: GraphResolveOptions\n\t): Query {\n\t\tconst tree = this._get_resolve_tree(info)\n\t\treturn this._resolve_page(query, paginator, { tree, filters, context })\n\t}\n\n\t_get_resolve_tree(info: GraphQLResolveInfo) {\n\t\treturn parseResolveInfo(info) as ResolveTree\n\t}\n\n\t_resolve_type(query: Query, context: GraphResolveContext): Query {\n\t\tconst { tree } = context\n\t\tconst type = Object.keys(tree.fieldsByTypeName)[0]\n\t\tconst type_resolver = this.type_resolvers[type]\n\t\tif (!type_resolver) {\n\t\t\tthrow new Error(`Resolver not found for type ${type}.`)\n\t\t}\n\t\treturn type_resolver.resolve(query, {\n\t\t\t...context,\n\t\t\tgraph: this as any,\n\t\t\ttree,\n\t\t\ttype,\n\t\t}) as Query\n\t}\n\n\t_resolve_page(\n\t\tquery: Query,\n\t\tpaginator: Paginator,\n\t\tcontext: GraphResolveContext\n\t): Query {\n\t\tlet { tree } = context\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, { ...context, tree })\n\t\treturn paginator.paginate(query, {\n\t\t\t...context,\n\t\t\tgraph: this as any,\n\t\t}) as Query\n\t}\n}\n","import { Paginator } from \"../paginators/base\"\nimport { FieldResolver } from \"./field\"\nimport { RelationResolverOptions } from \"./relation\"\n\nexport function definePageResolver<Query = unknown>(\n\tpaginator: Paginator,\n\toptions: RelationResolverOptions<Query> = {}\n): FieldResolver<Query> {\n\tconst { tableField, modify } = options\n\n\treturn function resolve(query, context) {\n\t\tconst { graph, field } = context\n\t\tconst pagination_context = {}\n\t\tquery = graph.orm.select_relation(query, {\n\t\t\trelation: tableField || field,\n\t\t\tas: field,\n\t\t\tmodify(subquery) {\n\t\t\t\tsubquery = graph._resolve_page(subquery, paginator, context)\n\t\t\t\t// The modify+finish hack is needed for both Objection and Orchid (with completely different implementations)\n\t\t\t\tsubquery = graph.orm.modify_subquery_pagination(\n\t\t\t\t\tsubquery,\n\t\t\t\t\tpagination_context\n\t\t\t\t)\n\t\t\t\treturn modify ? modify(subquery, context) : subquery\n\t\t\t},\n\t\t})\n\t\tquery = graph.orm.finish_query_pagination(query, field, pagination_context)\n\t\treturn query\n\t}\n}\n","import { FiltersDef } from \"../filters/filters\"\nimport { FieldResolver, FieldResolverOptions } from \"./field\"\nimport { TableResolveModifier } from \"./table\"\n\nexport interface RelationResolverOptions<Query = unknown>\n\textends Omit<FieldResolverOptions<Query>, \"modify\"> {\n\tfilters?: FiltersDef\n\tmodify?: TableResolveModifier<Query>\n}\n\nexport function defineRelationResolver<Query = unknown>(\n\toptions: RelationResolverOptions<Query> = {}\n): FieldResolver<Query> {\n\tconst { tableField, filters, modify } = options\n\n\treturn function resolve(query, context) {\n\t\tconst { graph, field } = context\n\t\treturn graph.orm.select_relation(query, {\n\t\t\trelation: tableField || field,\n\t\t\tas: field,\n\t\t\tmodify(subquery) {\n\t\t\t\tsubquery = graph._resolve_type(subquery, { ...context, filters })\n\t\t\t\treturn modify ? modify(subquery, context) : subquery\n\t\t\t},\n\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 { TableResolveContext } from \"../resolvers/table\"\nimport { is_plain_object } from \"../utils/is-plain-object\"\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\ninterface ApplyFiltersOptions<Query = unknown> {\n\tfilters: FiltersDef\n\tmodifiers?: Record<string, ApplyFiltersModifier<Query>>\n\tcontext: TableResolveContext<Query>\n}\n\nexport type ApplyFiltersModifier<Query = unknown> = (\n\tquery: Query,\n\tvalue: any,\n\tcontext: TableResolveContext<Query>\n) => Query\n\nexport function apply_filters<Query = unknown>(\n\tquery: Query,\n\t{ filters, modifiers, context }: ApplyFiltersOptions<Query>\n): Query {\n\tif (!filters) {\n\t\treturn query\n\t}\n\tconst filter_obj = context.tree.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, context)\n\t\t} else {\n\t\t\tconst [table_field, op0] = field.split(\"__\")\n\t\t\tconst op = op0?.toLowerCase()\n\t\t\t// TODO: validate op\n\t\t\tquery = context.graph.orm.where(query, table_field, op, value)\n\t\t}\n\t}\n\treturn query\n}\n","import { apply_filters, ApplyFiltersModifier } from \"../filters/filters\"\nimport { OrmAdapter } from \"../orm/orm\"\nimport { run_after_query } from \"../utils/run-after\"\nimport { defineFieldResolver, FieldResolver } from \"./field\"\nimport type { GraphResolveContext, GraphResolver } from \"./graph\"\nimport { defineRelationResolver } from \"./relation\"\n\nexport interface TableResolverOptions<Query = unknown> {\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<Query>>\n\tmodifiers?: Record<string, ApplyFiltersModifier<Query>>\n\tmodify?: TableResolveModifier<Query>\n\ttransform?(instance: any, context: any): void | PromiseLike<void>\n}\n\nexport type SimpleFieldResolver<Query> = true | string | FieldResolver<Query>\n\nexport type TableResolveModifier<Query = unknown> = (\n\tquery: Query,\n\tcontext: TableResolveContext<Query>\n) => Query\n\nexport interface TableResolveContext<Query = unknown>\n\textends GraphResolveContext {\n\tgraph: GraphResolver<Query>\n\t/** GraphQL type */\n\ttype: string\n}\n\nexport class TableResolver<Query = unknown> {\n\t// Introspection results\n\treadonly relations: Set<string>\n\treadonly virtual_fields: Set<string>\n\treadonly modifiers?: Record<string, ApplyFiltersModifier<Query>>\n\n\treadonly table_field_resolvers?: Record<string, FieldResolver<Query>>\n\n\tconstructor(\n\t\treadonly orm: OrmAdapter<any, any>,\n\t\treadonly table: unknown,\n\t\treadonly options: TableResolverOptions<Query> = {}\n\t) {\n\t\tthis.relations = new Set(orm.get_table_relations(table))\n\t\tthis.virtual_fields = new Set(orm.get_table_virtual_fields(table))\n\t\tthis.modifiers = { ...orm.get_table_modifiers(table), ...options.modifiers }\n\n\t\t// Pre-create field resolvers\n\t\tconst { fields } = options\n\t\tif (fields) {\n\t\t\tthis.table_field_resolvers = Object.keys(fields).reduce<\n\t\t\t\tRecord<string, FieldResolver<Query>>\n\t\t\t>((resolvers, field) => {\n\t\t\t\tconst r0 = fields[field]\n\t\t\t\tconst r: FieldResolver<Query> | undefined =\n\t\t\t\t\ttypeof r0 === \"function\"\n\t\t\t\t\t\t? r0\n\t\t\t\t\t\t: r0 === true\n\t\t\t\t\t\t? this._get_default_field_resolver(field)\n\t\t\t\t\t\t: typeof r0 === \"string\"\n\t\t\t\t\t\t? this._get_default_field_resolver(field, r0)\n\t\t\t\t\t\t: undefined\n\t\t\t\tif (r === undefined) {\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t`Field resolver must be a function, string, or true; found ${typeof r0}.`\n\t\t\t\t\t)\n\t\t\t\t}\n\t\t\t\tresolvers[field] = r\n\t\t\t\treturn resolvers\n\t\t\t}, {})\n\t\t}\n\t}\n\n\t/** Modify query to select fields/relations and filter the result set. */\n\tresolve(query: Query, context: TableResolveContext<Query>) {\n\t\tconst { modify, transform } = this.options\n\t\tconst { graph, tree, type, filters } = context\n\n\t\tconst query_table = this.orm.get_query_table(query)\n\t\tconst table_table = this.orm.get_table_table(this.table)\n\n\t\tif (query_table !== table_table) {\n\t\t\tthrow new Error(\n\t\t\t\t`Mismatching query table for type ${type}: expected ${table_table}, received ${query_table}.`\n\t\t\t)\n\t\t}\n\n\t\tconst allow_all_fields =\n\t\t\tthis.options.allowAllFields ??\n\t\t\tgraph.options.allowAllFields ??\n\t\t\t!this.options.fields\n\n\t\tif (!allow_all_fields && !this.table_field_resolvers) {\n\t\t\tthrow new Error(\n\t\t\t\t`Resolver for type ${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, context)\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: FieldResolver<Query> | undefined =\n\t\t\t\tthis.table_field_resolvers?.[field] ||\n\t\t\t\t(allow_all_fields ? this._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, { ...context, tree: subtree, field })\n\t\t\t}\n\t\t}\n\n\t\tconst allow_all_filters =\n\t\t\tthis.options.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<Query>(query, {\n\t\t\t\tfilters: effective_filters,\n\t\t\t\tmodifiers: this.modifiers,\n\t\t\t\tcontext,\n\t\t\t})\n\t\t}\n\n\t\tif (transform) {\n\t\t\tquery = run_after_query(this.orm, query, (instance) => {\n\t\t\t\treturn transform(instance, context)\n\t\t\t})\n\t\t}\n\n\t\tquery = this.orm.prevent_select_all(query)\n\n\t\treturn query\n\t}\n\n\t/**\n\t * Create field resolver which will modify query to resolve GraphQL field.\n\t */\n\t_get_default_field_resolver(\n\t\tfield: string,\n\t\ttableField?: string\n\t): FieldResolver<Query> {\n\t\tconst table_field_lookup = tableField || field\n\t\tif (\n\t\t\tthis.options.modifiers?.[table_field_lookup] ||\n\t\t\tthis.virtual_fields.has(table_field_lookup)\n\t\t) {\n\t\t\t// Keep query as is.\n\t\t\treturn (query) => query\n\t\t} else if (this.relations.has(table_field_lookup)) {\n\t\t\t// TODO: pre-create and cache\n\t\t\treturn defineRelationResolver({ tableField })\n\t\t} else {\n\t\t\t// TODO: create simplified resolver?\n\t\t\treturn defineFieldResolver({ tableField })\n\t\t}\n\t}\n}\n","import { OrmAdapter } from \"graphql-orm-resolver\"\nimport { overrideParserInQuery } from \"orchid-core\"\nimport { DbTable } from \"orchid-orm\"\nimport { Query } from \"pqb\"\n\nexport const orm: OrmAdapter<DbTable<any>, Query> = {\n\t// Reflection\n\n\tget_table_table(table) {\n\t\treturn table.table\n\t},\n\n\tget_table_relations(table) {\n\t\treturn Object.keys(table.relations)\n\t},\n\n\tget_table_virtual_fields() {\n\t\t// Not supported by Orchid.\n\t\treturn []\n\t},\n\n\tget_table_modifiers() {\n\t\treturn undefined\n\t},\n\n\tget_query_table(query) {\n\t\tif (!query.table) {\n\t\t\tthrow new Error(\"Query must have table.\")\n\t\t}\n\t\treturn query.table\n\t},\n\n\t// Select\n\n\tselect_field(query, { field, as }) {\n\t\treturn query.select({ [as]: field })\n\t},\n\n\tselect_relation(query, { relation, as, modify }) {\n\t\treturn query.select({\n\t\t\t[as]: (q) => modify((q as any)[relation]),\n\t\t})\n\t},\n\n\t// Find\n\n\twhere(query, field, op, value) {\n\t\treturn query.where({ [field]: op ? { [op]: value } : value })\n\t},\n\n\twhere_raw(query, expression, bindings) {\n\t\treturn query.where(query.raw(expression, bindings))\n\t},\n\n\t// Order & Limit\n\n\treset_query_order(query) {\n\t\treturn query.clear(\"order\")\n\t},\n\n\tadd_query_order(query, field, desc) {\n\t\treturn query.order({ [field]: desc ? \"DESC\" : \"ASC\" })\n\t},\n\n\tset_query_limit(query, limit) {\n\t\treturn query.limit(limit)\n\t},\n\n\t// Pagination helpers\n\n\tset_query_page_result(query, get_page) {\n\t\t// For root query\n\t\tconst _query = query.query\n\t\tconst { handleResult } = _query\n\t\t_query.handleResult = (q, result, s) => {\n\t\t\tconst data = handleResult(q, result, s)\n\t\t\t// Sometimes this is called for subqueries, sometimes not.\n\t\t\t// TODO: investigate and use always.\n\t\t\treturn s ? data : get_page(data as any[])\n\t\t}\n\t\t// For subqueries\n\t\t;(_query as any)[s] = get_page\n\t\treturn query\n\t},\n\n\tmodify_subquery_pagination(subquery, context) {\n\t\tcontext.get_page = (subquery.query as any)[s]\n\t\treturn subquery\n\t},\n\n\tfinish_query_pagination(query, field, context) {\n\t\tconst { get_page } = context\n\t\tif (!get_page) {\n\t\t\tthrow new Error(`Internal error: paginator didn't provide page callback.`)\n\t\t}\n\t\toverrideParserInQuery(query.query, field, get_page)\n\t\treturn query\n\t},\n\n\t// Misc\n\n\trun_after_query(query, fn) {\n\t\treturn query.afterQuery(async (_, result) => fn(result))\n\t},\n\n\tprevent_select_all(query) {\n\t\t// Not needed in Orchid\n\t\treturn query\n\t},\n}\n\nconst s = Symbol(\"subquery_pagination_handler\")\n","import {\n\tGraphResolver,\n\tGraphResolverOptions,\n\tTableResolver,\n} from \"graphql-orm-resolver\"\nimport { Query } from \"pqb\"\n\nimport { orm } from \"../orm/orm\"\n\nexport function createGraphResolver(\n\ttypes: Record<string, TableResolver<Query>>,\n\toptions?: GraphResolverOptions<Query>\n) {\n\treturn new GraphResolver<Query>(orm, types, options)\n}\n","import { TableResolver, TableResolverOptions } from \"graphql-orm-resolver\"\nimport { DbTable, TableClass } from \"orchid-orm\"\nimport { Query } from \"pqb\"\n\nimport { orm } from \"../orm/orm\"\n\nexport function defineTableResolver<T extends TableClass>(\n\ttable: DbTable<T>,\n\toptions: TableResolverOptions<Query> = {}\n) {\n\treturn new TableResolver(orm, table, options)\n}\n"],"mappings":"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","names":["orm","cursor","orm","orm","orm","s"]}
|
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
|
|
4
|
+
"version": "1.0.0",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
7
7
|
"url": "https://github.com/IlyaSemenov/orchid-graphql"
|
|
@@ -20,51 +20,37 @@
|
|
|
20
20
|
"engines": {
|
|
21
21
|
"node": ">=14"
|
|
22
22
|
},
|
|
23
|
-
"scripts": {
|
|
24
|
-
"dev": "vite-node --watch playground/readme.sample.ts",
|
|
25
|
-
"build": "tsup",
|
|
26
|
-
"lint": "eslint --fix '**/*.{cjs,js,ts}'",
|
|
27
|
-
"prepack": "npm run build",
|
|
28
|
-
"prepare": "husky install",
|
|
29
|
-
"test": "vitest run",
|
|
30
|
-
"release": "npm run prepack && release-it"
|
|
31
|
-
},
|
|
32
23
|
"dependencies": {
|
|
33
24
|
"graphql-parse-resolve-info": "^4.12.0"
|
|
34
25
|
},
|
|
35
26
|
"peerDependencies": {
|
|
27
|
+
"graphql": "^16",
|
|
36
28
|
"orchid-core": "^0.4.11",
|
|
37
29
|
"orchid-orm": "^1.9.36",
|
|
38
30
|
"pqb": "^0.11.29"
|
|
39
31
|
},
|
|
40
32
|
"devDependencies": {
|
|
41
33
|
"@apollo/server": "~4.7.1",
|
|
42
|
-
"@commitlint/cli": "~17.6.3",
|
|
43
|
-
"@commitlint/config-conventional": "~17.6.3",
|
|
44
34
|
"@tsconfig/node18": "~2.0.1",
|
|
45
35
|
"@types/pg": "~8.10.1",
|
|
46
|
-
"@typescript-eslint/eslint-plugin": "~5.59.7",
|
|
47
|
-
"@typescript-eslint/parser": "~5.59.7",
|
|
48
|
-
"eslint": "~8.41.0",
|
|
49
|
-
"eslint-config-prettier": "~8.8.0",
|
|
50
|
-
"eslint-plugin-prettier": "~4.2.1",
|
|
51
|
-
"eslint-plugin-simple-import-sort": "~10.0.0",
|
|
52
36
|
"graphql": "~16.6.0",
|
|
53
37
|
"graphql-request": "~6.0.0",
|
|
54
38
|
"graphql-tag": "^2.12.6",
|
|
55
|
-
"
|
|
56
|
-
"
|
|
57
|
-
"orchid-core": "~0.4.11",
|
|
58
|
-
"orchid-orm": "~1.9.36",
|
|
39
|
+
"orchid-core": "~0.4.13",
|
|
40
|
+
"orchid-orm": "~1.9.40",
|
|
59
41
|
"pg": "~8.11.0",
|
|
60
|
-
"pqb": "~0.11.
|
|
61
|
-
"prettier": "~2.8.8",
|
|
62
|
-
"release-it": "~15.10.3",
|
|
42
|
+
"pqb": "~0.11.32",
|
|
63
43
|
"tsup": "~6.7.0",
|
|
64
44
|
"typescript": "~5.0.4",
|
|
65
45
|
"vite": "~4.3.8",
|
|
66
46
|
"vite-node": "~0.31.1",
|
|
67
47
|
"vite-tsconfig-paths": "~4.2.0",
|
|
68
|
-
"vitest": "~0.31.1"
|
|
48
|
+
"vitest": "~0.31.1",
|
|
49
|
+
"graphql-orm-resolver": "1.0.0"
|
|
50
|
+
},
|
|
51
|
+
"scripts": {
|
|
52
|
+
"dev": "vite-node --watch playground/readme.sample.ts",
|
|
53
|
+
"build": "tsup",
|
|
54
|
+
"test": "vitest run"
|
|
69
55
|
}
|
|
70
|
-
}
|
|
56
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -1,24 +1,24 @@
|
|
|
1
|
+
export {
|
|
2
|
+
createGraphResolver,
|
|
3
|
+
createGraphResolver as graph,
|
|
4
|
+
} from "./resolvers/graph"
|
|
5
|
+
export {
|
|
6
|
+
defineTableResolver,
|
|
7
|
+
defineTableResolver as table,
|
|
8
|
+
} from "./resolvers/table"
|
|
1
9
|
export {
|
|
2
10
|
defineCursorPaginator as cursor,
|
|
3
11
|
defineCursorPaginator,
|
|
4
|
-
} from "
|
|
12
|
+
} from "graphql-orm-resolver"
|
|
5
13
|
export {
|
|
6
14
|
defineFieldResolver,
|
|
7
15
|
defineFieldResolver as field,
|
|
8
|
-
} from "
|
|
9
|
-
export {
|
|
10
|
-
createGraphResolver,
|
|
11
|
-
createGraphResolver as graph,
|
|
12
|
-
} from "./resolvers/graph"
|
|
16
|
+
} from "graphql-orm-resolver"
|
|
13
17
|
export {
|
|
14
18
|
definePageResolver,
|
|
15
19
|
definePageResolver as page,
|
|
16
|
-
} from "
|
|
20
|
+
} from "graphql-orm-resolver"
|
|
17
21
|
export {
|
|
18
22
|
defineRelationResolver,
|
|
19
23
|
defineRelationResolver as relation,
|
|
20
|
-
} from "
|
|
21
|
-
export {
|
|
22
|
-
defineTableResolver,
|
|
23
|
-
defineTableResolver as table,
|
|
24
|
-
} from "./resolvers/table"
|
|
24
|
+
} from "graphql-orm-resolver"
|
package/src/orm/orm.ts
ADDED
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import { OrmAdapter } from "graphql-orm-resolver"
|
|
2
|
+
import { overrideParserInQuery } from "orchid-core"
|
|
3
|
+
import { DbTable } from "orchid-orm"
|
|
4
|
+
import { Query } from "pqb"
|
|
5
|
+
|
|
6
|
+
export const orm: OrmAdapter<DbTable<any>, Query> = {
|
|
7
|
+
// Reflection
|
|
8
|
+
|
|
9
|
+
get_table_table(table) {
|
|
10
|
+
return table.table
|
|
11
|
+
},
|
|
12
|
+
|
|
13
|
+
get_table_relations(table) {
|
|
14
|
+
return Object.keys(table.relations)
|
|
15
|
+
},
|
|
16
|
+
|
|
17
|
+
get_table_virtual_fields() {
|
|
18
|
+
// Not supported by Orchid.
|
|
19
|
+
return []
|
|
20
|
+
},
|
|
21
|
+
|
|
22
|
+
get_table_modifiers() {
|
|
23
|
+
return undefined
|
|
24
|
+
},
|
|
25
|
+
|
|
26
|
+
get_query_table(query) {
|
|
27
|
+
if (!query.table) {
|
|
28
|
+
throw new Error("Query must have table.")
|
|
29
|
+
}
|
|
30
|
+
return query.table
|
|
31
|
+
},
|
|
32
|
+
|
|
33
|
+
// Select
|
|
34
|
+
|
|
35
|
+
select_field(query, { field, as }) {
|
|
36
|
+
return query.select({ [as]: field })
|
|
37
|
+
},
|
|
38
|
+
|
|
39
|
+
select_relation(query, { relation, as, modify }) {
|
|
40
|
+
return query.select({
|
|
41
|
+
[as]: (q) => modify((q as any)[relation]),
|
|
42
|
+
})
|
|
43
|
+
},
|
|
44
|
+
|
|
45
|
+
// Find
|
|
46
|
+
|
|
47
|
+
where(query, field, op, value) {
|
|
48
|
+
return query.where({ [field]: op ? { [op]: value } : value })
|
|
49
|
+
},
|
|
50
|
+
|
|
51
|
+
where_raw(query, expression, bindings) {
|
|
52
|
+
return query.where(query.raw(expression, bindings))
|
|
53
|
+
},
|
|
54
|
+
|
|
55
|
+
// Order & Limit
|
|
56
|
+
|
|
57
|
+
reset_query_order(query) {
|
|
58
|
+
return query.clear("order")
|
|
59
|
+
},
|
|
60
|
+
|
|
61
|
+
add_query_order(query, field, desc) {
|
|
62
|
+
return query.order({ [field]: desc ? "DESC" : "ASC" })
|
|
63
|
+
},
|
|
64
|
+
|
|
65
|
+
set_query_limit(query, limit) {
|
|
66
|
+
return query.limit(limit)
|
|
67
|
+
},
|
|
68
|
+
|
|
69
|
+
// Pagination helpers
|
|
70
|
+
|
|
71
|
+
set_query_page_result(query, get_page) {
|
|
72
|
+
// For root query
|
|
73
|
+
const _query = query.query
|
|
74
|
+
const { handleResult } = _query
|
|
75
|
+
_query.handleResult = (q, result, s) => {
|
|
76
|
+
const data = handleResult(q, result, s)
|
|
77
|
+
// Sometimes this is called for subqueries, sometimes not.
|
|
78
|
+
// TODO: investigate and use always.
|
|
79
|
+
return s ? data : get_page(data as any[])
|
|
80
|
+
}
|
|
81
|
+
// For subqueries
|
|
82
|
+
;(_query as any)[s] = get_page
|
|
83
|
+
return query
|
|
84
|
+
},
|
|
85
|
+
|
|
86
|
+
modify_subquery_pagination(subquery, context) {
|
|
87
|
+
context.get_page = (subquery.query as any)[s]
|
|
88
|
+
return subquery
|
|
89
|
+
},
|
|
90
|
+
|
|
91
|
+
finish_query_pagination(query, field, context) {
|
|
92
|
+
const { get_page } = context
|
|
93
|
+
if (!get_page) {
|
|
94
|
+
throw new Error(`Internal error: paginator didn't provide page callback.`)
|
|
95
|
+
}
|
|
96
|
+
overrideParserInQuery(query.query, field, get_page)
|
|
97
|
+
return query
|
|
98
|
+
},
|
|
99
|
+
|
|
100
|
+
// Misc
|
|
101
|
+
|
|
102
|
+
run_after_query(query, fn) {
|
|
103
|
+
return query.afterQuery(async (_, result) => fn(result))
|
|
104
|
+
},
|
|
105
|
+
|
|
106
|
+
prevent_select_all(query) {
|
|
107
|
+
// Not needed in Orchid
|
|
108
|
+
return query
|
|
109
|
+
},
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
const s = Symbol("subquery_pagination_handler")
|
package/src/resolvers/graph.ts
CHANGED
|
@@ -1,92 +1,15 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
1
|
+
import {
|
|
2
|
+
GraphResolver,
|
|
3
|
+
GraphResolverOptions,
|
|
4
|
+
TableResolver,
|
|
5
|
+
} from "graphql-orm-resolver"
|
|
3
6
|
import { Query } from "pqb"
|
|
4
7
|
|
|
5
|
-
import {
|
|
6
|
-
import { Paginator } from "../paginators/base"
|
|
7
|
-
import { set_query_context } from "../utils/query-context"
|
|
8
|
-
import type { TableResolverFn, TableResolverOptions } from "./table"
|
|
9
|
-
|
|
10
|
-
export type GraphResolverOptions = Pick<
|
|
11
|
-
TableResolverOptions,
|
|
12
|
-
"allowAllFields" | "allowAllFilters"
|
|
13
|
-
>
|
|
8
|
+
import { orm } from "../orm/orm"
|
|
14
9
|
|
|
15
10
|
export function createGraphResolver(
|
|
16
|
-
types: Record<string,
|
|
17
|
-
options?: GraphResolverOptions
|
|
11
|
+
types: Record<string, TableResolver<Query>>,
|
|
12
|
+
options?: GraphResolverOptions<Query>
|
|
18
13
|
) {
|
|
19
|
-
return new GraphResolver(types, options)
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
export interface GraphResolveOptions {
|
|
23
|
-
info: GraphQLResolveInfo
|
|
24
|
-
context: any
|
|
25
|
-
filters?: FiltersDef
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
export class GraphResolver {
|
|
29
|
-
constructor(
|
|
30
|
-
public readonly tables: Record<string, TableResolverFn>,
|
|
31
|
-
public readonly options: GraphResolverOptions = {}
|
|
32
|
-
) {}
|
|
33
|
-
|
|
34
|
-
resolve(query: Query, { info, context, filters }: GraphResolveOptions) {
|
|
35
|
-
set_query_context(query, context)
|
|
36
|
-
const tree = this._get_resolve_tree(info)
|
|
37
|
-
return this._resolve_type({ query, tree, filters })
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
resolvePage(
|
|
41
|
-
query: Query,
|
|
42
|
-
paginator: Paginator,
|
|
43
|
-
{ info, context, filters }: GraphResolveOptions
|
|
44
|
-
) {
|
|
45
|
-
set_query_context(query, context)
|
|
46
|
-
const tree = this._get_resolve_tree(info)
|
|
47
|
-
return this._resolve_page({ query, tree, paginator, filters })
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
_get_resolve_tree(info: GraphQLResolveInfo) {
|
|
51
|
-
return parseResolveInfo(info) as ResolveTree
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
_resolve_type({
|
|
55
|
-
tree,
|
|
56
|
-
query,
|
|
57
|
-
filters,
|
|
58
|
-
}: {
|
|
59
|
-
query: Query
|
|
60
|
-
tree: ResolveTree
|
|
61
|
-
filters?: FiltersDef
|
|
62
|
-
}) {
|
|
63
|
-
const type = Object.keys(tree.fieldsByTypeName)[0]
|
|
64
|
-
const table_resolver = this.tables[type]
|
|
65
|
-
if (!table_resolver) {
|
|
66
|
-
throw new Error(`Table resolver not found for type ${type}.`)
|
|
67
|
-
}
|
|
68
|
-
return table_resolver({ tree, type, query, filters, graph: this })
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
_resolve_page({
|
|
72
|
-
tree,
|
|
73
|
-
query,
|
|
74
|
-
paginator,
|
|
75
|
-
filters,
|
|
76
|
-
}: {
|
|
77
|
-
query: Query
|
|
78
|
-
tree: ResolveTree
|
|
79
|
-
paginator: Paginator
|
|
80
|
-
filters?: FiltersDef
|
|
81
|
-
}) {
|
|
82
|
-
const { args } = tree
|
|
83
|
-
// Skip page subtree(s)
|
|
84
|
-
for (const field of paginator.path) {
|
|
85
|
-
const type = Object.keys(tree.fieldsByTypeName)[0]
|
|
86
|
-
tree = tree.fieldsByTypeName[type][field]
|
|
87
|
-
// TODO: raise exception if not found
|
|
88
|
-
}
|
|
89
|
-
query = this._resolve_type({ query, tree, filters })
|
|
90
|
-
return paginator.paginate(query, args)
|
|
91
|
-
}
|
|
14
|
+
return new GraphResolver<Query>(orm, types, options)
|
|
92
15
|
}
|
package/src/resolvers/table.ts
CHANGED
|
@@ -1,146 +1,12 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { TableResolver, TableResolverOptions } from "graphql-orm-resolver"
|
|
2
2
|
import { DbTable, TableClass } from "orchid-orm"
|
|
3
3
|
import { Query } from "pqb"
|
|
4
4
|
|
|
5
|
-
import {
|
|
6
|
-
import { Modifier } from "../utils/modifier"
|
|
7
|
-
import { get_query_context } from "../utils/query-context"
|
|
8
|
-
import { run_after_query } from "../utils/run-after"
|
|
9
|
-
import { defineFieldResolver, FieldResolverFn } from "./field"
|
|
10
|
-
import type { GraphResolver } from "./graph"
|
|
11
|
-
import { defineRelationResolver } from "./relation"
|
|
12
|
-
|
|
13
|
-
/** A function that modifies the query to select fields/relations and filter the result set. */
|
|
14
|
-
export type TableResolverFn = (args: {
|
|
15
|
-
tree: ResolveTree
|
|
16
|
-
/** GraphQL type */
|
|
17
|
-
type: string
|
|
18
|
-
query: Query
|
|
19
|
-
filters?: FiltersDef
|
|
20
|
-
graph: GraphResolver
|
|
21
|
-
}) => Query
|
|
22
|
-
|
|
23
|
-
export interface TableResolverOptions {
|
|
24
|
-
/** allow to resolve all table fields without explicitly listing them */
|
|
25
|
-
allowAllFields?: boolean
|
|
26
|
-
/** allow to filter all table fields without explicitly listing them */
|
|
27
|
-
allowAllFilters?: boolean
|
|
28
|
-
fields?: Record<string, SimpleFieldResolver>
|
|
29
|
-
modifiers?: Record<string, Modifier>
|
|
30
|
-
modify?: QueryTreeModifier
|
|
31
|
-
transform?(instance: any, context: any): void | PromiseLike<void>
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
export type SimpleFieldResolver = true | string | FieldResolverFn
|
|
35
|
-
|
|
36
|
-
export type QueryTreeModifier = (query: Query, tree: ResolveTree) => Query
|
|
5
|
+
import { orm } from "../orm/orm"
|
|
37
6
|
|
|
38
7
|
export function defineTableResolver<T extends TableClass>(
|
|
39
8
|
table: DbTable<T>,
|
|
40
|
-
options: TableResolverOptions = {}
|
|
41
|
-
)
|
|
42
|
-
|
|
43
|
-
* Create a field resolver which will modify the query to resolve a GraphQL field.
|
|
44
|
-
*/
|
|
45
|
-
const get_default_field_resolver = (
|
|
46
|
-
field: string,
|
|
47
|
-
tableField?: string
|
|
48
|
-
): FieldResolverFn | undefined => {
|
|
49
|
-
const table_field_lookup = tableField || field
|
|
50
|
-
if (options.modifiers?.[table_field_lookup]) {
|
|
51
|
-
// Keep query as is.
|
|
52
|
-
return (query) => query
|
|
53
|
-
} else if ((table.relations as any)?.[table_field_lookup]) {
|
|
54
|
-
return defineRelationResolver({ tableField })
|
|
55
|
-
} else {
|
|
56
|
-
return defineFieldResolver({ tableField })
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
// Pre-create field resolvers
|
|
61
|
-
const { fields } = options
|
|
62
|
-
const table_field_resolvers = fields
|
|
63
|
-
? Object.keys(fields).reduce<Record<string, FieldResolverFn>>(
|
|
64
|
-
(resolvers, field) => {
|
|
65
|
-
const r0 = fields[field]
|
|
66
|
-
const r: FieldResolverFn | undefined =
|
|
67
|
-
typeof r0 === "function"
|
|
68
|
-
? r0
|
|
69
|
-
: r0 === true
|
|
70
|
-
? get_default_field_resolver(field)
|
|
71
|
-
: typeof r0 === "string"
|
|
72
|
-
? get_default_field_resolver(field, r0)
|
|
73
|
-
: undefined
|
|
74
|
-
if (r === undefined) {
|
|
75
|
-
throw new Error(
|
|
76
|
-
`Field resolver must be a function, string, or true; found ${r0}`
|
|
77
|
-
)
|
|
78
|
-
}
|
|
79
|
-
resolvers[field] = r
|
|
80
|
-
return resolvers
|
|
81
|
-
},
|
|
82
|
-
{}
|
|
83
|
-
)
|
|
84
|
-
: undefined
|
|
85
|
-
|
|
86
|
-
const { modify, transform } = options
|
|
87
|
-
|
|
88
|
-
return function resolve({ tree, type, query, filters, graph }) {
|
|
89
|
-
if (query.table !== table.table) {
|
|
90
|
-
throw new Error(
|
|
91
|
-
`Mismatching query type (expected ${table.table}, found ${query.table}).`
|
|
92
|
-
)
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
const allow_all_fields =
|
|
96
|
-
options.allowAllFields ??
|
|
97
|
-
graph.options.allowAllFields ??
|
|
98
|
-
table_field_resolvers === undefined
|
|
99
|
-
|
|
100
|
-
if (!allow_all_fields && !table_field_resolvers) {
|
|
101
|
-
throw new Error(
|
|
102
|
-
`Table resolver for ${type} must either allow all fields or specify options.fields`
|
|
103
|
-
)
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
if (modify) {
|
|
107
|
-
query = modify(query, tree)
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
for (const subtree of Object.values(tree.fieldsByTypeName[type])) {
|
|
111
|
-
const field = subtree.name
|
|
112
|
-
const r =
|
|
113
|
-
table_field_resolvers?.[field] ||
|
|
114
|
-
(allow_all_fields ? get_default_field_resolver(field) : undefined)
|
|
115
|
-
if (!r) {
|
|
116
|
-
throw new Error(`No field resolver defined for field ${type}.${field}`)
|
|
117
|
-
}
|
|
118
|
-
if (r) {
|
|
119
|
-
query = r(query, { field, tree: subtree, graph })
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
const allow_all_filters =
|
|
124
|
-
options.allowAllFilters ?? graph.options.allowAllFilters
|
|
125
|
-
|
|
126
|
-
const effective_filters = allow_all_filters ? true : filters
|
|
127
|
-
|
|
128
|
-
if (effective_filters) {
|
|
129
|
-
query = apply_filters({
|
|
130
|
-
query,
|
|
131
|
-
filters: effective_filters,
|
|
132
|
-
args: tree.args,
|
|
133
|
-
modifiers: options.modifiers,
|
|
134
|
-
})
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
if (transform) {
|
|
138
|
-
const context = get_query_context(query)
|
|
139
|
-
query = run_after_query(query, (instance) => {
|
|
140
|
-
return transform(instance, context)
|
|
141
|
-
})
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
return query
|
|
145
|
-
}
|
|
9
|
+
options: TableResolverOptions<Query> = {}
|
|
10
|
+
) {
|
|
11
|
+
return new TableResolver(orm, table, options)
|
|
146
12
|
}
|