@pothos/plugin-drizzle 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (179) hide show
  1. package/CHANGELOG.md +7 -0
  2. package/LICENSE +6 -0
  3. package/README.md +437 -0
  4. package/TODO.md +21 -0
  5. package/drizzle/meta/_journal.json +1 -0
  6. package/drizzle.config.ts +10 -0
  7. package/dts/drizzle-field-builder.d.ts +124 -0
  8. package/dts/drizzle-field-builder.d.ts.map +1 -0
  9. package/dts/field-builder.d.ts +2 -0
  10. package/dts/field-builder.d.ts.map +1 -0
  11. package/dts/global-types.d.ts +92 -0
  12. package/dts/global-types.d.ts.map +1 -0
  13. package/dts/index.d.ts +13 -0
  14. package/dts/index.d.ts.map +1 -0
  15. package/dts/interface-ref.d.ts +9 -0
  16. package/dts/interface-ref.d.ts.map +1 -0
  17. package/dts/model-loader.d.ts +44 -0
  18. package/dts/model-loader.d.ts.map +1 -0
  19. package/dts/node-ref.d.ts +5 -0
  20. package/dts/node-ref.d.ts.map +1 -0
  21. package/dts/object-ref.d.ts +14 -0
  22. package/dts/object-ref.d.ts.map +1 -0
  23. package/dts/schema-builder.d.ts +2 -0
  24. package/dts/schema-builder.d.ts.map +1 -0
  25. package/dts/types.d.ts +147 -0
  26. package/dts/types.d.ts.map +1 -0
  27. package/dts/utils/config.d.ts +7 -0
  28. package/dts/utils/config.d.ts.map +1 -0
  29. package/dts/utils/cursors.d.ts +58 -0
  30. package/dts/utils/cursors.d.ts.map +1 -0
  31. package/dts/utils/deep-equal.d.ts +2 -0
  32. package/dts/utils/deep-equal.d.ts.map +1 -0
  33. package/dts/utils/drizzle-graphql.d.ts +18 -0
  34. package/dts/utils/drizzle-graphql.d.ts.map +1 -0
  35. package/dts/utils/loader-map.d.ts +11 -0
  36. package/dts/utils/loader-map.d.ts.map +1 -0
  37. package/dts/utils/map-query.d.ts +30 -0
  38. package/dts/utils/map-query.d.ts.map +1 -0
  39. package/dts/utils/refs.d.ts +5 -0
  40. package/dts/utils/refs.d.ts.map +1 -0
  41. package/dts/utils/selections.d.ts +22 -0
  42. package/dts/utils/selections.d.ts.map +1 -0
  43. package/dts/utils/usage.d.ts +5 -0
  44. package/dts/utils/usage.d.ts.map +1 -0
  45. package/esm/drizzle-field-builder.d.ts +216 -0
  46. package/esm/drizzle-field-builder.d.ts.map +1 -0
  47. package/esm/field-builder.d.ts +2 -0
  48. package/esm/field-builder.d.ts.map +1 -0
  49. package/esm/global-types.d.ts +124 -0
  50. package/esm/global-types.d.ts.map +1 -0
  51. package/esm/index.d.ts +13 -0
  52. package/esm/index.d.ts.map +1 -0
  53. package/esm/interface-ref.d.ts +9 -0
  54. package/esm/interface-ref.d.ts.map +1 -0
  55. package/esm/model-loader.d.ts +45 -0
  56. package/esm/model-loader.d.ts.map +1 -0
  57. package/esm/node-ref.d.ts +5 -0
  58. package/esm/node-ref.d.ts.map +1 -0
  59. package/esm/object-ref.d.ts +14 -0
  60. package/esm/object-ref.d.ts.map +1 -0
  61. package/esm/package.json +3 -0
  62. package/esm/schema-builder.d.ts +2 -0
  63. package/esm/schema-builder.d.ts.map +1 -0
  64. package/esm/src/drizzle-field-builder.js +215 -0
  65. package/esm/src/drizzle-field-builder.js.map +1 -0
  66. package/esm/src/field-builder.js +77 -0
  67. package/esm/src/field-builder.js.map +1 -0
  68. package/esm/src/global-types.js +2 -0
  69. package/esm/src/global-types.js.map +1 -0
  70. package/esm/src/index.js +107 -0
  71. package/esm/src/index.js.map +1 -0
  72. package/esm/src/interface-ref.js +26 -0
  73. package/esm/src/interface-ref.js.map +1 -0
  74. package/esm/src/model-loader.js +168 -0
  75. package/esm/src/model-loader.js.map +1 -0
  76. package/esm/src/node-ref.js +4 -0
  77. package/esm/src/node-ref.js.map +1 -0
  78. package/esm/src/object-ref.js +38 -0
  79. package/esm/src/object-ref.js.map +1 -0
  80. package/esm/src/schema-builder.js +190 -0
  81. package/esm/src/schema-builder.js.map +1 -0
  82. package/esm/src/types.js +2 -0
  83. package/esm/src/types.js.map +1 -0
  84. package/esm/src/utils/config.js +15 -0
  85. package/esm/src/utils/config.js.map +1 -0
  86. package/esm/src/utils/cursors.js +316 -0
  87. package/esm/src/utils/cursors.js.map +1 -0
  88. package/esm/src/utils/deep-equal.js +44 -0
  89. package/esm/src/utils/deep-equal.js.map +1 -0
  90. package/esm/src/utils/drizzle-graphql.js +176 -0
  91. package/esm/src/utils/drizzle-graphql.js.map +1 -0
  92. package/esm/src/utils/loader-map.js +35 -0
  93. package/esm/src/utils/loader-map.js.map +1 -0
  94. package/esm/src/utils/map-query.js +284 -0
  95. package/esm/src/utils/map-query.js.map +1 -0
  96. package/esm/src/utils/refs.js +14 -0
  97. package/esm/src/utils/refs.js.map +1 -0
  98. package/esm/src/utils/selections.js +136 -0
  99. package/esm/src/utils/selections.js.map +1 -0
  100. package/esm/src/utils/usage.js +59 -0
  101. package/esm/src/utils/usage.js.map +1 -0
  102. package/esm/types.d.ts +161 -0
  103. package/esm/types.d.ts.map +1 -0
  104. package/esm/utils/config.d.ts +7 -0
  105. package/esm/utils/config.d.ts.map +1 -0
  106. package/esm/utils/cursors.d.ts +58 -0
  107. package/esm/utils/cursors.d.ts.map +1 -0
  108. package/esm/utils/deep-equal.d.ts +2 -0
  109. package/esm/utils/deep-equal.d.ts.map +1 -0
  110. package/esm/utils/drizzle-graphql.d.ts +18 -0
  111. package/esm/utils/drizzle-graphql.d.ts.map +1 -0
  112. package/esm/utils/loader-map.d.ts +11 -0
  113. package/esm/utils/loader-map.d.ts.map +1 -0
  114. package/esm/utils/map-query.d.ts +30 -0
  115. package/esm/utils/map-query.d.ts.map +1 -0
  116. package/esm/utils/refs.d.ts +5 -0
  117. package/esm/utils/refs.d.ts.map +1 -0
  118. package/esm/utils/selections.d.ts +22 -0
  119. package/esm/utils/selections.d.ts.map +1 -0
  120. package/esm/utils/usage.d.ts +5 -0
  121. package/esm/utils/usage.d.ts.map +1 -0
  122. package/lib/src/drizzle-field-builder.js +225 -0
  123. package/lib/src/drizzle-field-builder.js.map +1 -0
  124. package/lib/src/field-builder.js +82 -0
  125. package/lib/src/field-builder.js.map +1 -0
  126. package/lib/src/global-types.js +6 -0
  127. package/lib/src/global-types.js.map +1 -0
  128. package/lib/src/index.js +180 -0
  129. package/lib/src/index.js.map +1 -0
  130. package/lib/src/interface-ref.js +36 -0
  131. package/lib/src/interface-ref.js.map +1 -0
  132. package/lib/src/model-loader.js +176 -0
  133. package/lib/src/model-loader.js.map +1 -0
  134. package/lib/src/node-ref.js +15 -0
  135. package/lib/src/node-ref.js.map +1 -0
  136. package/lib/src/object-ref.js +56 -0
  137. package/lib/src/object-ref.js.map +1 -0
  138. package/lib/src/schema-builder.js +236 -0
  139. package/lib/src/schema-builder.js.map +1 -0
  140. package/lib/src/types.js +13 -0
  141. package/lib/src/types.js.map +1 -0
  142. package/lib/src/utils/config.js +26 -0
  143. package/lib/src/utils/config.js.map +1 -0
  144. package/lib/src/utils/cursors.js +362 -0
  145. package/lib/src/utils/cursors.js.map +1 -0
  146. package/lib/src/utils/deep-equal.js +55 -0
  147. package/lib/src/utils/deep-equal.js.map +1 -0
  148. package/lib/src/utils/drizzle-graphql.js +192 -0
  149. package/lib/src/utils/drizzle-graphql.js.map +1 -0
  150. package/lib/src/utils/loader-map.js +57 -0
  151. package/lib/src/utils/loader-map.js.map +1 -0
  152. package/lib/src/utils/map-query.js +308 -0
  153. package/lib/src/utils/map-query.js.map +1 -0
  154. package/lib/src/utils/refs.js +33 -0
  155. package/lib/src/utils/refs.js.map +1 -0
  156. package/lib/src/utils/selections.js +163 -0
  157. package/lib/src/utils/selections.js.map +1 -0
  158. package/lib/src/utils/usage.js +84 -0
  159. package/lib/src/utils/usage.js.map +1 -0
  160. package/package.json +66 -0
  161. package/src/drizzle-field-builder.ts +500 -0
  162. package/src/field-builder.ts +168 -0
  163. package/src/global-types.ts +481 -0
  164. package/src/index.ts +175 -0
  165. package/src/interface-ref.ts +24 -0
  166. package/src/model-loader.ts +235 -0
  167. package/src/node-ref.ts +8 -0
  168. package/src/object-ref.ts +51 -0
  169. package/src/schema-builder.ts +299 -0
  170. package/src/types.ts +640 -0
  171. package/src/utils/config.ts +28 -0
  172. package/src/utils/cursors.ts +446 -0
  173. package/src/utils/deep-equal.ts +58 -0
  174. package/src/utils/drizzle-graphql.ts +235 -0
  175. package/src/utils/loader-map.ts +51 -0
  176. package/src/utils/map-query.ts +582 -0
  177. package/src/utils/refs.ts +25 -0
  178. package/src/utils/selections.ts +209 -0
  179. package/src/utils/usage.ts +64 -0
