@tryghost/metafield-types 0.1.2 → 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.
@@ -1,78 +1,266 @@
1
1
  /**
2
2
  * What a field type is made of, with no opinion on what a valid value looks like.
3
3
  *
4
- * This is the half of the catalog a renderer needs. Drawing an address means knowing
5
- * it has six parts, in that order, and that the last of them holds a country code —
6
- * nothing about lengths, formats, or what happens when one is left blank.
4
+ * Every type is composed from a few building blocks. A leaf is one value: text of a size, or a
5
+ * choice from a list. A type is a leaf on its own, a record of named leaves, or a set of options
6
+ * its field offers. Everything that stores, exports, edits, filters or draws a value is written
7
+ * once per building block, so a type composed from existing blocks needs nothing beyond its entry
8
+ * here.
7
9
  *
8
- * It is separate from `./index` because that half is built out of zod, and zod is
9
- * sixty-odd kilobytes. Ghost's server enforces the rules and can afford them; Portal
10
- * only draws the inputs, and it loads on every page view of every themed site. Split
11
- * this way a renderer imports well under a kilobyte and still gets the types.
12
- *
13
- * The two halves cannot drift, because the schemas are built from these declarations
14
- * rather than beside them: adding a part here without a rule in `./index` fails to
15
- * compile.
10
+ * This half is separate from `./index` because that half is built out of zod, and zod is
11
+ * sixty-odd kilobytes. Ghost's server enforces the rules and can afford them; Portal only draws
12
+ * the inputs, and it loads on every page view of every themed site.
16
13
  */
17
- /** The source for the union type, the zod enum and the `FIELD_TYPES` keys alike. */
18
- export declare const FIELD_TYPE_IDS: readonly ['short_text', 'long_text', 'address'];
19
- export type FieldType = (typeof FIELD_TYPE_IDS)[number];
14
+ /** How much text a text leaf holds. Each size has its bound, and its message, in `./index`. */
15
+ export declare const TEXT_SIZES: readonly ['line', 'code', 'long'];
16
+ export type TextSize = (typeof TEXT_SIZES)[number];
17
+ /** The lists a choice can pick from. Each list says which keys it accepts in `./index`. */
18
+ export declare const LIST_SOURCES: readonly ['countries'];
19
+ export type ListSource = (typeof LIST_SOURCES)[number];
20
+ export interface TextLeaf {
21
+ readonly leaf: 'text';
22
+ readonly size: TextSize;
23
+ }
24
+ export interface ChoiceLeaf {
25
+ readonly leaf: 'choice';
26
+ readonly from: ListSource;
27
+ }
28
+ /** One value, stored as one string. */
29
+ export type Leaf = TextLeaf | ChoiceLeaf;
30
+ export type LeafKind = Leaf['leaf'];
31
+ export declare const text: <const S extends TextSize>(size: S) => {
32
+ readonly leaf: 'text';
33
+ readonly size: S;
34
+ };
35
+ export declare const choice: <const F extends ListSource>(from: F) => {
36
+ readonly leaf: 'choice';
37
+ readonly from: F;
38
+ };
39
+ /** A country, as the two-letter code a list of countries offers. */
40
+ export declare const country: {
41
+ readonly leaf: 'choice';
42
+ readonly from: "countries";
43
+ };
44
+ /** A type whose value is one leaf. */
45
+ export interface ScalarStructure {
46
+ readonly shape: 'scalar';
47
+ readonly leaf: Leaf;
48
+ }
20
49
  /**
21
- * What kind of thing a type's value is, as anything comparing values needs to know.
22
- *
23
- * Coarser than the type: `short_text` and `long_text` are both text, and differ only in
24
- * how much of it. This is the level at which a value can be ordered, matched or grouped,
25
- * so it is what a filter, a sort or an export reads to decide how to treat a value —
26
- * without either of them enumerating the types themselves.
27
- *
28
- * Deliberately not presentation: it says a value is a date, not that its operator is
29
- * called "is before". Naming the operators stays with whoever renders them.
50
+ * A type whose value is a leaf per named part. Parts are listed in the order they are shown, and
51
+ * that order is relied on wherever parts are laid out.
30
52
  */
