@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,186 +1,186 @@
1
- import type { NixxieContext } from '../context'
2
- import type { BaseListTypeInfo } from '../type-info'
3
- import type { MaybePromise } from '../utils'
4
-
5
- export type BaseAccessArgs<ListTypeInfo extends BaseListTypeInfo> = {
6
- context: NixxieContext<ListTypeInfo['all']>
7
- session?: ListTypeInfo['all']['session'] // TODO: use context.session, remove in breaking change
8
- listKey: ListTypeInfo['key']
9
- }
10
-
11
- export type AccessOperation = 'create' | 'query' | 'update' | 'delete'
12
- export type FilterOperation = 'query' | 'update' | 'delete'
13
- export type ItemOperation = 'create' | 'update' | 'delete'
14
-
15
- export type ListOperationAccessControl<
16
- Operation extends AccessOperation,
17
- ListTypeInfo extends BaseListTypeInfo,
18
- > = (args: BaseAccessArgs<ListTypeInfo> & { operation: Operation }) => MaybePromise<boolean>
19
-
20
- export type ListFilterAccessControl<
21
- Operation extends FilterOperation,
22
- ListTypeInfo extends BaseListTypeInfo,
23
- > = (
24
- args: BaseAccessArgs<ListTypeInfo> & { operation: Operation }
25
- ) => MaybePromise<boolean | ListTypeInfo['inputs']['where']>
26
-
27
- export type ListItemAccessControl<
28
- Operation extends ItemOperation,
29
- ListTypeInfo extends BaseListTypeInfo,
30
- > = (
31
- args: BaseAccessArgs<ListTypeInfo> &
32
- {
33
- create: {
34
- operation: 'create'
35
-
36
- /**
37
- * The input passed in from the GraphQL API
38
- */
39
- inputData: ListTypeInfo['inputs']['create']
40
- }
41
- update: {
42
- operation: 'update'
43
-
44
- /**
45
- * The input passed in from the GraphQL API
46
- */
47
- inputData: ListTypeInfo['inputs']['update']
48
-
49
- /**
50
- * The item being updated
51
- */
52
- item: ListTypeInfo['item']
53
- }
54
- delete: {
55
- operation: 'delete'
56
-
57
- /**
58
- * The item being deleted
59
- */
60
- item: ListTypeInfo['item']
61
- }
62
- }[Operation]
63
- ) => MaybePromise<boolean>
64
-
65
- export type CreateListItemAccessControl<ListTypeInfo extends BaseListTypeInfo> =
66
- ListItemAccessControl<'create', ListTypeInfo>
67
- export type UpdateListItemAccessControl<ListTypeInfo extends BaseListTypeInfo> =
68
- ListItemAccessControl<'update', ListTypeInfo>
69
- export type DeleteListItemAccessControl<ListTypeInfo extends BaseListTypeInfo> =
70
- ListItemAccessControl<'delete', ListTypeInfo>
71
-
72
- type ListAccessControlFunction<ListTypeInfo extends BaseListTypeInfo> = (
73
- args: BaseAccessArgs<ListTypeInfo> & { operation: AccessOperation }
74
- ) => MaybePromise<boolean>
75
-
76
- type ListAccessControlObject<ListTypeInfo extends BaseListTypeInfo> = {
77
- // these functions should return `true` if access is allowed or `false` if access is denied.
78
- operation:
79
- | ListOperationAccessControl<AccessOperation, ListTypeInfo>
80
- | {
81
- query: ListOperationAccessControl<'query', ListTypeInfo>
82
- create: ListOperationAccessControl<'create', ListTypeInfo>
83
- update: ListOperationAccessControl<'update', ListTypeInfo>
84
- delete: ListOperationAccessControl<'delete', ListTypeInfo>
85
- }
86
-
87
- // The 'filter' rules can return either:
88
- // - a filter. In this case, the operation can proceed, but the filter will be additionally applied when updating/reading/deleting
89
- // which may make it appear that some of the items don't exist.
90
- // - boolean true/false. If false, treated as a filter that never matches.
91
- filter?: {
92
- query?: ListFilterAccessControl<'query', ListTypeInfo>
93
- // create?: not supported
94
- update?: ListFilterAccessControl<'update', ListTypeInfo>
95
- delete?: ListFilterAccessControl<'delete', ListTypeInfo>
96
- }
97
-
98
- // These rules are applied to each item being operated on individually. They return `true` or `false`,
99
- // and if false, an access denied error will be returned for the individual operation.
100
- item?: {
101
- // read?: not supported // TODO: why not
102
- create?: ListItemAccessControl<'create', ListTypeInfo>
103
- update?: ListItemAccessControl<'update', ListTypeInfo>
104
- delete?: ListItemAccessControl<'delete', ListTypeInfo>
105
- }
106
- }
107
-
108
- // List level access control lets you set permissions on the autogenerated CRUD API for each list.
109
- //
110
- // * `operation` access lets you check the information in the `context` and `session` objects to decide if the
111
- // user is allow to access the list.
112
- // * `filter` access lets you provide a GraphQL filter which defines the items the user is allowed to access.
113
- // * `item` access lets you write a function which inspects the provided input data and the existing object (if it exists)
114
- // and make a decision based on this extra data.
115
- //
116
- // If access is denied due to any of the access control methods then the following response will be returned from the GraphQL API:
117
- // Mutations:
118
- // - Single operations will return `null` and return an access denied error
119
- // - Multi operations will return a data array with `null` values for the items which have access denied.
120
- // Access denied errors will be return for each `null` items.
121
- // Queries:
122
- // - Single item queries will return `null` with no errors.
123
- // - Many item queries will filter out those items which have access denied, with no errors.
124
- // - Count queries will only count those items for which access is not denied, with no errors.
125
- //
126
- export type ListAccessControl<ListTypeInfo extends BaseListTypeInfo> =
127
- | ListAccessControlFunction<ListTypeInfo>
128
- | ListAccessControlObject<ListTypeInfo>
129
-
130
- // Field Access
131
- export type FieldAccessControlFunction<Args> = (args: Args) => MaybePromise<boolean>
132
-
133
- export type FieldCreateItemAccessArgs<ListTypeInfo extends BaseListTypeInfo> =
134
- BaseAccessArgs<ListTypeInfo> & {
135
- operation: 'create'
136
- fieldKey: string
137
- /**
138
- * The input passed in from the GraphQL API
139
- */
140
- inputData: ListTypeInfo['inputs']['create']
141
- }
142
-
143
- export type FieldReadItemAccessArgs<ListTypeInfo extends BaseListTypeInfo> =
144
- BaseAccessArgs<ListTypeInfo> & {
145
- operation: 'read'
146
- fieldKey: string
147
- /**
148
- * The item being read
149
- */
150
- item: ListTypeInfo['item']
151
- }
152
-
153
- export type FieldUpdateItemAccessArgs<ListTypeInfo extends BaseListTypeInfo> =
154
- BaseAccessArgs<ListTypeInfo> & {
155
- operation: 'update'
156
- fieldKey: string
157
- /**
158
- * The item being updated
159
- */
160
- item: ListTypeInfo['item']
161
- /**
162
- * The input passed in from the GraphQL API
163
- */
164
- inputData: ListTypeInfo['inputs']['update']
165
- }
166
-
167
- export type FieldAccessControl<ListTypeInfo extends BaseListTypeInfo> =
168
- | FieldAccessControlFunction<
169
- | FieldReadItemAccessArgs<ListTypeInfo>
170
- | FieldCreateItemAccessArgs<ListTypeInfo>
171
- | FieldUpdateItemAccessArgs<ListTypeInfo>
172
- // delete: not supported
173
- >
174
- | {
175
- read?: FieldAccessControlFunction<FieldReadItemAccessArgs<ListTypeInfo>>
176
- create?: FieldAccessControlFunction<FieldCreateItemAccessArgs<ListTypeInfo>>
177
- update?: FieldAccessControlFunction<FieldUpdateItemAccessArgs<ListTypeInfo>>
178
- // delete: not supported
179
- }
180
-
181
- // Action Access
182
- export type ActionAccessControlFunction<ListTypeInfo extends BaseListTypeInfo> = (
183
- args: BaseAccessArgs<ListTypeInfo> & {
184
- actionKey: string
185
- }
186
- ) => MaybePromise<boolean>
1
+ import type { NixxieContext } from '../context'
2
+ import type { BaseCollectionTypeInfo } from '../type-info'
3
+ import type { MaybePromise } from '../utils'
4
+
5
+ export type BaseAccessArgs<CollectionTypeInfo extends BaseCollectionTypeInfo> = {
6
+ context: NixxieContext<CollectionTypeInfo['all']>
7
+ session?: CollectionTypeInfo['all']['session'] // TODO: use context.session, remove in breaking change
8
+ listKey: CollectionTypeInfo['key']
9
+ }
10
+
11
+ export type AccessOperation = 'create' | 'query' | 'update' | 'delete'
12
+ export type FilterOperation = 'query' | 'update' | 'delete'
13
+ export type ItemOperation = 'create' | 'update' | 'delete'
14
+
15
+ export type CollectionOperationAccessControl<
16
+ Operation extends AccessOperation,
17
+ CollectionTypeInfo extends BaseCollectionTypeInfo,
18
+ > = (args: BaseAccessArgs<CollectionTypeInfo> & { operation: Operation }) => MaybePromise<boolean>
19
+
20
+ export type CollectionFilterAccessControl<
21
+ Operation extends FilterOperation,
22
+ CollectionTypeInfo extends BaseCollectionTypeInfo,
23
+ > = (
24
+ args: BaseAccessArgs<CollectionTypeInfo> & { operation: Operation }
25
+ ) => MaybePromise<boolean | CollectionTypeInfo['inputs']['where']>
26
+
27
+ export type CollectionItemAccessControl<
28
+ Operation extends ItemOperation,
29
+ CollectionTypeInfo extends BaseCollectionTypeInfo,
30
+ > = (
31
+ args: BaseAccessArgs<CollectionTypeInfo> &
32
+ {
33
+ create: {
34
+ operation: 'create'
35
+
36
+ /**
37
+ * The input passed in from the GraphQL API
38
+ */
39
+ inputData: CollectionTypeInfo['inputs']['create']
40
+ }
41
+ update: {
42
+ operation: 'update'
43
+
44
+ /**
45
+ * The input passed in from the GraphQL API
46
+ */
47
+ inputData: CollectionTypeInfo['inputs']['update']
48
+
49
+ /**
50
+ * The item being updated
51
+ */
52
+ item: CollectionTypeInfo['item']
53
+ }
54
+ delete: {
55
+ operation: 'delete'
56
+
57
+ /**
58
+ * The item being deleted
59
+ */
60
+ item: CollectionTypeInfo['item']
61
+ }
62
+ }[Operation]
63
+ ) => MaybePromise<boolean>
64
+
65
+ export type CreateCollectionItemAccessControl<CollectionTypeInfo extends BaseCollectionTypeInfo> =
66
+ CollectionItemAccessControl<'create', CollectionTypeInfo>
67
+ export type UpdateCollectionItemAccessControl<CollectionTypeInfo extends BaseCollectionTypeInfo> =
68
+ CollectionItemAccessControl<'update', CollectionTypeInfo>
69
+ export type DeleteCollectionItemAccessControl<CollectionTypeInfo extends BaseCollectionTypeInfo> =
70
+ CollectionItemAccessControl<'delete', CollectionTypeInfo>
71
+
72
+ type CollectionAccessControlFunction<CollectionTypeInfo extends BaseCollectionTypeInfo> = (
73
+ args: BaseAccessArgs<CollectionTypeInfo> & { operation: AccessOperation }
74
+ ) => MaybePromise<boolean>
75
+
76
+ type CollectionAccessControlObject<CollectionTypeInfo extends BaseCollectionTypeInfo> = {
77
+ // these functions should return `true` if access is allowed or `false` if access is denied.
78
+ operation:
79
+ | CollectionOperationAccessControl<AccessOperation, CollectionTypeInfo>
80
+ | {
81
+ query: CollectionOperationAccessControl<'query', CollectionTypeInfo>
82
+ create: CollectionOperationAccessControl<'create', CollectionTypeInfo>
83
+ update: CollectionOperationAccessControl<'update', CollectionTypeInfo>
84
+ delete: CollectionOperationAccessControl<'delete', CollectionTypeInfo>
85
+ }
86
+
87
+ // The 'filter' rules can return either:
88
+ // - a filter. In this case, the operation can proceed, but the filter will be additionally applied when updating/reading/deleting
89
+ // which may make it appear that some of the items don't exist.
90
+ // - boolean true/false. If false, treated as a filter that never matches.
91
+ filter?: {
92
+ query?: CollectionFilterAccessControl<'query', CollectionTypeInfo>
93
+ // create?: not supported
94
+ update?: CollectionFilterAccessControl<'update', CollectionTypeInfo>
95
+ delete?: CollectionFilterAccessControl<'delete', CollectionTypeInfo>
96
+ }
97
+
98
+ // These rules are applied to each item being operated on individually. They return `true` or `false`,
99
+ // and if false, an access denied error will be returned for the individual operation.
100
+ item?: {
101
+ // read?: not supported // TODO: why not
102
+ create?: CollectionItemAccessControl<'create', CollectionTypeInfo>
103
+ update?: CollectionItemAccessControl<'update', CollectionTypeInfo>
104
+ delete?: CollectionItemAccessControl<'delete', CollectionTypeInfo>
105
+ }
106
+ }
107
+
108
+ // List level access control lets you set permissions on the autogenerated CRUD API for each list.
109
+ //
110
+ // * `operation` access lets you check the information in the `context` and `session` objects to decide if the
111
+ // user is allow to access the list.
112
+ // * `filter` access lets you provide a GraphQL filter which defines the items the user is allowed to access.
113
+ // * `item` access lets you write a function which inspects the provided input data and the existing object (if it exists)
114
+ // and make a decision based on this extra data.
115
+ //
116
+ // If access is denied due to any of the access control methods then the following response will be returned from the GraphQL API:
117
+ // Mutations:
118
+ // - Single operations will return `null` and return an access denied error
119
+ // - Multi operations will return a data array with `null` values for the items which have access denied.
120
+ // Access denied errors will be return for each `null` items.
121
+ // Queries:
122
+ // - Single item queries will return `null` with no errors.
123
+ // - Many item queries will filter out those items which have access denied, with no errors.
124
+ // - Count queries will only count those items for which access is not denied, with no errors.
125
+ //
126
+ export type CollectionAccessControl<CollectionTypeInfo extends BaseCollectionTypeInfo> =
127
+ | CollectionAccessControlFunction<CollectionTypeInfo>
128
+ | CollectionAccessControlObject<CollectionTypeInfo>
129
+
130
+ // Field Access
131
+ export type FieldAccessControlFunction<Args> = (args: Args) => MaybePromise<boolean>
132
+
133
+ export type FieldCreateItemAccessArgs<CollectionTypeInfo extends BaseCollectionTypeInfo> =
134
+ BaseAccessArgs<CollectionTypeInfo> & {
135
+ operation: 'create'
136
+ fieldKey: string
137
+ /**
138
+ * The input passed in from the GraphQL API
139
+ */
140
+ inputData: CollectionTypeInfo['inputs']['create']
141
+ }
142
+
143
+ export type FieldReadItemAccessArgs<CollectionTypeInfo extends BaseCollectionTypeInfo> =
144
+ BaseAccessArgs<CollectionTypeInfo> & {
145
+ operation: 'read'
146
+ fieldKey: string
147
+ /**
148
+ * The item being read
149
+ */
150
+ item: CollectionTypeInfo['item']
151
+ }
152
+
153
+ export type FieldUpdateItemAccessArgs<CollectionTypeInfo extends BaseCollectionTypeInfo> =
154
+ BaseAccessArgs<CollectionTypeInfo> & {
155
+ operation: 'update'
156
+ fieldKey: string
157
+ /**
158
+ * The item being updated
159
+ */
160
+ item: CollectionTypeInfo['item']
161
+ /**
162
+ * The input passed in from the GraphQL API
163
+ */
164
+ inputData: CollectionTypeInfo['inputs']['update']
165
+ }
166
+
167
+ export type FieldAccessControl<CollectionTypeInfo extends BaseCollectionTypeInfo> =
168
+ | FieldAccessControlFunction<
169
+ | FieldReadItemAccessArgs<CollectionTypeInfo>
170
+ | FieldCreateItemAccessArgs<CollectionTypeInfo>
171
+ | FieldUpdateItemAccessArgs<CollectionTypeInfo>
172
+ // delete: not supported
173
+ >
174
+ | {
175
+ read?: FieldAccessControlFunction<FieldReadItemAccessArgs<CollectionTypeInfo>>
176
+ create?: FieldAccessControlFunction<FieldCreateItemAccessArgs<CollectionTypeInfo>>
177
+ update?: FieldAccessControlFunction<FieldUpdateItemAccessArgs<CollectionTypeInfo>>
178
+ // delete: not supported
179
+ }
180
+
181
+ // Action Access
182
+ export type ActionAccessControlFunction<CollectionTypeInfo extends BaseCollectionTypeInfo> = (
183
+ args: BaseAccessArgs<CollectionTypeInfo> & {
184
+ actionKey: string
185
+ }
186
+ ) => MaybePromise<boolean>
@@ -1,96 +1,96 @@
1
- import type { CacheHint } from '@apollo/cache-control-types'
2
- import type { NixxieContext } from '..'
3
- import type { FieldTypeFunc } from '../next-fields'
4
- import type { BaseListTypeInfo } from '../type-info'
5
- import type { FieldAccessControl } from './access-control'
6
- import type { FieldHooks } from './hooks'
7
- import type {
8
- MaybeBooleanSessionFunctionWithFilter,
9
- MaybeFieldFunction,
10
- MaybeItemFieldFunction,
11
- MaybeItemFieldFunctionWithFilter,
12
- MaybeSessionFunction,
13
- MaybeSessionFunctionWithFilter,
14
- } from './lists'
15
-
16
- export type BaseFields<ListTypeInfo extends BaseListTypeInfo> = {
17
- [key: string]: FieldTypeFunc<ListTypeInfo>
18
- }
19
-
20
- export type FilterOrderArgs<ListTypeInfo extends BaseListTypeInfo> = {
21
- context: NixxieContext<ListTypeInfo['all']>
22
- session?: ListTypeInfo['all']['session']
23
- listKey: ListTypeInfo['key']
24
- fieldKey: ListTypeInfo['fields']
25
- }
26
-
27
- export type BaseFieldTypeInfo = {
28
- item: any
29
- inputs: {
30
- create: any
31
- update: any
32
- where: any
33
- uniqueWhere: any
34
- orderBy: any
35
- }
36
- prisma: {
37
- create: any
38
- update: any
39
- }
40
- }
41
-
42
- export type CommonFieldConfig<
43
- ListTypeInfo extends BaseListTypeInfo,
44
- FieldTypeInfo extends BaseFieldTypeInfo,
45
- > = {
46
- access?: FieldAccessControl<ListTypeInfo>
47
- hooks?: FieldHooks<ListTypeInfo, FieldTypeInfo>
48
- ui?: {
49
- label?: string
50
- description?: string
51
- views?: string
52
- createView?: {
53
- fieldMode?: MaybeSessionFunctionWithFilter<'edit' | 'hidden', 'hidden', ListTypeInfo>
54
- isRequired?: MaybeBooleanSessionFunctionWithFilter<ListTypeInfo>
55
- }
56
- itemView?: {
57
- fieldMode?: MaybeItemFieldFunctionWithFilter<
58
- 'edit' | 'read' | 'hidden',
59
- 'read' | 'hidden',
60
- ListTypeInfo,
61
- FieldTypeInfo
62
- >
63
- fieldPosition?: MaybeItemFieldFunction<'form' | 'sidebar', ListTypeInfo, FieldTypeInfo>
64
- isRequired?: MaybeBooleanSessionFunctionWithFilter<ListTypeInfo>
65
- }
66
- listView?: {
67
- fieldMode?: MaybeSessionFunction<'read' | 'hidden', ListTypeInfo>
68
- }
69
- }
70
- graphql?: {
71
- cacheHint?: CacheHint
72
- isNonNull?:
73
- | boolean
74
- | {
75
- // whether this field is non-nullable on the {List} GraphQL type
76
- read?: boolean
77
- // whether this field is non-nullable on the {List}CreateInput GraphQL type
78
- create?: boolean
79
- // whether this field is non-nullable on the {List}UpdateInput GraphQL type
80
- update?: boolean
81
- }
82
-
83
- omit?:
84
- | boolean
85
- | {
86
- // whether this field is omitted from the {List} GraphQL type
87
- read?: boolean
88
- // whether this field is omitted from the {List}CreateInput GraphQL type
89
- create?: boolean
90
- // whether this field is omitted from the {List}UpdateInput GraphQL type
91
- update?: boolean
92
- }
93
- }
94
- isFilterable?: MaybeFieldFunction<ListTypeInfo>
95
- isOrderable?: MaybeFieldFunction<ListTypeInfo>
96
- }
1
+ import type { CacheHint } from '@apollo/cache-control-types'
2
+ import type { NixxieContext } from '..'
3
+ import type { FieldTypeFunc } from '../next-fields'
4
+ import type { BaseCollectionTypeInfo } from '../type-info'
5
+ import type { FieldAccessControl } from './access-control'
6
+ import type { FieldHooks } from './hooks'
7
+ import type {
8
+ MaybeBooleanSessionFunctionWithFilter,
9
+ MaybeFieldFunction,
10
+ MaybeItemFieldFunction,
11
+ MaybeItemFieldFunctionWithFilter,
12
+ MaybeSessionFunction,
13
+ MaybeSessionFunctionWithFilter,
14
+ } from './lists'
15
+
16
+ export type BaseFields<CollectionTypeInfo extends BaseCollectionTypeInfo> = {
17
+ [key: string]: FieldTypeFunc<CollectionTypeInfo>
18
+ }
19
+
20
+ export type FilterOrderArgs<CollectionTypeInfo extends BaseCollectionTypeInfo> = {
21
+ context: NixxieContext<CollectionTypeInfo['all']>
22
+ session?: CollectionTypeInfo['all']['session']
23
+ listKey: CollectionTypeInfo['key']
24
+ fieldKey: CollectionTypeInfo['fields']
25
+ }
26
+
27
+ export type BaseFieldTypeInfo = {
28
+ item: any
29
+ inputs: {
30
+ create: any
31
+ update: any
32
+ where: any
33
+ uniqueWhere: any
34
+ orderBy: any
35
+ }
36
+ prisma: {
37
+ create: any
38
+ update: any
39
+ }
40
+ }
41
+
42
+ export type CommonFieldConfig<
43
+ CollectionTypeInfo extends BaseCollectionTypeInfo,
44
+ FieldTypeInfo extends BaseFieldTypeInfo,
45
+ > = {
46
+ access?: FieldAccessControl<CollectionTypeInfo>
47
+ hooks?: FieldHooks<CollectionTypeInfo, FieldTypeInfo>
48
+ ui?: {
49
+ label?: string
50
+ description?: string
51
+ views?: string
52
+ createView?: {
53
+ fieldMode?: MaybeSessionFunctionWithFilter<'edit' | 'hidden', 'hidden', CollectionTypeInfo>
54
+ isRequired?: MaybeBooleanSessionFunctionWithFilter<CollectionTypeInfo>
55
+ }
56
+ itemView?: {
57
+ fieldMode?: MaybeItemFieldFunctionWithFilter<
58
+ 'edit' | 'read' | 'hidden',
59
+ 'read' | 'hidden',
60
+ CollectionTypeInfo,
61
+ FieldTypeInfo
62
+ >
63
+ fieldPosition?: MaybeItemFieldFunction<'form' | 'sidebar', CollectionTypeInfo, FieldTypeInfo>
64
+ isRequired?: MaybeBooleanSessionFunctionWithFilter<CollectionTypeInfo>
65
+ }
66
+ listView?: {
67
+ fieldMode?: MaybeSessionFunction<'read' | 'hidden', CollectionTypeInfo>
68
+ }
69
+ }
70
+ graphql?: {
71
+ cacheHint?: CacheHint
72
+ isNonNull?:
73
+ | boolean
74
+ | {
75
+ // whether this field is non-nullable on the {List} GraphQL type
76
+ read?: boolean
77
+ // whether this field is non-nullable on the {List}CreateInput GraphQL type
78
+ create?: boolean
79
+ // whether this field is non-nullable on the {List}UpdateInput GraphQL type
80
+ update?: boolean
81
+ }
82
+
83
+ omit?:
84
+ | boolean
85
+ | {
86
+ // whether this field is omitted from the {List} GraphQL type
87
+ read?: boolean
88
+ // whether this field is omitted from the {List}CreateInput GraphQL type
89
+ create?: boolean
90
+ // whether this field is omitted from the {List}UpdateInput GraphQL type
91
+ update?: boolean
92
+ }
93
+ }
94
+ isFilterable?: MaybeFieldFunction<CollectionTypeInfo>
95
+ isOrderable?: MaybeFieldFunction<CollectionTypeInfo>
96
+ }