@coffer-org/sdk 1.1.0 → 1.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (69) hide show
  1. package/dist/color-names.d.ts +0 -1
  2. package/dist/color-names.js +0 -1
  3. package/dist/condition.d.ts +3 -19
  4. package/dist/condition.js +50 -69
  5. package/dist/countries.d.ts +0 -2
  6. package/dist/countries.js +0 -1
  7. package/dist/currencies.d.ts +0 -10
  8. package/dist/currencies.js +0 -10
  9. package/dist/extend.d.ts +3 -22
  10. package/dist/extend.js +2 -6
  11. package/dist/field-helpers.d.ts +0 -7
  12. package/dist/field-helpers.js +0 -16
  13. package/dist/field-presets.d.ts +55 -87
  14. package/dist/field-presets.js +116 -108
  15. package/dist/fields/constants.d.ts +36 -0
  16. package/dist/fields/constants.js +18 -0
  17. package/dist/fields/normalize.d.ts +84 -0
  18. package/dist/fields/normalize.js +47 -0
  19. package/dist/fields/url.d.ts +13 -0
  20. package/dist/fields/url.js +49 -0
  21. package/dist/fields/validation.d.ts +30 -0
  22. package/dist/fields/validation.js +57 -0
  23. package/dist/fields.d.ts +222 -332
  24. package/dist/fields.js +435 -351
  25. package/dist/index.d.ts +14 -16
  26. package/dist/index.js +14 -16
  27. package/dist/module.d.ts +13 -103
  28. package/dist/module.js +51 -83
  29. package/dist/package.d.ts +3 -20
  30. package/dist/package.js +14 -19
  31. package/dist/plugin.d.ts +5 -45
  32. package/dist/plugin.js +5 -19
  33. package/dist/settings.d.ts +1 -2
  34. package/dist/settings.js +0 -1
  35. package/dist/units.d.ts +0 -1
  36. package/dist/units.js +0 -5
  37. package/dist/vault.d.ts +3 -8
  38. package/dist/vault.js +4 -1
  39. package/package.json +5 -1
  40. package/dist/color-names.d.ts.map +0 -1
  41. package/dist/color-names.js.map +0 -1
  42. package/dist/condition.d.ts.map +0 -1
  43. package/dist/condition.js.map +0 -1
  44. package/dist/countries.d.ts.map +0 -1
  45. package/dist/countries.js.map +0 -1
  46. package/dist/currencies.d.ts.map +0 -1
  47. package/dist/currencies.js.map +0 -1
  48. package/dist/extend.d.ts.map +0 -1
  49. package/dist/extend.js.map +0 -1
  50. package/dist/field-helpers.d.ts.map +0 -1
  51. package/dist/field-helpers.js.map +0 -1
  52. package/dist/field-presets.d.ts.map +0 -1
  53. package/dist/field-presets.js.map +0 -1
  54. package/dist/fields.d.ts.map +0 -1
  55. package/dist/fields.js.map +0 -1
  56. package/dist/index.d.ts.map +0 -1
  57. package/dist/index.js.map +0 -1
  58. package/dist/module.d.ts.map +0 -1
  59. package/dist/module.js.map +0 -1
  60. package/dist/package.d.ts.map +0 -1
  61. package/dist/package.js.map +0 -1
  62. package/dist/plugin.d.ts.map +0 -1
  63. package/dist/plugin.js.map +0 -1
  64. package/dist/settings.d.ts.map +0 -1
  65. package/dist/settings.js.map +0 -1
  66. package/dist/units.d.ts.map +0 -1
  67. package/dist/units.js.map +0 -1
  68. package/dist/vault.d.ts.map +0 -1
  69. package/dist/vault.js.map +0 -1
@@ -1,18 +1,7 @@
1
- /**
2
- * Пресети полів — тонкі обгортки над базовими примітивами з fields.ts.
3
- *
4
- * Кожен пресет = один kind (один віджет). Пресети не приймають `format` —
5
- * вони самі є семантичними типами. min/max/step — через `config`.
6
- *
7
- * Пресети додаються до `f` через `composeF`, який гарантує, що жоден пресет
8
- * не перебиває примітив.
9
- *
10
- * Циклічний імпорт з fields.ts безпечний: фабрики/хелпери — hoisted-декларації,
11
- * а пресети викликають їх лише в тілі своїх функцій.
12
- */
13
1
  import { z } from 'zod';
