orchid-graphql 1.9.0 → 2.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/package.json CHANGED
@@ -1,54 +1,63 @@
1
1
  {
2
2
  "name": "orchid-graphql",
3
3
  "type": "module",
4
- "version": "1.9.0",
4
+ "version": "2.0.0",
5
5
  "description": "orchid-orm plugin: resolve GraphQL query with Orchid ORM",
6
6
  "author": "Ilya Semenov",
7
7
  "license": "MIT",
8
8
  "repository": {
9
9
  "type": "git",
10
- "url": "https://github.com/IlyaSemenov/orchid-graphql"
10
+ "url": "git+https://github.com/IlyaSemenov/graphql-orm.git",
11
+ "directory": "packages/orchid"
11
12
  },
13
+ "sideEffects": false,
12
14
  "exports": {
13
15
  ".": {
14
- "types": "./dist/index.d.ts",
15
- "import": "./dist/index.js",
16
+ "import": "./dist/index.mjs",
16
17
  "require": "./dist/index.cjs"
17
- }
18
+ },
19
+ "./package.json": "./package.json"
18
20
  },
19
- "main": "dist/index.cjs",
21
+ "main": "./dist/index.cjs",
22
+ "module": "./dist/index.mjs",
23
+ "types": "./dist/index.d.cts",
20
24
  "files": [
21
25
  "dist",
22
26
  "src"
23
27
  ],
28
+ "publishConfig": {
29
+ "access": "public",
30
+ "provenance": true
31
+ },
24
32
  "engines": {
25
33
  "node": ">=14"
26
34
  },
35
+ "scripts": {
36
+ "dev": "vite-node --watch playground/readme.sample.ts",
37
+ "build": "tsdown",
38
+ "test": "vitest run && tsc --noEmit && tstyche --target 6.0.3",
39
+ "prepublishOnly": "bun run build"
40
+ },
27
41
  "peerDependencies": {
28
42
  "graphql": "^16",
29
- "orchid-orm": "^1.31.5"
43
+ "orchid-orm": "^1.51.0"
30
44
  },
31
45
  "dependencies": {
32
- "graphql-parse-resolve-info": "^4.13.0"
46
+ "graphql-parse-resolve-info": "^4.13.0",
47
+ "orchid-pagination": "^2.4.2"
33
48
  },
34
49
  "devDependencies": {
35
50
  "@apollo/server": "^4.7.1",
36
51
  "graphql": "^16.6.0",
37
52
  "graphql-request": "^6.0.0",
38
53
  "graphql-tag": "^2.12.6",
39
- "orchid-orm": "^1.31.5",
54
+ "orchid-orm": "~1.78.5",
55
+ "postgres": "^3.4.9",
40
56
  "tsconfig-vite-node": "^1.1.2",
41
57
  "tstyche": "^4.3.0",
42
- "tsup": "^8.5.0",
43
58
  "vite": "^7.0.5",
44
59
  "vite-node": "^3.2.4",
45
60
  "vite-tsconfig-paths": "^5.1.4",
46
- "vitest": "^3.2.4",
47
- "graphql-orm": "1.6.0"
48
- },
49
- "scripts": {
50
- "dev": "vite-node --watch playground/readme.sample.ts",
51
- "build": "tsup",
52
- "test": "vitest run && tsc --noEmit && tstyche"
61
+ "vitest": "^3.2.4"
53
62
  }
54
- }
63
+ }
package/src/orm/orm.ts CHANGED
@@ -1,6 +1,6 @@
1
- import type { OrmAdapter, SortOrder } from "graphql-orm"
2
- import type { Query, SelectQueryData, Table } from "orchid-orm"
3
- import { raw } from "orchid-orm"
1
+ import type { OrmAdapter } from "graphql-orm"
2
+ import type { Query, Table } from "orchid-orm"
3
+ import { prepareCursorPagination as prepareOrchidCursorPagination } from "orchid-pagination"
4
4
 
5
5
  export type OrchidOrm = OrmAdapter<
6
6
  Table,
