@nixxie-cms/core 1.0.3 → 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.
Files changed (203) hide show
  1. package/CHANGELOG.md +36 -0
  2. package/CHANGES-1.1.md +134 -0
  3. package/context/dist/nixxie-cms-core-context.cjs.js +4 -3
  4. package/context/dist/nixxie-cms-core-context.esm.js +3 -2
  5. package/dist/declarations/src/access.d.ts +2 -2
  6. package/dist/declarations/src/access.d.ts.map +1 -1
  7. package/dist/declarations/src/admin-ui/components/Navigation.d.ts +2 -2
  8. package/dist/declarations/src/admin-ui/components/Navigation.d.ts.map +1 -1
  9. package/dist/declarations/src/admin-ui/context.d.ts +6 -6
  10. package/dist/declarations/src/admin-ui/context.d.ts.map +1 -1
  11. package/dist/declarations/src/admin-ui/utils/Fields.d.ts +3 -3
  12. package/dist/declarations/src/admin-ui/utils/Fields.d.ts.map +1 -1
  13. package/dist/declarations/src/admin-ui/utils/filters.d.ts +5 -5
  14. package/dist/declarations/src/admin-ui/utils/filters.d.ts.map +1 -1
  15. package/dist/declarations/src/admin-ui/utils/useCreateItem.d.ts +3 -3
  16. package/dist/declarations/src/admin-ui/utils/useCreateItem.d.ts.map +1 -1
  17. package/dist/declarations/src/admin-ui/utils/utils.d.ts +2 -2
  18. package/dist/declarations/src/admin-ui/utils/utils.d.ts.map +1 -1
  19. package/dist/declarations/src/context.d.ts +1 -1
  20. package/dist/declarations/src/context.d.ts.map +1 -1
  21. package/dist/declarations/src/fields/types/bigInt/index.d.ts +3 -3
  22. package/dist/declarations/src/fields/types/bigInt/index.d.ts.map +1 -1
  23. package/dist/declarations/src/fields/types/bytes/index.d.ts +3 -3
  24. package/dist/declarations/src/fields/types/bytes/index.d.ts.map +1 -1
  25. package/dist/declarations/src/fields/types/calendarDay/index.d.ts +3 -3
  26. package/dist/declarations/src/fields/types/calendarDay/index.d.ts.map +1 -1
  27. package/dist/declarations/src/fields/types/checkbox/index.d.ts +3 -3
  28. package/dist/declarations/src/fields/types/checkbox/index.d.ts.map +1 -1
  29. package/dist/declarations/src/fields/types/decimal/index.d.ts +3 -3
  30. package/dist/declarations/src/fields/types/decimal/index.d.ts.map +1 -1
  31. package/dist/declarations/src/fields/types/file/index.d.ts +4 -4
  32. package/dist/declarations/src/fields/types/file/index.d.ts.map +1 -1
  33. package/dist/declarations/src/fields/types/float/index.d.ts +3 -3
  34. package/dist/declarations/src/fields/types/float/index.d.ts.map +1 -1
  35. package/dist/declarations/src/fields/types/image/index.d.ts +4 -4
  36. package/dist/declarations/src/fields/types/image/index.d.ts.map +1 -1
  37. package/dist/declarations/src/fields/types/integer/index.d.ts +3 -3
  38. package/dist/declarations/src/fields/types/integer/index.d.ts.map +1 -1
  39. package/dist/declarations/src/fields/types/json/index.d.ts +3 -3
  40. package/dist/declarations/src/fields/types/json/index.d.ts.map +1 -1
  41. package/dist/declarations/src/fields/types/multiselect/index.d.ts +3 -3
  42. package/dist/declarations/src/fields/types/multiselect/index.d.ts.map +1 -1
  43. package/dist/declarations/src/fields/types/multiselect/views/index.d.ts.map +1 -1
  44. package/dist/declarations/src/fields/types/password/index.d.ts +3 -3
  45. package/dist/declarations/src/fields/types/password/index.d.ts.map +1 -1
  46. package/dist/declarations/src/fields/types/relationship/index.d.ts +8 -8
  47. package/dist/declarations/src/fields/types/relationship/index.d.ts.map +1 -1
  48. package/dist/declarations/src/fields/types/relationship/views/ComboboxMany.d.ts +3 -3
  49. package/dist/declarations/src/fields/types/relationship/views/ComboboxMany.d.ts.map +1 -1
  50. package/dist/declarations/src/fields/types/relationship/views/ComboboxSingle.d.ts +3 -3
  51. package/dist/declarations/src/fields/types/relationship/views/ComboboxSingle.d.ts.map +1 -1
  52. package/dist/declarations/src/fields/types/relationship/views/index.d.ts +3 -3
  53. package/dist/declarations/src/fields/types/relationship/views/index.d.ts.map +1 -1
  54. package/dist/declarations/src/fields/types/relationship/views/types.d.ts +3 -3
  55. package/dist/declarations/src/fields/types/relationship/views/types.d.ts.map +1 -1
  56. package/dist/declarations/src/fields/types/select/index.d.ts +3 -3
  57. package/dist/declarations/src/fields/types/select/index.d.ts.map +1 -1
  58. package/dist/declarations/src/fields/types/text/index.d.ts +3 -3
  59. package/dist/declarations/src/fields/types/text/index.d.ts.map +1 -1
  60. package/dist/declarations/src/fields/types/timestamp/index.d.ts +3 -3
  61. package/dist/declarations/src/fields/types/timestamp/index.d.ts.map +1 -1
  62. package/dist/declarations/src/fields/types/virtual/index.d.ts +7 -7
  63. package/dist/declarations/src/fields/types/virtual/index.d.ts.map +1 -1
  64. package/dist/declarations/src/helpers.d.ts +249 -13
  65. package/dist/declarations/src/helpers.d.ts.map +1 -1
  66. package/dist/declarations/src/index.d.ts +9 -4
  67. package/dist/declarations/src/index.d.ts.map +1 -1
  68. package/dist/declarations/src/internal-unstable/admin-ui/pages/ListPage/index.d.ts.map +1 -1
  69. package/dist/declarations/src/lib/admin-meta.d.ts +11 -11
  70. package/dist/declarations/src/lib/admin-meta.d.ts.map +1 -1
  71. package/dist/declarations/src/lib/core/access-control.d.ts +18 -18
  72. package/dist/declarations/src/lib/core/access-control.d.ts.map +1 -1
  73. package/dist/declarations/src/lib/core/cascade.d.ts +47 -0
  74. package/dist/declarations/src/lib/core/cascade.d.ts.map +1 -0
  75. package/dist/declarations/src/lib/core/initialise-lists.d.ts +27 -24
  76. package/dist/declarations/src/lib/core/initialise-lists.d.ts.map +1 -1
  77. package/dist/declarations/src/lib/env.d.ts +9 -0
  78. package/dist/declarations/src/lib/env.d.ts.map +1 -0
  79. package/dist/declarations/src/lib/system.d.ts +1 -1
  80. package/dist/declarations/src/lib/system.d.ts.map +1 -1
  81. package/dist/declarations/src/list-features.d.ts +162 -0
  82. package/dist/declarations/src/list-features.d.ts.map +1 -0
  83. package/dist/declarations/src/schema.d.ts +24 -23
  84. package/dist/declarations/src/schema.d.ts.map +1 -1
  85. package/dist/declarations/src/session.d.ts +75 -0
  86. package/dist/declarations/src/session.d.ts.map +1 -1
  87. package/dist/declarations/src/types/admin-meta.d.ts +11 -11
  88. package/dist/declarations/src/types/admin-meta.d.ts.map +1 -1
  89. package/dist/declarations/src/types/config/access-control.d.ts +42 -42
  90. package/dist/declarations/src/types/config/access-control.d.ts.map +1 -1
  91. package/dist/declarations/src/types/config/fields.d.ts +19 -19
  92. package/dist/declarations/src/types/config/fields.d.ts.map +1 -1
  93. package/dist/declarations/src/types/config/hooks.d.ts +131 -131
  94. package/dist/declarations/src/types/config/hooks.d.ts.map +1 -1
  95. package/dist/declarations/src/types/config/index.d.ts +190 -8
  96. package/dist/declarations/src/types/config/index.d.ts.map +1 -1
  97. package/dist/declarations/src/types/config/lists.d.ts +146 -108
  98. package/dist/declarations/src/types/config/lists.d.ts.map +1 -1
  99. package/dist/declarations/src/types/context.d.ts +507 -47
  100. package/dist/declarations/src/types/context.d.ts.map +1 -1
  101. package/dist/declarations/src/types/next-fields.d.ts +28 -28
  102. package/dist/declarations/src/types/next-fields.d.ts.map +1 -1
  103. package/dist/declarations/src/types/type-info.d.ts +3 -3
  104. package/dist/declarations/src/types/type-info.d.ts.map +1 -1
  105. package/dist/{express-455ae20c.cjs.js → express-84d534c2.cjs.js} +6 -6
  106. package/dist/{express-7559ca2d.esm.js → express-d0a4ce99.esm.js} +6 -6
  107. package/dist/{index-15c8f81e.esm.js → index-5d8b0b4e.esm.js} +363 -183
  108. package/dist/index-6055753b.cjs.js +393 -0
  109. package/dist/{index-42045902.cjs.js → index-ac29f382.cjs.js} +363 -185
  110. package/dist/index-f1703b7b.esm.js +386 -0
  111. package/dist/nixxie-cms-core.cjs.js +1388 -30
  112. package/dist/nixxie-cms-core.esm.js +1362 -24
  113. package/dist/{non-null-graphql-add6bb3d.cjs.js → non-null-graphql-4a44c122.cjs.js} +1 -1
  114. package/dist/{non-null-graphql-a84ed64d.esm.js → non-null-graphql-8c5feaae.esm.js} +1 -1
  115. package/dist/{resolve-hooks-165a9ce2.cjs.js → resolve-hooks-10a5f84c.cjs.js} +240 -6
  116. package/dist/{resolve-hooks-6813a045.esm.js → resolve-hooks-9e676794.esm.js} +238 -7
  117. package/dist/{system-a321642d.cjs.js → system-6b37a5f8.cjs.js} +33 -7
  118. package/dist/{system-03e49e4f.esm.js → system-e591d821.esm.js} +33 -7
  119. package/fields/dist/nixxie-cms-core-fields.cjs.js +29 -576
  120. package/fields/dist/nixxie-cms-core-fields.esm.js +18 -565
  121. package/fields/types/bytes/dist/nixxie-cms-core-fields-types-bytes.cjs.js +4 -2
  122. package/fields/types/bytes/dist/nixxie-cms-core-fields-types-bytes.esm.js +4 -2
  123. package/fields/types/multiselect/views/dist/nixxie-cms-core-fields-types-multiselect-views.cjs.js +1 -6
  124. package/fields/types/multiselect/views/dist/nixxie-cms-core-fields-types-multiselect-views.esm.js +1 -6
  125. package/fields/types/password/dist/nixxie-cms-core-fields-types-password.cjs.js +4 -2
  126. package/fields/types/password/dist/nixxie-cms-core-fields-types-password.esm.js +4 -2
  127. package/internal-unstable/artifacts/dist/nixxie-cms-core-internal-unstable-artifacts.cjs.js +4 -3
  128. package/internal-unstable/artifacts/dist/nixxie-cms-core-internal-unstable-artifacts.esm.js +4 -3
  129. package/package.json +4 -4
  130. package/scripts/cli/dist/nixxie-cms-core-scripts-cli.cjs.js +4 -3
  131. package/scripts/cli/dist/nixxie-cms-core-scripts-cli.esm.js +4 -3
  132. package/scripts/dist/nixxie-cms-core-scripts.cjs.js +4 -3
  133. package/scripts/dist/nixxie-cms-core-scripts.esm.js +4 -3
  134. package/session/dist/nixxie-cms-core-session.cjs.js +286 -0
  135. package/session/dist/nixxie-cms-core-session.esm.js +279 -1
  136. package/src/access.ts +25 -25
  137. package/src/admin-ui/admin-meta-graphql.ts +5 -5
  138. package/src/admin-ui/components/CreateButtonLink.tsx +46 -46
  139. package/src/admin-ui/components/Navigation.tsx +3 -3
  140. package/src/admin-ui/context.tsx +6 -6
  141. package/src/admin-ui/utils/Fields.tsx +241 -241
  142. package/src/admin-ui/utils/actionData.ts +36 -36
  143. package/src/admin-ui/utils/filters.ts +148 -148
  144. package/src/admin-ui/utils/useCreateItem.ts +171 -171
  145. package/src/admin-ui/utils/utils.tsx +127 -127
  146. package/src/context.ts +1 -1
  147. package/src/fields/non-null-graphql.ts +115 -115
  148. package/src/fields/types/bigInt/index.ts +6 -6
  149. package/src/fields/types/bytes/index.ts +6 -6
  150. package/src/fields/types/calendarDay/index.ts +18 -19
  151. package/src/fields/types/checkbox/index.ts +6 -6
  152. package/src/fields/types/decimal/index.ts +6 -6
  153. package/src/fields/types/file/index.ts +8 -8
  154. package/src/fields/types/float/index.ts +6 -6
  155. package/src/fields/types/image/index.ts +8 -8
  156. package/src/fields/types/integer/index.ts +6 -6
  157. package/src/fields/types/json/index.ts +5 -5
  158. package/src/fields/types/multiselect/index.ts +7 -7
  159. package/src/fields/types/multiselect/views/index.tsx +149 -151
  160. package/src/fields/types/password/index.ts +6 -6
  161. package/src/fields/types/relationship/index.ts +13 -13
  162. package/src/fields/types/relationship/views/ComboboxMany.tsx +110 -110
  163. package/src/fields/types/relationship/views/ComboboxSingle.tsx +115 -115
  164. package/src/fields/types/relationship/views/ContextualActions.tsx +139 -139
  165. package/src/fields/types/relationship/views/index.tsx +492 -492
  166. package/src/fields/types/relationship/views/types.ts +46 -46
  167. package/src/fields/types/relationship/views/useApolloQuery.ts +185 -185
  168. package/src/fields/types/relationship/views/useFilter.tsx +109 -109
  169. package/src/fields/types/select/index.ts +6 -6
  170. package/src/fields/types/text/index.ts +6 -6
  171. package/src/fields/types/timestamp/index.ts +23 -21
  172. package/src/fields/types/virtual/index.ts +11 -11
  173. package/src/helpers.ts +773 -42
  174. package/src/index.ts +66 -24
  175. package/src/internal-unstable/admin-ui/pages/ItemPage/common.tsx +4 -4
  176. package/src/internal-unstable/admin-ui/pages/ItemPage/index.tsx +5 -5
  177. package/src/internal-unstable/admin-ui/pages/ListPage/index.tsx +8 -8
  178. package/src/lib/admin-meta.ts +369 -369
  179. package/src/lib/context/createContext.ts +6 -0
  180. package/src/lib/core/access-control.ts +434 -434
  181. package/src/lib/core/cascade.ts +236 -0
  182. package/src/lib/core/initialise-lists.ts +49 -33
  183. package/src/lib/core/mutations/index.ts +7 -0
  184. package/src/lib/core/mutations/nested-mutation-many-input-resolvers.ts +145 -145
  185. package/src/lib/core/mutations/nested-mutation-one-input-resolvers.ts +71 -71
  186. package/src/lib/core/queries/output-field.ts +178 -178
  187. package/src/lib/env.ts +50 -0
  188. package/src/lib/id-field.ts +2 -2
  189. package/src/lib/system.ts +221 -207
  190. package/src/lib/typescript-schema-printer.ts +227 -227
  191. package/src/list-features.ts +476 -0
  192. package/src/schema.ts +92 -22
  193. package/src/session.ts +225 -0
  194. package/src/types/admin-meta.ts +218 -218
  195. package/src/types/config/access-control.ts +186 -186
  196. package/src/types/config/fields.ts +96 -96
  197. package/src/types/config/hooks.ts +529 -529
  198. package/src/types/config/index.ts +206 -7
  199. package/src/types/config/lists.ts +606 -565
  200. package/src/types/context.ts +592 -55
  201. package/src/types/next-fields.ts +31 -31
  202. package/src/types/type-info.ts +38 -38
  203. 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
+ }