@nixxie-cms/core 1.0.0 → 1.0.2

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 (187) hide show
  1. package/README.md +2 -2
  2. package/admin-ui/components/dist/nixxie-cms-core-admin-ui-components.cjs.js +4 -4
  3. package/admin-ui/components/dist/nixxie-cms-core-admin-ui-components.esm.js +4 -4
  4. package/admin-ui/context/dist/nixxie-cms-core-admin-ui-context.cjs.js +2 -2
  5. package/admin-ui/context/dist/nixxie-cms-core-admin-ui-context.esm.js +2 -2
  6. package/context/dist/nixxie-cms-core-context.cjs.js +2 -2
  7. package/context/dist/nixxie-cms-core-context.esm.js +2 -2
  8. package/dist/{CreateItemDialog-33335548.esm.js → CreateItemDialog-7008b050.esm.js} +1 -1
  9. package/dist/{CreateItemDialog-56cf59b7.cjs.js → CreateItemDialog-a0cab315.cjs.js} +1 -1
  10. package/dist/{PageContainer-7db73317.esm.js → PageContainer-5ae731cc.esm.js} +25 -18
  11. package/dist/{PageContainer-27c27f10.cjs.js → PageContainer-abd7159f.cjs.js} +25 -18
  12. package/dist/{admin-meta-graphql-6f7f5331.esm.js → admin-meta-graphql-0e6e606e.esm.js} +1 -1
  13. package/dist/{admin-meta-graphql-c8f926e9.cjs.js → admin-meta-graphql-306c224a.cjs.js} +1 -1
  14. package/dist/{context-3132c3ed.esm.js → context-af9957ed.esm.js} +2 -2
  15. package/dist/{context-e7a45152.cjs.js → context-b5204629.cjs.js} +2 -2
  16. package/dist/declarations/src/admin-ui/components/Navigation.d.ts.map +1 -1
  17. package/dist/declarations/src/admin-ui/components/PageContainer.d.ts.map +1 -1
  18. package/dist/declarations/src/helpers.d.ts.map +1 -1
  19. package/dist/declarations/src/index.d.ts +1 -0
  20. package/dist/declarations/src/index.d.ts.map +1 -1
  21. package/dist/declarations/src/internal-unstable/admin-ui/id-field-view.d.ts.map +1 -0
  22. package/dist/declarations/src/internal-unstable/admin-ui/pages/App/index.d.ts.map +1 -0
  23. package/dist/declarations/src/internal-unstable/admin-ui/pages/CreateItemPage/index.d.ts.map +1 -0
  24. package/dist/declarations/src/internal-unstable/admin-ui/pages/HomePage/index.d.ts.map +1 -0
  25. package/dist/declarations/src/internal-unstable/admin-ui/pages/ItemPage/index.d.ts.map +1 -0
  26. package/dist/declarations/src/internal-unstable/admin-ui/pages/ListPage/index.d.ts.map +1 -0
  27. package/dist/declarations/src/internal-unstable/admin-ui/pages/NoAccessPage/index.d.ts.map +1 -0
  28. package/dist/declarations/src/internal-unstable/artifacts.d.ts.map +1 -0
  29. package/dist/declarations/src/lib/core/initialise-lists.d.ts +1 -1
  30. package/dist/declarations/src/schema.d.ts.map +1 -1
  31. package/dist/declarations/src/types/config/index.d.ts +60 -1
  32. package/dist/declarations/src/types/config/index.d.ts.map +1 -1
  33. package/dist/declarations/src/types/config/lists.d.ts +4 -4
  34. package/dist/declarations/src/types/context.d.ts +150 -0
  35. package/dist/declarations/src/types/context.d.ts.map +1 -1
  36. package/dist/declarations/src/types/next-fields.d.ts +1 -1
  37. package/dist/{express-e9ed9a7d.cjs.js → express-455ae20c.cjs.js} +1 -1
  38. package/dist/{express-6743b918.esm.js → express-7559ca2d.esm.js} +1 -1
  39. package/dist/{index-ac01583b.cjs.js → index-89635494.cjs.js} +4 -4
  40. package/dist/{index-24b78415.esm.js → index-baa799e0.esm.js} +4 -4
  41. package/dist/nixxie-cms-core.cjs.js +104 -77
  42. package/dist/nixxie-cms-core.esm.js +104 -77
  43. package/dist/{non-null-graphql-5315718c.esm.js → non-null-graphql-a84ed64d.esm.js} +1 -1
  44. package/dist/{non-null-graphql-17b83ddc.cjs.js → non-null-graphql-add6bb3d.cjs.js} +1 -1
  45. package/dist/{resolve-hooks-66fe8a8e.cjs.js → resolve-hooks-165a9ce2.cjs.js} +1 -1
  46. package/dist/{resolve-hooks-17aafd37.esm.js → resolve-hooks-6813a045.esm.js} +2 -2
  47. package/dist/{system-dfec2f0a.esm.js → system-03e49e4f.esm.js} +8 -4
  48. package/dist/{system-48c5f6df.cjs.js → system-a321642d.cjs.js} +8 -4
  49. package/dist/{useFilter-0b5a1ee6.esm.js → useFilter-9b6db1f9.esm.js} +1 -1
  50. package/dist/{useFilter-1a4e6900.cjs.js → useFilter-acc9d413.cjs.js} +1 -1
  51. package/fields/dist/nixxie-cms-core-fields.cjs.js +16 -16
  52. package/fields/dist/nixxie-cms-core-fields.esm.js +17 -17
  53. package/fields/types/bytes/dist/nixxie-cms-core-fields-types-bytes.cjs.js +3 -3
  54. package/fields/types/bytes/dist/nixxie-cms-core-fields-types-bytes.esm.js +3 -3
  55. package/fields/types/bytes/views/dist/nixxie-cms-core-fields-types-bytes-views.cjs.js +1 -1
  56. package/fields/types/bytes/views/dist/nixxie-cms-core-fields-types-bytes-views.esm.js +1 -1
  57. package/fields/types/password/dist/nixxie-cms-core-fields-types-password.cjs.js +3 -3
  58. package/fields/types/password/dist/nixxie-cms-core-fields-types-password.esm.js +3 -3
  59. package/fields/types/relationship/views/dist/nixxie-cms-core-fields-types-relationship-views.cjs.js +4 -4
  60. package/fields/types/relationship/views/dist/nixxie-cms-core-fields-types-relationship-views.esm.js +4 -4
  61. package/fields/types/select/views/dist/nixxie-cms-core-fields-types-select-views.cjs.js +1 -1
  62. package/fields/types/select/views/dist/nixxie-cms-core-fields-types-select-views.esm.js +1 -1
  63. package/fields/types/text/views/dist/nixxie-cms-core-fields-types-text-views.cjs.js +1 -1
  64. package/fields/types/text/views/dist/nixxie-cms-core-fields-types-text-views.esm.js +1 -1
  65. package/internal-unstable/admin-ui/id-field-view/dist/nixxie-cms-core-internal-unstable-admin-ui-id-field-view.cjs.d.ts +2 -0
  66. package/internal-unstable/admin-ui/id-field-view/dist/nixxie-cms-core-internal-unstable-admin-ui-id-field-view.cjs.js +244 -0
  67. package/internal-unstable/admin-ui/id-field-view/dist/nixxie-cms-core-internal-unstable-admin-ui-id-field-view.esm.js +235 -0
  68. package/internal-unstable/admin-ui/id-field-view/package.json +4 -0
  69. package/internal-unstable/admin-ui/next-config/package.json +4 -0
  70. package/internal-unstable/admin-ui/pages/App/dist/nixxie-cms-core-internal-unstable-admin-ui-pages-App.cjs.d.ts +2 -0
  71. package/internal-unstable/admin-ui/pages/App/dist/nixxie-cms-core-internal-unstable-admin-ui-pages-App.cjs.js +59 -0
  72. package/internal-unstable/admin-ui/pages/App/dist/nixxie-cms-core-internal-unstable-admin-ui-pages-App.esm.js +55 -0
  73. package/internal-unstable/admin-ui/pages/App/package.json +4 -0
  74. package/internal-unstable/admin-ui/pages/CreateItemPage/dist/nixxie-cms-core-internal-unstable-admin-ui-pages-CreateItemPage.cjs.d.ts +2 -0
  75. package/internal-unstable/admin-ui/pages/CreateItemPage/dist/nixxie-cms-core-internal-unstable-admin-ui-pages-CreateItemPage.cjs.js +116 -0
  76. package/internal-unstable/admin-ui/pages/CreateItemPage/dist/nixxie-cms-core-internal-unstable-admin-ui-pages-CreateItemPage.esm.js +112 -0
  77. package/internal-unstable/admin-ui/pages/CreateItemPage/package.json +4 -0
  78. package/internal-unstable/admin-ui/pages/HomePage/dist/nixxie-cms-core-internal-unstable-admin-ui-pages-HomePage.cjs.d.ts +2 -0
  79. package/internal-unstable/admin-ui/pages/HomePage/dist/nixxie-cms-core-internal-unstable-admin-ui-pages-HomePage.cjs.js +336 -0
  80. package/internal-unstable/admin-ui/pages/HomePage/dist/nixxie-cms-core-internal-unstable-admin-ui-pages-HomePage.esm.js +332 -0
  81. package/internal-unstable/admin-ui/pages/HomePage/package.json +4 -0
  82. package/internal-unstable/admin-ui/pages/ItemPage/dist/nixxie-cms-core-internal-unstable-admin-ui-pages-ItemPage.cjs.d.ts +2 -0
  83. package/internal-unstable/admin-ui/pages/ItemPage/dist/nixxie-cms-core-internal-unstable-admin-ui-pages-ItemPage.cjs.js +463 -0
  84. package/internal-unstable/admin-ui/pages/ItemPage/dist/nixxie-cms-core-internal-unstable-admin-ui-pages-ItemPage.esm.js +455 -0
  85. package/internal-unstable/admin-ui/pages/ItemPage/package.json +4 -0
  86. package/internal-unstable/admin-ui/pages/ListPage/dist/nixxie-cms-core-internal-unstable-admin-ui-pages-ListPage.cjs.d.ts +2 -0
  87. package/internal-unstable/admin-ui/pages/ListPage/dist/nixxie-cms-core-internal-unstable-admin-ui-pages-ListPage.cjs.js +1195 -0
  88. package/internal-unstable/admin-ui/pages/ListPage/dist/nixxie-cms-core-internal-unstable-admin-ui-pages-ListPage.esm.js +1187 -0
  89. package/internal-unstable/admin-ui/pages/ListPage/package.json +4 -0
  90. package/internal-unstable/admin-ui/pages/NoAccessPage/dist/nixxie-cms-core-internal-unstable-admin-ui-pages-NoAccessPage.cjs.d.ts +2 -0
  91. package/internal-unstable/admin-ui/pages/NoAccessPage/dist/nixxie-cms-core-internal-unstable-admin-ui-pages-NoAccessPage.cjs.js +40 -0
  92. package/internal-unstable/admin-ui/pages/NoAccessPage/dist/nixxie-cms-core-internal-unstable-admin-ui-pages-NoAccessPage.esm.js +35 -0
  93. package/internal-unstable/admin-ui/pages/NoAccessPage/package.json +4 -0
  94. package/internal-unstable/artifacts/dist/nixxie-cms-core-internal-unstable-artifacts.cjs.d.ts +2 -0
  95. package/internal-unstable/artifacts/dist/nixxie-cms-core-internal-unstable-artifacts.cjs.js +51 -0
  96. package/internal-unstable/artifacts/dist/nixxie-cms-core-internal-unstable-artifacts.esm.js +38 -0
  97. package/internal-unstable/artifacts/package.json +4 -0
  98. package/package.json +44 -44
  99. package/scripts/cli/dist/nixxie-cms-core-scripts-cli.cjs.js +44 -15
  100. package/scripts/cli/dist/nixxie-cms-core-scripts-cli.esm.js +44 -15
  101. package/scripts/dist/nixxie-cms-core-scripts.cjs.js +3 -3
  102. package/scripts/dist/nixxie-cms-core-scripts.esm.js +3 -3
  103. package/src/admin-ui/admin-meta-graphql.ts +168 -168
  104. package/src/admin-ui/components/CommandPalette.tsx +433 -431
  105. package/src/admin-ui/components/Navigation.tsx +389 -385
  106. package/src/admin-ui/components/PageContainer.tsx +311 -310
  107. package/src/admin-ui/components/WelcomeDialog.tsx +1 -1
  108. package/src/admin-ui/context.tsx +338 -338
  109. package/src/admin-ui/templates/app.ts +60 -60
  110. package/src/admin-ui/templates/create-item.ts +5 -5
  111. package/src/admin-ui/templates/home.ts +2 -2
  112. package/src/admin-ui/templates/item.tsx +5 -5
  113. package/src/admin-ui/templates/list.tsx +5 -5
  114. package/src/admin-ui/templates/next-config.ts +29 -0
  115. package/src/admin-ui/templates/no-access.ts +7 -7
  116. package/src/fields/types/bigInt/index.ts +181 -181
  117. package/src/fields/types/bytes/index.ts +275 -275
  118. package/src/fields/types/calendarDay/index.ts +194 -194
  119. package/src/fields/types/checkbox/index.ts +76 -76
  120. package/src/fields/types/decimal/index.ts +182 -182
  121. package/src/fields/types/file/index.ts +168 -168
  122. package/src/fields/types/float/index.ts +133 -133
  123. package/src/fields/types/image/index.ts +244 -244
  124. package/src/fields/types/integer/index.ts +156 -156
  125. package/src/fields/types/json/index.ts +77 -77
  126. package/src/fields/types/multiselect/index.ts +212 -212
  127. package/src/fields/types/password/index.ts +241 -241
  128. package/src/fields/types/relationship/index.ts +381 -381
  129. package/src/fields/types/relationship/views/RelationshipTable.tsx +190 -190
  130. package/src/fields/types/select/index.ts +226 -226
  131. package/src/fields/types/text/index.ts +207 -207
  132. package/src/fields/types/timestamp/index.ts +116 -116
  133. package/src/fields/types/virtual/index.ts +108 -108
  134. package/src/helpers.ts +342 -316
  135. package/src/index.ts +4 -0
  136. package/src/{___internal-do-not-use-will-break-in-patch → internal-unstable}/admin-ui/id-field-view.tsx +167 -167
  137. package/src/{___internal-do-not-use-will-break-in-patch → internal-unstable}/admin-ui/pages/App/index.tsx +22 -22
  138. package/src/{___internal-do-not-use-will-break-in-patch → internal-unstable}/admin-ui/pages/CreateItemPage/index.tsx +71 -71
  139. package/src/{___internal-do-not-use-will-break-in-patch → internal-unstable}/admin-ui/pages/HomePage/index.tsx +333 -333
  140. package/src/{___internal-do-not-use-will-break-in-patch → internal-unstable}/admin-ui/pages/ItemPage/common.tsx +358 -358
  141. package/src/{___internal-do-not-use-will-break-in-patch → internal-unstable}/admin-ui/pages/ItemPage/index.tsx +483 -483
  142. package/src/{___internal-do-not-use-will-break-in-patch → internal-unstable}/admin-ui/pages/ListPage/FilterAdd.tsx +221 -221
  143. package/src/{___internal-do-not-use-will-break-in-patch → internal-unstable}/admin-ui/pages/ListPage/PaginationControls.tsx +170 -170
  144. package/src/{___internal-do-not-use-will-break-in-patch → internal-unstable}/admin-ui/pages/ListPage/Tag.tsx +72 -72
  145. package/src/{___internal-do-not-use-will-break-in-patch → internal-unstable}/admin-ui/pages/ListPage/index.tsx +1006 -1006
  146. package/src/{___internal-do-not-use-will-break-in-patch → internal-unstable}/admin-ui/pages/NoAccessPage/index.tsx +24 -24
  147. package/src/{___internal-do-not-use-will-break-in-patch → internal-unstable}/artifacts.ts +5 -5
  148. package/src/lib/context/createContext.ts +165 -161
  149. package/src/lib/core/initialise-lists.ts +1097 -1097
  150. package/src/lib/id-field.ts +214 -214
  151. package/src/lib/telemetry.ts +342 -342
  152. package/src/schema.ts +237 -233
  153. package/src/scripts/telemetry.ts +1 -1
  154. package/src/types/config/index.ts +400 -333
  155. package/src/types/config/lists.ts +4 -4
  156. package/src/types/context.ts +700 -530
  157. package/src/types/next-fields.ts +499 -499
  158. package/src/types/telemetry.ts +51 -51
  159. package/tests/telemetry.test.ts +361 -361
  160. package/CHANGELOG.md +0 -3158
  161. package/___internal-do-not-use-will-break-in-patch/admin-ui/id-field-view/package.json +0 -4
  162. package/___internal-do-not-use-will-break-in-patch/admin-ui/next-config/package.json +0 -4
  163. package/___internal-do-not-use-will-break-in-patch/admin-ui/pages/App/package.json +0 -4
  164. package/___internal-do-not-use-will-break-in-patch/admin-ui/pages/CreateItemPage/package.json +0 -4
  165. package/___internal-do-not-use-will-break-in-patch/admin-ui/pages/HomePage/package.json +0 -4
  166. package/___internal-do-not-use-will-break-in-patch/admin-ui/pages/ItemPage/package.json +0 -4
  167. package/___internal-do-not-use-will-break-in-patch/admin-ui/pages/ListPage/package.json +0 -4
  168. package/___internal-do-not-use-will-break-in-patch/admin-ui/pages/NoAccessPage/package.json +0 -4
  169. package/___internal-do-not-use-will-break-in-patch/artifacts/package.json +0 -4
  170. package/dist/declarations/src/___internal-do-not-use-will-break-in-patch/admin-ui/id-field-view.d.ts.map +0 -1
  171. package/dist/declarations/src/___internal-do-not-use-will-break-in-patch/admin-ui/pages/App/index.d.ts.map +0 -1
  172. package/dist/declarations/src/___internal-do-not-use-will-break-in-patch/admin-ui/pages/CreateItemPage/index.d.ts.map +0 -1
  173. package/dist/declarations/src/___internal-do-not-use-will-break-in-patch/admin-ui/pages/HomePage/index.d.ts.map +0 -1
  174. package/dist/declarations/src/___internal-do-not-use-will-break-in-patch/admin-ui/pages/ItemPage/index.d.ts.map +0 -1
  175. package/dist/declarations/src/___internal-do-not-use-will-break-in-patch/admin-ui/pages/ListPage/index.d.ts.map +0 -1
  176. package/dist/declarations/src/___internal-do-not-use-will-break-in-patch/admin-ui/pages/NoAccessPage/index.d.ts.map +0 -1
  177. package/dist/declarations/src/___internal-do-not-use-will-break-in-patch/artifacts.d.ts.map +0 -1
  178. /package/dist/{common-1a350e11.cjs.js → common-5933f758.cjs.js} +0 -0
  179. /package/dist/{common-29fc82e6.esm.js → common-ea5c441a.esm.js} +0 -0
  180. /package/dist/declarations/src/{___internal-do-not-use-will-break-in-patch → internal-unstable}/admin-ui/id-field-view.d.ts +0 -0
  181. /package/dist/declarations/src/{___internal-do-not-use-will-break-in-patch → internal-unstable}/admin-ui/pages/App/index.d.ts +0 -0
  182. /package/dist/declarations/src/{___internal-do-not-use-will-break-in-patch → internal-unstable}/admin-ui/pages/CreateItemPage/index.d.ts +0 -0
  183. /package/dist/declarations/src/{___internal-do-not-use-will-break-in-patch → internal-unstable}/admin-ui/pages/HomePage/index.d.ts +0 -0
  184. /package/dist/declarations/src/{___internal-do-not-use-will-break-in-patch → internal-unstable}/admin-ui/pages/ItemPage/index.d.ts +0 -0
  185. /package/dist/declarations/src/{___internal-do-not-use-will-break-in-patch → internal-unstable}/admin-ui/pages/ListPage/index.d.ts +0 -0
  186. /package/dist/declarations/src/{___internal-do-not-use-will-break-in-patch → internal-unstable}/admin-ui/pages/NoAccessPage/index.d.ts +0 -0
  187. /package/dist/declarations/src/{___internal-do-not-use-will-break-in-patch → internal-unstable}/artifacts.d.ts +0 -0