@@ -0,0 +1,209 @@
1
+ /* eslint-disable no-param-reassign */
2
+ import {
3
+ DBQueryConfig,
4
+ RelationalSchemaConfig,
5
+ SQL,
6
+ TableRelationalConfig,
7
+ TablesRelationalConfig,
8
+ getOperators,
9
+ } from 'drizzle-orm';
10
+ import { PothosValidationError } from '@pothos/core';
11
+ import { deepEqual } from './deep-equal';
12
+ import { LoaderMappings } from './loader-map';
13
+ import { PothosDrizzleSchemaConfig } from './config';
14
+
15
+ export interface SelectionState {
16
+ table: TableRelationalConfig;
17
+ query: object;
18
+ allColumns: boolean;
19
+ columns: Set<string>;
20
+ with: Map<string, SelectionState>;
21
+ extras: Map<string, SQL.Aliased>;
22
+ mappings: LoaderMappings;
23
+ parent?: SelectionState;
24
+ depth: number;
25
+ }
26
+
27
+ export type SelectionMap = DBQueryConfig<'one', false>;
28
+
29
+ export function selectionCompatible(
30
+ state: SelectionState,
31
+ selectionMap: SelectionMap | boolean,
32
+ ignoreQuery = false,
33
+ ): boolean {
34
+ if (typeof selectionMap === 'boolean') {
35
+ return ignoreQuery || !selectionMap || Object.keys(state.query).length === 0;
36
+ }
37
+
38
+ const { with: withSelection, extras, columns, ...query } = selectionMap;
39
+
40
+ if (
41
+ withSelection &&
42
+ Object.entries(withSelection).some(
43
+ ([key, value]) =>
44
+ value &&
45
+ state.with.has(key) &&
46
+ // TODO: make sure nested extras are normalized
47
+ !selectionCompatible(state.with.get(key)!, value as SelectionMap),
48
+ )
49
+ ) {
50
+ return false;
51
+ }
52
+
53
+ const resolvedExtras =
54
+ typeof extras === 'function' ? extras(state.table.columns, getOperators()) : extras;
55
+
56
+ if (
57
+ resolvedExtras &&
58
+ Object.entries(resolvedExtras).some(([key, value]) => {
59
+ const sql = state.extras.get(key);
60
+
61
+ return sql && (sql.sql !== value.sql || sql.fieldAlias !== value.fieldAlias);
62
+ })
63
+ ) {
64
+ return false;
65
+ }
66
+
67
+ return ignoreQuery || deepEqual(state.query, query);
68
+ }
69
+
70
+ export function stateCompatible(
71
+ state: SelectionState,
72
+ newState: SelectionState,
73
+ ignoreQuery = false,
74
+ ): boolean {
75
+ for (const [name, relationState] of newState.with) {
76
+ if (state.with.has(name) && !stateCompatible(state.with.get(name)!, relationState)) {
77
+ return false;
78
+ }
79
+ }
80
+
81
+ return ignoreQuery || deepEqual(state.query, newState.query);
82
+ }
83
+
84
+ export function mergeState(state: SelectionState, newState: SelectionState) {
85
+ for (const [name, relationState] of newState.with) {
86
+ if (state.with.has(name)) {
87
+ mergeState(state.with.get(name)!, relationState);
88
+ }
89
+ }
90
+
91
+ if (!state.allColumns) {
92
+ if (newState.allColumns) {
93
+ state.allColumns = true;
94
+ } else {
95
+ for (const name of newState.columns) {
96
+ state.columns.add(name);
97
+ }
98
+ }
99
+ }
100
+
101
+ for (const [name, value] of newState.extras) {
102
+ state.extras.set(name, value);
103
+ }
104
+ }
105
+
106
+ export function createState(table: TableRelationalConfig, parent?: SelectionState): SelectionState {
107
+ return {
108
+ table,
109
+ parent,
110
+ query: {},
111
+ columns: new Set(),
112
+ with: new Map(),
113
+ extras: new Map(),
114
+ mappings: {},
115
+ allColumns: false,
116
+ depth: parent ? parent.depth + 1 : 0,
117
+ };
118
+ }
119
+
120
+ export function mergeSelection(
121
+ config: PothosDrizzleSchemaConfig,
122
+ state: SelectionState,
123
+ { with: withSelection, extras, columns, ...query }: SelectionMap,
124
+ ) {
125
+ if (withSelection) {
126
+ Object.entries(withSelection).forEach(([key, value]) => {
127
+ const relation = state.table.relations[key];
128
+
129
+ if (!relation) {
130
+ throw new PothosValidationError(`Relation ${key} does not exist on ${state.table.dbName}`);
131
+ }
132
+
133
+ merge(config.dbToSchema[relation.referencedTableName], key, value as SelectionMap | boolean);
134
+ });
135
+ }
136
+
137
+ if (Object.keys(query).length > 0) {
138
+ state.query = query;
139
+ }
140
+
141
+ const resolvedExtras =
142
+ typeof extras === 'function' ? extras(state.table.columns, getOperators()) : extras;
143
+
144
+ if (resolvedExtras) {
145
+ for (const [key, value] of Object.entries(resolvedExtras)) {
146
+ state.extras.set(key, value);
147
+ }
148
+ }
149
+
150
+ if (state.allColumns) {
151
+ return;
152
+ }
153
+
154
+ if (columns) {
155
+ for (const key of Object.keys(columns)) {
156
+ state.columns.add(key);
157
+ }
158
+ } else {
159
+ state.allColumns = true;
160
+ }
161
+
162
+ function merge(table: TableRelationalConfig, key: string, value?: SelectionMap | boolean) {
163
+ if (!value) {
164
+ return;
165
+ }
166
+
167
+ const selection = value === true ? {} : value;
168
+
169
+ if (state.with.has(key)) {
170
+ mergeSelection(config, state.with.get(key)!, selection);
171
+ } else {
172
+ const relatedState = createState(table, state);
173
+ mergeSelection(config, relatedState, selection);
174
+ state.with.set(key, relatedState);
175
+ }
176
+ }
177
+ }
178
+
179
+ export function selectionToQuery(state: SelectionState): SelectionMap {
180
+ const query: SelectionMap & { extras: Record<string, unknown> } = {
181
+ ...state.query,
182
+ with: {},
183
+ columns: {},
184
+ extras: {},
185
+ };
186
+
187
+ if (state.allColumns) {
188
+ for (const key of Object.keys(state.table.columns)) {
189
+ query.columns![key] = true;
190
+ }
191
+ } else {
192
+ for (const key of state.columns) {
193
+ query.columns![key] = true;
194
+ }
195
+ for (const { name } of state.table.primaryKey) {
196
+ query.columns![name] = true;
197
+ }
198
+ }
199
+
200
+ for (const [key, value] of state.extras) {
201
+ query.extras![key] = value;
202
+ }
203
+
204
+ state.with.forEach((sel, relation) => {
205
+ query.with![relation] = selectionToQuery(sel);
206
+ });
207
+
208
+ return query;
209
+ }
@@ -0,0 +1,64 @@
1
+ export const usageSymbol = Symbol.for('Pothos.isUsed');
2
+
3
+ export function wrapWithUsageCheck<T extends Object>(obj: T): T {
4
+ const result = {};
5
+ let used = true;
6
+
7
+ Object.defineProperty(result, usageSymbol, {
8
+ get() {
9
+ return used;
10
+ },
11
+ set(value: boolean) {
12
+ used = value;
13
+ },
14
+ enumerable: false,
15
+ });
16
+
17
+ for (const key of Object.keys(obj)) {
18
+ // only set to false if the object has keys
19
+ used = false;
20
+ Object.defineProperty(result, key, {
21
+ enumerable: true,
22
+ configurable: true,
23
+ // eslint-disable-next-line @typescript-eslint/no-loop-func
24
+ get() {
25
+ used = true;
26
+ return obj[key as keyof T];
27
+ },
28
+ });
29
+ }
30
+
31
+ return result as T;
32
+ }
33
+
34
+ export function isUsed(obj: object): boolean {
35
+ return !(usageSymbol in obj) || (obj as { [usageSymbol]: boolean })[usageSymbol];
36
+ }
37
+
38
+ export function extendWithUsage<T extends object, U extends object>(
39
+ original: T,
40
+ extension: U,
41
+ ): T & U {
42
+ if (!(usageSymbol in original)) {
43
+ return { ...original, ...extension };
44
+ }
45
+
46
+ const result = { ...extension };
47
+
48
+ for (const key of [usageSymbol, ...Object.keys(original)]) {
49
+ if (key in result) {
50
+ // eslint-disable-next-line no-continue
51
+ continue;
52
+ }
53
+
54
+ Object.defineProperty(result, key, {
55
+ enumerable: key !== usageSymbol,
56
+ configurable: key !== usageSymbol,
57
+ get() {
58
+ return original[key as keyof T];
59
+ },
60
+ });
61
+ }
62
+
63
+ return result as T & U;
64
+ }