@tryghost/metafield-types 0.2.0 → 0.3.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 +48 -0
- package/README.md +26 -20
- package/build/index.d.ts +278 -61
- package/build/index.d.ts.map +1 -1
- package/build/index.js +273 -96
- package/build/index.js.map +1 -1
- package/build/structure.d.ts +247 -59
- package/build/structure.d.ts.map +1 -1
- package/build/structure.js +158 -59
- package/build/structure.js.map +1 -1
- package/package.json +2 -2
package/build/index.js
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
|
-
import {
|
|
2
|
+
import { KeySchema, NamespaceSchema } from './identity.js';
|
|
3
|
+
import { FIELD_STRUCTURES, FIELD_TYPE_IDS, MAX_OPTIONS, MIN_OPTIONS, OPTION_SEPARATOR, optionText, matchField, matchLeaf, typesOfShape, } from './structure.js';
|
|
3
4
|
// Re-exported so a caller that needs both halves still has one import. The split is
|
|
4
5
|
// about what a bundle pays for, not about where the catalog lives.
|
|
5
|
-
export {
|
|
6
|
+
export { FIELD_STRUCTURES, FIELD_TYPE_IDS, LIST_SOURCES, MAX_OPTIONS, MIN_OPTIONS, OPTION_SEPARATOR, TEXT_SIZES, choice, country, editableAnswers, inOptionOrder, isFieldType, isRecordValue, matchField, matchLeaf, matchShape, partsOf, text, } from './structure.js';
|
|
6
7
|
/**
|
|
7
8
|
* The shared catalog of member metafield types.
|
|
8
9
|
*
|
|
@@ -12,10 +13,9 @@ export { FIELD_KINDS, FIELD_PARTS, FIELD_TYPE_IDS, PART_TYPE_IDS, partTypesOf, p
|
|
|
12
13
|
* last statement lives here and nowhere else, so that Ghost core, which enforces it, and
|
|
13
14
|
* admin, which gives instant feedback against it, cannot disagree about what is valid.
|
|
14
15
|
*
|
|
15
|
-
* A type is
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
* part being a record itself.
|
|
16
|
+
* A type is composed of leaves, each one value with its own rule. Most types are a single
|
|
17
|
+
* leaf. An address is a *record*: a set of named parts, each a leaf, from which the whole
|
|
18
|
+
* type's rule is derived. A part is always a leaf, never a record itself.
|
|
19
19
|
*
|
|
20
20
|
* ## What a write may say
|
|
21
21
|
*
|
|
@@ -53,9 +53,9 @@ export { FIELD_KINDS, FIELD_PARTS, FIELD_TYPE_IDS, PART_TYPE_IDS, partTypesOf, p
|
|
|
53
53
|
* answer and a disagreement between them is a file that silently stops round-tripping.
|
|
54
54
|
*
|
|
55
55
|
* The line is whether more than one renderer must agree on a string, not presentation
|
|
56
|
-
* against validity — the sentences above are presentation. Admin
|
|
57
|
-
*
|
|
58
|
-
*
|
|
56
|
+
* against validity — the sentences above are presentation. Admin and Portal each label a
|
|
57
|
+
* record's parts in their own words, and each is held against the catalog by a type, so a
|
|
58
|
+
* part added there fails to compile in both until it has a label.
|
|
59
59
|
*/
|
|
60
60
|
export const FieldTypeSchema = z.enum(FIELD_TYPE_IDS);
|
|
61
61
|
/**
|
|
@@ -74,6 +74,156 @@ export const MEMBER_ACCESS = {
|
|
|
74
74
|
read: 'read',
|
|
75
75
|
write: 'write',
|
|
76
76
|
};
|
|
77
|
+
/**
|
|
78
|
+
* Whether a field is in use. An archived field keeps its definition and the values members
|
|
79
|
+
* hold for it, so it can be restored, but it takes no new values and members no longer see it.
|
|
80
|
+
*/
|
|
81
|
+
export const FIELD_STATUSES = ['active', 'archived'];
|
|
82
|
+
export const FieldStatusSchema = z.enum(FIELD_STATUSES);
|
|
83
|
+
export const FIELD_STATUS = {
|
|
84
|
+
active: 'active',
|
|
85
|
+
archived: 'archived',
|
|
86
|
+
};
|
|
87
|
+
/**
|
|
88
|
+
* A set field's settings as stored or sent back: their shape alone, which every read checks. A
|
|
89
|
+
* write checks the rules `SetSettingsSchema` layers on top, so a rule tightened later never hides
|
|
90
|
+
* a field set up under the old one, the way a value's rule never hides what a member already holds.
|
|
91
|
+
*/
|
|
92
|
+
export const SetSettingsShape = z.object({
|
|
93
|
+
options: z.array(z.string({ error: 'Enter text for each option.' }), {
|
|
94
|
+
error: 'Give the list its options.',
|
|
95
|
+
}),
|
|
96
|
+
multiple: z.boolean({ error: 'Say whether members can pick more than one option.' }),
|
|
97
|
+
}, { error: 'Give the list its options.' });
|
|
98
|
+
/**
|
|
99
|
+
* Why an option's text, once tidied, can't be written, or null when it can. Its text is all that
|
|
100
|
+
* names it, so each bound is on the text as it is matched, and the separator a CSV cell joins
|
|
101
|
+
* options with can't appear in one.
|
|
102
|
+
*/
|
|
103
|
+
function optionProblem(option) {
|
|
104
|
+
if (option.length === 0) {
|
|
105
|
+
return 'Enter text for each option.';
|
|
106
|
+
}
|
|
107
|
+
if (option.length > 255) {
|
|
108
|
+
return 'Use 255 characters or fewer for each option.';
|
|
109
|
+
}
|
|
110
|
+
if (option.includes(OPTION_SEPARATOR)) {
|
|
111
|
+
return `Options can't contain ${OPTION_SEPARATOR}.`;
|
|
112
|
+
}
|
|
113
|
+
return null;
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* What a set field is set up with: its shape, with each option's text tidied and the rules a write
|
|
117
|
+
* must meet on top. Options are a set as well, so the same text can't be offered twice; they are
|
|
118
|
+
* listed in the order they are shown.
|
|
119
|
+
*/
|
|
120
|
+
export const SetSettingsSchema = SetSettingsShape.transform(({ options, multiple }) => ({
|
|
121
|
+
options: options.map(optionText),
|
|
122
|
+
multiple,
|
|
123
|
+
})).check((ctx) => {
|
|
124
|
+
const { options } = ctx.value;
|
|
125
|
+
options.forEach((option, index) => {
|
|
126
|
+
const problem = optionProblem(option);
|
|
127
|
+
if (problem) {
|
|
128
|
+
ctx.issues.push({
|
|
129
|
+
code: 'custom',
|
|
130
|
+
message: problem,
|
|
131
|
+
input: option,
|
|
132
|
+
path: ['options', index],
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
});
|
|
136
|
+
const listProblem = options.length < MIN_OPTIONS
|
|
137
|
+
? `Give the list at least ${MIN_OPTIONS} options.`
|
|
138
|
+
: options.length > MAX_OPTIONS
|
|
139
|
+
? `Give the list ${MAX_OPTIONS} options or fewer.`
|
|
140
|
+
: new Set(options).size !== options.length
|
|
141
|
+
? 'Give each option once.'
|
|
142
|
+
: null;
|
|
143
|
+
if (listProblem) {
|
|
144
|
+
ctx.issues.push({ code: 'custom', message: listProblem, input: options, path: ['options'] });
|
|
145
|
+
}
|
|
146
|
+
});
|
|
147
|
+
/**
|
|
148
|
+
* A field whose type has nothing to set up has no settings, so a write that gives it some is
|
|
149
|
+
* refused.
|
|
150
|
+
*/
|
|
151
|
+
const NO_SETTINGS = z.undefined({ error: 'Only a list field has settings.' }).optional();
|
|
152
|
+
const TYPE_ERROR = { error: 'Choose a type of custom field.' };
|
|
153
|
+
/**
|
|
154
|
+
* What a field holds beside its type, `base`, with its type and the settings that type's shape
|
|
155
|
+
* takes, held as `settings` says for each shape: a set's options, and nothing for any other shape.
|
|
156
|
+
* One variant per shape, so a field's settings are always read against its type. Writes give the
|
|
157
|
+
* rules, reads the shape alone, and Ghost's table its column.
|
|
158
|
+
*/
|
|
159
|
+
export const withTypedSettings = (base, settings) => {
|
|
160
|
+
// Keyed by shape, so a shape added to the catalog fails to compile here until it has a variant.
|
|
161
|
+
const variants = {
|
|
162
|
+
scalar: z.object({ ...base, type: z.enum(typesOfShape('scalar')), settings: settings.scalar }),
|
|
163
|
+
record: z.object({ ...base, type: z.enum(typesOfShape('record')), settings: settings.record }),
|
|
164
|
+
set: z.object({ ...base, type: z.enum(typesOfShape('set')), settings: settings.set }),
|
|
165
|
+
};
|
|
166
|
+
return z.discriminatedUnion('type', [variants.scalar, variants.record, variants.set], TYPE_ERROR);
|
|
167
|
+
};
|
|
168
|
+
/**
|
|
169
|
+
* Each shape's settings in one place: a set's options and whether a member picks several, and
|
|
170
|
+
* nothing for any other shape. A list's defaults have no options, which a list's write rules
|
|
171
|
+
* refuse, so an edit of a list read with its defaults always writes the settings it is given.
|
|
172
|
+
* Keyed by shape, so a shape added to the catalog fails to compile until it has an entry.
|
|
173
|
+
*/
|
|
174
|
+
export const SHAPE_SETTINGS = {
|
|
175
|
+
scalar: { written: NO_SETTINGS, read: NO_SETTINGS, defaults: undefined },
|
|
176
|
+
record: { written: NO_SETTINGS, read: NO_SETTINGS, defaults: undefined },
|
|
177
|
+
set: {
|
|
178
|
+
written: SetSettingsSchema,
|
|
179
|
+
read: SetSettingsShape,
|
|
180
|
+
defaults: { options: [], multiple: false },
|
|
181
|
+
},
|
|
182
|
+
};
|
|
183
|
+
/** Each shape's settings as a write states them, checked against the rules. */
|
|
184
|
+
export const WRITTEN_SETTINGS = {
|
|
185
|
+
scalar: SHAPE_SETTINGS.scalar.written,
|
|
186
|
+
record: SHAPE_SETTINGS.record.written,
|
|
187
|
+
set: SHAPE_SETTINGS.set.written,
|
|
188
|
+
};
|
|
189
|
+
/** Each shape's settings as they are read back, checked for their shape alone. */
|
|
190
|
+
export const READ_SETTINGS = {
|
|
191
|
+
scalar: SHAPE_SETTINGS.scalar.read,
|
|
192
|
+
record: SHAPE_SETTINGS.record.read,
|
|
193
|
+
set: SHAPE_SETTINGS.set.read,
|
|
194
|
+
};
|
|
195
|
+
/**
|
|
196
|
+
* Where a refusal points within what was sent: the path to the refused value, with its parts and
|
|
197
|
+
* positions joined by dots, such as `settings.options.2` for a field's third option. Ghost names
|
|
198
|
+
* a refusal's `property` this way, and a form files the problems it finds under the same keys, so
|
|
199
|
+
* each lands beside the input that set the value.
|
|
200
|
+
*/
|
|
201
|
+
export function refusedProperty(path) {
|
|
202
|
+
return path.map(String).join('.');
|
|
203
|
+
}
|
|
204
|
+
/**
|
|
205
|
+
* A field's type and settings as a write states them, checked together and against the rules:
|
|
206
|
+
* the settings must be what that type is set up with, so a list carries its options and
|
|
207
|
+
* nothing else carries any.
|
|
208
|
+
*/
|
|
209
|
+
export const TypedSettingsInputSchema = withTypedSettings({}, WRITTEN_SETTINGS);
|
|
210
|
+
/** A field's type and settings as they are read back: paired, but checked for their shape alone. */
|
|
211
|
+
export const TypedSettingsSchema = withTypedSettings({}, READ_SETTINGS);
|
|
212
|
+
/**
|
|
213
|
+
* A field definition as the Admin and Members APIs return it. Ghost writes every definition through
|
|
214
|
+
* this and Admin reads every one through it, so both ends are checked against one shape. Portal
|
|
215
|
+
* uses the type without the check, because zod would add to every page view on every site. Dates
|
|
216
|
+
* are ISO strings, as JSON carries them.
|
|
217
|
+
*/
|
|
218
|
+
export const MetafieldDefinitionSchema = withTypedSettings({
|
|
219
|
+
namespace: NamespaceSchema,
|
|
220
|
+
key: KeySchema,
|
|
221
|
+
name: z.string(),
|
|
222
|
+
status: FieldStatusSchema,
|
|
223
|
+
access: z.object({ member: MemberAccessSchema }),
|
|
224
|
+
created_at: z.iso.datetime(),
|
|
225
|
+
updated_at: z.iso.datetime().nullable(),
|
|
226
|
+
}, READ_SETTINGS);
|
|
77
227
|
/**
|
|
78
228
|
* Where a change to a member's values was made, as a member's activity feed names it.
|
|
79
229
|
* Shared so a place added on the server is one Admin has to be told how to describe.
|
|
@@ -86,7 +236,7 @@ export const METAFIELD_CHANGE_SOURCES = [
|
|
|
86
236
|
'checkout',
|
|
87
237
|
];
|
|
88
238
|
/** Whether a source is one this build knows how to name; a newer server can send others. */
|
|
89
|
-
export const isMetafieldChangeSource = (source) => METAFIELD_CHANGE_SOURCES.
|
|
239
|
+
export const isMetafieldChangeSource = (source) => METAFIELD_CHANGE_SOURCES.some((known) => known === source);
|
|
90
240
|
/** A field as an activity feed entry names it: its name is copied so the entry outlives a rename. */
|
|
91
241
|
export const MetafieldChangeEventFieldSchema = z.object({
|
|
92
242
|
namespace: z.string(),
|
|
@@ -101,103 +251,130 @@ export const MAX_LONG_TEXT_BYTES = 65535;
|
|
|
101
251
|
// TextEncoder rather than Buffer: this package runs in the browser too.
|
|
102
252
|
const byteLength = (value) => new TextEncoder().encode(value).length;
|
|
103
253
|
/**
|
|
104
|
-
* Every
|
|
105
|
-
*
|
|
106
|
-
*
|
|
107
|
-
*
|
|
108
|
-
* Builders are named after what a value is rather than taking a size, so that a bound
|
|
109
|
-
* lives with everything else true of that thing instead of as a number at the call site.
|
|
254
|
+
* Every leaf's rule is built from this, so no two leaves can disagree about whitespace: a value
|
|
255
|
+
* of nothing but spaces is nothing, whichever field it was typed into. Trimming first also makes
|
|
256
|
+
* each bound measure the value rather than its padding.
|
|
110
257
|
*/
|
|
111
|
-
const
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
})
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
//
|
|
126
|
-
//
|
|
127
|
-
|
|
128
|
-
//
|
|
129
|
-
// them. Membership of that list is contested, and a closed list here would make Ghost
|
|
130
|
-
// the arbiter of it for every member of every site. The collection form can offer
|
|
131
|
-
// countries to pick from without this deciding which ones exist.
|
|
132
|
-
//
|
|
133
|
-
// Case is normalized so that `gb` and `GB` are not two values for one place, which a
|
|
134
|
-
// filter for either would silently half-miss.
|
|
258
|
+
const trimmed = () => z.string({ error: 'Enter text.' }).trim();
|
|
259
|
+
/** Each text size's bound. Each message is a literal, so it can be a translation key. */
|
|
260
|
+
const TEXT_RULES = {
|
|
261
|
+
line: () => trimmed().max(255, { error: 'Use 255 characters or fewer.' }),
|
|
262
|
+
// A sanity limit rather than a format, used for postal codes: they vary too much between
|
|
263
|
+
// countries to check the shape of one without knowing the country, and the country is a
|
|
264
|
+
// sibling part rather than something this can see.
|
|
265
|
+
code: () => trimmed().max(32, { error: 'Use 32 characters or fewer.' }),
|
|
266
|
+
long: () => trimmed().refine((value) => byteLength(value) <= MAX_LONG_TEXT_BYTES, {
|
|
267
|
+
error: 'This text is too long to save. Shorten it a little.',
|
|
268
|
+
}),
|
|
269
|
+
};
|
|
270
|
+
/** Which keys each list accepts. */
|
|
271
|
+
const LIST_RULES = {
|
|
272
|
+
// The shape of an ISO 3166-1 alpha-2 code, deliberately not checked against the list of them.
|
|
273
|
+
// Membership of that list is contested, and a closed list here would make Ghost the arbiter of
|
|
274
|
+
// it for every member of every site. Clients offer countries to pick from without this deciding
|
|
275
|
+
// which ones exist.
|
|
135
276
|
//
|
|
136
|
-
//
|
|
137
|
-
//
|
|
138
|
-
|
|
277
|
+
// Case is normalized so that `gb` and `GB` are not two values for one place, which a filter for
|
|
278
|
+
// either would silently half-miss. Checked as two ASCII letters on the way in rather than by
|
|
279
|
+
// length on the way out, because uppercasing does not preserve length: `ß` becomes `SS`.
|
|
280
|
+
countries: () => trimmed()
|
|
139
281
|
.regex(/^[A-Za-z]{2}$/, { error: 'Enter a 2-letter country code, like US.' })
|
|
140
282
|
.toUpperCase(),
|
|
141
|
-
// Every part type declared next door needs a rule here, and nothing here may
|
|
142
|
-
// invent one that is not declared there.
|
|
143
283
|
};
|
|
144
|
-
const
|
|
284
|
+
const leafRule = (leaf) => matchLeaf(leaf, {
|
|
285
|
+
text: ({ size }) => TEXT_RULES[size](),
|
|
286
|
+
choice: ({ from }) => LIST_RULES[from](),
|
|
287
|
+
});
|
|
145
288
|
/**
|
|
146
|
-
* A part as a write may name it: absent, empty, or a value of its own
|
|
147
|
-
*
|
|
148
|
-
*
|
|
149
|
-
* and would leave its part the only one that could be set but never removed.
|
|
289
|
+
* A part as a write may name it: absent, empty, or a value of its own leaf. A rule that is a bound
|
|
290
|
+
* would admit empty on its own; one that is a format would not, and would leave its part the only
|
|
291
|
+
* one that could be set but never removed.
|
|
150
292
|
*/
|
|
151
|
-
const clearable = (
|
|
152
|
-
.pipe(z.union([z.literal(''),
|
|
293
|
+
const clearable = (rule) => trimmed()
|
|
294
|
+
.pipe(z.union([z.literal(''), rule]))
|
|
153
295
|
.optional();
|
|
296
|
+
/** What each record type says when a write names none of its parts. */
|
|
297
|
+
const RECORD_EMPTY = {
|
|
298
|
+
address: 'Enter at least one part of the address.',
|
|
299
|
+
};
|
|
154
300
|
/**
|
|
155
|
-
*
|
|
156
|
-
*
|
|
157
|
-
*
|
|
301
|
+
* A record type's rule, derived from its parts.
|
|
302
|
+
*
|
|
303
|
+
* A record's parts are all optional, because none of an address's exists everywhere: there is no
|
|
304
|
+
* postal code in Ireland or Hong Kong, and no city in an Irish townland address. What holds instead
|
|
305
|
+
* is that a value names at least one part. The check is on each part being a string because an
|
|
306
|
+
* optional part that is explicitly undefined survives parsing as a key holding undefined, and a
|
|
307
|
+
* bare presence check would let `{line1: undefined}` through as if it named something.
|
|
308
|
+
*
|
|
309
|
+
* A record is strict, so a part nobody declared is refused rather than dropped, in zod's wording,
|
|
310
|
+
* which names the offending key.
|
|
158
311
|
*/
|
|
159
|
-
function
|
|
160
|
-
return
|
|
312
|
+
function recordRule(type) {
|
|
313
|
+
return z
|
|
314
|
+
.strictObject(Object.fromEntries(Object.entries(FIELD_STRUCTURES[type].parts).map(([part, leaf]) => [
|
|
315
|
+
part,
|
|
316
|
+
clearable(leafRule(leaf)),
|
|
317
|
+
])))
|
|
318
|
+
.refine((value) => Object.values(value).some((entry) => typeof entry === 'string'), {
|
|
319
|
+
error: RECORD_EMPTY[type],
|
|
320
|
+
});
|
|
161
321
|
}
|
|
162
322
|
/**
|
|
163
|
-
*
|
|
164
|
-
*
|
|
165
|
-
*
|
|
166
|
-
*
|
|
167
|
-
*
|
|
168
|
-
*
|
|
169
|
-
*
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
323
|
+
* A set field's rule, from its own options: the text of each option picked, picking any option
|
|
324
|
+
* once however often it is named, and only one of them when the field takes one. A failure is
|
|
325
|
+
* reported against the whole field rather than at a position in the list, which a client would
|
|
326
|
+
* read as an option named by a number.
|
|
327
|
+
*
|
|
328
|
+
* Checked when an answer is given and never again: a publisher can change the options later, and
|
|
329
|
+
* an answer keeps what was picked.
|
|
330
|
+
*/
|
|
331
|
+
function setRule({ options, multiple }) {
|
|
332
|
+
const offered = new Set(options);
|
|
333
|
+
return z
|
|
334
|
+
.array(z.unknown(), { error: 'Choose from the options this field offers.' })
|
|
335
|
+
.transform((picked, ctx) => {
|
|
336
|
+
const texts = picked.filter((option) => typeof option === 'string');
|
|
337
|
+
if (texts.length < picked.length) {
|
|
338
|
+
ctx.issues.push({
|
|
339
|
+
code: 'custom',
|
|
340
|
+
message: 'Choose from the options this field offers.',
|
|
341
|
+
input: picked,
|
|
342
|
+
});
|
|
343
|
+
return z.NEVER;
|
|
344
|
+
}
|
|
345
|
+
return [...new Set(texts.map(optionText))];
|
|
346
|
+
})
|
|
347
|
+
.check((ctx) => {
|
|
348
|
+
if (ctx.value.some((option) => !offered.has(option))) {
|
|
349
|
+
ctx.issues.push({
|
|
350
|
+
code: 'custom',
|
|
351
|
+
message: 'Choose from the options this field offers.',
|
|
352
|
+
input: ctx.value,
|
|
353
|
+
});
|
|
354
|
+
}
|
|
355
|
+
else if (!multiple && ctx.value.length > 1) {
|
|
356
|
+
ctx.issues.push({ code: 'custom', message: 'Choose one option.', input: ctx.value });
|
|
357
|
+
}
|
|
358
|
+
});
|
|
359
|
+
}
|
|
360
|
+
/** A field's rule, from what its type is composed of and, for a set, the options the field offers. */
|
|
361
|
+
function ruleOf(field) {
|
|
362
|
+
return matchField(field, {
|
|
363
|
+
scalar: ({ type }) => leafRule(FIELD_STRUCTURES[type].leaf),
|
|
364
|
+
record: ({ type }) => recordRule(type),
|
|
365
|
+
set: ({ settings }) => setRule(settings),
|
|
366
|
+
});
|
|
367
|
+
}
|
|
368
|
+
// Built once per type whose rule comes from the type alone: Ghost checks every value an import
|
|
369
|
+
// writes, and Admin every keystroke.
|
|
370
|
+
const RULES = new Map([...typesOfShape('scalar'), ...typesOfShape('record')].map((type) => [type, ruleOf({ type })]));
|
|
371
|
+
/**
|
|
372
|
+
* The rule a value of one field must satisfy. It takes the field rather than its type so that a
|
|
373
|
+
* rule depending on the field's own setup, such as the options a list field offers, changes here
|
|
374
|
+
* and nowhere else; such a rule is built from the field rather than kept per type. Throws for a
|
|
375
|
+
* type this build doesn't know.
|
|
376
|
+
*/
|
|
377
|
+
export function valueSchemaFor(field) {
|
|
378
|
+
return RULES.get(field.type) ?? ruleOf(field);
|
|
187
379
|
}
|
|
188
|
-
export const FIELD_TYPES = defineFieldTypes({
|
|
189
|
-
short_text: { kind: 'text', value: PART_TYPES.short_text },
|
|
190
|
-
long_text: { kind: 'text', value: longText() },
|
|
191
|
-
// An address is a delivery address, so its bounds are what a courier will accept
|
|
192
|
-
// rather than what the column could hold. Modeled on Stripe's Address object.
|
|
193
|
-
//
|
|
194
|
-
// Who the parcel is addressed to is not here. A parcel needs a name as well as an
|
|
195
|
-
// address, but that is a fact about posting parcels rather than about either type,
|
|
196
|
-
// and the name is often not the account name — gift subscriptions, workplace
|
|
197
|
-
// deliveries, c/o. A site that needs one keeps it in a field of its own, which is
|
|
198
|
-
// also how Stripe hands it back: beside the address rather than inside it.
|
|
199
|
-
address: record('address', { error: 'Enter at least one part of the address.' }),
|
|
200
|
-
});
|
|
201
|
-
/** Named for the admin types built on it, which speak of an address rather than a record. */
|
|
202
|
-
export const AddressValue = FIELD_TYPES.address.value;
|
|
203
380
|
//# sourceMappingURL=index.js.map
|
package/build/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|