@@ -1,275 +1,275 @@
1
- import {
2
- type BaseListTypeInfo,
3
- type CommonFieldConfig,
4
- type FieldTypeFunc,
5
- fieldType,
6
- orderDirectionEnum,
7
- } from '../../../types'
8
- import { g } from '../../..'
9
- import { makeValidateHook, defaultIsRequired } from '../../non-null-graphql'
10
- import { weakMemoize } from '../../../lib/core/utils'
11
- import { GraphQLError } from 'graphql'
12
- import type {
13
- GArg,
14
- GInputObjectType,
15
- GList,
16
- GNonNull,
17
- GScalarType,
18
- InferValueFromInputType,
19
- } from '@graphql-ts/schema'
20
-
21
- export type FieldTypeInfo = {
22
- item: Uint8Array | null
23
- inputs: {
24
- create: Uint8Array | null | undefined
25
- update: Uint8Array | null | undefined
26
- where: InferValueFromInputType<BytesFilterType> | undefined
27
- uniqueWhere: Uint8Array | null | undefined
28
- orderBy: undefined
29
- }
30
- prisma: {
31
- create: Uint8Array | null | undefined
32
- update: Uint8Array | null | undefined
33
- }
34
- }
35
-
36
- export type BytesFieldConfig<ListTypeInfo extends BaseListTypeInfo> = CommonFieldConfig<
37
- ListTypeInfo,
38
- FieldTypeInfo
39
- > & {
40
- isIndexed?: boolean | 'unique'
41
- graphql?: {
42
- scalar?: GScalarType<Uint8Array, string>
43
- }
44
- validation?: {
45
- /**
46
- * Makes the field disallow null values. It does not constrain the length of the value.
47
- */
48
- isRequired?: boolean
49
- /**
50
- * Specifies the minimum and maximum length of the value in _bytes_. It does _not_ represent the length in the encoded form.
51
- */
52
- length?: { min?: number; max?: number }
53
- }
54
- defaultValue?: Uint8Array | null
55
- db?: {
56
- isNullable?: boolean
57
- map?: string
58
- extendPrismaSchema?: (field: string) => string
59
- /**
60
- * The underlying database type.
61
- * Only some of the types are supported on PostgreSQL and MySQL.
62
- * The native type is not customisable on SQLite.
63
- * See Prisma's documentation for more information about the supported types.
64
- *
65
- * https://www.prisma.io/docs/orm/reference/prisma-schema-reference#bytes
66
- */
67
- nativeType?: string
68
- }
69
- }
70
-
71
- export type TextFieldMeta = {
72
- isNullable: boolean
73
- defaultValue: string | null
74
- }
75
-
76
- export function bytes<ListTypeInfo extends BaseListTypeInfo>(
77
- config: BytesFieldConfig<ListTypeInfo> = {}
78
- ): FieldTypeFunc<ListTypeInfo> {
79
- const { defaultValue = null, isIndexed, validation = {} } = config
80
-
81
- const scalar = config.graphql?.scalar ?? g.Hex
82
-
83
- config.db ??= {}
84
-
85
- const isRequired = validation.isRequired ?? false
86
- const min = validation.isRequired ? (validation.length?.min ?? 1) : validation.length?.min
87
- const max = validation.length?.max
88
-
89
- return meta => {
90
- {
91
- const serializedExample = scalar.serialize(new Uint8Array([0]))
92
- if (typeof serializedExample !== 'string') {
93
- throw new Error(
94
- `The GraphQL scalar type specified for ${meta.listKey}.${meta.fieldKey} must serialize Uint8Arrays to strings`
95
- )
96
- }
97
- }
98
- if (min !== undefined && (!Number.isInteger(min) || min < 0)) {
99
- throw new Error(
100
- `${meta.listKey}.${meta.fieldKey} specifies validation.length.min: ${min} but it must be a positive integer`
101
- )
102
- }
103
- if (max !== undefined && (!Number.isInteger(max) || max < 0)) {
104
- throw new Error(
105
- `${meta.listKey}.${meta.fieldKey} specifies validation.length.max: ${max} but it must be a positive integer`
106
- )
107
- }
108
- if (min !== undefined && max !== undefined && min > max) {
109
- throw new Error(
110
- `${meta.listKey}.${meta.fieldKey} specifies a validation.length.max that is less than the validation.length.min, and therefore has no valid options`
111
- )
112
- }
113
-
114
- const hasAdditionalValidation = min !== undefined || max !== undefined
115
- const { mode, validate } = makeValidateHook(
116
- meta,
117
- config,
118
- hasAdditionalValidation
119
- ? ({ resolvedData, operation, addValidationError }) => {
120
- if (operation === 'delete') return
121
-
122
- const value: Uint8Array | null | undefined = resolvedData[meta.fieldKey]
123
- if (value != null) {
124
- if (min !== undefined && value.length < min) {
125
- if (min === 1) {
126
- addValidationError(`value must not be empty`)
127
- } else {
128
- addValidationError(`value must be at least ${min} bytes long`)
129
- }
130
- }
131
- if (max !== undefined && value.length > max) {
132
- addValidationError(`value must be no longer than ${max} bytes`)
133
- }
134
- }
135
- }
136
- : undefined
137
- )
138
-
139
- let clientSideDefaultValue = null
140
- if (defaultValue !== null) {
141
- clientSideDefaultValue = scalar.serialize(defaultValue)
142
- if (typeof clientSideDefaultValue !== 'string') {
143
- throw new Error(
144
- `The GraphQL scalar type specified for ${meta.listKey}.${meta.fieldKey} must serialize Uint8Arrays to strings`
145
- )
146
- }
147
- } else if (mode === 'required') {
148
- clientSideDefaultValue = scalar.serialize(new Uint8Array(0))
149
- if (typeof clientSideDefaultValue !== 'string') {
150
- throw new Error(
151
- `The GraphQL scalar type specified for ${meta.listKey}.${meta.fieldKey} must serialize Uint8Arrays to strings`
152
- )
153
- }
154
- }
155
-
156
- return fieldType({
157
- kind: 'scalar',
158
- mode,
159
- scalar: 'Bytes',
160
- default: defaultValue === null ? undefined : { kind: 'literal', value: defaultValue },
161
- index: isIndexed === true ? 'index' : isIndexed || undefined,
162
- map: config.db?.map,
163
- nativeType: config.db?.nativeType,
164
- extendPrismaSchema: config.db?.extendPrismaSchema,
165
- })({
166
- ...config,
167
- ...defaultIsRequired(config, isRequired),
168
- hooks: {
169
- ...config.hooks,
170
- validate,
171
- },
172
- input: {
173
- uniqueWhere: isIndexed === 'unique' ? { arg: g.arg({ type: scalar }) } : undefined,
174
- where: {
175
- arg: g.arg({
176
- type: mode === 'optional' ? getNullableFilterType(scalar) : getFilterType(scalar),
177
- }),
178
- },
179
- create: {
180
- arg: g.arg({
181
- type: scalar,
182
- }),
183
- resolve(val) {
184
- if (val !== undefined) return val
185
- return defaultValue ?? null
186
- },
187
- },
188
- update: { arg: g.arg({ type: scalar }) },
189
- orderBy: { arg: g.arg({ type: orderDirectionEnum }) },
190
- },
191
- output: g.field({ type: scalar }),
192
- __ksTelemetryFieldTypeName: '@nixxie-cms/bytes',
193
- views: '@nixxie-cms/core/fields/types/bytes/views',
194
- getAdminMeta(): TextFieldMeta {
195
- return {
196
- defaultValue: clientSideDefaultValue,
197
- isNullable: mode === 'optional',
198
- }
199
- },
200
- })
201
- }
202
- }
203
-
204
- type BytesFilterType = GInputObjectType<{
205
- equals?: GArg<GScalarType<Uint8Array, string>>
206
- in?: GArg<GList<GNonNull<GScalarType<Uint8Array, string>>>>
207
- notIn?: GArg<GList<GNonNull<GScalarType<Uint8Array, string>>>>
208
- not?: GArg<BytesFilterType>
209
- }>
210
-
211
- // the weakMemoizes are important so reusing the same scalar type for multiple `bytes` fields uses the same (===) filter type
212
- // rather than a duplicate one which would cause an error about two types with the same name
213
- const getFilterType = weakMemoize((scalar: GScalarType<Uint8Array, string>) => {
214
- const filter: BytesFilterType = g.inputObject({
215
- name: `${scalar.name}Filter`,
216
- fields: () => ({
217
- equals: g.arg({ type: scalar }),
218
- in: g.arg({ type: g.list(g.nonNull(scalar)) }),
219
- notIn: g.arg({ type: g.list(g.nonNull(scalar)) }),
220
- not: g.arg({ type: filter }),
221
- }),
222
- })
223
- return filter
224
- })
225
-
226
- const getNullableFilterType = weakMemoize((scalar: GScalarType<Uint8Array, string>) => {
227
- const filter: BytesFilterType = g.inputObject({
228
- name: `${scalar.name}NullableFilter`,
229
- fields: () => ({
230
- equals: g.arg({ type: scalar }),
231
- in: g.arg({ type: g.list(g.nonNull(scalar)) }),
232
- notIn: g.arg({ type: g.list(g.nonNull(scalar)) }),
233
- not: g.arg({ type: filter }),
234
- }),
235
- })
236
- return filter
237
- })
238
-
239
- export function bytesScalar(opts: {
240
- name: string
241
- serialize: (value: Uint8Array) => string
242
- parse: (value: string) => Uint8Array
243
- description?: string
244
- specifiedByURL?: string
245
- }) {
246
- return g.scalar<Uint8Array, string>({
247
- name: opts.name,
248
- description: opts.description,
249
- specifiedByURL: opts.specifiedByURL,
250
- parseLiteral(value) {
251
- if (value.kind !== 'StringValue') {
252
- throw new GraphQLError(`${opts.name} only accepts values as strings`)
253
- }
254
- return opts.parse(value.value)
255
- },
256
- parseValue(value) {
257
- // so that when you're doing a mutation in a resolver, you can just pass in a Uint8Array directly
258
- if (value instanceof Uint8Array) {
259
- // duplicate it though to avoid any weirdness with the array being mutated
260
- // + ensuring that if you pass in a Buffer, resolvers receive a normal Uint8Array
261
- return Uint8Array.from(value)
262
- }
263
- if (typeof value !== 'string') {
264
- throw new GraphQLError(`${opts.name} only accepts values as strings`)
265
- }
266
- return opts.parse(value)
267
- },
268
- serialize(value) {
269
- if (!(value instanceof Uint8Array)) {
270
- throw new GraphQLError(`unexpected value provided to ${opts.name} scalar: ${value}`)
271
- }
272
- return opts.serialize(value)
273
- },
274
- })
275
- }
1
+ import {
2
+ type BaseListTypeInfo,
3
+ type CommonFieldConfig,
4
+ type FieldTypeFunc,
5
+ fieldType,
6
+ orderDirectionEnum,
7
+ } from '../../../types'
8
+ import { g } from '../../..'
9
+ import { makeValidateHook, defaultIsRequired } from '../../non-null-graphql'
10
+ import { weakMemoize } from '../../../lib/core/utils'
11
+ import { GraphQLError } from 'graphql'
12
+ import type {
13
+ GArg,
14
+ GInputObjectType,
15
+ GList,
16
+ GNonNull,
17
+ GScalarType,
18
+ InferValueFromInputType,
19
+ } from '@graphql-ts/schema'
20
+
21
+ export type FieldTypeInfo = {
22
+ item: Uint8Array | null
23
+ inputs: {
24
+ create: Uint8Array | null | undefined
25
+ update: Uint8Array | null | undefined
26
+ where: InferValueFromInputType<BytesFilterType> | undefined
27
+ uniqueWhere: Uint8Array | null | undefined
28
+ orderBy: undefined
29
+ }
30
+ prisma: {
31
+ create: Uint8Array | null | undefined
32
+ update: Uint8Array | null | undefined
33
+ }
34
+ }
35
+
36
+ export type BytesFieldConfig<ListTypeInfo extends BaseListTypeInfo> = CommonFieldConfig<
37
+ ListTypeInfo,
38
+ FieldTypeInfo
39
+ > & {
40
+ isIndexed?: boolean | 'unique'
41
+ graphql?: {
42
+ scalar?: GScalarType<Uint8Array, string>
43
+ }
44
+ validation?: {
45
+ /**
46
+ * Makes the field disallow null values. It does not constrain the length of the value.
47
+ */
48
+ isRequired?: boolean
49
+ /**
50
+ * Specifies the minimum and maximum length of the value in _bytes_. It does _not_ represent the length in the encoded form.
51
+ */
52
+ length?: { min?: number; max?: number }
53
+ }
54
+ defaultValue?: Uint8Array | null
55
+ db?: {
56
+ isNullable?: boolean
57
+ map?: string
58
+ extendPrismaSchema?: (field: string) => string
59
+ /**
60
+ * The underlying database type.
61
+ * Only some of the types are supported on PostgreSQL and MySQL.
62
+ * The native type is not customisable on SQLite.
63
+ * See Prisma's documentation for more information about the supported types.
64
+ *
65
+ * https://www.prisma.io/docs/orm/reference/prisma-schema-reference#bytes
66
+ */
67
+ nativeType?: string
68
+ }
69
+ }
70
+
71
+ export type TextFieldMeta = {
72
+ isNullable: boolean
73
+ defaultValue: string | null
74
+ }
75
+
76
+ export function bytes<ListTypeInfo extends BaseListTypeInfo>(
77
+ config: BytesFieldConfig<ListTypeInfo> = {}
78
+ ): FieldTypeFunc<ListTypeInfo> {
79
+ const { defaultValue = null, isIndexed, validation = {} } = config
80
+
81
+ const scalar = config.graphql?.scalar ?? g.Hex
82
+
83
+ config.db ??= {}
84
+
85
+ const isRequired = validation.isRequired ?? false
86
+ const min = validation.isRequired ? (validation.length?.min ?? 1) : validation.length?.min
87
+ const max = validation.length?.max
88
+
89
+ return meta => {
90
+ {
91
+ const serializedExample = scalar.serialize(new Uint8Array([0]))
92
+ if (typeof serializedExample !== 'string') {
93
+ throw new Error(
94
+ `The GraphQL scalar type specified for ${meta.listKey}.${meta.fieldKey} must serialize Uint8Arrays to strings`
95
+ )
96
+ }
97
+ }
98
+ if (min !== undefined && (!Number.isInteger(min) || min < 0)) {
99
+ throw new Error(
100
+ `${meta.listKey}.${meta.fieldKey} specifies validation.length.min: ${min} but it must be a positive integer`
101
+ )
102
+ }
103
+ if (max !== undefined && (!Number.isInteger(max) || max < 0)) {
104
+ throw new Error(
105
+ `${meta.listKey}.${meta.fieldKey} specifies validation.length.max: ${max} but it must be a positive integer`
106
+ )
107
+ }
108
+ if (min !== undefined && max !== undefined && min > max) {
109
+ throw new Error(
110
+ `${meta.listKey}.${meta.fieldKey} specifies a validation.length.max that is less than the validation.length.min, and therefore has no valid options`
111
+ )
112
+ }
113
+
114
+ const hasAdditionalValidation = min !== undefined || max !== undefined
115
+ const { mode, validate } = makeValidateHook(
116
+ meta,
117
+ config,
118
+ hasAdditionalValidation
119
+ ? ({ resolvedData, operation, addValidationError }) => {
120
+ if (operation === 'delete') return
121
+
122
+ const value: Uint8Array | null | undefined = resolvedData[meta.fieldKey]
123
+ if (value != null) {
124
+ if (min !== undefined && value.length < min) {
125
+ if (min === 1) {
126
+ addValidationError(`value must not be empty`)
127
+ } else {
128
+ addValidationError(`value must be at least ${min} bytes long`)
129
+ }
130
+ }
131
+ if (max !== undefined && value.length > max) {
132
+ addValidationError(`value must be no longer than ${max} bytes`)
133
+ }
134
+ }
135
+ }
136
+ : undefined
137
+ )
138
+
139
+ let clientSideDefaultValue = null
140
+ if (defaultValue !== null) {
141
+ clientSideDefaultValue = scalar.serialize(defaultValue)
142
+ if (typeof clientSideDefaultValue !== 'string') {
143
+ throw new Error(
144
+ `The GraphQL scalar type specified for ${meta.listKey}.${meta.fieldKey} must serialize Uint8Arrays to strings`
145
+ )
146
+ }
147
+ } else if (mode === 'required') {
148
+ clientSideDefaultValue = scalar.serialize(new Uint8Array(0))
149
+ if (typeof clientSideDefaultValue !== 'string') {
150
+ throw new Error(
151
+ `The GraphQL scalar type specified for ${meta.listKey}.${meta.fieldKey} must serialize Uint8Arrays to strings`
152
+ )
153
+ }
154
+ }
155
+
156
+ return fieldType({
157
+ kind: 'scalar',
158
+ mode,
159
+ scalar: 'Bytes',
160
+ default: defaultValue === null ? undefined : { kind: 'literal', value: defaultValue },
161
+ index: isIndexed === true ? 'index' : isIndexed || undefined,
162
+ map: config.db?.map,
163
+ nativeType: config.db?.nativeType,
164
+ extendPrismaSchema: config.db?.extendPrismaSchema,
165
+ })({
166
+ ...config,
167
+ ...defaultIsRequired(config, isRequired),
168
+ hooks: {
169
+ ...config.hooks,
170
+ validate,
171
+ },
172
+ input: {
173
+ uniqueWhere: isIndexed === 'unique' ? { arg: g.arg({ type: scalar }) } : undefined,
174
+ where: {
175
+ arg: g.arg({
176
+ type: mode === 'optional' ? getNullableFilterType(scalar) : getFilterType(scalar),
177
+ }),
178
+ },
179
+ create: {
180
+ arg: g.arg({
181
+ type: scalar,
182
+ }),
183
+ resolve(val) {
184
+ if (val !== undefined) return val
185
+ return defaultValue ?? null
186
+ },
187
+ },
188
+ update: { arg: g.arg({ type: scalar }) },
189
+ orderBy: { arg: g.arg({ type: orderDirectionEnum }) },
190
+ },
191
+ output: g.field({ type: scalar }),
192
+ __nxTelemetryFieldTypeName: '@nixxie-cms/bytes',
193
+ views: '@nixxie-cms/core/fields/types/bytes/views',
194
+ getAdminMeta(): TextFieldMeta {
195
+ return {
196
+ defaultValue: clientSideDefaultValue,
197
+ isNullable: mode === 'optional',
198
+ }
199
+ },
200
+ })
201
+ }
202
+ }
203
+
204
+ type BytesFilterType = GInputObjectType<{
205
+ equals?: GArg<GScalarType<Uint8Array, string>>
206
+ in?: GArg<GList<GNonNull<GScalarType<Uint8Array, string>>>>
207
+ notIn?: GArg<GList<GNonNull<GScalarType<Uint8Array, string>>>>
208
+ not?: GArg<BytesFilterType>
209
+ }>
210
+
211
+ // the weakMemoizes are important so reusing the same scalar type for multiple `bytes` fields uses the same (===) filter type
212
+ // rather than a duplicate one which would cause an error about two types with the same name
213
+ const getFilterType = weakMemoize((scalar: GScalarType<Uint8Array, string>) => {
214
+ const filter: BytesFilterType = g.inputObject({
215
+ name: `${scalar.name}Filter`,
216
+ fields: () => ({
217
+ equals: g.arg({ type: scalar }),
218
+ in: g.arg({ type: g.list(g.nonNull(scalar)) }),
219
+ notIn: g.arg({ type: g.list(g.nonNull(scalar)) }),
220
+ not: g.arg({ type: filter }),
221
+ }),
222
+ })
223
+ return filter
224
+ })
225
+
226
+ const getNullableFilterType = weakMemoize((scalar: GScalarType<Uint8Array, string>) => {
227
+ const filter: BytesFilterType = g.inputObject({
228
+ name: `${scalar.name}NullableFilter`,
229
+ fields: () => ({
230
+ equals: g.arg({ type: scalar }),
231
+ in: g.arg({ type: g.list(g.nonNull(scalar)) }),
232
+ notIn: g.arg({ type: g.list(g.nonNull(scalar)) }),
233
+ not: g.arg({ type: filter }),
234
+ }),
235
+ })
236
+ return filter
237
+ })
238
+
239
+ export function bytesScalar(opts: {
240
+ name: string
241
+ serialize: (value: Uint8Array) => string
242
+ parse: (value: string) => Uint8Array
243
+ description?: string
244
+ specifiedByURL?: string
245
+ }) {
246
+ return g.scalar<Uint8Array, string>({
247
+ name: opts.name,
248
+ description: opts.description,
249
+ specifiedByURL: opts.specifiedByURL,
250
+ parseLiteral(value) {
251
+ if (value.kind !== 'StringValue') {
252
+ throw new GraphQLError(`${opts.name} only accepts values as strings`)
253
+ }
254
+ return opts.parse(value.value)
255
+ },
256
+ parseValue(value) {
257
+ // so that when you're doing a mutation in a resolver, you can just pass in a Uint8Array directly
258
+ if (value instanceof Uint8Array) {
259
+ // duplicate it though to avoid any weirdness with the array being mutated
260
+ // + ensuring that if you pass in a Buffer, resolvers receive a normal Uint8Array
261
+ return Uint8Array.from(value)
262
+ }
263
+ if (typeof value !== 'string') {
264
+ throw new GraphQLError(`${opts.name} only accepts values as strings`)
265
+ }
266
+ return opts.parse(value)
267
+ },
268
+ serialize(value) {
269
+ if (!(value instanceof Uint8Array)) {
270
+ throw new GraphQLError(`unexpected value provided to ${opts.name} scalar: ${value}`)
271
+ }
272
+ return opts.serialize(value)
273
+ },
274
+ })
275
+ }