@nixxie-cms/core 1.0.0 → 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (186) 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 +15 -15
  100. package/scripts/cli/dist/nixxie-cms-core-scripts-cli.esm.js +15 -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/no-access.ts +7 -7
  115. package/src/fields/types/bigInt/index.ts +181 -181
  116. package/src/fields/types/bytes/index.ts +275 -275
  117. package/src/fields/types/calendarDay/index.ts +194 -194
  118. package/src/fields/types/checkbox/index.ts +76 -76
  119. package/src/fields/types/decimal/index.ts +182 -182
  120. package/src/fields/types/file/index.ts +168 -168
  121. package/src/fields/types/float/index.ts +133 -133
  122. package/src/fields/types/image/index.ts +244 -244
  123. package/src/fields/types/integer/index.ts +156 -156
  124. package/src/fields/types/json/index.ts +77 -77
  125. package/src/fields/types/multiselect/index.ts +212 -212
  126. package/src/fields/types/password/index.ts +241 -241
  127. package/src/fields/types/relationship/index.ts +381 -381
  128. package/src/fields/types/relationship/views/RelationshipTable.tsx +190 -190
  129. package/src/fields/types/select/index.ts +226 -226
  130. package/src/fields/types/text/index.ts +207 -207
  131. package/src/fields/types/timestamp/index.ts +116 -116
  132. package/src/fields/types/virtual/index.ts +108 -108
  133. package/src/helpers.ts +342 -316
  134. package/src/index.ts +4 -0
  135. package/src/{___internal-do-not-use-will-break-in-patch → internal-unstable}/admin-ui/id-field-view.tsx +167 -167
  136. package/src/{___internal-do-not-use-will-break-in-patch → internal-unstable}/admin-ui/pages/App/index.tsx +22 -22
  137. package/src/{___internal-do-not-use-will-break-in-patch → internal-unstable}/admin-ui/pages/CreateItemPage/index.tsx +71 -71
  138. package/src/{___internal-do-not-use-will-break-in-patch → internal-unstable}/admin-ui/pages/HomePage/index.tsx +333 -333
  139. package/src/{___internal-do-not-use-will-break-in-patch → internal-unstable}/admin-ui/pages/ItemPage/common.tsx +358 -358
  140. package/src/{___internal-do-not-use-will-break-in-patch → internal-unstable}/admin-ui/pages/ItemPage/index.tsx +483 -483
  141. package/src/{___internal-do-not-use-will-break-in-patch → internal-unstable}/admin-ui/pages/ListPage/FilterAdd.tsx +221 -221
  142. package/src/{___internal-do-not-use-will-break-in-patch → internal-unstable}/admin-ui/pages/ListPage/PaginationControls.tsx +170 -170
  143. package/src/{___internal-do-not-use-will-break-in-patch → internal-unstable}/admin-ui/pages/ListPage/Tag.tsx +72 -72
  144. package/src/{___internal-do-not-use-will-break-in-patch → internal-unstable}/admin-ui/pages/ListPage/index.tsx +1006 -1006
  145. package/src/{___internal-do-not-use-will-break-in-patch → internal-unstable}/admin-ui/pages/NoAccessPage/index.tsx +24 -24
  146. package/src/{___internal-do-not-use-will-break-in-patch → internal-unstable}/artifacts.ts +5 -5
  147. package/src/lib/context/createContext.ts +165 -161
  148. package/src/lib/core/initialise-lists.ts +1097 -1097
  149. package/src/lib/id-field.ts +214 -214
  150. package/src/lib/telemetry.ts +342 -342
  151. package/src/schema.ts +237 -233
  152. package/src/scripts/telemetry.ts +1 -1
  153. package/src/types/config/index.ts +400 -333
  154. package/src/types/config/lists.ts +4 -4
  155. package/src/types/context.ts +700 -530
  156. package/src/types/next-fields.ts +499 -499
  157. package/src/types/telemetry.ts +51 -51
  158. package/tests/telemetry.test.ts +361 -361
  159. package/CHANGELOG.md +0 -3158
  160. package/___internal-do-not-use-will-break-in-patch/admin-ui/id-field-view/package.json +0 -4
  161. package/___internal-do-not-use-will-break-in-patch/admin-ui/next-config/package.json +0 -4
  162. package/___internal-do-not-use-will-break-in-patch/admin-ui/pages/App/package.json +0 -4
  163. package/___internal-do-not-use-will-break-in-patch/admin-ui/pages/CreateItemPage/package.json +0 -4
  164. package/___internal-do-not-use-will-break-in-patch/admin-ui/pages/HomePage/package.json +0 -4
  165. package/___internal-do-not-use-will-break-in-patch/admin-ui/pages/ItemPage/package.json +0 -4
  166. package/___internal-do-not-use-will-break-in-patch/admin-ui/pages/ListPage/package.json +0 -4
  167. package/___internal-do-not-use-will-break-in-patch/admin-ui/pages/NoAccessPage/package.json +0 -4
  168. package/___internal-do-not-use-will-break-in-patch/artifacts/package.json +0 -4
  169. package/dist/declarations/src/___internal-do-not-use-will-break-in-patch/admin-ui/id-field-view.d.ts.map +0 -1
  170. package/dist/declarations/src/___internal-do-not-use-will-break-in-patch/admin-ui/pages/App/index.d.ts.map +0 -1
  171. package/dist/declarations/src/___internal-do-not-use-will-break-in-patch/admin-ui/pages/CreateItemPage/index.d.ts.map +0 -1
  172. package/dist/declarations/src/___internal-do-not-use-will-break-in-patch/admin-ui/pages/HomePage/index.d.ts.map +0 -1
  173. package/dist/declarations/src/___internal-do-not-use-will-break-in-patch/admin-ui/pages/ItemPage/index.d.ts.map +0 -1
  174. package/dist/declarations/src/___internal-do-not-use-will-break-in-patch/admin-ui/pages/ListPage/index.d.ts.map +0 -1
  175. package/dist/declarations/src/___internal-do-not-use-will-break-in-patch/admin-ui/pages/NoAccessPage/index.d.ts.map +0 -1
  176. package/dist/declarations/src/___internal-do-not-use-will-break-in-patch/artifacts.d.ts.map +0 -1
  177. /package/dist/{common-1a350e11.cjs.js → common-5933f758.cjs.js} +0 -0
  178. /package/dist/{common-29fc82e6.esm.js → common-ea5c441a.esm.js} +0 -0
  179. /package/dist/declarations/src/{___internal-do-not-use-will-break-in-patch → internal-unstable}/admin-ui/id-field-view.d.ts +0 -0
  180. /package/dist/declarations/src/{___internal-do-not-use-will-break-in-patch → internal-unstable}/admin-ui/pages/App/index.d.ts +0 -0
  181. /package/dist/declarations/src/{___internal-do-not-use-will-break-in-patch → internal-unstable}/admin-ui/pages/CreateItemPage/index.d.ts +0 -0
  182. /package/dist/declarations/src/{___internal-do-not-use-will-break-in-patch → internal-unstable}/admin-ui/pages/HomePage/index.d.ts +0 -0
  183. /package/dist/declarations/src/{___internal-do-not-use-will-break-in-patch → internal-unstable}/admin-ui/pages/ItemPage/index.d.ts +0 -0
  184. /package/dist/declarations/src/{___internal-do-not-use-will-break-in-patch → internal-unstable}/admin-ui/pages/ListPage/index.d.ts +0 -0
  185. /package/dist/declarations/src/{___internal-do-not-use-will-break-in-patch → internal-unstable}/admin-ui/pages/NoAccessPage/index.d.ts +0 -0
  186. /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
+ }