@nixxie-cms/core 1.0.3 → 1.1.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.
Files changed (202) hide show
  1. package/CHANGES-1.1.md +134 -0
  2. package/context/dist/nixxie-cms-core-context.cjs.js +4 -3
  3. package/context/dist/nixxie-cms-core-context.esm.js +3 -2
  4. package/dist/declarations/src/access.d.ts +2 -2
  5. package/dist/declarations/src/access.d.ts.map +1 -1
  6. package/dist/declarations/src/admin-ui/components/Navigation.d.ts +2 -2
  7. package/dist/declarations/src/admin-ui/components/Navigation.d.ts.map +1 -1
  8. package/dist/declarations/src/admin-ui/context.d.ts +6 -6
  9. package/dist/declarations/src/admin-ui/context.d.ts.map +1 -1
  10. package/dist/declarations/src/admin-ui/utils/Fields.d.ts +3 -3
  11. package/dist/declarations/src/admin-ui/utils/Fields.d.ts.map +1 -1
  12. package/dist/declarations/src/admin-ui/utils/filters.d.ts +5 -5
  13. package/dist/declarations/src/admin-ui/utils/filters.d.ts.map +1 -1
  14. package/dist/declarations/src/admin-ui/utils/useCreateItem.d.ts +3 -3
  15. package/dist/declarations/src/admin-ui/utils/useCreateItem.d.ts.map +1 -1
  16. package/dist/declarations/src/admin-ui/utils/utils.d.ts +2 -2
  17. package/dist/declarations/src/admin-ui/utils/utils.d.ts.map +1 -1
  18. package/dist/declarations/src/context.d.ts +1 -1
  19. package/dist/declarations/src/context.d.ts.map +1 -1
  20. package/dist/declarations/src/fields/types/bigInt/index.d.ts +3 -3
  21. package/dist/declarations/src/fields/types/bigInt/index.d.ts.map +1 -1
  22. package/dist/declarations/src/fields/types/bytes/index.d.ts +3 -3
  23. package/dist/declarations/src/fields/types/bytes/index.d.ts.map +1 -1
  24. package/dist/declarations/src/fields/types/calendarDay/index.d.ts +3 -3
  25. package/dist/declarations/src/fields/types/calendarDay/index.d.ts.map +1 -1
  26. package/dist/declarations/src/fields/types/checkbox/index.d.ts +3 -3
  27. package/dist/declarations/src/fields/types/checkbox/index.d.ts.map +1 -1
  28. package/dist/declarations/src/fields/types/decimal/index.d.ts +3 -3
  29. package/dist/declarations/src/fields/types/decimal/index.d.ts.map +1 -1
  30. package/dist/declarations/src/fields/types/file/index.d.ts +4 -4
  31. package/dist/declarations/src/fields/types/file/index.d.ts.map +1 -1
  32. package/dist/declarations/src/fields/types/float/index.d.ts +3 -3
  33. package/dist/declarations/src/fields/types/float/index.d.ts.map +1 -1
  34. package/dist/declarations/src/fields/types/image/index.d.ts +4 -4
  35. package/dist/declarations/src/fields/types/image/index.d.ts.map +1 -1
  36. package/dist/declarations/src/fields/types/integer/index.d.ts +3 -3
  37. package/dist/declarations/src/fields/types/integer/index.d.ts.map +1 -1
  38. package/dist/declarations/src/fields/types/json/index.d.ts +3 -3
  39. package/dist/declarations/src/fields/types/json/index.d.ts.map +1 -1
  40. package/dist/declarations/src/fields/types/multiselect/index.d.ts +3 -3
  41. package/dist/declarations/src/fields/types/multiselect/index.d.ts.map +1 -1
  42. package/dist/declarations/src/fields/types/multiselect/views/index.d.ts.map +1 -1
  43. package/dist/declarations/src/fields/types/password/index.d.ts +3 -3
  44. package/dist/declarations/src/fields/types/password/index.d.ts.map +1 -1
  45. package/dist/declarations/src/fields/types/relationship/index.d.ts +8 -8
  46. package/dist/declarations/src/fields/types/relationship/index.d.ts.map +1 -1
  47. package/dist/declarations/src/fields/types/relationship/views/ComboboxMany.d.ts +3 -3
  48. package/dist/declarations/src/fields/types/relationship/views/ComboboxMany.d.ts.map +1 -1
  49. package/dist/declarations/src/fields/types/relationship/views/ComboboxSingle.d.ts +3 -3
  50. package/dist/declarations/src/fields/types/relationship/views/ComboboxSingle.d.ts.map +1 -1
  51. package/dist/declarations/src/fields/types/relationship/views/index.d.ts +3 -3
  52. package/dist/declarations/src/fields/types/relationship/views/index.d.ts.map +1 -1
  53. package/dist/declarations/src/fields/types/relationship/views/types.d.ts +3 -3
  54. package/dist/declarations/src/fields/types/relationship/views/types.d.ts.map +1 -1
  55. package/dist/declarations/src/fields/types/select/index.d.ts +3 -3
  56. package/dist/declarations/src/fields/types/select/index.d.ts.map +1 -1
  57. package/dist/declarations/src/fields/types/text/index.d.ts +3 -3
  58. package/dist/declarations/src/fields/types/text/index.d.ts.map +1 -1
  59. package/dist/declarations/src/fields/types/timestamp/index.d.ts +3 -3
  60. package/dist/declarations/src/fields/types/timestamp/index.d.ts.map +1 -1
  61. package/dist/declarations/src/fields/types/virtual/index.d.ts +7 -7
  62. package/dist/declarations/src/fields/types/virtual/index.d.ts.map +1 -1
  63. package/dist/declarations/src/helpers.d.ts +249 -13
  64. package/dist/declarations/src/helpers.d.ts.map +1 -1
  65. package/dist/declarations/src/index.d.ts +9 -4
  66. package/dist/declarations/src/index.d.ts.map +1 -1
  67. package/dist/declarations/src/internal-unstable/admin-ui/pages/ListPage/index.d.ts.map +1 -1
  68. package/dist/declarations/src/lib/admin-meta.d.ts +11 -11
  69. package/dist/declarations/src/lib/admin-meta.d.ts.map +1 -1
  70. package/dist/declarations/src/lib/core/access-control.d.ts +18 -18
  71. package/dist/declarations/src/lib/core/access-control.d.ts.map +1 -1
  72. package/dist/declarations/src/lib/core/cascade.d.ts +47 -0
  73. package/dist/declarations/src/lib/core/cascade.d.ts.map +1 -0
  74. package/dist/declarations/src/lib/core/initialise-lists.d.ts +27 -24
  75. package/dist/declarations/src/lib/core/initialise-lists.d.ts.map +1 -1
  76. package/dist/declarations/src/lib/env.d.ts +9 -0
  77. package/dist/declarations/src/lib/env.d.ts.map +1 -0
  78. package/dist/declarations/src/lib/system.d.ts +1 -1
  79. package/dist/declarations/src/lib/system.d.ts.map +1 -1
  80. package/dist/declarations/src/list-features.d.ts +162 -0
  81. package/dist/declarations/src/list-features.d.ts.map +1 -0
  82. package/dist/declarations/src/schema.d.ts +24 -23
  83. package/dist/declarations/src/schema.d.ts.map +1 -1
  84. package/dist/declarations/src/session.d.ts +75 -0
  85. package/dist/declarations/src/session.d.ts.map +1 -1
  86. package/dist/declarations/src/types/admin-meta.d.ts +11 -11
  87. package/dist/declarations/src/types/admin-meta.d.ts.map +1 -1
  88. package/dist/declarations/src/types/config/access-control.d.ts +42 -42
  89. package/dist/declarations/src/types/config/access-control.d.ts.map +1 -1
  90. package/dist/declarations/src/types/config/fields.d.ts +19 -19
  91. package/dist/declarations/src/types/config/fields.d.ts.map +1 -1
  92. package/dist/declarations/src/types/config/hooks.d.ts +131 -131
  93. package/dist/declarations/src/types/config/hooks.d.ts.map +1 -1
  94. package/dist/declarations/src/types/config/index.d.ts +171 -8
  95. package/dist/declarations/src/types/config/index.d.ts.map +1 -1
  96. package/dist/declarations/src/types/config/lists.d.ts +146 -108
  97. package/dist/declarations/src/types/config/lists.d.ts.map +1 -1
  98. package/dist/declarations/src/types/context.d.ts +349 -47
  99. package/dist/declarations/src/types/context.d.ts.map +1 -1
  100. package/dist/declarations/src/types/next-fields.d.ts +28 -28
  101. package/dist/declarations/src/types/next-fields.d.ts.map +1 -1
  102. package/dist/declarations/src/types/type-info.d.ts +3 -3
  103. package/dist/declarations/src/types/type-info.d.ts.map +1 -1
  104. package/dist/{express-7559ca2d.esm.js → express-0abbce07.esm.js} +6 -6
  105. package/dist/{express-455ae20c.cjs.js → express-7ca6f76a.cjs.js} +6 -6
  106. package/dist/{index-15c8f81e.esm.js → index-5d8b0b4e.esm.js} +363 -183
  107. package/dist/index-6055753b.cjs.js +393 -0
  108. package/dist/{index-42045902.cjs.js → index-ac29f382.cjs.js} +363 -185
  109. package/dist/index-f1703b7b.esm.js +386 -0
  110. package/dist/nixxie-cms-core.cjs.js +1387 -30
  111. package/dist/nixxie-cms-core.esm.js +1361 -24
  112. package/dist/{non-null-graphql-add6bb3d.cjs.js → non-null-graphql-4a44c122.cjs.js} +1 -1
  113. package/dist/{non-null-graphql-a84ed64d.esm.js → non-null-graphql-8c5feaae.esm.js} +1 -1
  114. package/dist/{resolve-hooks-165a9ce2.cjs.js → resolve-hooks-10a5f84c.cjs.js} +240 -6
  115. package/dist/{resolve-hooks-6813a045.esm.js → resolve-hooks-9e676794.esm.js} +238 -7
  116. package/dist/{system-03e49e4f.esm.js → system-4d2a2648.esm.js} +32 -7
  117. package/dist/{system-a321642d.cjs.js → system-69e1a285.cjs.js} +32 -7
  118. package/fields/dist/nixxie-cms-core-fields.cjs.js +29 -576
  119. package/fields/dist/nixxie-cms-core-fields.esm.js +18 -565
  120. package/fields/types/bytes/dist/nixxie-cms-core-fields-types-bytes.cjs.js +4 -2
  121. package/fields/types/bytes/dist/nixxie-cms-core-fields-types-bytes.esm.js +4 -2
  122. package/fields/types/multiselect/views/dist/nixxie-cms-core-fields-types-multiselect-views.cjs.js +1 -6
  123. package/fields/types/multiselect/views/dist/nixxie-cms-core-fields-types-multiselect-views.esm.js +1 -6
  124. package/fields/types/password/dist/nixxie-cms-core-fields-types-password.cjs.js +4 -2
  125. package/fields/types/password/dist/nixxie-cms-core-fields-types-password.esm.js +4 -2
  126. package/internal-unstable/artifacts/dist/nixxie-cms-core-internal-unstable-artifacts.cjs.js +4 -3
  127. package/internal-unstable/artifacts/dist/nixxie-cms-core-internal-unstable-artifacts.esm.js +4 -3
  128. package/package.json +4 -4
  129. package/scripts/cli/dist/nixxie-cms-core-scripts-cli.cjs.js +4 -3
  130. package/scripts/cli/dist/nixxie-cms-core-scripts-cli.esm.js +4 -3
  131. package/scripts/dist/nixxie-cms-core-scripts.cjs.js +4 -3
  132. package/scripts/dist/nixxie-cms-core-scripts.esm.js +4 -3
  133. package/session/dist/nixxie-cms-core-session.cjs.js +286 -0
  134. package/session/dist/nixxie-cms-core-session.esm.js +279 -1
  135. package/src/access.ts +25 -25
  136. package/src/admin-ui/admin-meta-graphql.ts +5 -5
  137. package/src/admin-ui/components/CreateButtonLink.tsx +46 -46
  138. package/src/admin-ui/components/Navigation.tsx +3 -3
  139. package/src/admin-ui/context.tsx +6 -6
  140. package/src/admin-ui/utils/Fields.tsx +241 -241
  141. package/src/admin-ui/utils/actionData.ts +36 -36
  142. package/src/admin-ui/utils/filters.ts +148 -148
  143. package/src/admin-ui/utils/useCreateItem.ts +171 -171
  144. package/src/admin-ui/utils/utils.tsx +127 -127
  145. package/src/context.ts +1 -1
  146. package/src/fields/non-null-graphql.ts +115 -115
  147. package/src/fields/types/bigInt/index.ts +6 -6
  148. package/src/fields/types/bytes/index.ts +6 -6
  149. package/src/fields/types/calendarDay/index.ts +18 -19
  150. package/src/fields/types/checkbox/index.ts +6 -6
  151. package/src/fields/types/decimal/index.ts +6 -6
  152. package/src/fields/types/file/index.ts +8 -8
  153. package/src/fields/types/float/index.ts +6 -6
  154. package/src/fields/types/image/index.ts +8 -8
  155. package/src/fields/types/integer/index.ts +6 -6
  156. package/src/fields/types/json/index.ts +5 -5
  157. package/src/fields/types/multiselect/index.ts +7 -7
  158. package/src/fields/types/multiselect/views/index.tsx +149 -151
  159. package/src/fields/types/password/index.ts +6 -6
  160. package/src/fields/types/relationship/index.ts +13 -13
  161. package/src/fields/types/relationship/views/ComboboxMany.tsx +110 -110
  162. package/src/fields/types/relationship/views/ComboboxSingle.tsx +115 -115
  163. package/src/fields/types/relationship/views/ContextualActions.tsx +139 -139
  164. package/src/fields/types/relationship/views/index.tsx +492 -492
  165. package/src/fields/types/relationship/views/types.ts +46 -46
  166. package/src/fields/types/relationship/views/useApolloQuery.ts +185 -185
  167. package/src/fields/types/relationship/views/useFilter.tsx +109 -109
  168. package/src/fields/types/select/index.ts +6 -6
  169. package/src/fields/types/text/index.ts +6 -6
  170. package/src/fields/types/timestamp/index.ts +23 -21
  171. package/src/fields/types/virtual/index.ts +11 -11
  172. package/src/helpers.ts +773 -42
  173. package/src/index.ts +66 -24
  174. package/src/internal-unstable/admin-ui/pages/ItemPage/common.tsx +4 -4
  175. package/src/internal-unstable/admin-ui/pages/ItemPage/index.tsx +5 -5
  176. package/src/internal-unstable/admin-ui/pages/ListPage/index.tsx +8 -8
  177. package/src/lib/admin-meta.ts +369 -369
  178. package/src/lib/context/createContext.ts +5 -0
  179. package/src/lib/core/access-control.ts +434 -434
  180. package/src/lib/core/cascade.ts +236 -0
  181. package/src/lib/core/initialise-lists.ts +49 -33
  182. package/src/lib/core/mutations/index.ts +7 -0
  183. package/src/lib/core/mutations/nested-mutation-many-input-resolvers.ts +145 -145
  184. package/src/lib/core/mutations/nested-mutation-one-input-resolvers.ts +71 -71
  185. package/src/lib/core/queries/output-field.ts +178 -178
  186. package/src/lib/env.ts +50 -0
  187. package/src/lib/id-field.ts +2 -2
  188. package/src/lib/system.ts +221 -207
  189. package/src/lib/typescript-schema-printer.ts +227 -227
  190. package/src/list-features.ts +476 -0
  191. package/src/schema.ts +91 -22
  192. package/src/session.ts +225 -0
  193. package/src/types/admin-meta.ts +218 -218
  194. package/src/types/config/access-control.ts +186 -186
  195. package/src/types/config/fields.ts +96 -96
  196. package/src/types/config/hooks.ts +529 -529
  197. package/src/types/config/index.ts +185 -7
  198. package/src/types/config/lists.ts +606 -565
  199. package/src/types/context.ts +426 -55
  200. package/src/types/next-fields.ts +31 -31
  201. package/src/types/type-info.ts +38 -38
  202. package/src/types/type-tests.ts +21 -21
