@nixxie-cms/core 1.0.3 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +36 -0
- package/CHANGES-1.1.md +134 -0
- package/context/dist/nixxie-cms-core-context.cjs.js +4 -3
- package/context/dist/nixxie-cms-core-context.esm.js +3 -2
- package/dist/declarations/src/access.d.ts +2 -2
- package/dist/declarations/src/access.d.ts.map +1 -1
- package/dist/declarations/src/admin-ui/components/Navigation.d.ts +2 -2
- package/dist/declarations/src/admin-ui/components/Navigation.d.ts.map +1 -1
- package/dist/declarations/src/admin-ui/context.d.ts +6 -6
- package/dist/declarations/src/admin-ui/context.d.ts.map +1 -1
- package/dist/declarations/src/admin-ui/utils/Fields.d.ts +3 -3
- package/dist/declarations/src/admin-ui/utils/Fields.d.ts.map +1 -1
- package/dist/declarations/src/admin-ui/utils/filters.d.ts +5 -5
- package/dist/declarations/src/admin-ui/utils/filters.d.ts.map +1 -1
- package/dist/declarations/src/admin-ui/utils/useCreateItem.d.ts +3 -3
- package/dist/declarations/src/admin-ui/utils/useCreateItem.d.ts.map +1 -1
- package/dist/declarations/src/admin-ui/utils/utils.d.ts +2 -2
- package/dist/declarations/src/admin-ui/utils/utils.d.ts.map +1 -1
- package/dist/declarations/src/context.d.ts +1 -1
- package/dist/declarations/src/context.d.ts.map +1 -1
- package/dist/declarations/src/fields/types/bigInt/index.d.ts +3 -3
- package/dist/declarations/src/fields/types/bigInt/index.d.ts.map +1 -1
- package/dist/declarations/src/fields/types/bytes/index.d.ts +3 -3
- package/dist/declarations/src/fields/types/bytes/index.d.ts.map +1 -1
- package/dist/declarations/src/fields/types/calendarDay/index.d.ts +3 -3
- package/dist/declarations/src/fields/types/calendarDay/index.d.ts.map +1 -1
- package/dist/declarations/src/fields/types/checkbox/index.d.ts +3 -3
- package/dist/declarations/src/fields/types/checkbox/index.d.ts.map +1 -1
- package/dist/declarations/src/fields/types/decimal/index.d.ts +3 -3
- package/dist/declarations/src/fields/types/decimal/index.d.ts.map +1 -1
- package/dist/declarations/src/fields/types/file/index.d.ts +4 -4
- package/dist/declarations/src/fields/types/file/index.d.ts.map +1 -1
- package/dist/declarations/src/fields/types/float/index.d.ts +3 -3
- package/dist/declarations/src/fields/types/float/index.d.ts.map +1 -1
- package/dist/declarations/src/fields/types/image/index.d.ts +4 -4
- package/dist/declarations/src/fields/types/image/index.d.ts.map +1 -1
- package/dist/declarations/src/fields/types/integer/index.d.ts +3 -3
- package/dist/declarations/src/fields/types/integer/index.d.ts.map +1 -1
- package/dist/declarations/src/fields/types/json/index.d.ts +3 -3
- package/dist/declarations/src/fields/types/json/index.d.ts.map +1 -1
- package/dist/declarations/src/fields/types/multiselect/index.d.ts +3 -3
- package/dist/declarations/src/fields/types/multiselect/index.d.ts.map +1 -1
- package/dist/declarations/src/fields/types/multiselect/views/index.d.ts.map +1 -1
- package/dist/declarations/src/fields/types/password/index.d.ts +3 -3
- package/dist/declarations/src/fields/types/password/index.d.ts.map +1 -1
- package/dist/declarations/src/fields/types/relationship/index.d.ts +8 -8
- package/dist/declarations/src/fields/types/relationship/index.d.ts.map +1 -1
- package/dist/declarations/src/fields/types/relationship/views/ComboboxMany.d.ts +3 -3
- package/dist/declarations/src/fields/types/relationship/views/ComboboxMany.d.ts.map +1 -1
- package/dist/declarations/src/fields/types/relationship/views/ComboboxSingle.d.ts +3 -3
- package/dist/declarations/src/fields/types/relationship/views/ComboboxSingle.d.ts.map +1 -1
- package/dist/declarations/src/fields/types/relationship/views/index.d.ts +3 -3
- package/dist/declarations/src/fields/types/relationship/views/index.d.ts.map +1 -1
- package/dist/declarations/src/fields/types/relationship/views/types.d.ts +3 -3
- package/dist/declarations/src/fields/types/relationship/views/types.d.ts.map +1 -1
- package/dist/declarations/src/fields/types/select/index.d.ts +3 -3
- package/dist/declarations/src/fields/types/select/index.d.ts.map +1 -1
- package/dist/declarations/src/fields/types/text/index.d.ts +3 -3
- package/dist/declarations/src/fields/types/text/index.d.ts.map +1 -1
- package/dist/declarations/src/fields/types/timestamp/index.d.ts +3 -3
- package/dist/declarations/src/fields/types/timestamp/index.d.ts.map +1 -1
- package/dist/declarations/src/fields/types/virtual/index.d.ts +7 -7
- package/dist/declarations/src/fields/types/virtual/index.d.ts.map +1 -1
- package/dist/declarations/src/helpers.d.ts +249 -13
- package/dist/declarations/src/helpers.d.ts.map +1 -1
- package/dist/declarations/src/index.d.ts +9 -4
- package/dist/declarations/src/index.d.ts.map +1 -1
- package/dist/declarations/src/internal-unstable/admin-ui/pages/ListPage/index.d.ts.map +1 -1
- package/dist/declarations/src/lib/admin-meta.d.ts +11 -11
- package/dist/declarations/src/lib/admin-meta.d.ts.map +1 -1
- package/dist/declarations/src/lib/core/access-control.d.ts +18 -18
- package/dist/declarations/src/lib/core/access-control.d.ts.map +1 -1
- package/dist/declarations/src/lib/core/cascade.d.ts +47 -0
- package/dist/declarations/src/lib/core/cascade.d.ts.map +1 -0
- package/dist/declarations/src/lib/core/initialise-lists.d.ts +27 -24
- package/dist/declarations/src/lib/core/initialise-lists.d.ts.map +1 -1
- package/dist/declarations/src/lib/env.d.ts +9 -0
- package/dist/declarations/src/lib/env.d.ts.map +1 -0
- package/dist/declarations/src/lib/system.d.ts +1 -1
- package/dist/declarations/src/lib/system.d.ts.map +1 -1
- package/dist/declarations/src/list-features.d.ts +162 -0
- package/dist/declarations/src/list-features.d.ts.map +1 -0
- package/dist/declarations/src/schema.d.ts +24 -23
- package/dist/declarations/src/schema.d.ts.map +1 -1
- package/dist/declarations/src/session.d.ts +75 -0
- package/dist/declarations/src/session.d.ts.map +1 -1
- package/dist/declarations/src/types/admin-meta.d.ts +11 -11
- package/dist/declarations/src/types/admin-meta.d.ts.map +1 -1
- package/dist/declarations/src/types/config/access-control.d.ts +42 -42
- package/dist/declarations/src/types/config/access-control.d.ts.map +1 -1
- package/dist/declarations/src/types/config/fields.d.ts +19 -19
- package/dist/declarations/src/types/config/fields.d.ts.map +1 -1
- package/dist/declarations/src/types/config/hooks.d.ts +131 -131
- package/dist/declarations/src/types/config/hooks.d.ts.map +1 -1
- package/dist/declarations/src/types/config/index.d.ts +190 -8
- package/dist/declarations/src/types/config/index.d.ts.map +1 -1
- package/dist/declarations/src/types/config/lists.d.ts +146 -108
- package/dist/declarations/src/types/config/lists.d.ts.map +1 -1
- package/dist/declarations/src/types/context.d.ts +507 -47
- package/dist/declarations/src/types/context.d.ts.map +1 -1
- package/dist/declarations/src/types/next-fields.d.ts +28 -28
- package/dist/declarations/src/types/next-fields.d.ts.map +1 -1
- package/dist/declarations/src/types/type-info.d.ts +3 -3
- package/dist/declarations/src/types/type-info.d.ts.map +1 -1
- package/dist/{express-455ae20c.cjs.js → express-84d534c2.cjs.js} +6 -6
- package/dist/{express-7559ca2d.esm.js → express-d0a4ce99.esm.js} +6 -6
- package/dist/{index-15c8f81e.esm.js → index-5d8b0b4e.esm.js} +363 -183
- package/dist/index-6055753b.cjs.js +393 -0
- package/dist/{index-42045902.cjs.js → index-ac29f382.cjs.js} +363 -185
- package/dist/index-f1703b7b.esm.js +386 -0
- package/dist/nixxie-cms-core.cjs.js +1388 -30
- package/dist/nixxie-cms-core.esm.js +1362 -24
- package/dist/{non-null-graphql-add6bb3d.cjs.js → non-null-graphql-4a44c122.cjs.js} +1 -1
- package/dist/{non-null-graphql-a84ed64d.esm.js → non-null-graphql-8c5feaae.esm.js} +1 -1
- package/dist/{resolve-hooks-165a9ce2.cjs.js → resolve-hooks-10a5f84c.cjs.js} +240 -6
- package/dist/{resolve-hooks-6813a045.esm.js → resolve-hooks-9e676794.esm.js} +238 -7
- package/dist/{system-a321642d.cjs.js → system-6b37a5f8.cjs.js} +33 -7
- package/dist/{system-03e49e4f.esm.js → system-e591d821.esm.js} +33 -7
- package/fields/dist/nixxie-cms-core-fields.cjs.js +29 -576
- package/fields/dist/nixxie-cms-core-fields.esm.js +18 -565
- package/fields/types/bytes/dist/nixxie-cms-core-fields-types-bytes.cjs.js +4 -2
- package/fields/types/bytes/dist/nixxie-cms-core-fields-types-bytes.esm.js +4 -2
- package/fields/types/multiselect/views/dist/nixxie-cms-core-fields-types-multiselect-views.cjs.js +1 -6
- package/fields/types/multiselect/views/dist/nixxie-cms-core-fields-types-multiselect-views.esm.js +1 -6
- package/fields/types/password/dist/nixxie-cms-core-fields-types-password.cjs.js +4 -2
- package/fields/types/password/dist/nixxie-cms-core-fields-types-password.esm.js +4 -2
- package/internal-unstable/artifacts/dist/nixxie-cms-core-internal-unstable-artifacts.cjs.js +4 -3
- package/internal-unstable/artifacts/dist/nixxie-cms-core-internal-unstable-artifacts.esm.js +4 -3
- package/package.json +4 -4
- package/scripts/cli/dist/nixxie-cms-core-scripts-cli.cjs.js +4 -3
- package/scripts/cli/dist/nixxie-cms-core-scripts-cli.esm.js +4 -3
- package/scripts/dist/nixxie-cms-core-scripts.cjs.js +4 -3
- package/scripts/dist/nixxie-cms-core-scripts.esm.js +4 -3
- package/session/dist/nixxie-cms-core-session.cjs.js +286 -0
- package/session/dist/nixxie-cms-core-session.esm.js +279 -1
- package/src/access.ts +25 -25
- package/src/admin-ui/admin-meta-graphql.ts +5 -5
- package/src/admin-ui/components/CreateButtonLink.tsx +46 -46
- package/src/admin-ui/components/Navigation.tsx +3 -3
- package/src/admin-ui/context.tsx +6 -6
- package/src/admin-ui/utils/Fields.tsx +241 -241
- package/src/admin-ui/utils/actionData.ts +36 -36
- package/src/admin-ui/utils/filters.ts +148 -148
- package/src/admin-ui/utils/useCreateItem.ts +171 -171
- package/src/admin-ui/utils/utils.tsx +127 -127
- package/src/context.ts +1 -1
- package/src/fields/non-null-graphql.ts +115 -115
- package/src/fields/types/bigInt/index.ts +6 -6
- package/src/fields/types/bytes/index.ts +6 -6
- package/src/fields/types/calendarDay/index.ts +18 -19
- package/src/fields/types/checkbox/index.ts +6 -6
- package/src/fields/types/decimal/index.ts +6 -6
- package/src/fields/types/file/index.ts +8 -8
- package/src/fields/types/float/index.ts +6 -6
- package/src/fields/types/image/index.ts +8 -8
- package/src/fields/types/integer/index.ts +6 -6
- package/src/fields/types/json/index.ts +5 -5
- package/src/fields/types/multiselect/index.ts +7 -7
- package/src/fields/types/multiselect/views/index.tsx +149 -151
- package/src/fields/types/password/index.ts +6 -6
- package/src/fields/types/relationship/index.ts +13 -13
- package/src/fields/types/relationship/views/ComboboxMany.tsx +110 -110
- package/src/fields/types/relationship/views/ComboboxSingle.tsx +115 -115
- package/src/fields/types/relationship/views/ContextualActions.tsx +139 -139
- package/src/fields/types/relationship/views/index.tsx +492 -492
- package/src/fields/types/relationship/views/types.ts +46 -46
- package/src/fields/types/relationship/views/useApolloQuery.ts +185 -185
- package/src/fields/types/relationship/views/useFilter.tsx +109 -109
- package/src/fields/types/select/index.ts +6 -6
- package/src/fields/types/text/index.ts +6 -6
- package/src/fields/types/timestamp/index.ts +23 -21
- package/src/fields/types/virtual/index.ts +11 -11
- package/src/helpers.ts +773 -42
- package/src/index.ts +66 -24
- package/src/internal-unstable/admin-ui/pages/ItemPage/common.tsx +4 -4
- package/src/internal-unstable/admin-ui/pages/ItemPage/index.tsx +5 -5
- package/src/internal-unstable/admin-ui/pages/ListPage/index.tsx +8 -8
- package/src/lib/admin-meta.ts +369 -369
- package/src/lib/context/createContext.ts +6 -0
- package/src/lib/core/access-control.ts +434 -434
- package/src/lib/core/cascade.ts +236 -0
- package/src/lib/core/initialise-lists.ts +49 -33
- package/src/lib/core/mutations/index.ts +7 -0
- package/src/lib/core/mutations/nested-mutation-many-input-resolvers.ts +145 -145
- package/src/lib/core/mutations/nested-mutation-one-input-resolvers.ts +71 -71
- package/src/lib/core/queries/output-field.ts +178 -178
- package/src/lib/env.ts +50 -0
- package/src/lib/id-field.ts +2 -2
- package/src/lib/system.ts +221 -207
- package/src/lib/typescript-schema-printer.ts +227 -227
- package/src/list-features.ts +476 -0
- package/src/schema.ts +92 -22
- package/src/session.ts +225 -0
- package/src/types/admin-meta.ts +218 -218
- package/src/types/config/access-control.ts +186 -186
- package/src/types/config/fields.ts +96 -96
- package/src/types/config/hooks.ts +529 -529
- package/src/types/config/index.ts +206 -7
- package/src/types/config/lists.ts +606 -565
- package/src/types/context.ts +592 -55
- package/src/types/next-fields.ts +31 -31
- package/src/types/type-info.ts +38 -38
- package/src/types/type-tests.ts +21 -21
|
@@ -1,127 +1,127 @@
|
|
|
1
|
-
import isDeepEqual from 'fast-deep-equal'
|
|
2
|
-
import { type FragmentDefinitionNode, type SelectionSetNode, parse } from 'graphql'
|
|
3
|
-
import { useMemo } from 'react'
|
|
4
|
-
|
|
5
|
-
import type {
|
|
6
|
-
|
|
7
|
-
ConditionalFilterCase,
|
|
8
|
-
FieldController,
|
|
9
|
-
FieldMeta,
|
|
10
|
-
} from '../../types'
|
|
11
|
-
import { serializeItemForConditionalFilters, testFilter } from './filters'
|
|
12
|
-
|
|
13
|
-
function extractRootFields(selectedFields: Set<string>, selectionSet: SelectionSetNode) {
|
|
14
|
-
selectionSet.selections.forEach(selection => {
|
|
15
|
-
if (selection.kind === 'Field') {
|
|
16
|
-
selectedFields.add(selection.alias ? selection.alias.value : selection.name.value)
|
|
17
|
-
}
|
|
18
|
-
if (selection.kind === 'InlineFragment') {
|
|
19
|
-
extractRootFields(selectedFields, selection.selectionSet)
|
|
20
|
-
}
|
|
21
|
-
// FragmentSpread will never happen for the use cases of getRootFieldsFromSelection
|
|
22
|
-
})
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
export function getRootGraphQLFieldsFromFieldController(controller: FieldController<any, any>) {
|
|
26
|
-
const ast = parse(`fragment X on Y { id, ${controller.graphqlSelection} }`)
|
|
27
|
-
const selectedFields = new Set<string>()
|
|
28
|
-
const fragmentNode = ast.definitions[0] as FragmentDefinitionNode
|
|
29
|
-
extractRootFields(selectedFields, fragmentNode.selectionSet)
|
|
30
|
-
return [...selectedFields]
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
export function useInvalidFields(
|
|
34
|
-
fields: Record<string, FieldMeta>,
|
|
35
|
-
item: Record<string, unknown>,
|
|
36
|
-
isRequireds: Record<string, ConditionalFilterCase<
|
|
37
|
-
): ReadonlySet<string> {
|
|
38
|
-
return useMemo(() => {
|
|
39
|
-
const invalidFields = new Set<string>()
|
|
40
|
-
const serialized = serializeItemForConditionalFilters(fields, item)
|
|
41
|
-
|
|
42
|
-
for (const fieldKey in item) {
|
|
43
|
-
const validateFn = fields[fieldKey]?.controller?.validate
|
|
44
|
-
if (!validateFn) continue
|
|
45
|
-
const isRequired = testFilter(isRequireds[fieldKey] ?? false, serialized)
|
|
46
|
-
const fieldValue = item[fieldKey]
|
|
47
|
-
const valid = validateFn(fieldValue, { isRequired })
|
|
48
|
-
if (valid) continue
|
|
49
|
-
|
|
50
|
-
invalidFields.add(fieldKey)
|
|
51
|
-
}
|
|
52
|
-
return invalidFields
|
|
53
|
-
}, [fields, isRequireds, item])
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
export function makeDefaultValueState(fields: Record<string, FieldMeta>) {
|
|
57
|
-
const result: Record<string, unknown> = {}
|
|
58
|
-
for (const fieldKey in fields) {
|
|
59
|
-
result[fieldKey] = fields[fieldKey].controller.defaultValue
|
|
60
|
-
}
|
|
61
|
-
return result
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
export function deserializeItemToValue(
|
|
65
|
-
fields: Record<string, FieldMeta>,
|
|
66
|
-
item: Record<string, unknown | null>
|
|
67
|
-
) {
|
|
68
|
-
const result: Record<string, unknown | null> = {}
|
|
69
|
-
for (const [fieldKey, field] of Object.entries(fields)) {
|
|
70
|
-
const itemForField: Record<string, unknown> = {}
|
|
71
|
-
for (const graphqlField of getRootGraphQLFieldsFromFieldController(field.controller)) {
|
|
72
|
-
itemForField[graphqlField] = item?.[graphqlField] ?? null
|
|
73
|
-
}
|
|
74
|
-
result[fieldKey] = field.controller.deserialize(itemForField)
|
|
75
|
-
}
|
|
76
|
-
return result
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
export function serializeValueToOperationItem(
|
|
80
|
-
operation: 'create' | 'update',
|
|
81
|
-
fields: Record<string, FieldMeta>,
|
|
82
|
-
value: Record<string, unknown>,
|
|
83
|
-
valueReference?: Record<string, unknown>
|
|
84
|
-
) {
|
|
85
|
-
const result: Record<string, unknown> = {}
|
|
86
|
-
valueReference ??= makeDefaultValueState(fields)
|
|
87
|
-
|
|
88
|
-
for (const fieldKey in fields) {
|
|
89
|
-
const field = fields[fieldKey]
|
|
90
|
-
const fieldValue = value[fieldKey]
|
|
91
|
-
const fieldValueSerialized = field.controller.serialize(fieldValue)
|
|
92
|
-
const fieldValueReference = valueReference[fieldKey]
|
|
93
|
-
|
|
94
|
-
const isAlwaysRequired = field.isNonNull.includes(operation)
|
|
95
|
-
if (!isAlwaysRequired) {
|
|
96
|
-
if (isDeepEqual(fieldValueSerialized, field.controller.serialize(fieldValueReference)))
|
|
97
|
-
continue
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
Object.assign(result, fieldValueSerialized)
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
return result
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
export function useHasChanges(
|
|
107
|
-
operation: 'create' | 'update',
|
|
108
|
-
fields: Record<string, FieldMeta>,
|
|
109
|
-
value: Record<string, unknown>,
|
|
110
|
-
valueReference?: Record<string, unknown>
|
|
111
|
-
) {
|
|
112
|
-
return useMemo(() => {
|
|
113
|
-
valueReference ??= makeDefaultValueState(fields)
|
|
114
|
-
|
|
115
|
-
for (const fieldKey in fields) {
|
|
116
|
-
const field = fields[fieldKey]
|
|
117
|
-
const fieldValue = value[fieldKey]
|
|
118
|
-
const fieldValueSerialized = field.controller.serialize(fieldValue)
|
|
119
|
-
const fieldValueReference = valueReference[fieldKey]
|
|
120
|
-
|
|
121
|
-
if (!isDeepEqual(fieldValueSerialized, field.controller.serialize(fieldValueReference)))
|
|
122
|
-
return true
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
return false
|
|
126
|
-
}, [fields, operation, value, valueReference])
|
|
127
|
-
}
|
|
1
|
+
import isDeepEqual from 'fast-deep-equal'
|
|
2
|
+
import { type FragmentDefinitionNode, type SelectionSetNode, parse } from 'graphql'
|
|
3
|
+
import { useMemo } from 'react'
|
|
4
|
+
|
|
5
|
+
import type {
|
|
6
|
+
BaseCollectionTypeInfo,
|
|
7
|
+
ConditionalFilterCase,
|
|
8
|
+
FieldController,
|
|
9
|
+
FieldMeta,
|
|
10
|
+
} from '../../types'
|
|
11
|
+
import { serializeItemForConditionalFilters, testFilter } from './filters'
|
|
12
|
+
|
|
13
|
+
function extractRootFields(selectedFields: Set<string>, selectionSet: SelectionSetNode) {
|
|
14
|
+
selectionSet.selections.forEach(selection => {
|
|
15
|
+
if (selection.kind === 'Field') {
|
|
16
|
+
selectedFields.add(selection.alias ? selection.alias.value : selection.name.value)
|
|
17
|
+
}
|
|
18
|
+
if (selection.kind === 'InlineFragment') {
|
|
19
|
+
extractRootFields(selectedFields, selection.selectionSet)
|
|
20
|
+
}
|
|
21
|
+
// FragmentSpread will never happen for the use cases of getRootFieldsFromSelection
|
|
22
|
+
})
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export function getRootGraphQLFieldsFromFieldController(controller: FieldController<any, any>) {
|
|
26
|
+
const ast = parse(`fragment X on Y { id, ${controller.graphqlSelection} }`)
|
|
27
|
+
const selectedFields = new Set<string>()
|
|
28
|
+
const fragmentNode = ast.definitions[0] as FragmentDefinitionNode
|
|
29
|
+
extractRootFields(selectedFields, fragmentNode.selectionSet)
|
|
30
|
+
return [...selectedFields]
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export function useInvalidFields(
|
|
34
|
+
fields: Record<string, FieldMeta>,
|
|
35
|
+
item: Record<string, unknown>,
|
|
36
|
+
isRequireds: Record<string, ConditionalFilterCase<BaseCollectionTypeInfo>>
|
|
37
|
+
): ReadonlySet<string> {
|
|
38
|
+
return useMemo(() => {
|
|
39
|
+
const invalidFields = new Set<string>()
|
|
40
|
+
const serialized = serializeItemForConditionalFilters(fields, item)
|
|
41
|
+
|
|
42
|
+
for (const fieldKey in item) {
|
|
43
|
+
const validateFn = fields[fieldKey]?.controller?.validate
|
|
44
|
+
if (!validateFn) continue
|
|
45
|
+
const isRequired = testFilter(isRequireds[fieldKey] ?? false, serialized)
|
|
46
|
+
const fieldValue = item[fieldKey]
|
|
47
|
+
const valid = validateFn(fieldValue, { isRequired })
|
|
48
|
+
if (valid) continue
|
|
49
|
+
|
|
50
|
+
invalidFields.add(fieldKey)
|
|
51
|
+
}
|
|
52
|
+
return invalidFields
|
|
53
|
+
}, [fields, isRequireds, item])
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export function makeDefaultValueState(fields: Record<string, FieldMeta>) {
|
|
57
|
+
const result: Record<string, unknown> = {}
|
|
58
|
+
for (const fieldKey in fields) {
|
|
59
|
+
result[fieldKey] = fields[fieldKey].controller.defaultValue
|
|
60
|
+
}
|
|
61
|
+
return result
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export function deserializeItemToValue(
|
|
65
|
+
fields: Record<string, FieldMeta>,
|
|
66
|
+
item: Record<string, unknown | null>
|
|
67
|
+
) {
|
|
68
|
+
const result: Record<string, unknown | null> = {}
|
|
69
|
+
for (const [fieldKey, field] of Object.entries(fields)) {
|
|
70
|
+
const itemForField: Record<string, unknown> = {}
|
|
71
|
+
for (const graphqlField of getRootGraphQLFieldsFromFieldController(field.controller)) {
|
|
72
|
+
itemForField[graphqlField] = item?.[graphqlField] ?? null
|
|
73
|
+
}
|
|
74
|
+
result[fieldKey] = field.controller.deserialize(itemForField)
|
|
75
|
+
}
|
|
76
|
+
return result
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
export function serializeValueToOperationItem(
|
|
80
|
+
operation: 'create' | 'update',
|
|
81
|
+
fields: Record<string, FieldMeta>,
|
|
82
|
+
value: Record<string, unknown>,
|
|
83
|
+
valueReference?: Record<string, unknown>
|
|
84
|
+
) {
|
|
85
|
+
const result: Record<string, unknown> = {}
|
|
86
|
+
valueReference ??= makeDefaultValueState(fields)
|
|
87
|
+
|
|
88
|
+
for (const fieldKey in fields) {
|
|
89
|
+
const field = fields[fieldKey]
|
|
90
|
+
const fieldValue = value[fieldKey]
|
|
91
|
+
const fieldValueSerialized = field.controller.serialize(fieldValue)
|
|
92
|
+
const fieldValueReference = valueReference[fieldKey]
|
|
93
|
+
|
|
94
|
+
const isAlwaysRequired = field.isNonNull.includes(operation)
|
|
95
|
+
if (!isAlwaysRequired) {
|
|
96
|
+
if (isDeepEqual(fieldValueSerialized, field.controller.serialize(fieldValueReference)))
|
|
97
|
+
continue
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
Object.assign(result, fieldValueSerialized)
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
return result
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
export function useHasChanges(
|
|
107
|
+
operation: 'create' | 'update',
|
|
108
|
+
fields: Record<string, FieldMeta>,
|
|
109
|
+
value: Record<string, unknown>,
|
|
110
|
+
valueReference?: Record<string, unknown>
|
|
111
|
+
) {
|
|
112
|
+
return useMemo(() => {
|
|
113
|
+
valueReference ??= makeDefaultValueState(fields)
|
|
114
|
+
|
|
115
|
+
for (const fieldKey in fields) {
|
|
116
|
+
const field = fields[fieldKey]
|
|
117
|
+
const fieldValue = value[fieldKey]
|
|
118
|
+
const fieldValueSerialized = field.controller.serialize(fieldValue)
|
|
119
|
+
const fieldValueReference = valueReference[fieldKey]
|
|
120
|
+
|
|
121
|
+
if (!isDeepEqual(fieldValueSerialized, field.controller.serialize(fieldValueReference)))
|
|
122
|
+
return true
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
return false
|
|
126
|
+
}, [fields, operation, value, valueReference])
|
|
127
|
+
}
|
package/src/context.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export {
|
|
1
|
+
export { createNixxieContext } from './lib/system'
|
|
@@ -1,115 +1,115 @@
|
|
|
1
|
-
import type { BaseFieldTypeInfo, CommonFieldConfig } from '../types'
|
|
2
|
-
import { type
|
|
3
|
-
import type { FieldHooks } from '../types/config/hooks'
|
|
4
|
-
import { type ValidateFieldHook } from '../types/config/hooks'
|
|
5
|
-
import { merge } from './resolve-hooks'
|
|
6
|
-
|
|
7
|
-
export function resolveDbNullable(
|
|
8
|
-
validation: undefined | { isRequired?: boolean },
|
|
9
|
-
db: undefined | { isNullable?: boolean }
|
|
10
|
-
): boolean {
|
|
11
|
-
if (db?.isNullable === false) return false
|
|
12
|
-
if (db?.isNullable === undefined && validation?.isRequired) {
|
|
13
|
-
return false
|
|
14
|
-
}
|
|
15
|
-
return true
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
export function makeValidateHook<
|
|
19
|
-
meta: FieldData<
|
|
20
|
-
config: {
|
|
21
|
-
label?: string
|
|
22
|
-
db?: {
|
|
23
|
-
isNullable?: boolean
|
|
24
|
-
}
|
|
25
|
-
graphql?: {
|
|
26
|
-
isNonNull?:
|
|
27
|
-
| boolean
|
|
28
|
-
| {
|
|
29
|
-
read?: boolean
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
validation?: {
|
|
33
|
-
isRequired?: boolean
|
|
34
|
-
[key: string]: unknown
|
|
35
|
-
}
|
|
36
|
-
hooks?: {
|
|
37
|
-
validate?: FieldHooks<
|
|
38
|
-
}
|
|
39
|
-
},
|
|
40
|
-
f?: ValidateFieldHook<
|
|
41
|
-
hasPrismaDefaultValue: boolean = false
|
|
42
|
-
) {
|
|
43
|
-
const dbNullable = resolveDbNullable(config.validation, config.db)
|
|
44
|
-
const mode = dbNullable ? ('optional' as const) : ('required' as const)
|
|
45
|
-
const valueRequired = (config.validation?.isRequired || !dbNullable) && !hasPrismaDefaultValue
|
|
46
|
-
|
|
47
|
-
assertReadIsNonNullAllowed(meta, config, dbNullable)
|
|
48
|
-
const addValidation = config.db?.isNullable === false || config.validation?.isRequired
|
|
49
|
-
if (addValidation) {
|
|
50
|
-
const validate = async function (args) {
|
|
51
|
-
const { operation, addValidationError, resolvedData } = args
|
|
52
|
-
|
|
53
|
-
if (valueRequired) {
|
|
54
|
-
const value = resolvedData?.[meta.fieldKey]
|
|
55
|
-
if (
|
|
56
|
-
(operation === 'create' && value === undefined) ||
|
|
57
|
-
((operation === 'create' || operation === 'update') && value === null)
|
|
58
|
-
) {
|
|
59
|
-
addValidationError(`missing value`)
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
await f?.(args)
|
|
64
|
-
} satisfies ValidateFieldHook<
|
|
65
|
-
|
|
66
|
-
return {
|
|
67
|
-
mode,
|
|
68
|
-
validate: merge(validate, config.hooks?.validate),
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
return {
|
|
73
|
-
mode,
|
|
74
|
-
validate: merge(f, config.hooks?.validate),
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
export function assertReadIsNonNullAllowed<
|
|
79
|
-
meta: FieldData<
|
|
80
|
-
config: {
|
|
81
|
-
graphql?: {
|
|
82
|
-
isNonNull?:
|
|
83
|
-
| boolean
|
|
84
|
-
| {
|
|
85
|
-
read?: boolean
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
},
|
|
89
|
-
dbNullable: boolean
|
|
90
|
-
) {
|
|
91
|
-
if (!dbNullable) return
|
|
92
|
-
if (!config.graphql?.isNonNull) return
|
|
93
|
-
if (typeof config.graphql?.isNonNull === 'object' && !config.graphql.isNonNull.read) return
|
|
94
|
-
|
|
95
|
-
throw new Error(
|
|
96
|
-
`${meta.listKey}.${meta.fieldKey} sets graphql.isNonNull.read: true, but not validation.isRequired: true (or db.isNullable: false)\n` +
|
|
97
|
-
`Set validation.isRequired: true, or db.isNullable: false, or graphql.isNonNull.read: false`
|
|
98
|
-
)
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
export function defaultIsRequired(config: CommonFieldConfig<any, any>, isRequired: boolean) {
|
|
102
|
-
return {
|
|
103
|
-
ui: {
|
|
104
|
-
...config.ui,
|
|
105
|
-
createView: {
|
|
106
|
-
...config.ui?.createView,
|
|
107
|
-
isRequired: config.ui?.createView?.isRequired ?? isRequired,
|
|
108
|
-
},
|
|
109
|
-
itemView: {
|
|
110
|
-
...config.ui?.itemView,
|
|
111
|
-
isRequired: config.ui?.itemView?.isRequired ?? isRequired,
|
|
112
|
-
},
|
|
113
|
-
},
|
|
114
|
-
}
|
|
115
|
-
}
|
|
1
|
+
import type { BaseFieldTypeInfo, CommonFieldConfig } from '../types'
|
|
2
|
+
import { type BaseCollectionTypeInfo, type FieldData } from '../types'
|
|
3
|
+
import type { FieldHooks } from '../types/config/hooks'
|
|
4
|
+
import { type ValidateFieldHook } from '../types/config/hooks'
|
|
5
|
+
import { merge } from './resolve-hooks'
|
|
6
|
+
|
|
7
|
+
export function resolveDbNullable(
|
|
8
|
+
validation: undefined | { isRequired?: boolean },
|
|
9
|
+
db: undefined | { isNullable?: boolean }
|
|
10
|
+
): boolean {
|
|
11
|
+
if (db?.isNullable === false) return false
|
|
12
|
+
if (db?.isNullable === undefined && validation?.isRequired) {
|
|
13
|
+
return false
|
|
14
|
+
}
|
|
15
|
+
return true
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export function makeValidateHook<CollectionTypeInfo extends BaseCollectionTypeInfo>(
|
|
19
|
+
meta: FieldData<CollectionTypeInfo>,
|
|
20
|
+
config: {
|
|
21
|
+
label?: string
|
|
22
|
+
db?: {
|
|
23
|
+
isNullable?: boolean
|
|
24
|
+
}
|
|
25
|
+
graphql?: {
|
|
26
|
+
isNonNull?:
|
|
27
|
+
| boolean
|
|
28
|
+
| {
|
|
29
|
+
read?: boolean
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
validation?: {
|
|
33
|
+
isRequired?: boolean
|
|
34
|
+
[key: string]: unknown
|
|
35
|
+
}
|
|
36
|
+
hooks?: {
|
|
37
|
+
validate?: FieldHooks<CollectionTypeInfo, any>['validate']
|
|
38
|
+
}
|
|
39
|
+
},
|
|
40
|
+
f?: ValidateFieldHook<CollectionTypeInfo, 'create' | 'update' | 'delete', BaseFieldTypeInfo>,
|
|
41
|
+
hasPrismaDefaultValue: boolean = false
|
|
42
|
+
) {
|
|
43
|
+
const dbNullable = resolveDbNullable(config.validation, config.db)
|
|
44
|
+
const mode = dbNullable ? ('optional' as const) : ('required' as const)
|
|
45
|
+
const valueRequired = (config.validation?.isRequired || !dbNullable) && !hasPrismaDefaultValue
|
|
46
|
+
|
|
47
|
+
assertReadIsNonNullAllowed(meta, config, dbNullable)
|
|
48
|
+
const addValidation = config.db?.isNullable === false || config.validation?.isRequired
|
|
49
|
+
if (addValidation) {
|
|
50
|
+
const validate = async function (args) {
|
|
51
|
+
const { operation, addValidationError, resolvedData } = args
|
|
52
|
+
|
|
53
|
+
if (valueRequired) {
|
|
54
|
+
const value = resolvedData?.[meta.fieldKey]
|
|
55
|
+
if (
|
|
56
|
+
(operation === 'create' && value === undefined) ||
|
|
57
|
+
((operation === 'create' || operation === 'update') && value === null)
|
|
58
|
+
) {
|
|
59
|
+
addValidationError(`missing value`)
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
await f?.(args)
|
|
64
|
+
} satisfies ValidateFieldHook<CollectionTypeInfo, 'create' | 'update' | 'delete', BaseFieldTypeInfo>
|
|
65
|
+
|
|
66
|
+
return {
|
|
67
|
+
mode,
|
|
68
|
+
validate: merge(validate, config.hooks?.validate),
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
return {
|
|
73
|
+
mode,
|
|
74
|
+
validate: merge(f, config.hooks?.validate),
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export function assertReadIsNonNullAllowed<CollectionTypeInfo extends BaseCollectionTypeInfo>(
|
|
79
|
+
meta: FieldData<CollectionTypeInfo>,
|
|
80
|
+
config: {
|
|
81
|
+
graphql?: {
|
|
82
|
+
isNonNull?:
|
|
83
|
+
| boolean
|
|
84
|
+
| {
|
|
85
|
+
read?: boolean
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
},
|
|
89
|
+
dbNullable: boolean
|
|
90
|
+
) {
|
|
91
|
+
if (!dbNullable) return
|
|
92
|
+
if (!config.graphql?.isNonNull) return
|
|
93
|
+
if (typeof config.graphql?.isNonNull === 'object' && !config.graphql.isNonNull.read) return
|
|
94
|
+
|
|
95
|
+
throw new Error(
|
|
96
|
+
`${meta.listKey}.${meta.fieldKey} sets graphql.isNonNull.read: true, but not validation.isRequired: true (or db.isNullable: false)\n` +
|
|
97
|
+
`Set validation.isRequired: true, or db.isNullable: false, or graphql.isNonNull.read: false`
|
|
98
|
+
)
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
export function defaultIsRequired(config: CommonFieldConfig<any, any>, isRequired: boolean) {
|
|
102
|
+
return {
|
|
103
|
+
ui: {
|
|
104
|
+
...config.ui,
|
|
105
|
+
createView: {
|
|
106
|
+
...config.ui?.createView,
|
|
107
|
+
isRequired: config.ui?.createView?.isRequired ?? isRequired,
|
|
108
|
+
},
|
|
109
|
+
itemView: {
|
|
110
|
+
...config.ui?.itemView,
|
|
111
|
+
isRequired: config.ui?.itemView?.isRequired ?? isRequired,
|
|
112
|
+
},
|
|
113
|
+
},
|
|
114
|
+
}
|
|
115
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { SimpleFieldTypeInfo } from '../../../types'
|
|
2
2
|
import {
|
|
3
|
-
type
|
|
3
|
+
type BaseCollectionTypeInfo,
|
|
4
4
|
type CommonFieldConfig,
|
|
5
5
|
type FieldTypeFunc,
|
|
6
6
|
fieldType,
|
|
@@ -11,8 +11,8 @@ import { filters } from '../../filters'
|
|
|
11
11
|
import { resolveDbNullable, makeValidateHook, defaultIsRequired } from '../../non-null-graphql'
|
|
12
12
|
import type { controller } from './views'
|
|
13
13
|
|
|
14
|
-
export type BigIntFieldConfig<
|
|
15
|
-
|
|
14
|
+
export type BigIntFieldConfig<CollectionTypeInfo extends BaseCollectionTypeInfo> = CommonFieldConfig<
|
|
15
|
+
CollectionTypeInfo,
|
|
16
16
|
SimpleFieldTypeInfo<'BigInt'>
|
|
17
17
|
> & {
|
|
18
18
|
isIndexed?: boolean | 'unique'
|
|
@@ -34,9 +34,9 @@ const MAX_INT = 9223372036854775807n
|
|
|
34
34
|
const MIN_INT = -9223372036854775808n
|
|
35
35
|
|
|
36
36
|
// TODO: https://github.com/Nixxie/keystatic/blob/main/design-system/pkg/src/number-field/NumberField.tsx
|
|
37
|
-
export function bigInt<
|
|
38
|
-
config: BigIntFieldConfig<
|
|
39
|
-
): FieldTypeFunc<
|
|
37
|
+
export function bigInt<CollectionTypeInfo extends BaseCollectionTypeInfo>(
|
|
38
|
+
config: BigIntFieldConfig<CollectionTypeInfo> = {}
|
|
39
|
+
): FieldTypeFunc<CollectionTypeInfo> {
|
|
40
40
|
const { defaultValue: defaultValue_ = null, isIndexed, validation = {} } = config
|
|
41
41
|
|
|
42
42
|
const { isRequired = false, min, max } = validation
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import {
|
|
2
|
-
type
|
|
2
|
+
type BaseCollectionTypeInfo,
|
|
3
3
|
type CommonFieldConfig,
|
|
4
4
|
type FieldTypeFunc,
|
|
5
5
|
fieldType,
|
|
@@ -33,8 +33,8 @@ export type FieldTypeInfo = {
|
|
|
33
33
|
}
|
|
34
34
|
}
|
|
35
35
|
|
|
36
|
-
export type BytesFieldConfig<
|
|
37
|
-
|
|
36
|
+
export type BytesFieldConfig<CollectionTypeInfo extends BaseCollectionTypeInfo> = CommonFieldConfig<
|
|
37
|
+
CollectionTypeInfo,
|
|
38
38
|
FieldTypeInfo
|
|
39
39
|
> & {
|
|
40
40
|
isIndexed?: boolean | 'unique'
|
|
@@ -73,9 +73,9 @@ export type TextFieldMeta = {
|
|
|
73
73
|
defaultValue: string | null
|
|
74
74
|
}
|
|
75
75
|
|
|
76
|
-
export function bytes<
|
|
77
|
-
config: BytesFieldConfig<
|
|
78
|
-
): FieldTypeFunc<
|
|
76
|
+
export function bytes<CollectionTypeInfo extends BaseCollectionTypeInfo>(
|
|
77
|
+
config: BytesFieldConfig<CollectionTypeInfo> = {}
|
|
78
|
+
): FieldTypeFunc<CollectionTypeInfo> {
|
|
79
79
|
const { defaultValue = null, isIndexed, validation = {} } = config
|
|
80
80
|
|
|
81
81
|
const scalar = config.graphql?.scalar ?? g.Hex
|
|
@@ -8,7 +8,7 @@ import type {
|
|
|
8
8
|
|
|
9
9
|
import { g } from '../../..'
|
|
10
10
|
import {
|
|
11
|
-
type
|
|
11
|
+
type BaseCollectionTypeInfo,
|
|
12
12
|
type CommonFieldConfig,
|
|
13
13
|
type FieldTypeFunc,
|
|
14
14
|
type SimpleFieldTypeInfo,
|
|
@@ -19,25 +19,23 @@ import { filters } from '../../filters'
|
|
|
19
19
|
import { defaultIsRequired, makeValidateHook } from '../../non-null-graphql'
|
|
20
20
|
import type { CalendarDayFieldMeta } from './views'
|
|
21
21
|
|
|
22
|
-
export type CalendarDayFieldConfig<
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
map?: string
|
|
22
|
+
export type CalendarDayFieldConfig<CollectionTypeInfo extends BaseCollectionTypeInfo> =
|
|
23
|
+
CommonFieldConfig<CollectionTypeInfo, SimpleFieldTypeInfo<'String' | 'DateTime'>> & {
|
|
24
|
+
isIndexed?: boolean | 'unique'
|
|
25
|
+
validation?: {
|
|
26
|
+
isRequired?: boolean
|
|
27
|
+
}
|
|
28
|
+
defaultValue?: string
|
|
29
|
+
db?: {
|
|
30
|
+
isNullable?: boolean
|
|
31
|
+
extendPrismaSchema?: (field: string) => string
|
|
32
|
+
map?: string
|
|
33
|
+
}
|
|
35
34
|
}
|
|
36
|
-
}
|
|
37
35
|
|
|
38
|
-
export function calendarDay<
|
|
39
|
-
config: CalendarDayFieldConfig<
|
|
40
|
-
): FieldTypeFunc<
|
|
36
|
+
export function calendarDay<CollectionTypeInfo extends BaseCollectionTypeInfo>(
|
|
37
|
+
config: CalendarDayFieldConfig<CollectionTypeInfo> = {}
|
|
38
|
+
): FieldTypeFunc<CollectionTypeInfo> {
|
|
41
39
|
const { isIndexed, validation, defaultValue } = config
|
|
42
40
|
return meta => {
|
|
43
41
|
if (typeof defaultValue === 'string') {
|
|
@@ -45,7 +43,8 @@ export function calendarDay<ListTypeInfo extends BaseListTypeInfo>(
|
|
|
45
43
|
g.CalendarDay.parseValue(defaultValue)
|
|
46
44
|
} catch (err) {
|
|
47
45
|
throw new Error(
|
|
48
|
-
`The calendarDay field at ${meta.listKey}.${meta.fieldKey} specifies defaultValue: ${defaultValue} but values must be provided as a full-date ISO8601 string such as 1970-01-01
|
|
46
|
+
`The calendarDay field at ${meta.listKey}.${meta.fieldKey} specifies defaultValue: ${defaultValue} but values must be provided as a full-date ISO8601 string such as 1970-01-01`,
|
|
47
|
+
{ cause: err }
|
|
49
48
|
)
|
|
50
49
|
}
|
|
51
50
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { userInputError } from '../../../lib/core/graphql-errors'
|
|
2
2
|
import type { SimpleFieldTypeInfo } from '../../../types'
|
|
3
3
|
import {
|
|
4
|
-
type
|
|
4
|
+
type BaseCollectionTypeInfo,
|
|
5
5
|
type CommonFieldConfig,
|
|
6
6
|
type FieldTypeFunc,
|
|
7
7
|
fieldType,
|
|
@@ -12,8 +12,8 @@ import { assertReadIsNonNullAllowed } from '../../non-null-graphql'
|
|
|
12
12
|
import { filters } from '../../filters'
|
|
13
13
|
import type { controller } from './views'
|
|
14
14
|
|
|
15
|
-
export type CheckboxFieldConfig<
|
|
16
|
-
|
|
15
|
+
export type CheckboxFieldConfig<CollectionTypeInfo extends BaseCollectionTypeInfo> = CommonFieldConfig<
|
|
16
|
+
CollectionTypeInfo,
|
|
17
17
|
SimpleFieldTypeInfo<'Boolean'>
|
|
18
18
|
> & {
|
|
19
19
|
defaultValue?: boolean
|
|
@@ -23,9 +23,9 @@ export type CheckboxFieldConfig<ListTypeInfo extends BaseListTypeInfo> = CommonF
|
|
|
23
23
|
}
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
-
export function checkbox<
|
|
27
|
-
config: CheckboxFieldConfig<
|
|
28
|
-
): FieldTypeFunc<
|
|
26
|
+
export function checkbox<CollectionTypeInfo extends BaseCollectionTypeInfo>(
|
|
27
|
+
config: CheckboxFieldConfig<CollectionTypeInfo> = {}
|
|
28
|
+
): FieldTypeFunc<CollectionTypeInfo> {
|
|
29
29
|
const { defaultValue = false } = config
|
|
30
30
|
|
|
31
31
|
return meta => {
|