@@ -16,24 +16,24 @@ export const orm: OrchidOrm = {
16
16
 
17
17
  // Reflection
18
18
 
19
- get_table_table(table) {
19
+ getTableName(table) {
20
20
  return table.table!
21
21
  },
22
22
 
23
- get_table_relations(table) {
23
+ getTableRelations(table) {
24
24
  return Object.keys(table.relations)
25
25
  },
26
26
 
27
- get_table_virtual_fields() {
27
+ getTableVirtualFields() {
28
28
  // Not supported by Orchid.
29
29
  return []
30
30
  },
31
31
 
32
- get_table_modifiers() {
32
+ getTableModifiers() {
33
33
  return undefined
34
34
  },
35
35
 
36
- get_query_table(query) {
36
+ getQueryTable(query) {
37
37
  if (!query.table) {
38
38
  throw new Error("Query must have table.")
39
39
  }
@@ -42,11 +42,11 @@ export const orm: OrchidOrm = {
42
42
 
43
43
  // Select
44
44
 
45
- select_field(query, { field, as }) {
45
+ selectField(query, { field, as }) {
46
46
  return query.select({ [as]: field })
47
47
  },
48
48
 
49
- select_relation(query, { relation, as, modify }) {
49
+ selectRelation(query, { relation, as, modify }) {
50
50
  // as any casts needed in orchid-orm 1.31+
51
51
  return query.select({
52
52
  [as]: (q: any) => modify(q[relation]),
@@ -59,66 +59,48 @@ export const orm: OrchidOrm = {
59
59
  return query.where({ [field]: op ? { [op]: value } : value })
60
60
  },
61
61
 
62
- where_raw(query, expression, bindings) {
63
- return query.where(raw({ raw: expression, values: bindings }))
64
- },
65
-
66
- // Order & Limit
67
-
68
- reset_query_order(query) {
69
- return query.clear("order")
70
- },
71
-
72
- add_query_order(query, { field, dir }) {
73
- return query.order({ [field]: dir })
74
- },
62
+ // Pagination helpers
75
63
 
76
- get_query_order(query) {
77
- return (
78
- (query.q as SelectQueryData).order?.flatMap<SortOrder>((orderItem) => {
79
- if (typeof orderItem === "string") {
80
- return { field: "orderItem", dir: "ASC" }
81
- } else if (typeof orderItem === "object") {
82
- return Object.entries(orderItem).map<SortOrder>(([field, order]) => {
83
- const [dir] = order.split(" ", 1)
84
- if (dir === "ASC" || dir === "DESC") {
85
- return { field, dir }
86
- } else {
87
- throw new Error("Unsupported order: " + order)
88
- }
89
- })
90
- } else {
91
- throw new TypeError("Unsupported order type: " + orderItem)
92
- }
93
- }) || []
64
+ prepareCursorPagination(query, { cursor, fields, limit }) {
65
+ if (fields) {
66
+ query = query.clear("order")
67
+ for (const { field, dir } of fields) {
68
+ query = query.order({ [field]: dir })
69
+ }
70
+ }
71
+ const prepared = prepareOrchidCursorPagination(
72
+ query as never,
73
+ { limit },
74
+ { cursor },
94
75
  )
76
+ return {
77
+ query: prepared.query,
78
+ getPage(nodes) {
79
+ const page = prepared.finalize(nodes as never)
80
+ return { nodes: page.items, cursor: page.nextCursor }
81
+ },
82
+ }
95
83
  },
96
84
 
97
- set_query_limit(query, limit) {
98
- return query.limit(limit)
99
- },
100
-
101
- // Pagination helpers
102
-
103
- set_query_page_result(query, get_page) {
85
+ setQueryPageResult(query, get_page) {
104
86
  return query.transform(nodes => get_page(nodes as any))
105
87
  },
106
88
 
107
- modify_subquery_pagination(subquery) {
89
+ modifySubqueryPagination(subquery) {
108
90
  return subquery
109
91
  },
110
92
 
111
- finish_query_pagination(query) {
93
+ finishQueryPagination(query) {
112
94
  return query
113
95
  },
114
96
 
115
97
  // Misc
116
98
 
117
- run_after_query(query, fn) {
99
+ runAfterQuery(query, fn) {
118
100
  return query.afterQuery(data => fn(data))
119
101
  },
120
102
 
121
- prevent_select_all(query) {
103
+ preventSelectAll(query) {
122
104
  // Not needed in Orchid
123
105
  return query
124
106
  },
package/LICENSE DELETED
@@ -1,21 +0,0 @@
1
- MIT License
2
-
3
- Copyright (c) 2023 Ilya Semenov
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be included in all
13
- copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
- SOFTWARE.
package/dist/index.d.ts DELETED
@@ -1,192 +0,0 @@
1
- import { GraphQLResolveInfo } from 'graphql';
2
- import { ResolveTree } from 'graphql-parse-resolve-info';
3
- import { Table, Query } from 'orchid-orm';
4
-
5
- interface FieldResolverOptions<Orm extends OrmAdapter, Context> {
6
- /** Table field (if different from GraphQL field) */
7
- tableField?: string;
8
- /** Legacy alias for `tableField`. */
9
- modelField?: string;
10
- /** Custom query modifier (if different than simply selecting a field). */
11
- modify?: FieldResolveModifier<Orm, Context>;
12
- /** Post-process selected value. Return a new value or a promise. */
13
- transform?(value: any, instance: any, context: FieldResolveContext<Orm, Context>): any;
14
- }
15
- type FieldResolveModifier<Orm extends OrmAdapter, Context> = (query: Orm["Query"], context: FieldResolveContext<Orm, Context>) => Orm["Query"];
16
- interface FieldResolveContext<Orm extends OrmAdapter, Context> extends TableResolveContext<Orm, Context> {
17
- /** GraphQL field */
18
- field: string;
19
- }
20
- type FieldResolver<Orm extends OrmAdapter, Context> = FieldResolveModifier<Orm, Context>;
21
- declare function defineFieldResolver<Orm extends OrmAdapter, Context>(options?: FieldResolverOptions<Orm, Context>): FieldResolver<Orm, Context>;
22
-
23
- interface TableResolverOptions<Orm extends OrmAdapter, Context> {
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<Orm, Context>>;
29
- modifiers?: Record<string, TableFilterModifier<Orm, Context>>;
30
- modify?: TableResolveModifier<Orm, Context>;
31
- transform?(instance: any, context: any): void | PromiseLike<void>;
32
- }
33
- type SimpleFieldResolver<Orm extends OrmAdapter, Context> = true | string | FieldResolver<Orm, Context>;
34
- type TableResolveModifier<Orm extends OrmAdapter, Context> = (query: Orm["Query"], context: TableResolveContext<Orm, Context>) => Orm["Query"];
35
- interface TableResolveContext<Orm extends OrmAdapter, Context> extends GraphResolveContext<Context> {
36
- graph: GraphResolver<Orm, Context>;
37
- /** GraphQL type */
38
- type: string;
39
- }
40
- type TableFilterModifier<Orm extends OrmAdapter, Context> = FilterModifier$1<Orm, TableResolveContext<Orm, Context>>;
41
- declare class TableResolver<Orm extends OrmAdapter, Context> {
42
- readonly orm: Orm;
43
- readonly table: Orm["Table"];
44
- readonly options: TableResolverOptions<Orm, Context>;
45
- readonly relations: Set<string>;
46
- readonly virtual_fields: Set<string>;
47
- readonly modifiers?: Record<string, TableFilterModifier<Orm, Context>>;
48
- readonly table_field_resolvers?: Record<string, FieldResolver<Orm, Context>>;
49
- constructor(orm: Orm, table: Orm["Table"], options?: TableResolverOptions<Orm, Context>);
50
- /** Modify query to select fields/relations and filter the result set. */
51
- resolve(query: Orm["Query"], context: TableResolveContext<Orm, Context>): Orm["Query"];
52
- /**
53
- * Create field resolver which will modify query to resolve GraphQL field.
54
- */
55
- _get_default_field_resolver(field: string, tableField?: string): FieldResolver<Orm, Context>;
56
- }
57
-
58
- type GraphResolverOptions<Orm extends OrmAdapter, Context> = Pick<TableResolverOptions<Orm, Context>, "allowAllFields" | "allowAllFilters">;
59
- interface GraphResolveOptions<Context> {
60
- info: GraphQLResolveInfo;
61
- context: Context;
62
- filters?: FilterConfig;
63
- /** Subfield path if not resolving root query, e.g.: ['user'] */
64
- path?: string[];
65
- }
66
- type GraphResolveContext<Context> = Omit<GraphResolveOptions<Context>, "info"> & {
67
- tree: ResolveTree;
68
- };
69
- declare class GraphResolver<Orm extends OrmAdapter, Context> {
70
- readonly orm: Orm;
71
- readonly type_resolvers: Record<string, TableResolver<Orm, Context>>;
72
- readonly options: GraphResolverOptions<Orm, Context>;
73
- constructor(orm: Orm, type_resolvers: Record<string, TableResolver<Orm, Context>>, options?: GraphResolverOptions<Orm, Context>);
74
- resolve<T>(query: Orm["Query"], { info, ...context }: GraphResolveOptions<Context>): Promise<T>;
75
- resolvePage(query: Orm["Query"], paginator: Paginator<Orm, Context>, { info, ...context }: GraphResolveOptions<Context>): Orm["QueryTransform"];
76
- _get_resolve_tree(info: GraphQLResolveInfo): ResolveTree;
77
- _resolve_type(query: Orm["Query"], context: GraphResolveContext<Context>): Orm["Query"];
78
- _resolve_page(query: Orm["Query"], paginator: Paginator<Orm, Context>, context: GraphResolveContext<Context>): Orm["QueryTransform"];
79
- }
80
-
81
- interface Paginator<Orm extends OrmAdapter, Context> {
82
- /** GraphQL path, for example: `["nodes"]` */
83
- readonly path: string[];
84
- paginate(query: Orm["Query"], context: PaginateContext<Orm, Context>): Orm["QueryTransform"];
85
- }
86
- interface PaginateContext<Orm extends OrmAdapter, Context> extends GraphResolveContext<Context> {
87
- graph: GraphResolver<Orm, Context>;
88
- }
89
- type GetPageFn = (nodes: any[]) => any;
90
-
91
- type OrmModifier<Orm extends OrmAdapter> = (query: Orm["Query"], ...args: any[]) => Orm["Query"];
92
- interface SortOrder {
93
- field: string;
94
- dir: "ASC" | "DESC";
95
- }
96
- interface OrmAdapter<Table = any, Query = any, QueryTransform = any> {
97
- Table: Table;
98
- Query: Query;
99
- QueryTransform: QueryTransform;
100
- /** ORM table -> db table */
101
- get_table_table(table: Table): string;
102
- /** ORM table -> relation names */
103
- get_table_relations(table: Table): string[];
104
- /** ORM table -> virtual fields */
105
- get_table_virtual_fields(table: Table): string[];
106
- get_table_modifiers(table: Table): Record<string, OrmModifier<this>> | undefined;
107
- /** ORM query -> db table */
108
- get_query_table(query: Query): string;
109
- select_field(query: Query, opts: {
110
- field: string;
111
- as: string;
112
- }): Query;
113
- select_relation(query: Query, opts: {
114
- relation: string;
115
- as: string;
116
- modify: (subquery: Query) => Query;
117
- }): Query;
118
- where(query: Query, field: string, op: string | undefined, value: any): Query;
119
- where_raw(query: Query, expression: string, bindings: Record<string, any>): Query;
120
- reset_query_order(query: Query): Query;
121
- add_query_order(query: Query, order: SortOrder): Query;
122
- get_query_order(query: Query): SortOrder[];
123
- set_query_limit(query: Query, limit: number): Query;
124
- set_query_page_result(query: Query, get_page: GetPageFn): QueryTransform;
125
- modify_subquery_pagination(subquery: Query, context: Record<string, any>): Query;
126
- finish_query_pagination(query: Query, field: string, context: Record<string, any>): Query;
127
- /** Set ORM query to run callback afterwards */
128
- run_after_query(query: Query, fn: (result: any) => any): Query;
129
- /** Prevent `SELECT *` by explicitly selecting ID */
130
- prevent_select_all(query: Query): Query;
131
- }
132
-
133
- type FilterConfig = boolean;
134
- type FieldFilterScalarValue = null | string | number | boolean;
135
- type FieldFilterValue = FieldFilterScalarValue | Exclude<FieldFilterScalarValue, null>[];
136
- type FilterValue = {
137
- [property: string]: FieldFilterValue;
138
- };
139
- type FilterQueryOptions$1<Orm extends OrmAdapter, Context = unknown> = {
140
- modifiers?: FilterModifiers$1<Orm, Context>;
141
- } & (Context extends undefined ? {
142
- context?: Context;
143
- } : {
144
- context: Context;
145
- });
146
- type FilterModifier$1<Orm extends OrmAdapter, Context> = (query: Orm["Query"], value: any, context: Context) => Orm["Query"];
147
- type FilterModifiers$1<Orm extends OrmAdapter, Context> = Record<string, FilterModifier$1<Orm, Context>>;
148
-
149
- declare function defineCursorPaginator(options?: Partial<CursorPaginatorOptions>): CursorPaginator<OrmAdapter<any, any, any>, unknown>;
150
- interface CursorPaginatorOptions {
151
- fields?: string[];
152
- take?: number;
153
- }
154
- declare class CursorPaginator<Orm extends OrmAdapter, Context> implements Paginator<Orm, Context> {
155
- readonly path: string[];
156
- readonly pageSize: number;
157
- readonly fields?: Array<{
158
- name: string;
159
- desc: boolean;
160
- }>;
161
- constructor(options?: CursorPaginatorOptions);
162
- paginate(query: Orm["Query"], context: PaginateContext<Orm, Context>): any;
163
- }
164
-
165
- interface RelationResolverOptions<Orm extends OrmAdapter, Context> extends Omit<FieldResolverOptions<Orm, Context>, "modify"> {
166
- filters?: FilterConfig;
167
- modify?: TableResolveModifier<Orm, Context>;
168
- }
169
- declare function defineRelationResolver<Orm extends OrmAdapter, Context>(options?: RelationResolverOptions<Orm, Context>): FieldResolver<Orm, Context>;
170
-
171
- declare function definePageResolver<Orm extends OrmAdapter, Context>(paginator: Paginator<Orm, Context>, options?: RelationResolverOptions<Orm, Context>): FieldResolver<Orm, Context>;
172
-
173
- type OrchidOrm = OrmAdapter<Table, Query, Pick<Promise<any>, "then" | "catch">>;
174
-
175
- type FilterQueryOptions<Context = undefined> = FilterQueryOptions$1<OrchidOrm, Context>;
176
- type FilterModifier<Context = undefined> = FilterModifier$1<OrchidOrm, Context>;
177
- type FilterModifiers<Context = undefined> = FilterModifiers$1<OrchidOrm, Context>;
178
- declare function filterQuery<Q extends Query, Context = undefined>(query: Q, filter: FilterValue, options?: FilterQueryOptions<Context>): Q;
179
-
180
- declare function createGraphResolver<Context = unknown>(types: Record<string, TableResolver<OrchidOrm, Context>>, options?: GraphResolverOptions<OrchidOrm, Context>): OrchidGraphResolver<Context>;
181
- declare class OrchidGraphResolver<Context> extends GraphResolver<OrchidOrm, Context> {
182
- readonly types: Record<string, TableResolver<OrchidOrm, Context>>;
183
- readonly options: GraphResolverOptions<OrchidOrm, Context>;
184
- constructor(types: Record<string, TableResolver<OrchidOrm, Context>>, options?: GraphResolverOptions<OrchidOrm, Context>);
185
- resolve<T>(query: Query & {
186
- returnType: unknown extends T ? any : T extends unknown[] ? undefined | "all" : T extends undefined ? "one" : "oneOrThrow";
187
- }, options: GraphResolveOptions<Context>): Promise<T>;
188
- }
189
-
190
- declare function defineTableResolver<Context = unknown>(table: Table, options?: TableResolverOptions<OrchidOrm, Context>): TableResolver<OrchidOrm, Context>;
191
-
192
- export { type FilterModifier, type FilterModifiers, type FilterQueryOptions, type FilterValue, createGraphResolver, defineCursorPaginator as cursor, defineCursorPaginator, defineFieldResolver, definePageResolver, defineRelationResolver, defineTableResolver, defineFieldResolver as field, filterQuery, createGraphResolver as graph, definePageResolver as page, defineRelationResolver as relation, defineTableResolver as table };