@coffer-org/plugin-documents 4.0.0 → 5.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/dist/person_identity/index.js +2 -2
- package/dist/personal_document/index.js +4 -4
- package/dist/schema.js +128 -133
- package/package.json +4 -4
|
@@ -12,7 +12,7 @@ nationality — ISO alpha-2. variants — given/family name per language (field.
|
|
|
12
12
|
label: 'documents.person_identity.fields.nationality',
|
|
13
13
|
options: 'countries',
|
|
14
14
|
strict: true,
|
|
15
|
-
|
|
15
|
+
noSearch: true,
|
|
16
16
|
}),
|
|
17
17
|
variants: field.keyed({
|
|
18
18
|
label: 'documents.person_identity.fields.variants',
|
|
@@ -22,7 +22,7 @@ nationality — ISO alpha-2. variants — given/family name per language (field.
|
|
|
22
22
|
label: 'documents.person_identity.variants.lang',
|
|
23
23
|
options: 'languages',
|
|
24
24
|
strict: true,
|
|
25
|
-
|
|
25
|
+
noSearch: true,
|
|
26
26
|
}),
|
|
27
27
|
name: field.string({ label: 'documents.person_identity.variants.name' }),
|
|
28
28
|
surname: field.string({ label: 'documents.person_identity.variants.surname' }),
|
|
@@ -12,7 +12,7 @@ export default defineShelf({
|
|
|
12
12
|
name: field.title({ label: 'core.fields.name' }),
|
|
13
13
|
about: field.illustrated({
|
|
14
14
|
label: 'documents.personal_document.fields.about',
|
|
15
|
-
fields: { image: field.avatar({ role: 'avatar' }), text: field.text({ rules: { max: 1000 } }) },
|
|
15
|
+
fields: { image: field.avatar({ ui: { role: 'avatar' } }), text: field.text({ rules: { max: 1000 } }) },
|
|
16
16
|
}),
|
|
17
17
|
idcard: field.idcard({
|
|
18
18
|
number: { number: field.string({ label: 'documents.personal_document.fields.number', rules: { max: 50 } }) },
|
|
@@ -38,7 +38,7 @@ export default defineShelf({
|
|
|
38
38
|
sex: field.string({
|
|
39
39
|
label: 'documents.personal_document.fields.sex',
|
|
40
40
|
strict: true,
|
|
41
|
-
|
|
41
|
+
noSearch: true,
|
|
42
42
|
options: [
|
|
43
43
|
{ value: 'M', title: 'documents.personal_document.options.sex.M' },
|
|
44
44
|
{ value: 'F', title: 'documents.personal_document.options.sex.F' },
|
|
@@ -49,7 +49,7 @@ export default defineShelf({
|
|
|
49
49
|
label: 'documents.personal_document.fields.nationality',
|
|
50
50
|
options: 'countries',
|
|
51
51
|
strict: true,
|
|
52
|
-
|
|
52
|
+
noSearch: true,
|
|
53
53
|
ui: { span: 4 },
|
|
54
54
|
}),
|
|
55
55
|
owner: field.relation({
|
|
@@ -73,7 +73,7 @@ export default defineShelf({
|
|
|
73
73
|
label: 'core.fields.type',
|
|
74
74
|
required: true,
|
|
75
75
|
strict: true,
|
|
76
|
-
|
|
76
|
+
noSearch: true,
|
|
77
77
|
options: [
|
|
78
78
|
{ value: 'P', title: 'documents.personal_document.options.type.P' },
|
|
79
79
|
{ value: 'PA', title: 'documents.personal_document.options.type.PA' },
|
package/dist/schema.js
CHANGED
|
@@ -4371,8 +4371,28 @@ var UNITS_MAP = {
|
|
|
4371
4371
|
label: "core.units.ppm"
|
|
4372
4372
|
}]
|
|
4373
4373
|
};
|
|
4374
|
+
/**
|
|
4375
|
+
* Resolve a unit spec — a named scale or an explicit option list — to its options.
|
|
4376
|
+
*
|
|
4377
|
+
* Throws rather than returning `undefined`, because both ways of reaching `undefined` here
|
|
4378
|
+
* produce a field that CONSTRUCTS and then crashes when someone tries to save through it:
|
|
4379
|
+
* `measured`'s unit role closes over these options and calls `.some(…)` on them inside its
|
|
4380
|
+
* refine, so a missing spec or a typo'd scale name turns a user's save into a
|
|
4381
|
+
* `Cannot read properties of undefined` instead of a validation message. The golden matrix
|
|
4382
|
+
* recorded exactly that for `f.measured({})`.
|
|
4383
|
+
*
|
|
4384
|
+
* A declaration error belongs at declaration time, where the plugin author sees it and the
|
|
4385
|
+
* message can name the scale they meant — the same reason the host-services seam fails at
|
|
4386
|
+
* registration rather than at first render.
|
|
4387
|
+
*/
|
|
4374
4388
|
function resolveUnits(u) {
|
|
4375
|
-
|
|
4389
|
+
if (typeof u === "string") {
|
|
4390
|
+
const known = UNITS_MAP[u];
|
|
4391
|
+
if (!known) throw new Error(`units: unknown scale '${u}' (known: ${Object.keys(UNITS_MAP).sort().join(", ")})`);
|
|
4392
|
+
return known;
|
|
4393
|
+
}
|
|
4394
|
+
if (!Array.isArray(u)) throw new Error("units: a unit spec is required — a named scale, or an explicit list of options");
|
|
4395
|
+
return u;
|
|
4376
4396
|
}
|
|
4377
4397
|
//#endregion
|
|
4378
4398
|
//#region ../sdk/src/fields/validation.ts
|
|
@@ -4395,6 +4415,23 @@ function typeErr(code = "invalid_type") {
|
|
|
4395
4415
|
function reqTypeErr() {
|
|
4396
4416
|
return { error: (iss) => iss.code === "invalid_type" ? iss.input === void 0 ? vmsg("required") : vmsg("invalid_type") : void 0 };
|
|
4397
4417
|
}
|
|
4418
|
+
/**
|
|
4419
|
+
* A string schema whose CONTENT checks only speak once the value is known to be a string.
|
|
4420
|
+
*
|
|
4421
|
+
* zod's length checks are not type-guarded: `min`/`max` read `input.length`, and an ARRAY has
|
|
4422
|
+
* one. So `z.string().min(1)` answers `[]` with `invalid_type` AND `too_small` — two messages
|
|
4423
|
+
* about a single wrongness, both of which reach the user, since `mutate.ts` and `extend-io.ts`
|
|
4424
|
+
* turn every issue into its own `ValidationError`. (A number answers with `invalid_type`
|
|
4425
|
+
* alone, having no `length` to read — so the redundancy was array-shaped and invisible until
|
|
4426
|
+
* the golden matrix started recording the whole issue list instead of `issues[0]`.)
|
|
4427
|
+
*
|
|
4428
|
+
* Piping puts the type question first and alone: `add` never runs on a non-string. Pass the
|
|
4429
|
+
* content checks as a builder rather than chaining them onto the result, because a `ZodPipe`
|
|
4430
|
+
* has no `.min`/`.max`/`.regex` to chain.
|
|
4431
|
+
*/
|
|
4432
|
+
function stringContent(add) {
|
|
4433
|
+
return string$1(reqTypeErr()).pipe(add(string$1()));
|
|
4434
|
+
}
|
|
4398
4435
|
/** Parse a JSON string, else return the native value (object/array) as-is.
|
|
4399
4436
|
* Tolerant input for native form-state AND legacy JSON-string payloads.
|
|
4400
4437
|
* A string that fails JSON.parse is returned unchanged — callers detect
|
|
@@ -4721,11 +4758,9 @@ function wrapKey(key, opts, meta) {
|
|
|
4721
4758
|
//#region ../sdk/src/fields/normalize.ts
|
|
4722
4759
|
function normalizeOpts(rawIn) {
|
|
4723
4760
|
const raw = rawIn;
|
|
4761
|
+
if (raw["view"] !== void 0) throw new Error("[normalizeOpts] `view` is gone — presentational options live in `ui: {}` (see CLAUDE.md § field author options and the field-types skill).");
|
|
4724
4762
|
const r = raw.rules ?? {};
|
|
4725
|
-
const v = {
|
|
4726
|
-
...raw.view ?? {},
|
|
4727
|
-
...raw.ui ?? {}
|
|
4728
|
-
};
|
|
4763
|
+
const v = raw.ui ?? {};
|
|
4729
4764
|
const config = {};
|
|
4730
4765
|
if (r.min != null && typeof r.min === "number") config.min = r.min;
|
|
4731
4766
|
if (r.max != null && typeof r.max === "number") config.max = r.max;
|
|
@@ -4734,7 +4769,7 @@ function normalizeOpts(rawIn) {
|
|
|
4734
4769
|
if (r.messageKey != null) config.messageKey = r.messageKey;
|
|
4735
4770
|
if (r.granularity != null) config.granularity = r.granularity;
|
|
4736
4771
|
if (r.language != null) config.language = r.language;
|
|
4737
|
-
const { rules: _r,
|
|
4772
|
+
const { rules: _r, ui: _ui, ...flat } = raw;
|
|
4738
4773
|
const result = {
|
|
4739
4774
|
...flat,
|
|
4740
4775
|
...Object.keys(config).length ? { config } : {},
|
|
@@ -4749,7 +4784,6 @@ function normalizeOpts(rawIn) {
|
|
|
4749
4784
|
step: r.step,
|
|
4750
4785
|
hidden: v.hidden,
|
|
4751
4786
|
noEditControl: v.noEditControl,
|
|
4752
|
-
noSearch: v.noSearch,
|
|
4753
4787
|
display: v.display,
|
|
4754
4788
|
kind: v.kind,
|
|
4755
4789
|
icon: v.icon,
|
|
@@ -4757,7 +4791,11 @@ function normalizeOpts(rawIn) {
|
|
|
4757
4791
|
...v.keyLabel !== void 0 ? { keyLabel: v.keyLabel } : {},
|
|
4758
4792
|
...v.valueLabel !== void 0 ? { valueLabel: v.valueLabel } : {},
|
|
4759
4793
|
compareWith: v.compareWith,
|
|
4760
|
-
span: v.span
|
|
4794
|
+
span: v.span,
|
|
4795
|
+
emphasis: v.emphasis,
|
|
4796
|
+
noLabel: v.noLabel,
|
|
4797
|
+
role: v.role,
|
|
4798
|
+
editor: v.editor
|
|
4761
4799
|
};
|
|
4762
4800
|
return Object.fromEntries(Object.entries(result).filter(([, val]) => val !== void 0));
|
|
4763
4801
|
}
|
|
@@ -4908,16 +4946,17 @@ function registerPreset(factory, base, presetOpts, over = {}) {
|
|
|
4908
4946
|
function buildComposite(def, opts, parts) {
|
|
4909
4947
|
const required = opts.required ?? false;
|
|
4910
4948
|
const roleZod = def.roleZod(opts, parts);
|
|
4911
|
-
const rowSchema = object(partsRowShape(roleZod, parts, required
|
|
4912
|
-
const absentRowSchema = required === true ? object(partsRowShape(roleZod, parts,
|
|
4949
|
+
const rowSchema = object(partsRowShape(roleZod, parts, required === true ? "strict" : "null"));
|
|
4950
|
+
const absentRowSchema = required === true ? object(partsRowShape(roleZod, parts, "null-or-missing")) : rowSchema;
|
|
4913
4951
|
const roleKeys = (which) => parts.filter((p) => p.mode === "stored" && (which?.(p) ?? true)).map(partValueKey);
|
|
4914
4952
|
const absenceKeys = def.absenceRoles ? roleKeys((p) => def.absenceRoles.includes(p.role)) : void 0;
|
|
4915
4953
|
const clientKeys = def.absenceRoles ? roleKeys() : void 0;
|
|
4916
4954
|
const zod = unknown().transform((raw, ctx) => {
|
|
4917
4955
|
const parsed = jsonValue(raw);
|
|
4918
4956
|
const p = parsed;
|
|
4957
|
+
const isRow = p == null || typeof p === "object" && !Array.isArray(p);
|
|
4919
4958
|
/** Every one of `keys` empty in this value — `null`/absent alike. */
|
|
4920
|
-
const allEmpty = (keys) => p == null ||
|
|
4959
|
+
const allEmpty = (keys) => isRow && (p == null || keys.length > 0 && keys.every((k) => p[k] == null));
|
|
4921
4960
|
let absent = false;
|
|
4922
4961
|
if (absenceKeys && clientKeys) {
|
|
4923
4962
|
absent = allEmpty(absenceKeys);
|
|
@@ -5157,15 +5196,14 @@ function materializeDef(def) {
|
|
|
5157
5196
|
* open: a magnitude may be real/int/rating, a unit may be a select or a relation.
|
|
5158
5197
|
*/
|
|
5159
5198
|
/**
|
|
5160
|
-
* `NormalizedOpts` (what `FieldDecl.opts` actually is) has no single `
|
|
5161
|
-
* author's `
|
|
5162
|
-
* by `normalizeOpts`. A correction that wants to carry
|
|
5163
|
-
* flat fields back into the nested shape `declare()`'s own `normalizeOpts` call expects.
|
|
5199
|
+
* `NormalizedOpts` (what `FieldDecl.opts` actually is) has no single `ui` property — the
|
|
5200
|
+
* author's `ui` is flattened into individual fields (`hidden`, `display`, `kind`, …)
|
|
5201
|
+
* by `normalizeOpts`. A correction that wants to carry presentation forward has to collect
|
|
5202
|
+
* those flat fields back into the nested shape `declare()`'s own `normalizeOpts` call expects.
|
|
5164
5203
|
*/
|
|
5165
|
-
var
|
|
5204
|
+
var UI_KEYS = [
|
|
5166
5205
|
"hidden",
|
|
5167
5206
|
"noEditControl",
|
|
5168
|
-
"noSearch",
|
|
5169
5207
|
"display",
|
|
5170
5208
|
"kind",
|
|
5171
5209
|
"icon",
|
|
@@ -5176,11 +5214,11 @@ var VIEW_KEYS = [
|
|
|
5176
5214
|
"span"
|
|
5177
5215
|
];
|
|
5178
5216
|
/** The author's presentation opts, re-nested from `opts`'s flat fields — `undefined` when
|
|
5179
|
-
* none were set, so a correction never adds an empty `
|
|
5180
|
-
function
|
|
5217
|
+
* none were set, so a correction never adds an empty `ui: {}` no filling ever had. */
|
|
5218
|
+
function uiOf(opts) {
|
|
5181
5219
|
if (!opts) return void 0;
|
|
5182
5220
|
const v = {};
|
|
5183
|
-
for (const k of
|
|
5221
|
+
for (const k of UI_KEYS) if (opts[k] !== void 0) v[k] = opts[k];
|
|
5184
5222
|
return Object.keys(v).length ? v : void 0;
|
|
5185
5223
|
}
|
|
5186
5224
|
/** A filling built from a ported factory arrives as a FieldDecl — build it into the
|
|
@@ -5203,7 +5241,7 @@ function accepts(def, d) {
|
|
|
5203
5241
|
}
|
|
5204
5242
|
/**
|
|
5205
5243
|
* The correction every role gets for free: keep what the author said ABOUT the field
|
|
5206
|
-
* (`label`, `required`, `
|
|
5244
|
+
* (`label`, `required`, `ui`, `value` — a constant or a ComputeFn), replace the type, and
|
|
5207
5245
|
* drop what belonged to the OLD type (`rules` — a number's min/max mean nothing to a
|
|
5208
5246
|
* picture — and `multiple`, because a composite role owns exactly one column). A role whose
|
|
5209
5247
|
* own default needs more than a bare factory (`measured`'s unit, `period`'s endpoints)
|
|
@@ -5216,7 +5254,8 @@ function retypeTo(factory) {
|
|
|
5216
5254
|
label,
|
|
5217
5255
|
required,
|
|
5218
5256
|
value,
|
|
5219
|
-
|
|
5257
|
+
noSearch: d?.opts.noSearch,
|
|
5258
|
+
ui: uiOf(d?.opts)
|
|
5220
5259
|
});
|
|
5221
5260
|
};
|
|
5222
5261
|
}
|
|
@@ -5399,56 +5438,13 @@ function partColumns(parts) {
|
|
|
5399
5438
|
}
|
|
5400
5439
|
return cols;
|
|
5401
5440
|
}
|
|
5402
|
-
|
|
5403
|
-
* A composite's write-time row shape, DERIVED from its resolved parts. `shape` carries
|
|
5404
|
-
* the composite's DEFAULT schema per role — the literal the factory writes by hand
|
|
5405
|
-
* (`{ value: numSchema, unit: z.string().refine(…) }`) — and each part decides which
|
|
5406
|
-
* schema guards its (role-named) key:
|
|
5407
|
-
*
|
|
5408
|
-
* - a plain STORED part is keyed by its role name, matching the value object and the
|
|
5409
|
-
* column `<field>__<role>` that `flattenEmbeddedAt`/`nestEmbeddedAt` read. A role left
|
|
5410
|
-
* to its default filling keeps the default schema — byte-identical to the hand-written
|
|
5411
|
-
* literal, so every existing structure/unit/range code and message is preserved.
|
|
5412
|
-
* - an OVERRIDDEN stored part is validated by its OWN zod (`meta.zod`) instead of the
|
|
5413
|
-
* default schema for that role. This is what makes a RETYPED filling real: an
|
|
5414
|
-
* `f.int({})` magnitude rejects 5.5 (its own `int` check) and gets an integer column,
|
|
5415
|
-
* and an `f.relation({…})` currency accepts a record id instead of being measured
|
|
5416
|
-
* against an ISO-4217 string rule it was never meant to satisfy. The filling also
|
|
5417
|
-
* brings its own optionality and its own min/max — an author replacing a filling
|
|
5418
|
-
* takes over that role's constraints, so `f.real({ rules: { min: 0 } })` is how a
|
|
5419
|
-
* replaced magnitude keeps a bound.
|
|
5420
|
-
* - a COMPUTED-AND-STORED part ('computedStored') is keyed by its role name like any
|
|
5421
|
-
* other part, but its schema is `z.unknown().optional()`: the SERVER owns the value, so
|
|
5422
|
-
* whatever the client sends there is ignored — `stripServerOwnedParts` deletes it a
|
|
5423
|
-
* moment later and the write path recomputes the column. It is stripped rather than
|
|
5424
|
-
* `z.never()`-rejected because a read hands the client that key (it is a real column,
|
|
5425
|
-
* present in every response), so rejecting it would break a read → PATCH-the-whole-object
|
|
5426
|
-
* round trip.
|
|
5427
|
-
* - a CLIENT-OWNED stored part of a composite that is not `required: true` also accepts
|
|
5428
|
-
* an explicit `null` (`tolerateNull`), which is what closes the read → write round trip
|
|
5429
|
-
* for a PARTIALLY FILLED composite. A SELECT returns every sub-column, so a record whose
|
|
5430
|
-
* magnitude column is set and whose unit column is empty reads back as
|
|
5431
|
-
* `{value: 900, unit: null}` (`nestEmbeddedAt` drops the key only when EVERY column is
|
|
5432
|
-
* empty — `0` is a value), and feeding that exact object back used to fail with
|
|
5433
|
-
* `measured_structure`: the write path refused the shape its own read produced. The null
|
|
5434
|
-
* slot now parses through and is written back as NULL, so the round trip is closed and
|
|
5435
|
-
* clearing ONE role of a filled composite works instead of erroring.
|
|
5436
|
-
* NULL, not absence: a read emits every stored role (empty ones as `null`), so `null` is
|
|
5437
|
-
* how "this record has no value there" arrives, while an ABSENT key is a writer that
|
|
5438
|
-
* never mentioned a role it owns — which stays the structure error it has always been
|
|
5439
|
-
* (`{unit: 'kg'}` with no magnitude, `{lat: 50}` with no longitude). That is the
|
|
5440
|
-
* all-or-nothing rule for a DECLARATION, and it is untouched.
|
|
5441
|
-
* A `required: true` composite keeps every client-owned slot MANDATORY, null included —
|
|
5442
|
-
* "tolerate null" must not turn a required field optional, so an empty or half-empty
|
|
5443
|
-
* value still fails with the same structure code it fails with today. A filling the
|
|
5444
|
-
* author declared `required` keeps its own mandate too.
|
|
5445
|
-
*/
|
|
5446
|
-
function partsRowShape(shape, parts, tolerateNull = false) {
|
|
5441
|
+
function partsRowShape(shape, parts, tolerance = "strict") {
|
|
5447
5442
|
const out = { ...shape };
|
|
5448
5443
|
for (const p of parts) if (p.mode === "computedStored") out[p.key] = unknown().optional();
|
|
5449
5444
|
else {
|
|
5450
5445
|
const own = p.overridden ? p.meta.zod : shape[p.role] ?? unknown().optional();
|
|
5451
|
-
|
|
5446
|
+
const relaxed = tolerance !== "strict" && !(p.overridden && p.meta.required === true);
|
|
5447
|
+
out[p.key] = relaxed ? tolerance === "null-or-missing" ? own.nullish() : own.nullable() : own;
|
|
5452
5448
|
}
|
|
5453
5449
|
return out;
|
|
5454
5450
|
}
|
|
@@ -5643,7 +5639,7 @@ function internalApiToken(o) {
|
|
|
5643
5639
|
label: o.label,
|
|
5644
5640
|
multiple: true,
|
|
5645
5641
|
rules: { unique: ["name"] },
|
|
5646
|
-
|
|
5642
|
+
ui: { kind: "internalApiToken" },
|
|
5647
5643
|
fields: {
|
|
5648
5644
|
name: string({}),
|
|
5649
5645
|
token: password({}),
|
|
@@ -5669,7 +5665,7 @@ function internalOauthGrants(o) {
|
|
|
5669
5665
|
scope: "nest",
|
|
5670
5666
|
label: o.label,
|
|
5671
5667
|
multiple: true,
|
|
5672
|
-
|
|
5668
|
+
ui: { kind: "internalOauthGrants" },
|
|
5673
5669
|
fields: {
|
|
5674
5670
|
clientName: string({}),
|
|
5675
5671
|
createdAt: string({}),
|
|
@@ -6296,10 +6292,8 @@ function country(raw) {
|
|
|
6296
6292
|
...raw,
|
|
6297
6293
|
options: "countries",
|
|
6298
6294
|
strict: true,
|
|
6299
|
-
|
|
6300
|
-
|
|
6301
|
-
noSearch: true
|
|
6302
|
-
}
|
|
6295
|
+
ui: { ...raw.ui ?? {} },
|
|
6296
|
+
noSearch: true
|
|
6303
6297
|
});
|
|
6304
6298
|
}
|
|
6305
6299
|
/**
|
|
@@ -6323,10 +6317,8 @@ function currency(raw) {
|
|
|
6323
6317
|
...raw,
|
|
6324
6318
|
options: "currencies",
|
|
6325
6319
|
strict: true,
|
|
6326
|
-
|
|
6327
|
-
|
|
6328
|
-
noSearch: true
|
|
6329
|
-
}
|
|
6320
|
+
ui: { ...raw.ui ?? {} },
|
|
6321
|
+
noSearch: true
|
|
6330
6322
|
});
|
|
6331
6323
|
}
|
|
6332
6324
|
/**
|
|
@@ -6486,7 +6478,7 @@ function bento(opts) {
|
|
|
6486
6478
|
label: opts.label,
|
|
6487
6479
|
icon: opts.icon,
|
|
6488
6480
|
fields,
|
|
6489
|
-
|
|
6481
|
+
ui: { kind: "bento" }
|
|
6490
6482
|
}),
|
|
6491
6483
|
view: {
|
|
6492
6484
|
kind: "bento",
|
|
@@ -6515,7 +6507,7 @@ function split(opts) {
|
|
|
6515
6507
|
return {
|
|
6516
6508
|
...group({
|
|
6517
6509
|
fields: merge("split", opts.columns[0], opts.columns[1]),
|
|
6518
|
-
|
|
6510
|
+
ui: { kind: "split" }
|
|
6519
6511
|
}),
|
|
6520
6512
|
view: {
|
|
6521
6513
|
kind: "split",
|
|
@@ -6539,7 +6531,7 @@ function grid(opts) {
|
|
|
6539
6531
|
label: opts.label,
|
|
6540
6532
|
icon: opts.icon,
|
|
6541
6533
|
fields: opts.fields,
|
|
6542
|
-
|
|
6534
|
+
ui: { kind: "grid" }
|
|
6543
6535
|
}),
|
|
6544
6536
|
view: {
|
|
6545
6537
|
kind: "grid",
|
|
@@ -6564,7 +6556,7 @@ function spread(opts) {
|
|
|
6564
6556
|
return {
|
|
6565
6557
|
...group({
|
|
6566
6558
|
fields: merge("spread", visual, quote, opts.facts),
|
|
6567
|
-
|
|
6559
|
+
ui: { kind: "spread" }
|
|
6568
6560
|
}),
|
|
6569
6561
|
view: {
|
|
6570
6562
|
kind: "spread",
|
|
@@ -6589,7 +6581,7 @@ function aside(opts) {
|
|
|
6589
6581
|
return {
|
|
6590
6582
|
...group({
|
|
6591
6583
|
fields: merge("aside", opts.fields, opts.aside),
|
|
6592
|
-
|
|
6584
|
+
ui: { kind: "aside" }
|
|
6593
6585
|
}),
|
|
6594
6586
|
view: {
|
|
6595
6587
|
kind: "aside",
|
|
@@ -6621,7 +6613,7 @@ function tabs(opts) {
|
|
|
6621
6613
|
return {
|
|
6622
6614
|
...group({
|
|
6623
6615
|
fields,
|
|
6624
|
-
|
|
6616
|
+
ui: { kind: "tabs" }
|
|
6625
6617
|
}),
|
|
6626
6618
|
view: {
|
|
6627
6619
|
kind: "tabs",
|
|
@@ -6653,7 +6645,7 @@ function accordion(opts) {
|
|
|
6653
6645
|
return {
|
|
6654
6646
|
...group({
|
|
6655
6647
|
fields,
|
|
6656
|
-
|
|
6648
|
+
ui: { kind: "accordion" }
|
|
6657
6649
|
}),
|
|
6658
6650
|
view: {
|
|
6659
6651
|
kind: "accordion",
|
|
@@ -6683,7 +6675,7 @@ function prose(opts) {
|
|
|
6683
6675
|
label: opts.label,
|
|
6684
6676
|
icon: opts.icon,
|
|
6685
6677
|
fields: opts.fields,
|
|
6686
|
-
|
|
6678
|
+
ui: { kind: "prose" }
|
|
6687
6679
|
}),
|
|
6688
6680
|
view: {
|
|
6689
6681
|
kind: "prose",
|
|
@@ -6709,7 +6701,7 @@ function plaque(opts) {
|
|
|
6709
6701
|
label: opts.label,
|
|
6710
6702
|
icon: opts.icon,
|
|
6711
6703
|
fields: merge("plaque", title, opts.subtitle),
|
|
6712
|
-
|
|
6704
|
+
ui: { kind: "plaque" }
|
|
6713
6705
|
}),
|
|
6714
6706
|
view: {
|
|
6715
6707
|
kind: "plaque",
|
|
@@ -6732,7 +6724,7 @@ function ledger(opts) {
|
|
|
6732
6724
|
label: opts.label,
|
|
6733
6725
|
icon: opts.icon,
|
|
6734
6726
|
fields: opts.fields,
|
|
6735
|
-
|
|
6727
|
+
ui: { kind: "ledger" }
|
|
6736
6728
|
}),
|
|
6737
6729
|
view: { kind: "ledger" }
|
|
6738
6730
|
};
|
|
@@ -6751,7 +6743,7 @@ function stats(opts) {
|
|
|
6751
6743
|
label: opts.label,
|
|
6752
6744
|
icon: opts.icon,
|
|
6753
6745
|
fields: opts.fields,
|
|
6754
|
-
|
|
6746
|
+
ui: { kind: "stats" }
|
|
6755
6747
|
}),
|
|
6756
6748
|
view: { kind: "stats" }
|
|
6757
6749
|
};
|
|
@@ -6770,7 +6762,7 @@ function facets(opts) {
|
|
|
6770
6762
|
label: opts.label,
|
|
6771
6763
|
icon: opts.icon,
|
|
6772
6764
|
fields: opts.fields,
|
|
6773
|
-
|
|
6765
|
+
ui: { kind: "facets" }
|
|
6774
6766
|
}),
|
|
6775
6767
|
view: { kind: "facets" }
|
|
6776
6768
|
};
|
|
@@ -6789,7 +6781,7 @@ function terminal(opts) {
|
|
|
6789
6781
|
label: opts.label,
|
|
6790
6782
|
icon: opts.icon,
|
|
6791
6783
|
fields: opts.fields,
|
|
6792
|
-
|
|
6784
|
+
ui: { kind: "terminal" }
|
|
6793
6785
|
}),
|
|
6794
6786
|
view: {
|
|
6795
6787
|
kind: "terminal",
|
|
@@ -6811,7 +6803,7 @@ function callout(opts) {
|
|
|
6811
6803
|
label: opts.label,
|
|
6812
6804
|
icon: opts.icon,
|
|
6813
6805
|
fields: opts.fields,
|
|
6814
|
-
|
|
6806
|
+
ui: { kind: "callout" }
|
|
6815
6807
|
}),
|
|
6816
6808
|
view: {
|
|
6817
6809
|
kind: "callout",
|
|
@@ -6836,7 +6828,7 @@ function compare(opts) {
|
|
|
6836
6828
|
label: opts.label,
|
|
6837
6829
|
icon: opts.icon,
|
|
6838
6830
|
fields: merge("compare", opts.left, opts.right),
|
|
6839
|
-
|
|
6831
|
+
ui: { kind: "compare" }
|
|
6840
6832
|
}),
|
|
6841
6833
|
view: {
|
|
6842
6834
|
kind: "compare",
|
|
@@ -6867,7 +6859,7 @@ function figure(opts) {
|
|
|
6867
6859
|
return {
|
|
6868
6860
|
...group({
|
|
6869
6861
|
fields: merge("figure", image, caption),
|
|
6870
|
-
|
|
6862
|
+
ui: { kind: "figure" }
|
|
6871
6863
|
}),
|
|
6872
6864
|
view: {
|
|
6873
6865
|
kind: "figure",
|
|
@@ -6892,7 +6884,7 @@ function epigraph(opts) {
|
|
|
6892
6884
|
return {
|
|
6893
6885
|
...group({
|
|
6894
6886
|
fields: merge("epigraph", source, attribution),
|
|
6895
|
-
|
|
6887
|
+
ui: { kind: "epigraph" }
|
|
6896
6888
|
}),
|
|
6897
6889
|
view: {
|
|
6898
6890
|
kind: "epigraph",
|
|
@@ -6918,7 +6910,7 @@ function masthead(opts) {
|
|
|
6918
6910
|
return {
|
|
6919
6911
|
...group({
|
|
6920
6912
|
fields: merge("masthead", overline, title, opts.meta),
|
|
6921
|
-
|
|
6913
|
+
ui: { kind: "masthead" }
|
|
6922
6914
|
}),
|
|
6923
6915
|
view: {
|
|
6924
6916
|
kind: "masthead",
|
|
@@ -6942,7 +6934,7 @@ function timeline(opts) {
|
|
|
6942
6934
|
label: opts.label,
|
|
6943
6935
|
icon: opts.icon,
|
|
6944
6936
|
fields: opts.fields,
|
|
6945
|
-
|
|
6937
|
+
ui: { kind: "timeline" }
|
|
6946
6938
|
}),
|
|
6947
6939
|
view: { kind: "timeline" }
|
|
6948
6940
|
};
|
|
@@ -6961,7 +6953,7 @@ function countdown(opts) {
|
|
|
6961
6953
|
...group({
|
|
6962
6954
|
label: opts.label,
|
|
6963
6955
|
fields: source,
|
|
6964
|
-
|
|
6956
|
+
ui: { kind: "countdown" }
|
|
6965
6957
|
}),
|
|
6966
6958
|
view: {
|
|
6967
6959
|
kind: "countdown",
|
|
@@ -6984,7 +6976,7 @@ function deck(opts) {
|
|
|
6984
6976
|
...group({
|
|
6985
6977
|
label: opts.label,
|
|
6986
6978
|
fields: source,
|
|
6987
|
-
|
|
6979
|
+
ui: { kind: "deck" }
|
|
6988
6980
|
}),
|
|
6989
6981
|
view: {
|
|
6990
6982
|
kind: "deck",
|
|
@@ -7006,7 +6998,7 @@ function people(opts) {
|
|
|
7006
6998
|
...group({
|
|
7007
6999
|
label: opts.label,
|
|
7008
7000
|
fields: source,
|
|
7009
|
-
|
|
7001
|
+
ui: { kind: "people" }
|
|
7010
7002
|
}),
|
|
7011
7003
|
view: {
|
|
7012
7004
|
kind: "people",
|
|
@@ -7032,7 +7024,7 @@ function identity(opts) {
|
|
|
7032
7024
|
return {
|
|
7033
7025
|
...group({
|
|
7034
7026
|
fields: merge("identity", avatar, name, role, opts.channels),
|
|
7035
|
-
|
|
7027
|
+
ui: { kind: "identity" }
|
|
7036
7028
|
}),
|
|
7037
7029
|
view: {
|
|
7038
7030
|
kind: "identity",
|
|
@@ -7058,7 +7050,7 @@ function score(opts) {
|
|
|
7058
7050
|
...group({
|
|
7059
7051
|
label: opts.label,
|
|
7060
7052
|
fields: merge("score", source, verdict),
|
|
7061
|
-
|
|
7053
|
+
ui: { kind: "score" }
|
|
7062
7054
|
}),
|
|
7063
7055
|
view: {
|
|
7064
7056
|
kind: "score",
|
|
@@ -7083,7 +7075,7 @@ function status(opts) {
|
|
|
7083
7075
|
...group({
|
|
7084
7076
|
label: opts.label,
|
|
7085
7077
|
fields: merge("status", source, since),
|
|
7086
|
-
|
|
7078
|
+
ui: { kind: "status" }
|
|
7087
7079
|
}),
|
|
7088
7080
|
view: {
|
|
7089
7081
|
kind: "status",
|
|
@@ -7107,7 +7099,7 @@ function meter(opts) {
|
|
|
7107
7099
|
...group({
|
|
7108
7100
|
label: opts.label,
|
|
7109
7101
|
fields: merge("meter", source, of),
|
|
7110
|
-
|
|
7102
|
+
ui: { kind: "meter" }
|
|
7111
7103
|
}),
|
|
7112
7104
|
view: {
|
|
7113
7105
|
kind: "meter",
|
|
@@ -7134,7 +7126,7 @@ function receipt(opts) {
|
|
|
7134
7126
|
...group({
|
|
7135
7127
|
label: opts.label,
|
|
7136
7128
|
fields: merge("receipt", opts.fields, total),
|
|
7137
|
-
|
|
7129
|
+
ui: { kind: "receipt" }
|
|
7138
7130
|
}),
|
|
7139
7131
|
view: {
|
|
7140
7132
|
kind: "receipt",
|
|
@@ -7157,7 +7149,7 @@ function balance(opts) {
|
|
|
7157
7149
|
...group({
|
|
7158
7150
|
label: opts.label,
|
|
7159
7151
|
fields: source,
|
|
7160
|
-
|
|
7152
|
+
ui: { kind: "balance" }
|
|
7161
7153
|
}),
|
|
7162
7154
|
view: {
|
|
7163
7155
|
kind: "balance",
|
|
@@ -7185,7 +7177,7 @@ function route(opts) {
|
|
|
7185
7177
|
return {
|
|
7186
7178
|
...group({
|
|
7187
7179
|
fields: merge("route", from, to, depart, arrive, duration),
|
|
7188
|
-
|
|
7180
|
+
ui: { kind: "route" }
|
|
7189
7181
|
}),
|
|
7190
7182
|
view: {
|
|
7191
7183
|
kind: "route",
|
|
@@ -7334,7 +7326,7 @@ function nutrition(opts) {
|
|
|
7334
7326
|
...group({
|
|
7335
7327
|
label: opts.label,
|
|
7336
7328
|
fields: merge("nutrition", energy, opts.fields),
|
|
7337
|
-
|
|
7329
|
+
ui: { kind: "nutrition" }
|
|
7338
7330
|
}),
|
|
7339
7331
|
view: {
|
|
7340
7332
|
kind: "nutrition",
|
|
@@ -7360,7 +7352,7 @@ function specimen(opts) {
|
|
|
7360
7352
|
return {
|
|
7361
7353
|
...group({
|
|
7362
7354
|
fields: merge("specimen", title, subtitle, opts.conditions),
|
|
7363
|
-
|
|
7355
|
+
ui: { kind: "specimen" }
|
|
7364
7356
|
}),
|
|
7365
7357
|
view: {
|
|
7366
7358
|
kind: "specimen",
|
|
@@ -7437,7 +7429,7 @@ function idcard(opts) {
|
|
|
7437
7429
|
return {
|
|
7438
7430
|
...group({
|
|
7439
7431
|
fields: merge("idcard", overline, number, opts.meta),
|
|
7440
|
-
|
|
7432
|
+
ui: { kind: "idcard" }
|
|
7441
7433
|
}),
|
|
7442
7434
|
view: {
|
|
7443
7435
|
kind: "idcard",
|
|
@@ -7463,7 +7455,7 @@ function properties(opts) {
|
|
|
7463
7455
|
label: opts.label,
|
|
7464
7456
|
icon: opts.icon,
|
|
7465
7457
|
fields: opts.fields,
|
|
7466
|
-
|
|
7458
|
+
ui: { kind: "properties" }
|
|
7467
7459
|
}),
|
|
7468
7460
|
view: {
|
|
7469
7461
|
kind: "properties",
|
|
@@ -7485,7 +7477,7 @@ function stack(opts) {
|
|
|
7485
7477
|
label: opts.label,
|
|
7486
7478
|
icon: opts.icon,
|
|
7487
7479
|
fields: opts.fields,
|
|
7488
|
-
|
|
7480
|
+
ui: { kind: "stack" }
|
|
7489
7481
|
}),
|
|
7490
7482
|
view: { kind: "stack" }
|
|
7491
7483
|
};
|
|
@@ -8381,8 +8373,9 @@ var isNamedField = (x) => hasValue(x) && !hasChildren(x) && x.key !== void 0;
|
|
|
8381
8373
|
* @example f.group({ scope: 'nest', label: 'mod.fields.contact', fields: { name: f.string({}) } })
|
|
8382
8374
|
*/
|
|
8383
8375
|
function group(o) {
|
|
8376
|
+
if (o["view"] !== void 0) throw new Error("[group] `view` is gone — presentational options live in `ui: {}` (see CLAUDE.md § field author options and the field-types skill).");
|
|
8384
8377
|
const r = o.rules ?? {};
|
|
8385
|
-
const v = o.
|
|
8378
|
+
const v = o.ui ?? {};
|
|
8386
8379
|
const fields = materializeTree(o.fields);
|
|
8387
8380
|
const scope = o.scope ?? "hoist";
|
|
8388
8381
|
if (scope === "nest") {
|
|
@@ -8428,7 +8421,7 @@ function row(o) {
|
|
|
8428
8421
|
multiple: o.multiple,
|
|
8429
8422
|
required: o.required,
|
|
8430
8423
|
rules: o.rules,
|
|
8431
|
-
|
|
8424
|
+
ui: { display: "scroll" }
|
|
8432
8425
|
});
|
|
8433
8426
|
}
|
|
8434
8427
|
/**
|
|
@@ -8456,7 +8449,7 @@ function sheet(o) {
|
|
|
8456
8449
|
label: o.label,
|
|
8457
8450
|
icon: o.icon,
|
|
8458
8451
|
fields: rows,
|
|
8459
|
-
|
|
8452
|
+
ui: { display: "sheet" }
|
|
8460
8453
|
});
|
|
8461
8454
|
}
|
|
8462
8455
|
/**
|
|
@@ -8475,7 +8468,7 @@ function url(o) {
|
|
|
8475
8468
|
scope: "nest",
|
|
8476
8469
|
label: o.label,
|
|
8477
8470
|
required: o.required,
|
|
8478
|
-
|
|
8471
|
+
ui: { kind: "url" },
|
|
8479
8472
|
fields: {
|
|
8480
8473
|
scheme: string({}),
|
|
8481
8474
|
username: string({}),
|
|
@@ -8637,13 +8630,15 @@ registerType("string", {
|
|
|
8637
8630
|
build(o) {
|
|
8638
8631
|
const cfg = o.config ?? {};
|
|
8639
8632
|
const min = cfg.min ?? (o.required === true ? 1 : 0);
|
|
8640
|
-
let s = string$1(reqTypeErr());
|
|
8641
|
-
if (min > 0) s = s.min(min, { message: vmsg("min_length", { min }) });
|
|
8642
|
-
if (cfg.max != null) s = s.max(cfg.max, { message: vmsg("max_length", { max: cfg.max }) });
|
|
8643
|
-
if (cfg.pattern) s = s.regex(new RegExp(cfg.pattern), { message: vmsg("pattern", cfg.messageKey ? { messageKey: cfg.messageKey } : void 0) });
|
|
8644
8633
|
return {
|
|
8645
8634
|
column: "text",
|
|
8646
|
-
zod:
|
|
8635
|
+
zod: stringContent((str) => {
|
|
8636
|
+
let c = str;
|
|
8637
|
+
if (min > 0) c = c.min(min, { message: vmsg("min_length", { min }) });
|
|
8638
|
+
if (cfg.max != null) c = c.max(cfg.max, { message: vmsg("max_length", { max: cfg.max }) });
|
|
8639
|
+
if (cfg.pattern) c = c.regex(new RegExp(cfg.pattern), { message: vmsg("pattern", cfg.messageKey ? { messageKey: cfg.messageKey } : void 0) });
|
|
8640
|
+
return c;
|
|
8641
|
+
}),
|
|
8647
8642
|
hints: {
|
|
8648
8643
|
minLength: cfg.min,
|
|
8649
8644
|
maxLength: cfg.max
|
|
@@ -8664,9 +8659,7 @@ function string(o) {
|
|
|
8664
8659
|
}
|
|
8665
8660
|
/** Shared by localDir/localFile's build(): a server path, min-length-1 when required. */
|
|
8666
8661
|
function pathZod(o) {
|
|
8667
|
-
|
|
8668
|
-
if (o.required === true) s = s.min(1, { message: vmsg("min_length", { min: 1 }) });
|
|
8669
|
-
return s;
|
|
8662
|
+
return stringContent((s) => o.required === true ? s.min(1, { message: vmsg("min_length", { min: 1 }) }) : s);
|
|
8670
8663
|
}
|
|
8671
8664
|
registerType("localDir", {
|
|
8672
8665
|
kind: "localDir",
|
|
@@ -9328,7 +9321,8 @@ var MEASURED_ROLES = (opts) => {
|
|
|
9328
9321
|
label,
|
|
9329
9322
|
required,
|
|
9330
9323
|
value,
|
|
9331
|
-
|
|
9324
|
+
noSearch: d?.opts.noSearch,
|
|
9325
|
+
ui: uiOf(d?.opts),
|
|
9332
9326
|
options: opts.units,
|
|
9333
9327
|
strict: true
|
|
9334
9328
|
});
|
|
@@ -9697,7 +9691,7 @@ function periodMkSubDecl(granularity) {
|
|
|
9697
9691
|
* (`mkSubDecl`), so it writes its own `normalize` rather than using `role()`. A CORRECTED
|
|
9698
9692
|
* filling still keeps the composite's own granularity (`canonical.opts`) — the same
|
|
9699
9693
|
* `date`/`datetime` config the role's own default carries — with the author's
|
|
9700
|
-
* label/required/
|
|
9694
|
+
* label/required/ui/value layered on top, exactly like `retypeTo`'s default.
|
|
9701
9695
|
*/
|
|
9702
9696
|
function periodRole(key, label, mkSubDecl) {
|
|
9703
9697
|
const def = {
|
|
@@ -9713,7 +9707,8 @@ function periodRole(key, label, mkSubDecl) {
|
|
|
9713
9707
|
label: l ?? canonical.opts.label,
|
|
9714
9708
|
required,
|
|
9715
9709
|
value,
|
|
9716
|
-
|
|
9710
|
+
noSearch: d.opts.noSearch,
|
|
9711
|
+
ui: uiOf(d.opts)
|
|
9717
9712
|
});
|
|
9718
9713
|
}
|
|
9719
9714
|
};
|
|
@@ -11032,7 +11027,7 @@ var personal_document_default = defineShelf({
|
|
|
11032
11027
|
about: field.illustrated({
|
|
11033
11028
|
label: "documents.personal_document.fields.about",
|
|
11034
11029
|
fields: {
|
|
11035
|
-
image: field.avatar({ role: "avatar" }),
|
|
11030
|
+
image: field.avatar({ ui: { role: "avatar" } }),
|
|
11036
11031
|
text: field.text({ rules: { max: 1e3 } })
|
|
11037
11032
|
}
|
|
11038
11033
|
}),
|
|
@@ -11070,7 +11065,7 @@ var personal_document_default = defineShelf({
|
|
|
11070
11065
|
sex: field.string({
|
|
11071
11066
|
label: "documents.personal_document.fields.sex",
|
|
11072
11067
|
strict: true,
|
|
11073
|
-
|
|
11068
|
+
noSearch: true,
|
|
11074
11069
|
options: [{
|
|
11075
11070
|
value: "M",
|
|
11076
11071
|
title: "documents.personal_document.options.sex.M"
|
|
@@ -11084,7 +11079,7 @@ var personal_document_default = defineShelf({
|
|
|
11084
11079
|
label: "documents.personal_document.fields.nationality",
|
|
11085
11080
|
options: "countries",
|
|
11086
11081
|
strict: true,
|
|
11087
|
-
|
|
11082
|
+
noSearch: true,
|
|
11088
11083
|
ui: { span: 4 }
|
|
11089
11084
|
}),
|
|
11090
11085
|
owner: field.relation({
|
|
@@ -11121,7 +11116,7 @@ var personal_document_default = defineShelf({
|
|
|
11121
11116
|
label: "core.fields.type",
|
|
11122
11117
|
required: true,
|
|
11123
11118
|
strict: true,
|
|
11124
|
-
|
|
11119
|
+
noSearch: true,
|
|
11125
11120
|
options: [
|
|
11126
11121
|
{
|
|
11127
11122
|
value: "P",
|
|
@@ -11196,7 +11191,7 @@ nationality — ISO alpha-2. variants — given/family name per language (field.
|
|
|
11196
11191
|
label: "documents.person_identity.fields.nationality",
|
|
11197
11192
|
options: "countries",
|
|
11198
11193
|
strict: true,
|
|
11199
|
-
|
|
11194
|
+
noSearch: true
|
|
11200
11195
|
}),
|
|
11201
11196
|
variants: field.keyed({
|
|
11202
11197
|
label: "documents.person_identity.fields.variants",
|
|
@@ -11206,7 +11201,7 @@ nationality — ISO alpha-2. variants — given/family name per language (field.
|
|
|
11206
11201
|
label: "documents.person_identity.variants.lang",
|
|
11207
11202
|
options: "languages",
|
|
11208
11203
|
strict: true,
|
|
11209
|
-
|
|
11204
|
+
noSearch: true
|
|
11210
11205
|
}),
|
|
11211
11206
|
name: field.string({ label: "documents.person_identity.variants.name" }),
|
|
11212
11207
|
surname: field.string({ label: "documents.person_identity.variants.surname" })
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@coffer-org/plugin-documents",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "5.0.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"engines": {
|
|
6
6
|
"node": ">=24"
|
|
@@ -26,9 +26,9 @@
|
|
|
26
26
|
"postpack": "node ../../scripts/swap-exports.mjs src"
|
|
27
27
|
},
|
|
28
28
|
"dependencies": {
|
|
29
|
-
"@coffer-org/plugin-people": "^
|
|
30
|
-
"@coffer-org/sdk": "^
|
|
31
|
-
"@coffer-org/server": "^
|
|
29
|
+
"@coffer-org/plugin-people": "^5.0.0",
|
|
30
|
+
"@coffer-org/sdk": "^5.0.0",
|
|
31
|
+
"@coffer-org/server": "^5.0.0"
|
|
32
32
|
},
|
|
33
33
|
"coffer": {
|
|
34
34
|
"runtime": "node",
|