@@ -1,227 +1,227 @@
1
- import {
2
- type GraphQLNamedType,
3
- type GraphQLSchema,
4
- type GraphQLType,
5
- GraphQLEnumType,
6
- GraphQLInputObjectType,
7
- GraphQLList,
8
- GraphQLNonNull,
9
- GraphQLScalarType,
10
- introspectionTypes,
11
- } from 'graphql'
12
- import type { InitialisedList } from './core/initialise-lists'
13
-
14
- const introspectionTypesSet = new Set(introspectionTypes)
15
-
16
- // note this is the types for scalars as _input_ types
17
- // and before scalar parsing
18
- const SCALARS = {
19
- ID: 'string',
20
- Boolean: 'boolean',
21
- String: 'string',
22
- Int: 'number',
23
- Float: 'number',
24
- JSON: `import('@nixxie-cms/core/types').JSONValue`,
25
- Decimal: `import('@nixxie-cms/core/types').Decimal | string`,
26
- Empty: `{}`,
27
- } as const
28
-
29
- function stringify(x: string) {
30
- return JSON.stringify(x).slice(1, -1)
31
- }
32
-
33
- function printTypeReference(type: GraphQLType): string {
34
- if (type instanceof GraphQLNonNull) return printTypeReferenceWithoutNullable(type.ofType)
35
- return `${printTypeReferenceWithoutNullable(type)} | null`
36
- }
37
-
38
- function printTypeReferenceWithoutNullable(
39
- type: GraphQLNamedType | GraphQLList<GraphQLType>
40
- ): string {
41
- if (type instanceof GraphQLList)
42
- return `ReadonlyArray<${printTypeReference(type.ofType)}> | ${printTypeReference(type.ofType)}`
43
-
44
- const name = type.name
45
- if (type instanceof GraphQLScalarType) {
46
- if (name in SCALARS) return SCALARS[name as keyof typeof SCALARS]
47
- return `any`
48
- }
49
-
50
- return name
51
- }
52
-
53
- function printInterimType<L extends InitialisedList>(
54
- prismaClientPath: string,
55
- list: L,
56
- operation: 'create' | 'update'
57
- ) {
58
- const name = list.prisma.types[`${operation}InputName`]
59
- const prismaType = `import('${prismaClientPath}').Prisma.${name}`
60
- return [
61
- `type Resolved${name} = {`,
62
- ...Object.entries(list.fields).map(([fieldKey, { dbField, graphql }]) => {
63
- if (dbField.kind === 'none') return ` ${fieldKey}?: undefined`
64
-
65
- // TODO: this could be elsewhere, maybe id-field.ts
66
- if (fieldKey === 'id') {
67
- // autoincrement doesn't support passing an identifier
68
- if ('default' in dbField) {
69
- if (dbField.default?.kind === 'autoincrement') {
70
- return ` id?: undefined`
71
- }
72
- }
73
-
74
- // soft-block `id` updates for relationship safety
75
- if (operation === 'update') return ` id?: undefined`
76
- }
77
-
78
- if (dbField.kind === 'multi') {
79
- return [
80
- ` ${fieldKey}: {`,
81
- ...Object.entries(dbField.fields).map(([subFieldKey, subDbField]) => {
82
- const optional =
83
- operation === 'create' && subDbField.mode === 'required' && !subDbField.default
84
- ? ''
85
- : '?'
86
- return ` ${subFieldKey}${optional}: ${prismaType}['${fieldKey}_${subFieldKey}']`
87
- }),
88
- ` }`,
89
- ].join('\n')
90
- }
91
-
92
- const optional =
93
- (operation === 'create' && dbField.mode === 'required' && !dbField.default) ||
94
- graphql.isNonNull[operation]
95
- ? ''
96
- : '?'
97
- return ` ${fieldKey}${optional}: ${prismaType}['${fieldKey}']`
98
- }),
99
- `}`,
100
- ].join('\n')
101
- }
102
-
103
- export function printGeneratedTypes(
104
- prismaClientPath: string,
105
- graphQLSchema: GraphQLSchema,
106
- lists: Record<string, InitialisedList>
107
- ) {
108
- prismaClientPath = stringify(prismaClientPath).replace(/'/g, `\\'`)
109
-
110
- return [
111
- '/* eslint-disable */',
112
- '',
113
- [
114
- ...(function* () {
115
- for (const type of Object.values(graphQLSchema.getTypeMap())) {
116
- // We don't want to print TS types for the built-in GraphQL introspection types
117
- // they won't be used for anything we want to print here.
118
- if (introspectionTypesSet.has(type)) continue
119
- if (type instanceof GraphQLInputObjectType) {
120
- yield [
121
- `export type ${type.name} = {`,
122
- ...(function* () {
123
- for (const { name, type: type_ } of Object.values(type.getFields())) {
124
- const maybe = type_ instanceof GraphQLNonNull ? '' : '?'
125
- yield ` readonly ${name}${maybe}: ${printTypeReference(type_)}`
126
- }
127
- })(),
128
- '}',
129
- ].join('\n')
130
- continue
131
- }
132
-
133
- if (type instanceof GraphQLEnumType) {
134
- yield [
135
- `export type ${type.name} =`,
136
- type
137
- .getValues()
138
- .map(x => ` | '${stringify(x.name)}'`)
139
- .join('\n'),
140
- ].join('\n')
141
- continue
142
- }
143
-
144
- if (type.name === 'Empty') {
145
- yield `export type Empty = {}`
146
- continue
147
- }
148
- }
149
- })(),
150
- ].join('\n\n'),
151
- '',
152
- // Resolved* types
153
- ...(function* () {
154
- for (const list of Object.values(lists)) {
155
- yield printInterimType(prismaClientPath, list, 'create')
156
- yield printInterimType(prismaClientPath, list, 'update')
157
- }
158
- })(),
159
- '',
160
- 'export declare namespace Lists {',
161
- ...(function* () {
162
- for (const [listKey, list] of Object.entries(lists)) {
163
- const { createInputName, updateInputName } = list.prisma.types
164
- const listTypeInfoName = `Lists.${listKey}.TypeInfo`
165
-
166
- yield [
167
- `export type ${listKey}<Session = any> = import('@nixxie-cms/core/types').ListConfig<${listTypeInfoName}<Session>>`,
168
- `namespace ${listKey} {`,
169
- ` export type Item = import('${prismaClientPath}').${listKey}`,
170
- ` export type TypeInfo<Session = any> = {`,
171
- ` key: '${listKey}'`,
172
- ` isSingleton: ${list.isSingleton}`,
173
- ` fields: ${Object.keys(list.fields)
174
- .map(x => `'${x}'`)
175
- .join(' | ')}`,
176
- ` actions: ${
177
- Object.values(list.actions)
178
- .map(x => `'${x.actionKey}'`)
179
- .join(' | ') || 'never'
180
- }`,
181
- ` item: Item`,
182
- ` inputs: {`,
183
- ` where: ${printTypeReferenceWithoutNullable(list.graphql.types.where)}`,
184
- ` uniqueWhere: ${printTypeReferenceWithoutNullable(list.graphql.types.uniqueWhere)}`,
185
- ` create: ${printTypeReferenceWithoutNullable(list.graphql.types.create)}`,
186
- ` update: ${printTypeReferenceWithoutNullable(list.graphql.types.update)}`,
187
- ` orderBy: ${printTypeReferenceWithoutNullable(list.graphql.types.orderBy)}`,
188
- ` }`,
189
- ` prisma: {`,
190
- ` create: Resolved${createInputName}`,
191
- ` update: Resolved${updateInputName}`,
192
- ` }`,
193
- ` all: __TypeInfo<Session>`,
194
- ` }`,
195
- `}`,
196
- ]
197
- .map(line => ` ${line}`)
198
- .join('\n')
199
- }
200
- })(),
201
- '}',
202
- `export type Context<Session = any> = import('@nixxie-cms/core/types').NixxieContext<TypeInfo<Session>>`,
203
- `export type Config<Session = any> = import('@nixxie-cms/core/types').NixxieConfig<TypeInfo<Session>>`,
204
- '',
205
- 'export type TypeInfo<Session = any> = {',
206
- ` lists: {`,
207
- ...(function* () {
208
- for (const listKey in lists) {
209
- yield ` readonly ${listKey}: Lists.${listKey}.TypeInfo<Session>`
210
- }
211
- })(),
212
- ` }`,
213
- ` prisma: import('${prismaClientPath}').PrismaClient`,
214
- ` session: Session`,
215
- `}`,
216
- ``,
217
- // we need to reference the `TypeInfo` above in another type that is also called `TypeInfo`
218
- `type __TypeInfo<Session = any> = TypeInfo<Session>`,
219
- ``,
220
- `export type Lists<Session = any> = {`,
221
- ` [Key in keyof TypeInfo['lists']]?: import('@nixxie-cms/core/types').ListConfig<TypeInfo<Session>['lists'][Key]>`,
222
- `} & Record<string, import('@nixxie-cms/core/types').ListConfig<any>>`,
223
- ``,
224
- `export {}`,
225
- ``,
226
- ].join('\n')
227
- }
1
+ import {
2
+ type GraphQLNamedType,
3
+ type GraphQLSchema,
4
+ type GraphQLType,
5
+ GraphQLEnumType,
6
+ GraphQLInputObjectType,
7
+ GraphQLList,
8
+ GraphQLNonNull,
9
+ GraphQLScalarType,
10
+ introspectionTypes,
11
+ } from 'graphql'
12
+ import type { InitialisedList } from './core/initialise-lists'
13
+
14
+ const introspectionTypesSet = new Set(introspectionTypes)
15
+
16
+ // note this is the types for scalars as _input_ types
17
+ // and before scalar parsing
18
+ const SCALARS = {
19
+ ID: 'string',
20
+ Boolean: 'boolean',
21
+ String: 'string',
22
+ Int: 'number',
23
+ Float: 'number',
24
+ JSON: `import('@nixxie-cms/core/types').JSONValue`,
25
+ Decimal: `import('@nixxie-cms/core/types').Decimal | string`,
26
+ Empty: `{}`,
27
+ } as const
28
+
29
+ function stringify(x: string) {
30
+ return JSON.stringify(x).slice(1, -1)
31
+ }
32
+
33
+ function printTypeReference(type: GraphQLType): string {
34
+ if (type instanceof GraphQLNonNull) return printTypeReferenceWithoutNullable(type.ofType)
35
+ return `${printTypeReferenceWithoutNullable(type)} | null`
36
+ }
37
+
38
+ function printTypeReferenceWithoutNullable(
39
+ type: GraphQLNamedType | GraphQLList<GraphQLType>
40
+ ): string {
41
+ if (type instanceof GraphQLList)
42
+ return `ReadonlyArray<${printTypeReference(type.ofType)}> | ${printTypeReference(type.ofType)}`
43
+
44
+ const name = type.name
45
+ if (type instanceof GraphQLScalarType) {
46
+ if (name in SCALARS) return SCALARS[name as keyof typeof SCALARS]
47
+ return `any`
48
+ }
49
+
50
+ return name
51
+ }
52
+
53
+ function printInterimType<L extends InitialisedList>(
54
+ prismaClientPath: string,
55
+ list: L,
56
+ operation: 'create' | 'update'
57
+ ) {
58
+ const name = list.prisma.types[`${operation}InputName`]
59
+ const prismaType = `import('${prismaClientPath}').Prisma.${name}`
60
+ return [
61
+ `type Resolved${name} = {`,
62
+ ...Object.entries(list.fields).map(([fieldKey, { dbField, graphql }]) => {
63
+ if (dbField.kind === 'none') return ` ${fieldKey}?: undefined`
64
+
65
+ // TODO: this could be elsewhere, maybe id-field.ts
66
+ if (fieldKey === 'id') {
67
+ // autoincrement doesn't support passing an identifier
68
+ if ('default' in dbField) {
69
+ if (dbField.default?.kind === 'autoincrement') {
70
+ return ` id?: undefined`
71
+ }
72
+ }
73
+
74
+ // soft-block `id` updates for relationship safety
75
+ if (operation === 'update') return ` id?: undefined`
76
+ }
77
+
78
+ if (dbField.kind === 'multi') {
79
+ return [
80
+ ` ${fieldKey}: {`,
81
+ ...Object.entries(dbField.fields).map(([subFieldKey, subDbField]) => {
82
+ const optional =
83
+ operation === 'create' && subDbField.mode === 'required' && !subDbField.default
84
+ ? ''
85
+ : '?'
86
+ return ` ${subFieldKey}${optional}: ${prismaType}['${fieldKey}_${subFieldKey}']`
87
+ }),
88
+ ` }`,
89
+ ].join('\n')
90
+ }
91
+
92
+ const optional =
93
+ (operation === 'create' && dbField.mode === 'required' && !dbField.default) ||
94
+ graphql.isNonNull[operation]
95
+ ? ''
96
+ : '?'
97
+ return ` ${fieldKey}${optional}: ${prismaType}['${fieldKey}']`
98
+ }),
99
+ `}`,
100
+ ].join('\n')
101
+ }
102
+
103
+ export function printGeneratedTypes(
104
+ prismaClientPath: string,
105
+ graphQLSchema: GraphQLSchema,
106
+ lists: Record<string, InitialisedList>
107
+ ) {
108
+ prismaClientPath = stringify(prismaClientPath).replace(/'/g, `\\'`)
109
+
110
+ return [
111
+ '/* eslint-disable */',
112
+ '',
113
+ [
114
+ ...(function* () {
115
+ for (const type of Object.values(graphQLSchema.getTypeMap())) {
116
+ // We don't want to print TS types for the built-in GraphQL introspection types
117
+ // they won't be used for anything we want to print here.
118
+ if (introspectionTypesSet.has(type)) continue
119
+ if (type instanceof GraphQLInputObjectType) {
120
+ yield [
121
+ `export type ${type.name} = {`,
122
+ ...(function* () {
123
+ for (const { name, type: type_ } of Object.values(type.getFields())) {
124
+ const maybe = type_ instanceof GraphQLNonNull ? '' : '?'
125
+ yield ` readonly ${name}${maybe}: ${printTypeReference(type_)}`
126
+ }
127
+ })(),
128
+ '}',
129
+ ].join('\n')
130
+ continue
131
+ }
132
+
133
+ if (type instanceof GraphQLEnumType) {
134
+ yield [
135
+ `export type ${type.name} =`,
136
+ type
137
+ .getValues()
138
+ .map(x => ` | '${stringify(x.name)}'`)
139
+ .join('\n'),
140
+ ].join('\n')
141
+ continue
142
+ }
143
+
144
+ if (type.name === 'Empty') {
145
+ yield `export type Empty = {}`
146
+ continue
147
+ }
148
+ }
149
+ })(),
150
+ ].join('\n\n'),
151
+ '',
152
+ // Resolved* types
153
+ ...(function* () {
154
+ for (const list of Object.values(lists)) {
155
+ yield printInterimType(prismaClientPath, list, 'create')
156
+ yield printInterimType(prismaClientPath, list, 'update')
157
+ }
158
+ })(),
159
+ '',
160
+ 'export declare namespace Collections {',
161
+ ...(function* () {
162
+ for (const [listKey, list] of Object.entries(lists)) {
163
+ const { createInputName, updateInputName } = list.prisma.types
164
+ const listTypeInfoName = `Collections.${listKey}.TypeInfo`
165
+
166
+ yield [
167
+ `export type ${listKey}<Session = any> = import('@nixxie-cms/core/types').CollectionConfig<${listTypeInfoName}<Session>>`,
168
+ `namespace ${listKey} {`,
169
+ ` export type Item = import('${prismaClientPath}').${listKey}`,
170
+ ` export type TypeInfo<Session = any> = {`,
171
+ ` key: '${listKey}'`,
172
+ ` isSingleton: ${list.isSingleton}`,
173
+ ` fields: ${Object.keys(list.fields)
174
+ .map(x => `'${x}'`)
175
+ .join(' | ')}`,
176
+ ` actions: ${
177
+ Object.values(list.actions)
178
+ .map(x => `'${x.actionKey}'`)
179
+ .join(' | ') || 'never'
180
+ }`,
181
+ ` item: Item`,
182
+ ` inputs: {`,
183
+ ` where: ${printTypeReferenceWithoutNullable(list.graphql.types.where)}`,
184
+ ` uniqueWhere: ${printTypeReferenceWithoutNullable(list.graphql.types.uniqueWhere)}`,
185
+ ` create: ${printTypeReferenceWithoutNullable(list.graphql.types.create)}`,
186
+ ` update: ${printTypeReferenceWithoutNullable(list.graphql.types.update)}`,
187
+ ` orderBy: ${printTypeReferenceWithoutNullable(list.graphql.types.orderBy)}`,
188
+ ` }`,
189
+ ` prisma: {`,
190
+ ` create: Resolved${createInputName}`,
191
+ ` update: Resolved${updateInputName}`,
192
+ ` }`,
193
+ ` all: __TypeInfo<Session>`,
194
+ ` }`,
195
+ `}`,
196
+ ]
197
+ .map(line => ` ${line}`)
198
+ .join('\n')
199
+ }
200
+ })(),
201
+ '}',
202
+ `export type Context<Session = any> = import('@nixxie-cms/core/types').NixxieContext<TypeInfo<Session>>`,
203
+ `export type Config<Session = any> = import('@nixxie-cms/core/types').NixxieConfig<TypeInfo<Session>>`,
204
+ '',
205
+ 'export type TypeInfo<Session = any> = {',
206
+ ` lists: {`,
207
+ ...(function* () {
208
+ for (const listKey in lists) {
209
+ yield ` readonly ${listKey}: Collections.${listKey}.TypeInfo<Session>`
210
+ }
211
+ })(),
212
+ ` }`,
213
+ ` prisma: import('${prismaClientPath}').PrismaClient`,
214
+ ` session: Session`,
215
+ `}`,
216
+ ``,
217
+ // we need to reference the `TypeInfo` above in another type that is also called `TypeInfo`
218
+ `type __TypeInfo<Session = any> = TypeInfo<Session>`,
219
+ ``,
220
+ `export type Collections<Session = any> = {`,
221
+ ` [Key in keyof TypeInfo['lists']]?: import('@nixxie-cms/core/types').CollectionConfig<TypeInfo<Session>['lists'][Key]>`,
222
+ `} & Record<string, import('@nixxie-cms/core/types').CollectionConfig<any>>`,
223
+ ``,
224
+ `export {}`,
225
+ ``,
226
+ ].join('\n')
227
+ }