14
- import { real, int, text, select, vmsg, typeErr, jsonRefined, optionalize, applyMultiple, wrapKey, } from './fields.js';
15
- export function email(o) {
2
+ import { real, int, text, date, select, vmsg, jsonRefined, typeErr, optionalize, applyMultiple, wrapKey, normalizeOpts, } from "./fields.js";
3
+ export function email(raw) {
4
+ const o = normalizeOpts(raw);
16
5
  const required = o.required ?? false;
17
6
  let s = z.string().email({ message: vmsg('email') });
18
7
  if (required)
@@ -29,26 +18,11 @@ export function email(o) {
29
18
  const meta = applyMultiple(base, o.multiple ?? false);
30
19
  return wrapKey(o, meta);
31
20
  }
32
- export function url(o) {
21
+ export function tel(raw) {
22
+ const o = normalizeOpts(raw);
33
23
  const required = o.required ?? false;
34
- let s = z.string().url({ message: vmsg('url') });
35
- if (required)
36
- s = s.min(1, { message: vmsg('min_length', { min: 1 }) });
37
- const base = {
38
- kind: 'url',
39
- label: o.label ?? '',
40
- required,
41
- prim: 'text',
42
- column: 'text',
43
- hints: { format: 'url', inputType: 'url' },
44
- zod: optionalize(s, required),
45
- };
46
- const meta = applyMultiple(base, o.multiple ?? false);
47
- return wrapKey(o, meta);
48
- }
49
- export function tel(o) {
50
- const required = o.required ?? false;
51
- const s = required ? z.string().min(1, { message: vmsg('min_length', { min: 1 }) }) : z.string();
24
+ const base_z = z.string().regex(TEL_RE, { message: vmsg('pattern', { messageKey: 'core.presets.tel' }) });
25
+ const s = required ? base_z.min(1, { message: vmsg('min_length', { min: 1 }) }) : base_z;
52
26
  const base = {
53
27
  kind: 'tel',
54
28
  label: o.label ?? '',
@@ -61,7 +35,8 @@ export function tel(o) {
61
35
  const meta = applyMultiple(base, o.multiple ?? false);
62
36
  return wrapKey(o, meta);
63
37
  }
64
- export function password(o) {
38
+ export function password(raw) {
39
+ const o = normalizeOpts(raw);
65
40
  const required = o.required ?? false;
66
41
  const s = required ? z.string().min(1, { message: vmsg('min_length', { min: 1 }) }) : z.string();
67
42
  const base = {
@@ -73,11 +48,11 @@ export function password(o) {
73
48
  hints: { format: 'password', inputType: 'password' },
74
49
  zod: optionalize(s, required),
75
50
  };
76
- const meta = applyMultiple(base, o.multiple ?? false);
77
- return wrapKey(o, meta);
51
+ return wrapKey(o, base);
78
52
  }
79
53
  const SLUG_RE = /^[a-z0-9-]+$/;
80
- export function slug(o) {
54
+ export function slug(raw) {
55
+ const o = normalizeOpts(raw);
81
56
  const required = o.required ?? false;
82
57
  const s = z.string().regex(SLUG_RE, { message: vmsg('pattern', { messageKey: 'core.presets.slug' }) });
83
58
  const base = {
@@ -93,7 +68,8 @@ export function slug(o) {
93
68
  return wrapKey(o, meta);
94
69
  }
95
70
  const COLOR_RE = /^#[0-9a-fA-F]{6}$/;
96
- export function color(o) {
71
+ export function color(raw) {
72
+ const o = normalizeOpts(raw);
97
73
  const required = o.required ?? false;
98
74
  const s = z.string().regex(COLOR_RE, { message: vmsg('color_format') });
99
75
  const base = {
@@ -108,9 +84,10 @@ export function color(o) {
108
84
  const meta = applyMultiple(base, o.multiple ?? false);
109
85
  return wrapKey(o, meta);
110
86
  }
111
- export function colorname(o) {
87
+ export function colorname(raw) {
88
+ const o = normalizeOpts(raw);
112
89
  const required = o.required ?? false;
113
- const s = required ? z.string().min(1, { message: vmsg('min_length', { min: 1 }) }) : z.string();
90
+ const s = (required ? z.string().min(1, { message: vmsg('min_length', { min: 1 }) }) : z.string()).refine((v) => CSS_COLOR_NAMES.has(v.toLowerCase()), { message: vmsg('colorname') });
114
91
  const base = {
115
92
  kind: 'colorname',
116
93
  label: o.label ?? '',
@@ -123,7 +100,8 @@ export function colorname(o) {
123
100
  const meta = applyMultiple(base, o.multiple ?? false);
124
101
  return wrapKey(o, meta);
125
102
  }
126
- export function title(o) {
103
+ export function title(raw) {
104
+ const o = normalizeOpts(raw);
127
105
  const required = o.required ?? false;
128
106
  const s = required ? z.string().min(1, { message: vmsg('min_length', { min: 1 }) }) : z.string();
129
107
  const base = {
@@ -138,93 +116,91 @@ export function title(o) {
138
116
  const meta = applyMultiple(base, o.multiple ?? false);
139
117
  return wrapKey(o, meta);
140
118
  }
141
- // string-родина: pattern-обгортки (kind-семантика + regex)
142
- const IMEI_RE = /^\d{15}$/;
143
- const MAC_RE = /^([0-9A-Fa-f]{2}[:-]){5}[0-9A-Fa-f]{2}$/;
144
- const IBAN_RE = /^[A-Za-z]{2}\d{2}[A-Za-z0-9]{11,30}$/;
145
- export function imei(o) {
146
- const required = o.required ?? false;
147
- const s = z.string().regex(IMEI_RE, { message: vmsg('pattern', { messageKey: 'core.presets.imei' }) });
148
- const base = {
149
- kind: 'imei',
150
- label: o.label ?? '',
151
- required,
152
- prim: 'text',
153
- column: 'text',
154
- hints: {},
155
- zod: optionalize(s, required),
156
- };
157
- const meta = applyMultiple(base, o.multiple ?? false);
158
- return wrapKey(o, meta);
159
- }
160
- export function mac(o) {
119
+ export function link(raw) {
120
+ const o = normalizeOpts(raw);
161
121
  const required = o.required ?? false;
162
- const s = z.string().regex(MAC_RE, { message: vmsg('pattern', { messageKey: 'core.presets.mac' }) });
122
+ const base_z = z.string().regex(LINK_RE, { message: vmsg('pattern', { messageKey: 'core.presets.link' }) });
123
+ const s = required ? base_z.min(1, { message: vmsg('min_length', { min: 1 }) }) : base_z;
163
124
  const base = {
164
- kind: 'mac',
125
+ kind: 'link',
165
126
  label: o.label ?? '',
166
127
  required,
167
128
  prim: 'text',
168
129
  column: 'text',
169
- hints: {},
130
+ hints: { format: 'url', inputType: 'url' },
170
131
  zod: optionalize(s, required),
171
132
  };
172
133
  const meta = applyMultiple(base, o.multiple ?? false);
173
134
  return wrapKey(o, meta);
174
135
  }
175
- export function iban(o) {
136
+ const TEL_RE = /^\+?[\d\s()-]{4,}$/;
137
+ const LINK_RE = /^([a-z][a-z0-9+.-]*:\/\/\S+|[\w-]+(\.[\w-]+)+(:\d+)?(\/\S*)?)$/i;
138
+ const CSS_COLOR_NAMES = new Set([
139
+ 'aliceblue', 'antiquewhite', 'aqua', 'aquamarine', 'azure', 'beige', 'bisque', 'black', 'blanchedalmond', 'blue',
140
+ 'blueviolet', 'brown', 'burlywood', 'cadetblue', 'chartreuse', 'chocolate', 'coral', 'cornflowerblue', 'cornsilk',
141
+ 'crimson', 'cyan', 'darkblue', 'darkcyan', 'darkgoldenrod', 'darkgray', 'darkgreen', 'darkgrey', 'darkkhaki',
142
+ 'darkmagenta', 'darkolivegreen', 'darkorange', 'darkorchid', 'darkred', 'darksalmon', 'darkseagreen',
143
+ 'darkslateblue', 'darkslategray', 'darkslategrey', 'darkturquoise', 'darkviolet', 'deeppink', 'deepskyblue',
144
+ 'dimgray', 'dimgrey', 'dodgerblue', 'firebrick', 'floralwhite', 'forestgreen', 'fuchsia', 'gainsboro', 'ghostwhite',
145
+ 'gold', 'goldenrod', 'gray', 'green', 'greenyellow', 'grey', 'honeydew', 'hotpink', 'indianred', 'indigo', 'ivory',
146
+ 'khaki', 'lavender', 'lavenderblush', 'lawngreen', 'lemonchiffon', 'lightblue', 'lightcoral', 'lightcyan',
147
+ 'lightgoldenrodyellow', 'lightgray', 'lightgreen', 'lightgrey', 'lightpink', 'lightsalmon', 'lightseagreen',
148
+ 'lightskyblue', 'lightslategray', 'lightslategrey', 'lightsteelblue', 'lightyellow', 'lime', 'limegreen', 'linen',
149
+ 'magenta', 'maroon', 'mediumaquamarine', 'mediumblue', 'mediumorchid', 'mediumpurple', 'mediumseagreen',
150
+ 'mediumslateblue', 'mediumspringgreen', 'mediumturquoise', 'mediumvioletred', 'midnightblue', 'mintcream',
151
+ 'mistyrose', 'moccasin', 'navajowhite', 'navy', 'oldlace', 'olive', 'olivedrab', 'orange', 'orangered', 'orchid',
152
+ 'palegoldenrod', 'palegreen', 'paleturquoise', 'palevioletred', 'papayawhip', 'peachpuff', 'peru', 'pink', 'plum',
153
+ 'powderblue', 'purple', 'rebeccapurple', 'red', 'rosybrown', 'royalblue', 'saddlebrown', 'salmon', 'sandybrown',
154
+ 'seagreen', 'seashell', 'sienna', 'silver', 'skyblue', 'slateblue', 'slategray', 'slategrey', 'snow', 'springgreen',
155
+ 'steelblue', 'tan', 'teal', 'thistle', 'tomato', 'turquoise', 'violet', 'wheat', 'white', 'whitesmoke', 'yellow',
156
+ 'yellowgreen', 'transparent',
157
+ ]);
158
+ export function tag(raw) {
159
+ const o = normalizeOpts(raw);
176
160
  const required = o.required ?? false;
177
- const s = z.string().regex(IBAN_RE, { message: vmsg('pattern', { messageKey: 'core.presets.iban' }) });
161
+ const s = z.string().min(1, { message: vmsg('min_length', { min: 1 }) });
162
+ const suggestions = Array.isArray(raw.options) ? raw.options : [];
163
+ const source = typeof raw.options === 'string' ? raw.options : null;
178
164
  const base = {
179
- kind: 'iban',
165
+ kind: 'tag',
180
166
  label: o.label ?? '',
181
167
  required,
182
168
  prim: 'text',
183
169
  column: 'text',
184
- hints: {},
170
+ hints: { suggestions, ...(source ? { source } : {}) },
185
171
  zod: optionalize(s, required),
186
172
  };
187
173
  const meta = applyMultiple(base, o.multiple ?? false);
188
174
  return wrapKey(o, meta);
189
175
  }
190
176
  export function tags(o) {
191
- const required = o.required ?? false;
192
- const s = jsonRefined(z.array(z.string().min(1)), 'tags_list');
193
- const suggestions = Array.isArray(o.options) ? o.options : [];
194
- const source = typeof o.options === 'string' ? o.options : null;
195
- const base = {
196
- kind: 'tags',
197
- label: o.label ?? '',
198
- required,
199
- prim: 'text',
200
- column: 'text',
201
- hints: { suggestions, ...(source ? { source } : {}) },
202
- zod: optionalize(s, required),
203
- };
204
- return wrapKey(o, base);
177
+ return tag({ ...o, multiple: true });
205
178
  }
206
- export function markdown(o) {
179
+ export function markdown(raw) {
180
+ const norm = normalizeOpts(raw);
207
181
  const meta = {
208
- ...text({ label: o.label, required: o.required, config: o.config }),
182
+ ...text({ label: raw.label, rules: raw.rules, view: raw.view }),
209
183
  prim: 'text',
210
184
  kind: 'markdown',
211
185
  };
212
- return wrapKey(o, meta);
186
+ return wrapKey(norm, meta);
213
187
  }
214
- export function snippet(o) {
215
- const language = o.config?.language;
216
- const base = text({ label: o.label, required: o.required, config: o.config });
188
+ export function snippet(raw) {
189
+ const language = raw.rules?.language;
190
+ const norm = normalizeOpts(raw);
191
+ const base = text({ label: raw.label, rules: raw.rules, view: raw.view });
217
192
  const meta = {
218
193
  ...base,
219
194
  prim: 'text',
220
195
  kind: 'snippet',
221
196
  hints: { ...base.hints, ...(language ? { language } : {}) },
222
197
  };
223
- return wrapKey(o, meta);
198
+ return wrapKey(norm, meta);
224
199
  }
225
- export function rating(o) {
200
+ export function rating(raw) {
201
+ const o = normalizeOpts(raw);
226
202
  const required = o.required ?? false;
227
- const max = o.max ?? 5;
203
+ const max = raw.rules?.max ?? 5;
228
204
  const s = z.coerce
229
205
  .number(typeErr())
230
206
  .int({ message: vmsg('int') })
@@ -242,10 +218,11 @@ export function rating(o) {
242
218
  const meta = applyMultiple(base, o.multiple ?? false);
243
219
  return wrapKey(o, meta);
244
220
  }
245
- export function duration(o) {
221
+ export function duration(raw) {
222
+ const o = normalizeOpts(raw);
246
223
  const required = o.required ?? false;
247
- const max = o.max ?? 604800; // 1 week in seconds
248
- const step = o.step ?? 60; // 1 minute in seconds
224
+ const max = raw.rules?.max ?? 604800;
225
+ const step = raw.rules?.step ?? 60;
249
226
  const s = z.coerce
250
227
  .number(typeErr())
251
228
  .int({ message: vmsg('int') })
@@ -263,41 +240,72 @@ export function duration(o) {
263
240
  const meta = applyMultiple(base, o.multiple ?? false);
264
241
  return wrapKey(o, meta);
265
242
  }
266
- // Internal impl-signatures to bypass overload strict key/value checking
243
+ export function reminder(raw) {
244
+ const norm = normalizeOpts(raw);
245
+ const base = date({ label: raw.label, rules: raw.rules, view: raw.view });
246
+ const meta = {
247
+ ...base,
248
+ kind: 'reminder',
249
+ hints: { ...base.hints, remind: true, lead: raw.rules?.lead ?? 30 },
250
+ };
251
+ return wrapKey(norm, meta);
252
+ }
267
253
  const _real = real;
268
254
  const _int = int;
269
- /** Відсоток 0..100 — real({config:{min:0,max:100}}). */
270
255
  export function percent(o) {
271
- return _real({ ...o, config: { ...o.config, min: 0, max: 100 } });
256
+ return _real({ ...o, rules: { min: 0, max: 100, ...o.rules } });
272
257
  }
273
- /** Рік — int({config:{min:1900,max:2100}}); межі перекриваються через config.min/max. */
274
258
  export function year(o) {
275
- const cfg = o.config ?? {};
276
- return _int({ ...o, config: { ...cfg, min: cfg.min ?? 1900, max: cfg.max ?? 2100 } });
259
+ return _int({ ...o, rules: { min: 1900, max: 2100, ...o.rules } });
260
+ }
261
+ export function weight(raw) {
262
+ const norm = normalizeOpts(raw);
263
+ const base = int({ label: raw.label, rules: { min: 1, ...raw.rules }, view: raw.view });
264
+ return wrapKey(norm, { ...base, kind: 'weight', hints: { ...base.hints, unit: 'g' } });
265
+ }
266
+ export function dimensions(raw) {
267
+ const o = normalizeOpts(raw);
268
+ const required = o.required ?? false;
269
+ const dim = z.object({
270
+ w: z.number().int().nonnegative(),
271
+ h: z.number().int().nonnegative(),
272
+ d: z.number().int().nonnegative(),
273
+ });
274
+ const s = jsonRefined(dim, 'json');
275
+ const meta = {
276
+ kind: 'dimensions',
277
+ label: o.label ?? '',
278
+ required,
279
+ prim: 'text',
280
+ column: 'text',
281
+ hints: { unit: 'mm' },
282
+ columns: { w: 'integer', h: 'integer', d: 'integer' },
283
+ zod: optionalize(s, required),
284
+ };
285
+ return wrapKey(o, meta);
277
286
  }
278
- export function country(o) {
279
- return select({ ...o, options: 'countries' });
287
+ export function country(raw) {
288
+ return select({ ...raw, options: 'countries' });
280
289
  }
281
- // ─── Реєстр пресетів (мерджиться в `f` через composeF) ──────────────────────
282
290
  export const presets = {
283
291
  email,
284
- url,
285
292
  tel,
286
293
  slug,
287
294
  color,
288
295
  colorname,
289
296
  title,
290
297
  password,
298
+ link,
299
+ tag,
291
300
  tags,
292
- imei,
293
- mac,
294
- iban,
295
301
  markdown,
296
302
  snippet,
297
303
  rating,
298
304
  duration,
305
+ reminder,
299
306
  percent,
300
307
  year,
308
+ weight,
309
+ dimensions,
301
310
  country,
302
311
  };
303
- //# sourceMappingURL=field-presets.js.map
@@ -0,0 +1,36 @@
1
+ export declare const LANGUAGES: {
2
+ code: string;
3
+ name: string;
4
+ }[];
5
+ export declare const SEX_OPTIONS: [{
6
+ readonly value: "M";
7
+ readonly title: "core.sex.M";
8
+ }, {
9
+ readonly value: "F";
10
+ readonly title: "core.sex.F";
11
+ }, {
12
+ readonly value: "other";
13
+ readonly title: "core.sex.other";
14
+ }];
15
+ export declare const WEEKDAY_OPTIONS: [{
16
+ readonly value: "mon";
17
+ readonly title: "core.weekdays.mon";
18
+ }, {
19
+ readonly value: "tue";
20
+ readonly title: "core.weekdays.tue";
21
+ }, {
22
+ readonly value: "wed";
23
+ readonly title: "core.weekdays.wed";
24
+ }, {
25
+ readonly value: "thu";
26
+ readonly title: "core.weekdays.thu";
27
+ }, {
28
+ readonly value: "fri";
29
+ readonly title: "core.weekdays.fri";
30
+ }, {
31
+ readonly value: "sat";
32
+ readonly title: "core.weekdays.sat";
33
+ }, {
34
+ readonly value: "sun";
35
+ readonly title: "core.weekdays.sun";
36
+ }];
@@ -0,0 +1,18 @@
1
+ import ISO6391 from 'iso-639-1';
2
+ export const LANGUAGES = ISO6391.getAllCodes()
3
+ .map((code) => ({ code, name: ISO6391.getNativeName(code) }))
4
+ .sort((a, b) => a.name.localeCompare(b.name));
5
+ export const SEX_OPTIONS = [
6
+ { value: 'M', title: 'core.sex.M' },
7
+ { value: 'F', title: 'core.sex.F' },
8
+ { value: 'other', title: 'core.sex.other' },
9
+ ];
10
+ export const WEEKDAY_OPTIONS = [
11
+ { value: 'mon', title: 'core.weekdays.mon' },
12
+ { value: 'tue', title: 'core.weekdays.tue' },
13
+ { value: 'wed', title: 'core.weekdays.wed' },
14
+ { value: 'thu', title: 'core.weekdays.thu' },
15
+ { value: 'fri', title: 'core.weekdays.fri' },
16
+ { value: 'sat', title: 'core.weekdays.sat' },
17
+ { value: 'sun', title: 'core.weekdays.sun' },
18
+ ];
@@ -0,0 +1,84 @@
1
+ import type { Condition } from '../condition.ts';
2
+ import type { FieldItem } from '../fields.ts';
3
+ export interface Rules {
4
+ min?: number | string;
5
+ max?: number | string;
6
+ step?: number;
7
+ pattern?: string;
8
+ messageKey?: string;
9
+ granularity?: 'minute' | 'hour' | 'day' | 'month' | 'year' | 'second' | 'datetime';
10
+ language?: string;
11
+ defaultCurrency?: string;
12
+ defaultLang?: string;
13
+ unique?: string[];
14
+ fixed?: boolean;
15
+ exts?: string[];
16
+ lead?: number;
17
+ by?: FieldItem;
18
+ }
19
+ export interface View {
20
+ hidden?: boolean | Condition;
21
+ noEditControl?: boolean;
22
+ display?: 'wrap' | 'scroll' | 'table' | 'sheet';
23
+ kind?: string;
24
+ icon?: string;
25
+ displayKey?: string;
26
+ keyLabel?: string;
27
+ valueLabel?: string;
28
+ compareWith?: string;
29
+ }
30
+ export interface GroupedCore {
31
+ key?: string;
32
+ value?: unknown;
33
+ label?: string;
34
+ rules?: Rules;
35
+ view?: View;
36
+ }
37
+ export interface FieldConfig {
38
+ min?: number;
39
+ max?: number;
40
+ step?: number;
41
+ pattern?: string;
42
+ messageKey?: string;
43
+ granularity?: 'minute' | 'hour' | 'day' | 'month' | 'year' | 'second' | 'datetime';
44
+ language?: string;
45
+ defaultCurrency?: string;
46
+ defaultLang?: string;
47
+ }
48
+ export type NormalizedOpts = {
49
+ key?: string;
50
+ value?: unknown;
51
+ label?: string;
52
+ options?: string | unknown[];
53
+ slots?: string[];
54
+ from?: string;
55
+ pick?: string[];
56
+ option?: unknown;
57
+ relation?: {
58
+ vault: string;
59
+ module: string;
60
+ };
61
+ fields?: unknown;
62
+ config?: FieldConfig;
63
+ required?: boolean | Condition;
64
+ default?: string | number | boolean | null;
65
+ multiple?: boolean;
66
+ unique?: string[];
67
+ fixed?: boolean;
68
+ exts?: string[];
69
+ lead?: number;
70
+ by?: FieldItem;
71
+ min?: number | string;
72
+ max?: number | string;
73
+ step?: number;
74
+ hidden?: View['hidden'];
75
+ noEditControl?: boolean;
76
+ display?: View['display'];
77
+ kind?: string;
78
+ icon?: string;
79
+ displayKey?: string;
80
+ keyLabel?: string;
81
+ valueLabel?: string;
82
+ compareWith?: string;
83
+ };
84
+ export declare function normalizeOpts<T extends GroupedCore>(rawIn: T): NormalizedOpts;
@@ -0,0 +1,47 @@
1
+ export function normalizeOpts(rawIn) {
2
+ const raw = rawIn;
3
+ const r = raw.rules ?? {};
4
+ const v = raw.view ?? {};
5
+ const config = {};
6
+ if (r.min != null && typeof r.min === 'number')
7
+ config.min = r.min;
8
+ if (r.max != null && typeof r.max === 'number')
9
+ config.max = r.max;
10
+ if (r.step != null)
11
+ config.step = r.step;
12
+ if (r.pattern != null)
13
+ config.pattern = r.pattern;
14
+ if (r.messageKey != null)
15
+ config.messageKey = r.messageKey;
16
+ if (r.granularity != null)
17
+ config.granularity = r.granularity;
18
+ if (r.language != null)
19
+ config.language = r.language;
20
+ if (r.defaultCurrency != null)
21
+ config.defaultCurrency = r.defaultCurrency;
22
+ if (r.defaultLang != null)
23
+ config.defaultLang = r.defaultLang;
24
+ const { rules: _r, view: _v, ...flat } = raw;
25
+ const result = {
26
+ ...flat,
27
+ ...(Object.keys(config).length ? { config } : {}),
28
+ unique: r.unique,
29
+ fixed: r.fixed,
30
+ exts: r.exts,
31
+ lead: r.lead,
32
+ by: r.by,
33
+ min: r.min,
34
+ max: r.max,
35
+ step: r.step,
36
+ hidden: v.hidden,
37
+ noEditControl: v.noEditControl,
38
+ display: v.display,
39
+ kind: v.kind,
40
+ icon: v.icon,
41
+ displayKey: v.displayKey,
42
+ ...(v.keyLabel !== undefined ? { keyLabel: v.keyLabel } : {}),
43
+ ...(v.valueLabel !== undefined ? { valueLabel: v.valueLabel } : {}),
44
+ compareWith: v.compareWith,
45
+ };
46
+ return Object.fromEntries(Object.entries(result).filter(([, v]) => v !== undefined));
47
+ }
@@ -0,0 +1,13 @@
1
+ export interface UrlValue {
2
+ scheme?: string;
3
+ username?: string;
4
+ password?: string;
5
+ host?: string;
6
+ port?: number;
7
+ path?: string;
8
+ query?: string;
9
+ hash?: string;
10
+ }
11
+ export declare function parseUrl(s: string): UrlValue | null;
12
+ export declare function buildUrl(v: UrlValue | null | undefined): string;
13
+ export declare function hrefOf(v: UrlValue | null | undefined): string;
@@ -0,0 +1,49 @@
1
+ const SCHEME_RE = /^[a-z][a-z0-9+.-]*:\/\//i;
2
+ export function parseUrl(s) {
3
+ const raw = s.trim();
4
+ if (!raw)
5
+ return null;
6
+ const hasScheme = SCHEME_RE.test(raw);
7
+ let u;
8
+ try {
9
+ u = new URL(hasScheme ? raw : `http://${raw}`);
10
+ }
11
+ catch {
12
+ return { host: raw };
13
+ }
14
+ const v = {};
15
+ if (hasScheme)
16
+ v.scheme = u.protocol.replace(/:$/, '');
17
+ if (u.username)
18
+ v.username = u.username;
19
+ if (u.password)
20
+ v.password = u.password;
21
+ if (u.hostname)
22
+ v.host = u.hostname;
23
+ if (u.port)
24
+ v.port = Number(u.port);
25
+ if (u.pathname && u.pathname !== '/')
26
+ v.path = u.pathname;
27
+ if (u.search)
28
+ v.query = u.search.slice(1);
29
+ if (u.hash)
30
+ v.hash = u.hash.slice(1);
31
+ return v;
32
+ }
33
+ export function buildUrl(v) {
34
+ if (!v)
35
+ return '';
36
+ const scheme = v.scheme ? `${v.scheme}://` : '';
37
+ const auth = v.username ? `${v.username}${v.password ? `:${v.password}` : ''}@` : '';
38
+ const host = v.host ?? '';
39
+ const port = v.port != null ? `:${v.port}` : '';
40
+ const path = v.path ?? '';
41
+ const query = v.query ? `?${v.query}` : '';
42
+ const hash = v.hash ? `#${v.hash}` : '';
43
+ return `${scheme}${auth}${host}${port}${path}${query}${hash}`;
44
+ }
45
+ export function hrefOf(v) {
46
+ if (!v || !buildUrl(v))
47
+ return '';
48
+ return v.scheme ? buildUrl(v) : `https://${buildUrl(v)}`;
49
+ }
@@ -0,0 +1,30 @@
1
+ import { z } from 'zod';
2
+ import type { Condition } from '../condition.ts';
3
+ export declare function vmsg(code: string, params?: Record<string, unknown>): string;
4
+ type ZErrCtx = {
5
+ input?: unknown;
6
+ code?: string;
7
+ };
8
+ export declare function reqErr(code?: string): {
9
+ error: (iss: ZErrCtx) => string | undefined;
10
+ };
11
+ export declare function typeErr(code?: string): {
12
+ error: (iss: ZErrCtx) => string | undefined;
13
+ };
14
+ export declare function reqTypeErr(): {
15
+ error: (iss: ZErrCtx) => string | undefined;
16
+ };
17
+ export declare function jsonValue(raw: unknown): unknown;
18
+ export declare function jsonRefined(inner: z.ZodTypeAny, code: string): z.ZodTypeAny;
19
+ export declare function optionalize(schema: z.ZodTypeAny, required: boolean | Condition): z.ZodTypeAny;
20
+ export declare function decodeVmsg(message: string): {
21
+ code: string;
22
+ params?: Record<string, unknown>;
23
+ };
24
+ export declare function validateField(field: {
25
+ zod: z.ZodTypeAny;
26
+ }, value: unknown): {
27
+ code: string;
28
+ params?: Record<string, unknown>;
29
+ } | null;
30
+ export {};