31
- export declare const FIELD_KINDS: readonly ['text', 'date', 'number', 'record'];
32
- export type FieldKind = (typeof FIELD_KINDS)[number];
53
+ export interface RecordStructure {
54
+ readonly shape: 'record';
55
+ readonly parts: Readonly<Record<string, Leaf>>;
56
+ }
33
57
  /**
34
- * The types a composite's parts can declare. A country code and a postal code both
35
- * store short text, but they are different things — the part's type is what a control
36
- * or a filter dispatches on, the way a field's own type is for a scalar.
58
+ * A type whose value is some of the options its field offers, each named by its text. Which
59
+ * options there are, and whether a member picks one or several, are settings of the field rather
60
+ * than of its type, so each field asks a question of its own.
37
61
  */
38
- export declare const PART_TYPE_IDS: readonly ['short_text', 'postal_code', 'country_code'];
39
- export type PartType = (typeof PART_TYPE_IDS)[number];
62
+ export interface SetStructure {
63
+ readonly shape: 'set';
64
+ }
65
+ export type FieldStructure = ScalarStructure | RecordStructure | SetStructure;
66
+ export type FieldShape = FieldStructure['shape'];
67
+ /** The source for the union type, the zod enum and the `FIELD_STRUCTURES` keys alike. */
68
+ export declare const FIELD_TYPE_IDS: readonly ['short_text', 'long_text', 'list', 'address'];
69
+ export type FieldType = (typeof FIELD_TYPE_IDS)[number];
40
70
  /**
41
- * Which parts each type has, in the order they are shown, and what each part holds.
42
- * `null` for a type whose value is a single thing.
71
+ * What each type is composed of.
43
72
  *
44
- * An address is a delivery address, modeled on Stripe's Address object. Who the parcel
45
- * is addressed to is not here: a parcel needs a name as well as an address, but that is
46
- * a fact about posting parcels rather than about either type, and the name is often not
47
- * the account name — gift subscriptions, workplace deliveries, c/o. A site that needs
48
- * one keeps it in a field of its own, which is also how Stripe hands it back.
49
- */
50
- export declare const FIELD_PARTS: {
51
- readonly short_text: null;
52
- readonly long_text: null;
73
+ * An address is a delivery address, modeled on Stripe's Address object. Who the parcel is
74
+ * addressed to is not here: a parcel needs a name as well as an address, but that is a fact about
75
+ * posting parcels rather than about either type, and the name is often not the account name, as
76
+ * with gift subscriptions, workplace deliveries or c/o. A site that needs one keeps it in a field of
77
+ * its own, which is also how Stripe hands it back.
78
+ */
79
+ export declare const FIELD_STRUCTURES: {
80
+ readonly short_text: {
81
+ readonly shape: 'scalar';
82
+ readonly leaf: {
83
+ readonly leaf: 'text';
84
+ readonly size: "line";
85
+ };
86
+ };
87
+ readonly long_text: {
88
+ readonly shape: 'scalar';
89
+ readonly leaf: {
90
+ readonly leaf: 'text';
91
+ readonly size: "long";
92
+ };
93
+ };
94
+ readonly list: {
95
+ readonly shape: 'set';
96
+ };
53
97
  readonly address: {
54
- readonly line1: 'short_text';
55
- readonly line2: 'short_text';
56
- readonly city: 'short_text';
57
- readonly state: 'short_text';
58
- readonly postal_code: 'postal_code';
59
- readonly country: 'country_code';
98
+ readonly shape: 'record';
99
+ readonly parts: {
100
+ readonly line1: {
101
+ readonly leaf: 'text';
102
+ readonly size: "line";
103
+ };
104
+ readonly line2: {
105
+ readonly leaf: 'text';
106
+ readonly size: "line";
107
+ };
108
+ readonly city: {
109
+ readonly leaf: 'text';
110
+ readonly size: "line";
111
+ };
112
+ readonly state: {
113
+ readonly leaf: 'text';
114
+ readonly size: "line";
115
+ };
116
+ readonly postal_code: {
117
+ readonly leaf: 'text';
118
+ readonly size: "code";
119
+ };
120
+ readonly country: {
121
+ readonly leaf: 'choice';
122
+ readonly from: "countries";
123
+ };
124
+ };
60
125
  };
61
126
  };
127
+ export type StructureOf<T extends FieldType> = (typeof FIELD_STRUCTURES)[T];
128
+ export type ShapeOf<T extends FieldType> = StructureOf<T>['shape'];
129
+ export type FieldTypeOfShape<S extends FieldShape> = {
130
+ [T in FieldType]: ShapeOf<T> extends S ? T : never;
131
+ }[FieldType];
62
132
  /**
63
- * The parts a record type declares, or never for a type whose value is a single thing.
64
- *
65
- * Distributed over `T`, so a caller holding a type it only knows as `FieldType` gets
66
- * every part any type declares rather than the empty intersection of all of them.
133
+ * The parts a record type declares, or never for another shape. Distributes over `T`, so a union
134
+ * of types gives every part any of them declares.
67
135
  */
68
- export type PartsOf<T extends FieldType> = T extends FieldType ? (typeof FIELD_PARTS)[T] extends null ? never : Extract<keyof (typeof FIELD_PARTS)[T], string> : never;
136
+ export type PartsOf<T extends FieldType> = T extends FieldType ? StructureOf<T> extends {
137
+ parts: infer P;
138
+ } ? Extract<keyof P, string> : never : never;
139
+ type ValueOfStructure<S extends FieldStructure> = {
140
+ scalar: string;
141
+ record: S extends {
142
+ parts: infer P;
143
+ } ? {
144
+ [K in keyof P]?: string;
145
+ } : never;
146
+ set: string[];
147
+ }[S['shape']];
69
148
  /**
70
- * The parts of a record type in declaration order, or null for a type with none.
71
- *
72
- * Typed to the parts the caller's type declares, so a caller holding one of these can
73
- * index a value of that type without restating which parts exist.
149
+ * A value of a type, by its shape: one string for a scalar, a string for any of its declared parts
150
+ * for a record, and the text of each option picked for a set, even when its field takes only one.
151
+ * Every value is laid out this way, so storage, which keeps one string per leaf or option, can
152
+ * always read back what was written.
153
+ */
154
+ export type ValueOf<T extends FieldType> = T extends FieldType ? ValueOfStructure<StructureOf<T>> : never;
155
+ /**
156
+ * What a field of a set type is set up with: the options it offers, in the order they are shown,
157
+ * and whether a member may pick more than one. An option is named by its text alone, so the same
158
+ * text is the same option whenever it is offered, and nothing else identifies one.
159
+ */
160
+ export interface SetSettings {
161
+ readonly options: string[];
162
+ readonly multiple: boolean;
163
+ }
164
+ /** How many options a set field offers: at least two, or it isn't a choice, and at most a hundred. */
165
+ export declare const MIN_OPTIONS = 2;
166
+ export declare const MAX_OPTIONS = 100;
167
+ /**
168
+ * What joins a member's options in one cell when a set is exported, and splits them when one is
169
+ * imported. No option may contain it, so a cell always splits back into what was joined. Chosen
170
+ * because it is rare in names and no spreadsheet splits columns on it by default.
171
+ */
172
+ export declare const OPTION_SEPARATOR = "|";
173
+ /**
174
+ * An option's text as it is matched: without surrounding spaces, and with accented letters
175
+ * encoded one way. Neither changes how the text reads, and without them an option pasted from a
176
+ * spreadsheet, or typed on a system that encodes accents differently, would not match one that
177
+ * reads exactly the same. Everything else is kept, case included, so an answer always reads as
178
+ * it was given.
179
+ */
180
+ export declare function optionText(option: string): string;
181
+ /** The answers among `held` that a set field offers, in the order it offers them. */
182
+ export declare function inOptionOrder(settings: SetSettings, held: readonly unknown[]): string[];
183
+ /**
184
+ * What a form editing a set field's answers starts from: only the options the field offers now,
185
+ * since one it no longer offers can't be picked again. A field that has gone from several answers
186
+ * to one starts unanswered while the member holds several, even if only one of them is still
187
+ * offered, so the next answer replaces them rather than one being shown as their only answer.
188
+ */
189
+ export declare function editableAnswers(settings: SetSettings, held: readonly unknown[]): string[];
190
+ /**
191
+ * What a field of each shape is set up with beyond its name: a set's options, and nothing for any
192
+ * other shape.
193
+ */
194
+ export interface SettingsOfShape {
195
+ scalar: undefined;
196
+ record: undefined;
197
+ set: SetSettings;
198
+ }
199
+ export type SettingsOf<T extends FieldType> = T extends FieldType ? SettingsOfShape[ShapeOf<T>] : never;
200
+ /** A field's settings, which a field whose type has nothing to set up doesn't have. */
201
+ type SettingsField<S> = [S] extends [undefined] ? {
202
+ readonly settings?: undefined;
203
+ } : {
204
+ readonly settings: S;
205
+ };
206
+ /**
207
+ * A field's type together with what the field is set up with. They are one value because only the
208
+ * two together say what the field takes: a list field without its options has no answers to
209
+ * offer, and a short text field has no settings at all.
210
+ */
211
+ export type TypedSettings = {
212
+ [T in FieldType]: {
213
+ readonly type: T;
214
+ } & SettingsField<SettingsOf<T>>;
215
+ }[FieldType];
216
+ /** The fields among `F` whose type has shape `S`, with their settings narrowed to match. */
217
+ export type FieldOfShape<S extends FieldShape, F extends TypedSettings = TypedSettings> = Extract<F, {
218
+ type: FieldTypeOfShape<S>;
219
+ }>;
220
+ /**
221
+ * Whether a value names a type this build knows. A site newer than an integration can send a type
222
+ * the integration doesn't know, so check a type from the wire with this first. `constructor` and
223
+ * other names every object has are not types.
224
+ */
225
+ export declare function isFieldType(value: unknown): value is FieldType;
226
+ export type ShapeHandlers<R> = {
227
+ [S in FieldShape]: (structure: Extract<FieldStructure, {
228
+ shape: S;
229
+ }>, type: FieldTypeOfShape<S>) => R;
230
+ };
231
+ /** Every type of shape `shape`, in catalog order. */
232
+ export declare const typesOfShape: <S extends FieldShape>(shape: S) => FieldTypeOfShape<S>[];
233
+ /**
234
+ * Calls the handler for the shape `type` declares, with the type narrowed to that shape. Throws,
235
+ * naming the type, for one this build doesn't know; check with `isFieldType` first.
236
+ */
237
+ export declare function matchShape<R>(type: FieldType, handlers: ShapeHandlers<R>): R;
238
+ export type FieldHandlers<F extends TypedSettings, R> = {
239
+ [S in FieldShape]: (field: FieldOfShape<S, F>) => R;
240
+ };
241
+ /**
242
+ * Calls the handler for the shape a field's type declares, with the field narrowed to that shape,
243
+ * settings included, for a caller that needs what the field is set up with rather than only its
244
+ * type. Throws, naming the type, for one this build doesn't know.
245
+ */
246
+ export declare function matchField<F extends TypedSettings, R>(field: F, handlers: FieldHandlers<F, R>): R;
247
+ export type LeafHandlers<R> = {
248
+ [K in LeafKind]: (leaf: Extract<Leaf, {
249
+ leaf: K;
250
+ }>) => R;
251
+ };
252
+ /** Calls the handler for a leaf's kind. */
253
+ export declare function matchLeaf<R>(leaf: Leaf, handlers: LeafHandlers<R>): R;
254
+ /**
255
+ * Whether a value is laid out as a record: an object of parts, which a list is not. What a record
256
+ * must hold is its type's rule to decide.
257
+ */
258
+ export declare function isRecordValue(value: unknown): value is Record<string, unknown>;
259
+ /**
260
+ * A record type's parts in declaration order, or null for any other type, including one this build
261
+ * doesn't know. Parts are plain strings here; `FIELD_STRUCTURES[type].parts` gives one type's parts
262
+ * with typed keys.
74
263
  */
75
- export declare function subFieldsOf<T extends FieldType>(type: T): PartsOf<T>[] | null;
76
- /** Each part's declared type, keyed by part; null for a type with none, and for one this build has never heard of. */
77
- export declare function partTypesOf<T extends FieldType>(type: T): Record<PartsOf<T>, PartType> | null;
264
+ export declare function partsOf(type: FieldType): string[] | null;
265
+ export {};
78
266
  //# sourceMappingURL=structure.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"structure.d.ts","sourceRoot":"","sources":["../src/structure.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,oFAAoF;AACpF,eAAO,MAAM,cAAc,YAAI,YAAY,EAAE,WAAW,EAAE,SAAS,CAAU,CAAC;AAC9E,MAAM,MAAM,SAAS,GAAG,CAAC,OAAO,cAAc,CAAC,CAAC,MAAM,CAAC,CAAC;AAExD;;;;;;;;;;GAUG;AACH,eAAO,MAAM,WAAW,YAAI,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,CAAU,CAAC;AACzE,MAAM,MAAM,SAAS,GAAG,CAAC,OAAO,WAAW,CAAC,CAAC,MAAM,CAAC,CAAC;AAErD;;;;GAIG;AACH,eAAO,MAAM,aAAa,YAAI,YAAY,EAAE,aAAa,EAAE,cAAc,CAAU,CAAC;AACpF,MAAM,MAAM,QAAQ,GAAG,CAAC,OAAO,aAAa,CAAC,CAAC,MAAM,CAAC,CAAC;AAEtD;;;;;;;;;GASG;AACH,eAAO,MAAM,WAAW;;;;iBAIpB,KAAK,EAAE,YAAY;iBACnB,KAAK,EAAE,YAAY;iBACnB,IAAI,EAAE,YAAY;iBAClB,KAAK,EAAE,YAAY;iBACnB,WAAW,EAAE,aAAa;iBAC1B,OAAO,EAAE,cAAc;;CAEsD,CAAC;AAElF;;;;;GAKG;AACH,MAAM,MAAM,OAAO,CAAC,CAAC,SAAS,SAAS,IAAI,CAAC,SAAS,SAAS,GAC1D,CAAC,OAAO,WAAW,CAAC,CAAC,CAAC,CAAC,SAAS,IAAI,GAClC,KAAK,GACL,OAAO,CAAC,MAAM,CAAC,OAAO,WAAW,CAAC,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,GAChD,KAAK,CAAC;AAEV;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,CAAC,SAAS,SAAS,EAAE,IAAI,EAAE,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,EAAE,GAAG,IAAI,CAK7E;AAED,sHAAsH;AACtH,wBAAgB,WAAW,CAAC,CAAC,SAAS,SAAS,EAAE,IAAI,EAAE,CAAC,GAAG,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,QAAQ,CAAC,GAAG,IAAI,CAG7F"}
1
+ {"version":3,"file":"structure.d.ts","sourceRoot":"","sources":["../src/structure.ts"],"names":[],"mappings":"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"}
@@ -1,76 +1,175 @@
1
1
  /**
2
2
  * What a field type is made of, with no opinion on what a valid value looks like.
3
3
  *
4
- * This is the half of the catalog a renderer needs. Drawing an address means knowing
5
- * it has six parts, in that order, and that the last of them holds a country code —
6
- * nothing about lengths, formats, or what happens when one is left blank.
4
+ * Every type is composed from a few building blocks. A leaf is one value: text of a size, or a
5
+ * choice from a list. A type is a leaf on its own, a record of named leaves, or a set of options
6
+ * its field offers. Everything that stores, exports, edits, filters or draws a value is written
7
+ * once per building block, so a type composed from existing blocks needs nothing beyond its entry
8
+ * here.
7
9
  *
8
- * It is separate from `./index` because that half is built out of zod, and zod is
9
- * sixty-odd kilobytes. Ghost's server enforces the rules and can afford them; Portal
10
- * only draws the inputs, and it loads on every page view of every themed site. Split
11
- * this way a renderer imports well under a kilobyte and still gets the types.
12
- *
13
- * The two halves cannot drift, because the schemas are built from these declarations
14
- * rather than beside them: adding a part here without a rule in `./index` fails to
15
- * compile.
10
+ * This half is separate from `./index` because that half is built out of zod, and zod is
11
+ * sixty-odd kilobytes. Ghost's server enforces the rules and can afford them; Portal only draws
12
+ * the inputs, and it loads on every page view of every themed site.
16
13
  */
17
- /** The source for the union type, the zod enum and the `FIELD_TYPES` keys alike. */
18
- export const FIELD_TYPE_IDS = ['short_text', 'long_text', 'address'];
14
+ /** How much text a text leaf holds. Each size has its bound, and its message, in `./index`. */
15
+ export const TEXT_SIZES = ['line', 'code', 'long'];
16
+ /** The lists a choice can pick from. Each list says which keys it accepts in `./index`. */
17
+ export const LIST_SOURCES = ['countries'];
18
+ export const text = (size) => ({ leaf: 'text', size });
19
+ export const choice = (from) => ({ leaf: 'choice', from });
20
+ /** A country, as the two-letter code a list of countries offers. */
21
+ export const country = choice('countries');
22
+ /** The source for the union type, the zod enum and the `FIELD_STRUCTURES` keys alike. */
23
+ export const FIELD_TYPE_IDS = ['short_text', 'long_text', 'list', 'address'];
19
24
  /**
20
- * What kind of thing a type's value is, as anything comparing values needs to know.
21
- *
22
- * Coarser than the type: `short_text` and `long_text` are both text, and differ only in
23
- * how much of it. This is the level at which a value can be ordered, matched or grouped,
24
- * so it is what a filter, a sort or an export reads to decide how to treat a value —
25
- * without either of them enumerating the types themselves.
25
+ * What each type is composed of.
26
26
  *
27
- * Deliberately not presentation: it says a value is a date, not that its operator is
28
- * called "is before". Naming the operators stays with whoever renders them.
27
+ * An address is a delivery address, modeled on Stripe's Address object. Who the parcel is
28
+ * addressed to is not here: a parcel needs a name as well as an address, but that is a fact about
29
+ * posting parcels rather than about either type, and the name is often not the account name, as
30
+ * with gift subscriptions, workplace deliveries or c/o. A site that needs one keeps it in a field of
31
+ * its own, which is also how Stripe hands it back.
29
32
  */
30
- export const FIELD_KINDS = ['text', 'date', 'number', 'record'];
33
+ export const FIELD_STRUCTURES = {
34
+ short_text: { shape: 'scalar', leaf: text('line') },
35
+ long_text: { shape: 'scalar', leaf: text('long') },
36
+ list: { shape: 'set' },
37
+ address: {
38
+ shape: 'record',
39
+ parts: {
40
+ line1: text('line'),
41
+ line2: text('line'),
42
+ city: text('line'),
43
+ state: text('line'),
44
+ postal_code: text('code'),
45
+ country,
46
+ },
47
+ },
48
+ };
49
+ /** How many options a set field offers: at least two, or it isn't a choice, and at most a hundred. */
50
+ export const MIN_OPTIONS = 2;
51
+ export const MAX_OPTIONS = 100;
31
52
  /**
32
- * The types a composite's parts can declare. A country code and a postal code both
33
- * store short text, but they are different things — the part's type is what a control
34
- * or a filter dispatches on, the way a field's own type is for a scalar.
53
+ * What joins a member's options in one cell when a set is exported, and splits them when one is
54
+ * imported. No option may contain it, so a cell always splits back into what was joined. Chosen
55
+ * because it is rare in names and no spreadsheet splits columns on it by default.
35
56
  */
36
- export const PART_TYPE_IDS = ['short_text', 'postal_code', 'country_code'];
57
+ export const OPTION_SEPARATOR = '|';
37
58
  /**
38
- * Which parts each type has, in the order they are shown, and what each part holds.
39
- * `null` for a type whose value is a single thing.
40
- *
41
- * An address is a delivery address, modeled on Stripe's Address object. Who the parcel
42
- * is addressed to is not here: a parcel needs a name as well as an address, but that is
43
- * a fact about posting parcels rather than about either type, and the name is often not
44
- * the account name — gift subscriptions, workplace deliveries, c/o. A site that needs
45
- * one keeps it in a field of its own, which is also how Stripe hands it back.
59
+ * An option's text as it is matched: without surrounding spaces, and with accented letters
60
+ * encoded one way. Neither changes how the text reads, and without them an option pasted from a
61
+ * spreadsheet, or typed on a system that encodes accents differently, would not match one that
62
+ * reads exactly the same. Everything else is kept, case included, so an answer always reads as
63
+ * it was given.
46
64
  */
47
- export const FIELD_PARTS = {
48
- short_text: null,
49
- long_text: null,
50
- address: {
51
- line1: 'short_text',
52
- line2: 'short_text',
53
- city: 'short_text',
54
- state: 'short_text',
55
- postal_code: 'postal_code',
56
- country: 'country_code',
57
- },
58
- };
65
+ export function optionText(option) {
66
+ return option.trim().normalize('NFC');
67
+ }
68
+ /** The answers among `held` that a set field offers, in the order it offers them. */
69
+ export function inOptionOrder(settings, held) {
70
+ return settings.options.filter((option) => held.includes(option));
71
+ }
59
72
  /**
60
- * The parts of a record type in declaration order, or null for a type with none.
61
- *
62
- * Typed to the parts the caller's type declares, so a caller holding one of these can
63
- * index a value of that type without restating which parts exist.
73
+ * What a form editing a set field's answers starts from: only the options the field offers now,
74
+ * since one it no longer offers can't be picked again. A field that has gone from several answers
75
+ * to one starts unanswered while the member holds several, even if only one of them is still
76
+ * offered, so the next answer replaces them rather than one being shown as their only answer.
77
+ */
78
+ export function editableAnswers(settings, held) {
79
+ return !settings.multiple && held.length > 1 ? [] : inOptionOrder(settings, held);
80
+ }
81
+ /**
82
+ * Whether a value names a type this build knows. A site newer than an integration can send a type
83
+ * the integration doesn't know, so check a type from the wire with this first. `constructor` and
84
+ * other names every object has are not types.
64
85
  */
65
- export function subFieldsOf(type) {
66
- // Optional because a caller built against an older catalog than the server it talks
67
- // to reaches here with a type this build has never heard of, which reads as no parts.
68
- const parts = FIELD_PARTS[type];
69
- return parts ? Object.keys(parts) : null;
86
+ export function isFieldType(value) {
87
+ return FIELD_TYPE_IDS.some((id) => id === value);
70
88
  }
71
- /** Each part's declared type, keyed by part; null for a type with none, and for one this build has never heard of. */
72
- export function partTypesOf(type) {
73
- const parts = FIELD_PARTS[type];
74
- return parts ? { ...parts } : null;
89
+ const hasShape = (shape) => (type) => isFieldType(type) && FIELD_STRUCTURES[type].shape === shape;
90
+ const isScalarType = hasShape('scalar');
91
+ const isRecordType = hasShape('record');
92
+ const isSetType = hasShape('set');
93
+ /** Every type of shape `shape`, in catalog order. */
94
+ export const typesOfShape = (shape) => FIELD_TYPE_IDS.filter(hasShape(shape));
95
+ /**
96
+ * Calls the handler for the shape `type` declares, with the type narrowed to that shape. Throws,
97
+ * naming the type, for one this build doesn't know; check with `isFieldType` first.
98
+ */
99
+ export function matchShape(type, handlers) {
100
+ if (isScalarType(type)) {
101
+ return handlers.scalar(FIELD_STRUCTURES[type], type);
102
+ }
103
+ if (isRecordType(type)) {
104
+ return handlers.record(FIELD_STRUCTURES[type], type);
105
+ }
106
+ if (isSetType(type)) {
107
+ return handlers.set(FIELD_STRUCTURES[type], type);
108
+ }
109
+ return unknownType(type);
110
+ }
111
+ const fieldHasShape = (shape) => (field) => hasShape(shape)(field.type);
112
+ const isScalarField = fieldHasShape('scalar');
113
+ const isRecordField = fieldHasShape('record');
114
+ const isSetField = fieldHasShape('set');
115
+ /**
116
+ * Calls the handler for the shape a field's type declares, with the field narrowed to that shape,
117
+ * settings included, for a caller that needs what the field is set up with rather than only its
118
+ * type. Throws, naming the type, for one this build doesn't know.
119
+ */
120
+ export function matchField(field, handlers) {
121
+ if (isScalarField(field)) {
122
+ return handlers.scalar(field);
123
+ }
124
+ if (isRecordField(field)) {
125
+ return handlers.record(field);
126
+ }
127
+ if (isSetField(field)) {
128
+ return handlers.set(field);
129
+ }
130
+ // A type this build doesn't know, which a plain JavaScript caller can still pass. The guards
131
+ // above can't narrow a generic field to never, so this can't be `unknownType`.
132
+ // oxlint-disable-next-line ghost/ghost-custom/no-native-error
133
+ throw new Error(`Unknown field type: ${String(field.type)}`);
134
+ }
135
+ /**
136
+ * Every shape has a branch above, so only a type this build doesn't know, which a plain
137
+ * JavaScript caller can still pass, reaches here.
138
+ */
139
+ function unknownType(type) {
140
+ // A native error, because this module imports nothing, @tryghost/errors included.
141
+ // oxlint-disable-next-line ghost/ghost-custom/no-native-error
142
+ throw new Error(`Unknown field type: ${String(type)}`);
143
+ }
144
+ /** Calls the handler for a leaf's kind. */
145
+ export function matchLeaf(leaf, handlers) {
146
+ switch (leaf.leaf) {
147
+ case 'text':
148
+ return handlers.text(leaf);
149
+ case 'choice':
150
+ return handlers.choice(leaf);
151
+ }
152
+ }
153
+ /**
154
+ * Whether a value is laid out as a record: an object of parts, which a list is not. What a record
155
+ * must hold is its type's rule to decide.
156
+ */
157
+ export function isRecordValue(value) {
158
+ return typeof value === 'object' && value !== null && !Array.isArray(value);
159
+ }
160
+ /**
161
+ * A record type's parts in declaration order, or null for any other type, including one this build
162
+ * doesn't know. Parts are plain strings here; `FIELD_STRUCTURES[type].parts` gives one type's parts
163
+ * with typed keys.
164
+ */
165
+ export function partsOf(type) {
166
+ if (!isFieldType(type)) {
167
+ return null;
168
+ }
169
+ return matchShape(type, {
170
+ scalar: () => null,
171
+ record: ({ parts }) => Object.keys(parts),
172
+ set: () => null,
173
+ });
75
174
  }
76
175
  //# sourceMappingURL=structure.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"structure.js","sourceRoot":"","sources":["../src/structure.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,oFAAoF;AACpF,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,YAAY,EAAE,WAAW,EAAE,SAAS,CAAU,CAAC;AAG9E;;;;;;;;;;GAUG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,CAAU,CAAC;AAGzE;;;;GAIG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,YAAY,EAAE,aAAa,EAAE,cAAc,CAAU,CAAC;AAGpF;;;;;;;;;GASG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG;IACzB,UAAU,EAAE,IAAI;IAChB,SAAS,EAAE,IAAI;IACf,OAAO,EAAE;QACP,KAAK,EAAE,YAAY;QACnB,KAAK,EAAE,YAAY;QACnB,IAAI,EAAE,YAAY;QAClB,KAAK,EAAE,YAAY;QACnB,WAAW,EAAE,aAAa;QAC1B,OAAO,EAAE,cAAc;KACxB;CAC8E,CAAC;AAclF;;;;;GAKG;AACH,MAAM,UAAU,WAAW,CAAsB,IAAO;IACtD,oFAAoF;IACpF,sFAAsF;IACtF,MAAM,KAAK,GAA0D,WAAW,CAAC,IAAI,CAAC,CAAC;IACvF,OAAO,KAAK,CAAC,CAAC,CAAE,MAAM,CAAC,IAAI,CAAC,KAAK,CAAkB,CAAC,CAAC,CAAC,IAAI,CAAC;AAC7D,CAAC;AAED,sHAAsH;AACtH,MAAM,UAAU,WAAW,CAAsB,IAAO;IACtD,MAAM,KAAK,GAA0D,WAAW,CAAC,IAAI,CAAC,CAAC;IACvF,OAAO,KAAK,CAAC,CAAC,CAAE,EAAE,GAAG,KAAK,EAAmC,CAAC,CAAC,CAAC,IAAI,CAAC;AACvE,CAAC"}
1
+ {"version":3,"file":"structure.js","sourceRoot":"","sources":["../src/structure.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tryghost/metafield-types",
3
- "version": "0.1.2",
3
+ "version": "0.3.0",
4
4
  "description": "Ghost member custom field types: which types exist, what each is made of, and how a value of each is validated",
5
5
  "license": "MIT",
6
6
  "author": "Ghost Foundation",
@@ -34,7 +34,7 @@
34
34
  }
35
35
  },
36
36
  "dependencies": {
37
- "zod": "4.6.5"
37
+ "zod": "4.6.7"
38
38
  },
39
39
  "scripts": {
40
40
  "build": "tsc",