@coffer-org/plugin-transit 7.1.0 → 7.1.1

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/schema.js CHANGED
@@ -29,6 +29,8 @@ function defineLibrary(v) {
29
29
  //#region ../sdk/src/plugin.ts
30
30
  function definePlugin(p) {
31
31
  if (!p.id) throw new Error("[plugin] missing id");
32
+ if (!p.label) throw new Error(`[plugin] ${p.id}: missing label`);
33
+ if (!p.description) throw new Error(`[plugin] ${p.id}: missing description`);
32
34
  if (!p.version) console.warn(`[plugin] ${p.id}: missing version`);
33
35
  return p;
34
36
  }
@@ -169,7 +171,7 @@ function slugify(input) {
169
171
  return input.toLowerCase().trim().replace(/[^\w\s-]/g, "").replace(/[\s_-]+/g, "-").replace(/^-+|-+$/g, "");
170
172
  }
171
173
  var captureStackTrace = "captureStackTrace" in Error ? Error.captureStackTrace : (..._args) => {};
172
- function isObject$1(data) {
174
+ function isObject(data) {
173
175
  return typeof data === "object" && data !== null && !Array.isArray(data);
174
176
  }
175
177
  var allowsEval = /* @__PURE__*/ cached(() => {
@@ -183,12 +185,12 @@ var allowsEval = /* @__PURE__*/ cached(() => {
183
185
  }
184
186
  });
185
187
  function isPlainObject(o) {
186
- if (isObject$1(o) === false) return false;
188
+ if (isObject(o) === false) return false;
187
189
  const ctor = o.constructor;
188
190
  if (ctor === void 0) return true;
189
191
  if (typeof ctor !== "function") return true;
190
192
  const prot = ctor.prototype;
191
- if (isObject$1(prot) === false) return false;
193
+ if (isObject(prot) === false) return false;
192
194
  if (Object.prototype.hasOwnProperty.call(prot, "isPrototypeOf") === false) return false;
193
195
  return true;
194
196
  }
@@ -1590,13 +1592,13 @@ var $ZodObject = /*@__PURE__*/ $constructor("$ZodObject", (inst, def) => {
1590
1592
  }
1591
1593
  return propValues;
1592
1594
  });
1593
- const isObject = isObject$1;
1595
+ const isObject$2 = isObject;
1594
1596
  const catchall = def.catchall;
1595
1597
  let value;
1596
1598
  inst._zod.parse = (payload, ctx) => {
1597
1599
  value ?? (value = _normalized.value);
1598
1600
  const input = payload.value;
1599
- if (!isObject(input)) {
1601
+ if (!isObject$2(input)) {
1600
1602
  payload.issues.push({
1601
1603
  expected: "object",
1602
1604
  code: "invalid_type",
@@ -1719,7 +1721,7 @@ var $ZodObjectJIT = /*@__PURE__*/ $constructor("$ZodObjectJIT", (inst, def) => {
1719
1721
  return (payload, ctx) => fn(shape, payload, ctx);
1720
1722
  };
1721
1723
  let fastpass;
1722
- const isObject = isObject$1;
1724
+ const isObject$1 = isObject;
1723
1725
  const jit = !globalConfig.jitless;
1724
1726
  const fastEnabled = jit && allowsEval.value;
1725
1727
  const catchall = def.catchall;
@@ -1727,7 +1729,7 @@ var $ZodObjectJIT = /*@__PURE__*/ $constructor("$ZodObjectJIT", (inst, def) => {
1727
1729
  inst._zod.parse = (payload, ctx) => {
1728
1730
  value ?? (value = _normalized.value);
1729
1731
  const input = payload.value;
1730
- if (!isObject(input)) {
1732
+ if (!isObject$1(input)) {
1731
1733
  payload.issues.push({
1732
1734
  expected: "object",
1733
1735
  code: "invalid_type",
@@ -2729,7 +2731,7 @@ function initializeContext(params) {
2729
2731
  external: params?.external ?? void 0
2730
2732
  };
2731
2733
  }
2732
- function process$1(schema, ctx, _params = {
2734
+ function process(schema, ctx, _params = {
2733
2735
  path: [],
2734
2736
  schemaPath: []
2735
2737
  }) {
@@ -2766,7 +2768,7 @@ function process$1(schema, ctx, _params = {
2766
2768
  const parent = schema._zod.parent;
2767
2769
  if (parent) {
2768
2770
  if (!result.ref) result.ref = parent;
2769
- process$1(parent, ctx, params);
2771
+ process(parent, ctx, params);
2770
2772
  ctx.seen.get(parent).isParent = true;
2771
2773
  }
2772
2774
  }
@@ -2986,7 +2988,7 @@ var createToJSONSchemaMethod = (schema, processors = {}) => (params) => {
2986
2988
  ...params,
2987
2989
  processors
2988
2990
  });
2989
- process$1(schema, ctx);
2991
+ process(schema, ctx);
2990
2992
  extractDefs(ctx, schema);
2991
2993
  return finalize(ctx, schema);
2992
2994
  };
@@ -2998,7 +3000,7 @@ var createStandardJSONSchemaMethod = (schema, io, processors = {}) => (params) =
2998
3000
  io,
2999
3001
  processors
3000
3002
  });
3001
- process$1(schema, ctx);
3003
+ process(schema, ctx);
3002
3004
  extractDefs(ctx, schema);
3003
3005
  return finalize(ctx, schema);
3004
3006
  };
@@ -3078,7 +3080,7 @@ var arrayProcessor = (schema, ctx, _json, params) => {
3078
3080
  if (typeof minimum === "number") json.minItems = minimum;
3079
3081
  if (typeof maximum === "number") json.maxItems = maximum;
3080
3082
  json.type = "array";
3081
- json.items = process$1(def.element, ctx, {
3083
+ json.items = process(def.element, ctx, {
3082
3084
  ...params,
3083
3085
  path: [...params.path, "items"]
3084
3086
  });
@@ -3089,7 +3091,7 @@ var objectProcessor = (schema, ctx, _json, params) => {
3089
3091
  json.type = "object";
3090
3092
  json.properties = {};
3091
3093
  const shape = def.shape;
3092
- for (const key in shape) json.properties[key] = process$1(shape[key], ctx, {
3094
+ for (const key in shape) json.properties[key] = process(shape[key], ctx, {
3093
3095
  ...params,
3094
3096
  path: [
3095
3097
  ...params.path,
@@ -3107,7 +3109,7 @@ var objectProcessor = (schema, ctx, _json, params) => {
3107
3109
  if (def.catchall?._zod.def.type === "never") json.additionalProperties = false;
3108
3110
  else if (!def.catchall) {
3109
3111
  if (ctx.io === "output") json.additionalProperties = false;
3110
- } else if (def.catchall) json.additionalProperties = process$1(def.catchall, ctx, {
3112
+ } else if (def.catchall) json.additionalProperties = process(def.catchall, ctx, {
3111
3113
  ...params,
3112
3114
  path: [...params.path, "additionalProperties"]
3113
3115
  });
@@ -3115,7 +3117,7 @@ var objectProcessor = (schema, ctx, _json, params) => {
3115
3117
  var unionProcessor = (schema, ctx, json, params) => {
3116
3118
  const def = schema._zod.def;
3117
3119
  const isExclusive = def.inclusive === false;
3118
- const options = def.options.map((x, i) => process$1(x, ctx, {
3120
+ const options = def.options.map((x, i) => process(x, ctx, {
3119
3121
  ...params,
3120
3122
  path: [
3121
3123
  ...params.path,
@@ -3128,7 +3130,7 @@ var unionProcessor = (schema, ctx, json, params) => {
3128
3130
  };
3129
3131
  var intersectionProcessor = (schema, ctx, json, params) => {
3130
3132
  const def = schema._zod.def;
3131
- const a = process$1(def.left, ctx, {
3133
+ const a = process(def.left, ctx, {
3132
3134
  ...params,
3133
3135
  path: [
3134
3136
  ...params.path,
@@ -3136,7 +3138,7 @@ var intersectionProcessor = (schema, ctx, json, params) => {
3136
3138
  0
3137
3139
  ]
3138
3140
  });
3139
- const b = process$1(def.right, ctx, {
3141
+ const b = process(def.right, ctx, {
3140
3142
  ...params,
3141
3143
  path: [
3142
3144
  ...params.path,
@@ -3149,7 +3151,7 @@ var intersectionProcessor = (schema, ctx, json, params) => {
3149
3151
  };
3150
3152
  var nullableProcessor = (schema, ctx, json, params) => {
3151
3153
  const def = schema._zod.def;
3152
- const inner = process$1(def.innerType, ctx, params);
3154
+ const inner = process(def.innerType, ctx, params);
3153
3155
  const seen = ctx.seen.get(schema);
3154
3156
  if (ctx.target === "openapi-3.0") {
3155
3157
  seen.ref = def.innerType;
@@ -3158,27 +3160,27 @@ var nullableProcessor = (schema, ctx, json, params) => {
3158
3160
  };
3159
3161
  var nonoptionalProcessor = (schema, ctx, _json, params) => {
3160
3162
  const def = schema._zod.def;
3161
- process$1(def.innerType, ctx, params);
3163
+ process(def.innerType, ctx, params);
3162
3164
  const seen = ctx.seen.get(schema);
3163
3165
  seen.ref = def.innerType;
3164
3166
  };
3165
3167
  var defaultProcessor = (schema, ctx, json, params) => {
3166
3168
  const def = schema._zod.def;
3167
- process$1(def.innerType, ctx, params);
3169
+ process(def.innerType, ctx, params);
3168
3170
  const seen = ctx.seen.get(schema);
3169
3171
  seen.ref = def.innerType;
3170
3172
  json.default = JSON.parse(JSON.stringify(def.defaultValue));
3171
3173
  };
3172
3174
  var prefaultProcessor = (schema, ctx, json, params) => {
3173
3175
  const def = schema._zod.def;
3174
- process$1(def.innerType, ctx, params);
3176
+ process(def.innerType, ctx, params);
3175
3177
  const seen = ctx.seen.get(schema);
3176
3178
  seen.ref = def.innerType;
3177
3179
  if (ctx.io === "input") json._prefault = JSON.parse(JSON.stringify(def.defaultValue));
3178
3180
  };
3179
3181
  var catchProcessor = (schema, ctx, json, params) => {
3180
3182
  const def = schema._zod.def;
3181
- process$1(def.innerType, ctx, params);
3183
+ process(def.innerType, ctx, params);
3182
3184
  const seen = ctx.seen.get(schema);
3183
3185
  seen.ref = def.innerType;
3184
3186
  let catchValue;
@@ -3193,20 +3195,20 @@ var pipeProcessor = (schema, ctx, _json, params) => {
3193
3195
  const def = schema._zod.def;
3194
3196
  const inIsTransform = def.in._zod.traits.has("$ZodTransform");
3195
3197
  const innerType = ctx.io === "input" ? inIsTransform ? def.out : def.in : def.out;
3196
- process$1(innerType, ctx, params);
3198
+ process(innerType, ctx, params);
3197
3199
  const seen = ctx.seen.get(schema);
3198
3200
  seen.ref = innerType;
3199
3201
  };
3200
3202
  var readonlyProcessor = (schema, ctx, json, params) => {
3201
3203
  const def = schema._zod.def;
3202
- process$1(def.innerType, ctx, params);
3204
+ process(def.innerType, ctx, params);
3203
3205
  const seen = ctx.seen.get(schema);
3204
3206
  seen.ref = def.innerType;
3205
3207
  json.readOnly = true;
3206
3208
  };
3207
3209
  var optionalProcessor = (schema, ctx, _json, params) => {
3208
3210
  const def = schema._zod.def;
3209
- process$1(def.innerType, ctx, params);
3211
+ process(def.innerType, ctx, params);
3210
3212
  const seen = ctx.seen.get(schema);
3211
3213
  seen.ref = def.innerType;
3212
3214
  };
@@ -4467,16 +4469,18 @@ function jsonRefined(inner, code) {
4467
4469
  });
4468
4470
  });
4469
4471
  }
4470
- function optionalize(schema, required) {
4471
- const req = required === true;
4472
- const pre = (v) => v === "" || v === null ? void 0 : v;
4473
- if (!req) return preprocess(pre, schema.optional());
4474
- return preprocess(pre, unknown().superRefine((v, ctx) => {
4475
- if (v === void 0) ctx.addIssue({
4476
- code: ZodIssueCode.custom,
4477
- message: vmsg("required")
4478
- });
4479
- }).pipe(schema));
4472
+ /**
4473
+ * An empty value is no value: `''` and `null` become `undefined`, and the field's own schema
4474
+ * never sees them. Every field is optional, so this is the ONLY shape a field cannot demand
4475
+ * a value, and the rules it carries judge what was entered rather than whether anything was.
4476
+ *
4477
+ * This used to have a second branch, for `required` fields, which turned the same emptiness
4478
+ * into a `required` issue through a `z.unknown()` guard piped into the schema. That branch is
4479
+ * why a `.min(1)` on a required string was unreachable: the empty string had already been
4480
+ * converted to the issue before the string schema ran.
4481
+ */
4482
+ function optionalize(schema) {
4483
+ return preprocess((v) => v === "" || v === null ? void 0 : v, schema.optional());
4480
4484
  }
4481
4485
  //#endregion
4482
4486
  //#region ../sdk/src/fields/meta.ts
@@ -4558,7 +4562,7 @@ function applyMultiple(base, multiple) {
4558
4562
  multiple: true
4559
4563
  },
4560
4564
  json: true,
4561
- zod: optionalize(s, base.required)
4565
+ zod: optionalize(s)
4562
4566
  };
4563
4567
  }
4564
4568
  /** Inline option entry → OptionItem (plain string = value and label at once). */
@@ -4673,13 +4677,6 @@ function wrapKey(key, opts, meta) {
4673
4677
  noLabel: true
4674
4678
  }
4675
4679
  };
4676
- if (opts.role) m = {
4677
- ...m,
4678
- hints: {
4679
- ...m.hints,
4680
- role: opts.role
4681
- }
4682
- };
4683
4680
  if (opts.editor) m = {
4684
4681
  ...m,
4685
4682
  hints: {
@@ -4810,7 +4807,6 @@ function normalizeOpts(rawIn) {
4810
4807
  faces: v.faces,
4811
4808
  emphasis: v.emphasis,
4812
4809
  noLabel: v.noLabel,
4813
- role: v.role,
4814
4810
  editor: v.editor,
4815
4811
  activate: v.activate
4816
4812
  };
@@ -4951,7 +4947,7 @@ function registerPreset(factory, base, presetOpts, over = {}) {
4951
4947
  * dimensions, check(single)) and differed only in the validation code and the per-role
4952
4948
  * default zod.
4953
4949
  *
4954
- * raw → jsonValue → absent by `absenceRoles`? (required 'required')
4950
+ * raw → jsonValue → carries nothing? (passthrough, when `acceptsEmptyRow`)
4955
4951
  * → carries nothing at all? (pass through, there is nothing to judge)
4956
4952
  * → rowSchema (partsRowShape) → stripServerOwnedParts → optional per-type refine
4957
4953
  *
@@ -4961,28 +4957,16 @@ function registerPreset(factory, base, presetOpts, over = {}) {
4961
4957
  * exactly once.
4962
4958
  */
4963
4959
  function buildComposite(def, opts, parts) {
4964
- const required = opts.required ?? false;
4965
- const roleZod = def.roleZod(opts, parts);
4966
- const rowSchema = object(partsRowShape(roleZod, parts, required === true ? "strict" : "null"));
4967
- const absentRowSchema = required === true ? object(partsRowShape(roleZod, parts, "null-or-missing")) : rowSchema;
4960
+ const rowSchema = object(partsRowShape(def.roleZod(opts, parts), parts));
4968
4961
  const roleKeys = (which) => parts.filter((p) => p.mode === "stored" && (which?.(p) ?? true)).map(partValueKey);
4969
- const absenceKeys = def.absenceRoles ? roleKeys((p) => def.absenceRoles.includes(p.role)) : void 0;
4970
- const clientKeys = def.absenceRoles ? roleKeys() : void 0;
4962
+ const clientKeys = def.acceptsEmptyRow ? roleKeys() : void 0;
4971
4963
  const zod = unknown().transform((raw, ctx) => {
4972
4964
  const parsed = jsonValue(raw);
4973
4965
  const p = parsed;
4974
4966
  const isRow = p == null || typeof p === "object" && !Array.isArray(p);
4975
4967
  /** Every one of `keys` empty in this value — `null`/absent alike. */
4976
4968
  const allEmpty = (keys) => isRow && (p == null || keys.length > 0 && keys.every((k) => p[k] == null));
4977
- let absent = false;
4978
- if (absenceKeys && clientKeys) {
4979
- absent = allEmpty(absenceKeys);
4980
- if (absent && required) ctx.addIssue({
4981
- code: ZodIssueCode.custom,
4982
- message: vmsg("required")
4983
- });
4984
- if (allEmpty(clientKeys)) return raw;
4985
- }
4969
+ if (clientKeys && allEmpty(clientKeys)) return raw;
4986
4970
  if (typeof parsed === "string") {
4987
4971
  ctx.addIssue({
4988
4972
  code: ZodIssueCode.custom,
@@ -4990,7 +4974,7 @@ function buildComposite(def, opts, parts) {
4990
4974
  });
4991
4975
  return NEVER;
4992
4976
  }
4993
- const r = (absent ? absentRowSchema : rowSchema).safeParse(parsed);
4977
+ const r = rowSchema.safeParse(parsed);
4994
4978
  if (!r.success) {
4995
4979
  const message = typeof def.structureCode === "function" ? def.structureCode(r.error) : vmsg(def.structureCode);
4996
4980
  ctx.addIssue({
@@ -5043,12 +5027,10 @@ function materialize(decl, name) {
5043
5027
  if (isComposite(type) && (opts.multiple ?? false) && parts.length > 0 && !type.selfManages?.has("multiple")) return collectionGroup(name, opts, parts, type.collectionView);
5044
5028
  const built = isComposite(type) ? buildComposite(type, opts, parts) : type.build(opts, parts, name);
5045
5029
  const selfOptional = type.selfManages?.has("optional") ?? false;
5046
- const required = selfOptional ? false : opts.required ?? false;
5047
5030
  const base = {
5048
5031
  kind: type.kind,
5049
5032
  label: opts.label ?? "",
5050
5033
  ...opts.agent !== void 0 && { agent: opts.agent },
5051
- required,
5052
5034
  prim: type.prim,
5053
5035
  column: built.column,
5054
5036
  hints: built.hints ?? {},
@@ -5059,7 +5041,7 @@ function materialize(decl, name) {
5059
5041
  columns: built.columns,
5060
5042
  parts
5061
5043
  },
5062
- zod: selfOptional ? built.zod : optionalize(built.zod, required)
5044
+ zod: selfOptional ? built.zod : optionalize(built.zod)
5063
5045
  };
5064
5046
  return wrapKey(name, opts, type.selfManages?.has("multiple") ? base : applyMultiple(base, opts.multiple ?? false));
5065
5047
  }
@@ -5089,7 +5071,6 @@ function collectionGroup(key, opts, parts, collectionView) {
5089
5071
  key,
5090
5072
  scope: "nest",
5091
5073
  multiple: true,
5092
- required: opts.required ?? false,
5093
5074
  label: opts.label ?? key,
5094
5075
  ...opts.agent !== void 0 && { agent: opts.agent },
5095
5076
  display: "wrap",
@@ -5260,7 +5241,7 @@ function accepts(def, d) {
5260
5241
  }
5261
5242
  /**
5262
5243
  * The correction every role gets for free: keep what the author said ABOUT the field
5263
- * (`label`, `required`, `ui`, `value` — a constant or a ComputeFn), replace the type, and
5244
+ * (`label`, `ui`, `value` — a constant or a ComputeFn), replace the type, and
5264
5245
  * drop what belonged to the OLD type (`rules` — a number's min/max mean nothing to a
5265
5246
  * picture — and `multiple`, because a composite role owns exactly one column). A role whose
5266
5247
  * own default needs more than a bare factory (`measured`'s unit, `period`'s endpoints)
@@ -5268,10 +5249,9 @@ function accepts(def, d) {
5268
5249
  */
5269
5250
  function retypeTo(factory) {
5270
5251
  return (d) => {
5271
- const { label, required, value } = d?.opts ?? {};
5252
+ const { label, value } = d?.opts ?? {};
5272
5253
  return declare(factory, {
5273
5254
  label,
5274
- required,
5275
5255
  value,
5276
5256
  noSearch: d?.opts.noSearch,
5277
5257
  ui: uiOf(d?.opts)
@@ -5457,72 +5437,73 @@ function partColumns(parts) {
5457
5437
  }
5458
5438
  return cols;
5459
5439
  }
5460
- function partsRowShape(shape, parts, tolerance = "strict") {
5440
+ /**
5441
+ * A composite's write-time row shape, DERIVED from its resolved parts. `shape` carries
5442
+ * the composite's DEFAULT schema per role — the literal the factory writes by hand
5443
+ * (`{ value: numSchema, unit: z.string().refine(…) }`) — and each part decides which
5444
+ * schema guards its (role-named) key:
5445
+ *
5446
+ * - a plain STORED part is keyed by its role name, matching the value object and the
5447
+ * column `<field>__<role>` that `flattenEmbeddedAt`/`nestEmbeddedAt` read. A role left
5448
+ * to its default filling keeps the default schema — byte-identical to the hand-written
5449
+ * literal, so every existing structure/unit/range code and message is preserved.
5450
+ * - an OVERRIDDEN stored part is validated by its OWN zod (`meta.zod`) instead of the
5451
+ * default schema for that role. This is what makes a RETYPED filling real: an
5452
+ * `f.int({})` magnitude rejects 5.5 (its own `int` check) and gets an integer column,
5453
+ * and an `f.relation({…})` currency accepts a record id instead of being measured
5454
+ * against an ISO-4217 string rule it was never meant to satisfy. The filling also
5455
+ * brings its own optionality and its own min/max — an author replacing a filling
5456
+ * takes over that role's constraints, so `f.real({ rules: { min: 0 } })` is how a
5457
+ * replaced magnitude keeps a bound.
5458
+ * - a COMPUTED-AND-STORED part ('computedStored') is keyed by its role name like any
5459
+ * other part, but its schema is `z.unknown().optional()`: the SERVER owns the value, so
5460
+ * whatever the client sends there is ignored — `stripServerOwnedParts` deletes it a
5461
+ * moment later and the write path recomputes the column. It is stripped rather than
5462
+ * `z.never()`-rejected because a read hands the client that key (it is a real column,
5463
+ * present in every response), so rejecting it would break a read → PATCH-the-whole-object
5464
+ * round trip.
5465
+ * - a CLIENT-OWNED stored part of a composite also accepts
5466
+ * an explicit `null` (`tolerateNull`), which is what closes the read → write round trip
5467
+ * for a PARTIALLY FILLED composite. A SELECT returns every sub-column, so a record whose
5468
+ * magnitude column is set and whose unit column is empty reads back as
5469
+ * `{value: 900, unit: null}` (`nestEmbeddedAt` drops the key only when EVERY column is
5470
+ * empty — `0` is a value), and feeding that exact object back used to fail with
5471
+ * `measured_structure`: the write path refused the shape its own read produced. The null
5472
+ * slot now parses through and is written back as NULL, so the round trip is closed and
5473
+ * clearing ONE role of a filled composite works instead of erroring.
5474
+ * NULL, not absence: a read emits every stored role (empty ones as `null`), so `null` is
5475
+ * how "this record has no value there" arrives, while an ABSENT key is a writer that
5476
+ * never mentioned a role it owns — which stays the structure error it has always been
5477
+ * (`{unit: 'kg'}` with no magnitude, `{lat: 50}` with no longitude). That is the
5478
+ * all-or-nothing rule for a DECLARATION, and it is untouched.
5479
+ * A composite used to be able to override this: `required: true` kept every client-owned
5480
+ * slot MANDATORY, null included, so that "tolerate null" could not turn a demanded field
5481
+ * optional. Nothing demands a value now, so there is no override and the rule above is the
5482
+ * only one.
5483
+ */
5484
+ /**
5485
+ * How much a CLIENT-OWNED slot forgives in the row shape: exactly one thing, an explicit
5486
+ * `null`. `.nullable()`, never `.nullish()` — a part that is MISSING entirely is still a
5487
+ * malformed row (`{lat: 5.5}` is half a coordinate), which is the one rule about composites
5488
+ * that judges CORRECTNESS rather than presence.
5489
+ *
5490
+ * There used to be a `RowTolerance` of three levels, and the field's `required` is what chose
5491
+ * between them: 'strict' when the field demanded a value, 'null-or-missing' when the value was
5492
+ * ABSENT under that demand — the third existing only so an absent required composite did not
5493
+ * report the same absence twice, once as `required` and once as a structure code. With nothing
5494
+ * able to demand a value there is no first issue to restate, so both levels and the type
5495
+ * itself are gone.
5496
+ */
5497
+ function partsRowShape(shape, parts) {
5461
5498
  const out = { ...shape };
5462
5499
  for (const p of parts) if (p.mode === "computedStored") out[p.key] = unknown().optional();
5463
5500
  else {
5464
5501
  const own = p.overridden ? p.meta.zod : shape[p.role] ?? unknown().optional();
5465
- const relaxed = tolerance !== "strict" && !(p.overridden && p.meta.required === true);
5466
- out[p.key] = relaxed ? tolerance === "null-or-missing" ? own.nullish() : own.nullable() : own;
5502
+ out[p.key] = own.nullable();
5467
5503
  }
5468
5504
  return out;
5469
5505
  }
5470
5506
  /**
5471
- * MIXED OWNERSHIP of the STORED parts: the composite has a computed-and-stored part (the
5472
- * server owns that column) AND a plain stored part (the client owns that one). Returns the
5473
- * two role lists, or null when the composite is uniformly owned.
5474
- *
5475
- * Such a composite IS materialized by the write path (`applyStoredParts`): the server's part
5476
- * is computed on every write, whether or not the write carries the field, and the client's
5477
- * columns keep whatever the record already holds. A computed sum exists whether or not a
5478
- * user has picked a unit, and a NULL column is invisible to SQL. See THE ABSENT-COMPOSITE
5479
- * RULE in `@coffer-org/server/part-injection` and `docs/decisions.md` (2026-08-12).
5480
- *
5481
- * The one shape this is still wrong for is a composite that MANDATES one of those client-owned
5482
- * roles — see `mandatedClientParts` below.
5483
- */
5484
- function mixedOwnedStoredParts(parts) {
5485
- const server = parts.filter((p) => p.mode === "computedStored").map((p) => p.role);
5486
- const client = parts.filter((p) => p.mode === "stored").map((p) => p.role);
5487
- return server.length > 0 && client.length > 0 ? {
5488
- server,
5489
- client
5490
- } : null;
5491
- }
5492
- /**
5493
- * The CLIENT-OWNED stored roles this composite demands a value for — the roles a
5494
- * server-materialized half-value would leave empty in breach of the field's own contract.
5495
- * Empty list → nothing is mandated and the composite is safe to materialize.
5496
- *
5497
- * THE MANDATE HAS TWO SOURCES, and reading only the first is a bug this had:
5498
- *
5499
- * - the FIELD's own `required`, which `partsRowShape` turns into `tolerateNull = false` for
5500
- * every client-owned slot;
5501
- * - the FILLING's `required`, per part: `partsRowShape` keeps an OVERRIDDEN part's own
5502
- * mandate ("a filling the author declared `required` keeps its mandate"), so
5503
- * `fields: { unit: f.string({ required: true, … }) }` makes THAT slot non-nullable even
5504
- * when the field around it is optional.
5505
- *
5506
- * Either way the materialized value — the server's column filled, the client's empty — reads
5507
- * back as `{value: 5, unit: null}` and is rejected by the composite's own zod with
5508
- * `{"code":"required"}` the moment a record form or an MCP agent feeds it straight back. So
5509
- * both sources must count, and the write path refuses to materialize when either speaks.
5510
- *
5511
- * A CONDITION counts too, though its harm is different and milder. `partsRowShape` compares
5512
- * `=== true`, so a conditional mandate does not make the slot non-nullable and the round trip
5513
- * still parses; what it does instead is let a materialized object satisfy
5514
- * `updateRecord`'s conditional-required check (which only asks whether the value is non-null),
5515
- * excusing the user from a field the schema says is mandatory. Nothing static can evaluate a
5516
- * Condition here, so any mandate that is not literally `false`/absent is treated as speaking —
5517
- * conservative in the safe direction, since refusing to materialize is exactly the older
5518
- * behaviour and loses nothing.
5519
- */
5520
- function mandatedClientParts(required, parts) {
5521
- const speaks = (flag) => flag !== void 0 && flag !== false;
5522
- const field = speaks(required);
5523
- return parts.filter((p) => p.mode === "stored" && (field || p.overridden && speaks(p.meta.required))).map((p) => p.role);
5524
- }
5525
- /**
5526
5507
  * Drops SERVER-OWNED part slots from a successfully parsed composite row: a computed-and-stored
5527
5508
  * role, keyed by its role name. Its value belongs to the schema, not to the writer — it is
5528
5509
  * recomputed and written by the server on the same write (`applyStoredParts`) — so a client
@@ -5569,13 +5550,10 @@ function email(o) {
5569
5550
  registerPreset("email", "string", {}, {
5570
5551
  kind: "email",
5571
5552
  widget: "email",
5572
- build(o) {
5573
- const required = o.required ?? false;
5574
- let s = string$1().email({ message: vmsg("email") });
5575
- if (required) s = s.min(1, { message: vmsg("min_length", { min: 1 }) });
5553
+ build() {
5576
5554
  return {
5577
5555
  column: "text",
5578
- zod: s,
5556
+ zod: string$1().email({ message: vmsg("email") }),
5579
5557
  hints: {
5580
5558
  format: "email",
5581
5559
  inputType: "email"
@@ -5598,12 +5576,10 @@ function tel(o) {
5598
5576
  registerPreset("tel", "string", {}, {
5599
5577
  kind: "tel",
5600
5578
  widget: "tel",
5601
- build(o) {
5602
- const required = o.required ?? false;
5603
- const base_z = string$1().regex(TEL_RE, { message: vmsg("pattern", { messageKey: "core.presets.tel" }) });
5579
+ build() {
5604
5580
  return {
5605
5581
  column: "text",
5606
- zod: required ? base_z.min(1, { message: vmsg("min_length", { min: 1 }) }) : base_z,
5582
+ zod: string$1().regex(TEL_RE, { message: vmsg("pattern", { messageKey: "core.presets.tel" }) }),
5607
5583
  hints: {
5608
5584
  format: "tel",
5609
5585
  inputType: "tel"
@@ -5627,10 +5603,10 @@ registerPreset("password", "string", {}, {
5627
5603
  kind: "password",
5628
5604
  widget: "password",
5629
5605
  selfManages: /* @__PURE__ */ new Set(["multiple"]),
5630
- build(o) {
5606
+ build() {
5631
5607
  return {
5632
5608
  column: "text",
5633
- zod: o.required ?? false ? string$1().min(1, { message: vmsg("min_length", { min: 1 }) }) : string$1(),
5609
+ zod: string$1(),
5634
5610
  hints: {
5635
5611
  format: "password",
5636
5612
  inputType: "password"
@@ -5692,6 +5668,31 @@ function internalOauthGrants(o) {
5692
5668
  }
5693
5669
  });
5694
5670
  }
5671
+ /**
5672
+ * The account page's linked-accounts section. Same trick as `internalApiToken`: a container
5673
+ * with a custom `ui.kind`, drawn by its own renderer, which reads `/api/auth/links` itself.
5674
+ * The declared children are what one ROW holds — the renderer reads them through the slot
5675
+ * contract, so this is a declaration, not a layout.
5676
+ *
5677
+ * @layer preset
5678
+ * @base group
5679
+ * @prim —
5680
+ * @widget internalIdentityLinks
5681
+ * @example f.internalIdentityLinks({ label: 'auth.linksTitle' })
5682
+ */
5683
+ function internalIdentityLinks(o) {
5684
+ return group({
5685
+ scope: "nest",
5686
+ label: o.label,
5687
+ multiple: true,
5688
+ ui: { kind: "internalIdentityLinks" },
5689
+ fields: {
5690
+ provider: string({}),
5691
+ externalId: string({}),
5692
+ linkedAt: string({})
5693
+ }
5694
+ });
5695
+ }
5695
5696
  var SLUG_RE = /^[a-z0-9-]+$/;
5696
5697
  /**
5697
5698
  * Slug — kind 'slug', `^[a-z0-9-]+$`.
@@ -5812,10 +5813,10 @@ function colorname(o) {
5812
5813
  registerPreset("colorname", "string", {}, {
5813
5814
  kind: "colorname",
5814
5815
  widget: "colorname",
5815
- build(o) {
5816
+ build() {
5816
5817
  return {
5817
5818
  column: "text",
5818
- zod: (o.required ?? false ? string$1().min(1, { message: vmsg("min_length", { min: 1 }) }) : string$1()).refine((v) => CSS_COLOR_NAMES.has(v.toLowerCase()), { message: vmsg("colorname") }),
5819
+ zod: string$1().refine((v) => CSS_COLOR_NAMES.has(v.toLowerCase()), { message: vmsg("colorname") }),
5819
5820
  hints: {}
5820
5821
  };
5821
5822
  }
@@ -5835,10 +5836,10 @@ function title(o) {
5835
5836
  registerPreset("title", "string", {}, {
5836
5837
  kind: "title",
5837
5838
  widget: "title",
5838
- build(o) {
5839
+ build() {
5839
5840
  return {
5840
5841
  column: "text",
5841
- zod: o.required ?? false ? string$1().min(1, { message: vmsg("min_length", { min: 1 }) }) : string$1(),
5842
+ zod: string$1(),
5842
5843
  hints: {}
5843
5844
  };
5844
5845
  }
@@ -5859,12 +5860,10 @@ function link(o) {
5859
5860
  registerPreset("link", "string", {}, {
5860
5861
  kind: "link",
5861
5862
  widget: "link",
5862
- build(o) {
5863
- const required = o.required ?? false;
5864
- const base_z = string$1().regex(LINK_RE, { message: vmsg("pattern", { messageKey: "core.presets.link" }) });
5863
+ build() {
5865
5864
  return {
5866
5865
  column: "text",
5867
- zod: required ? base_z.min(1, { message: vmsg("min_length", { min: 1 }) }) : base_z,
5866
+ zod: string$1().regex(LINK_RE, { message: vmsg("pattern", { messageKey: "core.presets.link" }) }),
5868
5867
  hints: {
5869
5868
  format: "url",
5870
5869
  inputType: "url"
@@ -6549,6 +6548,7 @@ var presets = {
6549
6548
  currency,
6550
6549
  money,
6551
6550
  internalApiToken,
6551
+ internalIdentityLinks,
6552
6552
  internalOauthGrants
6553
6553
  };
6554
6554
  //#endregion
@@ -8678,7 +8678,6 @@ function group(o) {
8678
8678
  scope,
8679
8679
  multiple: o.multiple,
8680
8680
  compute: o.value,
8681
- required: o.required,
8682
8681
  unique: r.unique,
8683
8682
  label: o.label,
8684
8683
  icon: o.icon,
@@ -8711,7 +8710,6 @@ function row(o) {
8711
8710
  icon: o.icon,
8712
8711
  fields: o.fields,
8713
8712
  multiple: o.multiple,
8714
- required: o.required,
8715
8713
  rules: o.rules,
8716
8714
  ui: { display: "scroll" }
8717
8715
  });
@@ -8759,7 +8757,6 @@ function url(o) {
8759
8757
  return group({
8760
8758
  scope: "nest",
8761
8759
  label: o.label,
8762
- required: o.required,
8763
8760
  ui: { kind: "url" },
8764
8761
  fields: {
8765
8762
  scheme: string({}),
@@ -8811,13 +8808,11 @@ function keyed(o) {
8811
8808
  }),
8812
8809
  scope: "nest",
8813
8810
  multiple: true,
8814
- required: o.required,
8815
8811
  unique: o.unique ?? [role],
8816
8812
  fixed: o.fixed,
8817
8813
  view: { by: role }
8818
8814
  };
8819
8815
  }
8820
- var isStorageGroup = (g) => g.scope === "nest";
8821
8816
  var isCollectionGroup = (g) => g.scope === "nest" && g.multiple === true;
8822
8817
  var isEmbeddedGroup = (g) => g.scope === "nest" && g.multiple !== true;
8823
8818
  /**
@@ -8935,7 +8930,7 @@ registerType("string", {
8935
8930
  widget: "text",
8936
8931
  build(o) {
8937
8932
  const cfg = o.config ?? {};
8938
- const min = cfg.min ?? (o.required === true ? 1 : 0);
8933
+ const min = cfg.min ?? 0;
8939
8934
  return {
8940
8935
  column: "text",
8941
8936
  zod: stringContent((str) => {
@@ -8963,9 +8958,9 @@ registerType("string", {
8963
8958
  function string(o) {
8964
8959
  return declare("string", o);
8965
8960
  }
8966
- /** Shared by localDir/localFile's build(): a server path, min-length-1 when required. */
8967
- function pathZod(o) {
8968
- return stringContent((s) => o.required === true ? s.min(1, { message: vmsg("min_length", { min: 1 }) }) : s);
8961
+ /** Shared by localDir/localFile's build(): a server path, judged only when one was entered. */
8962
+ function pathZod(_o) {
8963
+ return stringContent((s) => s);
8969
8964
  }
8970
8965
  registerType("localDir", {
8971
8966
  kind: "localDir",
@@ -9624,10 +9619,9 @@ var MEASURED_ROLES = (opts) => {
9624
9619
  accepts: ENUMERATED,
9625
9620
  normalize: (d) => {
9626
9621
  if (d && accepts(unitRole, d)) return d;
9627
- const { label, required, value } = d?.opts ?? {};
9622
+ const { label, value } = d?.opts ?? {};
9628
9623
  return declare("string", {
9629
9624
  label,
9630
- required,
9631
9625
  value,
9632
9626
  noSearch: d?.opts.noSearch,
9633
9627
  ui: uiOf(d?.opts),
@@ -9786,7 +9780,7 @@ registerType("geo", {
9786
9780
  label: string$1().nullish()
9787
9781
  }),
9788
9782
  structureCode: "geo_structure",
9789
- absenceRoles: ["lat", "lng"]
9783
+ acceptsEmptyRow: true
9790
9784
  });
9791
9785
  /**
9792
9786
  * Geographic point composite {lat, lng, label?}; lat/lng validated to valid coordinate
@@ -9864,7 +9858,7 @@ registerType("illustrated", {
9864
9858
  roles: ILLUSTRATED_ROLES,
9865
9859
  roleZod: () => defaultRoleZod(ILLUSTRATED_ROLES),
9866
9860
  structureCode: "illustrated_structure",
9867
- absenceRoles: ["text", "image"],
9861
+ acceptsEmptyRow: true,
9868
9862
  collectionView: "illustratedList",
9869
9863
  hints: (o) => o.config ? { config: o.config } : {}
9870
9864
  });
@@ -9908,7 +9902,7 @@ registerType("attachment", {
9908
9902
  roles: ATTACHMENT_ROLES,
9909
9903
  roleZod: () => defaultRoleZod(ATTACHMENT_ROLES),
9910
9904
  structureCode: "attachment_structure",
9911
- absenceRoles: ["file"],
9905
+ acceptsEmptyRow: true,
9912
9906
  collectionView: "attachmentList"
9913
9907
  });
9914
9908
  /**
@@ -10009,11 +10003,10 @@ function periodRole(key, label, mkSubDecl) {
10009
10003
  if (d && accepts(def, d)) return d;
10010
10004
  const canonical = mkSubDecl(label);
10011
10005
  if (!d) return canonical;
10012
- const { label: l, required, value } = d.opts;
10006
+ const { label: l, value } = d.opts;
10013
10007
  return declare(canonical.factory, {
10014
10008
  ...canonical.opts,
10015
10009
  label: l ?? canonical.opts.label,
10016
- required,
10017
10010
  value,
10018
10011
  noSearch: d.opts.noSearch,
10019
10012
  ui: uiOf(d.opts)
@@ -10297,8 +10290,7 @@ function keyValue(raw) {
10297
10290
  type: valueType
10298
10291
  }
10299
10292
  },
10300
- by: "key",
10301
- required: o.required
10293
+ by: "key"
10302
10294
  });
10303
10295
  }
10304
10296
  /** Roles of a range: the two endpoints, integer or real depending on `isInt`. */
@@ -10485,12 +10477,11 @@ var field = new Proxy({}, {
10485
10477
  has: (_t, k) => k in composedField()
10486
10478
  });
10487
10479
  function toClient(field) {
10488
- const { kind, label, agent, required, prim, hints, options, strict, relation, json, hidden, derived, parts, cache } = field;
10480
+ const { kind, label, agent, prim, hints, options, strict, relation, json, hidden, derived, parts, cache } = field;
10489
10481
  return {
10490
10482
  kind,
10491
10483
  label,
10492
10484
  ...agent !== void 0 && { agent },
10493
- required,
10494
10485
  prim,
10495
10486
  hints,
10496
10487
  options,
@@ -10514,680 +10505,6 @@ function defineSettings(s) {
10514
10505
  return materializeDef(s);
10515
10506
  }
10516
10507
  //#endregion
10517
- //#region ../../node_modules/sift/es5m/index.js
10518
- /******************************************************************************
10519
- Copyright (c) Microsoft Corporation.
10520
-
10521
- Permission to use, copy, modify, and/or distribute this software for any
10522
- purpose with or without fee is hereby granted.
10523
-
10524
- THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
10525
- REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
10526
- AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
10527
- INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
10528
- LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
10529
- OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
10530
- PERFORMANCE OF THIS SOFTWARE.
10531
- ***************************************************************************** */
10532
- var extendStatics = function(d, b) {
10533
- extendStatics = Object.setPrototypeOf || { __proto__: [] } instanceof Array && function(d, b) {
10534
- d.__proto__ = b;
10535
- } || function(d, b) {
10536
- for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p];
10537
- };
10538
- return extendStatics(d, b);
10539
- };
10540
- function __extends(d, b) {
10541
- if (typeof b !== "function" && b !== null) throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
10542
- extendStatics(d, b);
10543
- function __() {
10544
- this.constructor = d;
10545
- }
10546
- d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
10547
- }
10548
- var typeChecker = function(type) {
10549
- var typeString = "[object " + type + "]";
10550
- return function(value) {
10551
- return getClassName(value) === typeString;
10552
- };
10553
- };
10554
- var getClassName = function(value) {
10555
- return Object.prototype.toString.call(value);
10556
- };
10557
- var comparable = function(value) {
10558
- if (value instanceof Date) return value.getTime();
10559
- else if (isArray(value)) return value.map(comparable);
10560
- else if (value && typeof value.toJSON === "function") return value.toJSON();
10561
- return value;
10562
- };
10563
- var coercePotentiallyNull = function(value) {
10564
- return value == null ? null : value;
10565
- };
10566
- var isArray = typeChecker("Array");
10567
- var isObject = typeChecker("Object");
10568
- var isFunction = typeChecker("Function");
10569
- var isProperty = function(item, key) {
10570
- return item.hasOwnProperty(key) && !isFunction(item[key]);
10571
- };
10572
- var isVanillaObject = function(value) {
10573
- return value && (value.constructor === Object || value.constructor === Array || value.constructor.toString() === "function Object() { [native code] }" || value.constructor.toString() === "function Array() { [native code] }") && !value.toJSON;
10574
- };
10575
- var equals = function(a, b) {
10576
- if (a == null && a == b) return true;
10577
- if (a === b) return true;
10578
- if (Object.prototype.toString.call(a) !== Object.prototype.toString.call(b)) return false;
10579
- if (isArray(a)) {
10580
- if (a.length !== b.length) return false;
10581
- for (var i = 0, length_1 = a.length; i < length_1; i++) if (!equals(a[i], b[i])) return false;
10582
- return true;
10583
- } else if (isObject(a)) {
10584
- if (Object.keys(a).length !== Object.keys(b).length) return false;
10585
- for (var key in a) if (!equals(a[key], b[key])) return false;
10586
- return true;
10587
- }
10588
- return false;
10589
- };
10590
- /**
10591
- * Walks through each value given the context - used for nested operations. E.g:
10592
- * { "person.address": { $eq: "blarg" }}
10593
- */
10594
- var walkKeyPathValues = function(item, keyPath, next, depth, key, owner) {
10595
- var currentKey = keyPath[depth];
10596
- if (isArray(item) && isNaN(Number(currentKey)) && !isProperty(item, currentKey)) {
10597
- for (var i = 0, length_1 = item.length; i < length_1; i++) if (!walkKeyPathValues(item[i], keyPath, next, depth, i, item)) return false;
10598
- }
10599
- if (depth === keyPath.length || item == null) return next(item, key, owner, depth === 0, depth === keyPath.length);
10600
- return walkKeyPathValues(item[currentKey], keyPath, next, depth + 1, currentKey, item);
10601
- };
10602
- var BaseOperation = function() {
10603
- function BaseOperation(params, owneryQuery, options, name) {
10604
- this.params = params;
10605
- this.owneryQuery = owneryQuery;
10606
- this.options = options;
10607
- this.name = name;
10608
- this.init();
10609
- }
10610
- BaseOperation.prototype.init = function() {};
10611
- BaseOperation.prototype.reset = function() {
10612
- this.done = false;
10613
- this.keep = false;
10614
- };
10615
- return BaseOperation;
10616
- }();
10617
- var GroupOperation = function(_super) {
10618
- __extends(GroupOperation, _super);
10619
- function GroupOperation(params, owneryQuery, options, children) {
10620
- var _this = _super.call(this, params, owneryQuery, options) || this;
10621
- _this.children = children;
10622
- return _this;
10623
- }
10624
- /**
10625
- */
10626
- GroupOperation.prototype.reset = function() {
10627
- this.keep = false;
10628
- this.done = false;
10629
- for (var i = 0, length_2 = this.children.length; i < length_2; i++) this.children[i].reset();
10630
- };
10631
- /**
10632
- */
10633
- GroupOperation.prototype.childrenNext = function(item, key, owner, root, leaf) {
10634
- var done = true;
10635
- var keep = true;
10636
- for (var i = 0, length_3 = this.children.length; i < length_3; i++) {
10637
- var childOperation = this.children[i];
10638
- if (!childOperation.done) childOperation.next(item, key, owner, root, leaf);
10639
- if (!childOperation.keep) keep = false;
10640
- if (childOperation.done) {
10641
- if (!childOperation.keep) break;
10642
- } else done = false;
10643
- }
10644
- this.done = done;
10645
- this.keep = keep;
10646
- };
10647
- return GroupOperation;
10648
- }(BaseOperation);
10649
- var NamedGroupOperation = function(_super) {
10650
- __extends(NamedGroupOperation, _super);
10651
- function NamedGroupOperation(params, owneryQuery, options, children, name) {
10652
- var _this = _super.call(this, params, owneryQuery, options, children) || this;
10653
- _this.name = name;
10654
- return _this;
10655
- }
10656
- return NamedGroupOperation;
10657
- }(GroupOperation);
10658
- var QueryOperation = function(_super) {
10659
- __extends(QueryOperation, _super);
10660
- function QueryOperation() {
10661
- var _this = _super !== null && _super.apply(this, arguments) || this;
10662
- _this.propop = true;
10663
- return _this;
10664
- }
10665
- /**
10666
- */
10667
- QueryOperation.prototype.next = function(item, key, parent, root) {
10668
- this.childrenNext(item, key, parent, root);
10669
- };
10670
- return QueryOperation;
10671
- }(GroupOperation);
10672
- var NestedOperation = function(_super) {
10673
- __extends(NestedOperation, _super);
10674
- function NestedOperation(keyPath, params, owneryQuery, options, children) {
10675
- var _this = _super.call(this, params, owneryQuery, options, children) || this;
10676
- _this.keyPath = keyPath;
10677
- _this.propop = true;
10678
- /**
10679
- */
10680
- _this._nextNestedValue = function(value, key, owner, root, leaf) {
10681
- _this.childrenNext(value, key, owner, root, leaf);
10682
- return !_this.done;
10683
- };
10684
- return _this;
10685
- }
10686
- /**
10687
- */
10688
- NestedOperation.prototype.next = function(item, key, parent) {
10689
- walkKeyPathValues(item, this.keyPath, this._nextNestedValue, 0, key, parent);
10690
- };
10691
- return NestedOperation;
10692
- }(GroupOperation);
10693
- var createTester = function(a, compare) {
10694
- if (a instanceof Function) return a;
10695
- if (a instanceof RegExp) return function(b) {
10696
- var result = typeof b === "string" && a.test(b);
10697
- a.lastIndex = 0;
10698
- return result;
10699
- };
10700
- var comparableA = comparable(a);
10701
- return function(b) {
10702
- return compare(comparableA, comparable(b));
10703
- };
10704
- };
10705
- var EqualsOperation = function(_super) {
10706
- __extends(EqualsOperation, _super);
10707
- function EqualsOperation() {
10708
- var _this = _super !== null && _super.apply(this, arguments) || this;
10709
- _this.propop = true;
10710
- return _this;
10711
- }
10712
- EqualsOperation.prototype.init = function() {
10713
- this._test = createTester(this.params, this.options.compare);
10714
- };
10715
- EqualsOperation.prototype.next = function(item, key, parent) {
10716
- if (!Array.isArray(parent) || parent.hasOwnProperty(key)) {
10717
- if (this._test(item, key, parent)) {
10718
- this.done = true;
10719
- this.keep = true;
10720
- }
10721
- }
10722
- };
10723
- return EqualsOperation;
10724
- }(BaseOperation);
10725
- var numericalOperationCreator = function(createNumericalOperation) {
10726
- return function(params, owneryQuery, options, name) {
10727
- return createNumericalOperation(params, owneryQuery, options, name);
10728
- };
10729
- };
10730
- var numericalOperation = function(createTester) {
10731
- return numericalOperationCreator(function(params, owneryQuery, options, name) {
10732
- var typeofParams = typeof comparable(params);
10733
- var test = createTester(params);
10734
- return new EqualsOperation(function(b) {
10735
- var actualValue = coercePotentiallyNull(b);
10736
- return typeof comparable(actualValue) === typeofParams && test(actualValue);
10737
- }, owneryQuery, options, name);
10738
- });
10739
- };
10740
- var createNamedOperation = function(name, params, parentQuery, options) {
10741
- var operationCreator = options.operations[name];
10742
- if (!operationCreator) throwUnsupportedOperation(name);
10743
- return operationCreator(params, parentQuery, options, name);
10744
- };
10745
- var throwUnsupportedOperation = function(name) {
10746
- throw new Error("Unsupported operation: ".concat(name));
10747
- };
10748
- var containsOperation = function(query, options) {
10749
- for (var key in query) if (options.operations.hasOwnProperty(key) || key.charAt(0) === "$") return true;
10750
- return false;
10751
- };
10752
- var createNestedOperation = function(keyPath, nestedQuery, parentKey, owneryQuery, options) {
10753
- if (containsOperation(nestedQuery, options)) {
10754
- var _a = createQueryOperations(nestedQuery, parentKey, options), selfOperations = _a[0];
10755
- if (_a[1].length) throw new Error("Property queries must contain only operations, or exact objects.");
10756
- return new NestedOperation(keyPath, nestedQuery, owneryQuery, options, selfOperations);
10757
- }
10758
- return new NestedOperation(keyPath, nestedQuery, owneryQuery, options, [new EqualsOperation(nestedQuery, owneryQuery, options)]);
10759
- };
10760
- var createQueryOperation = function(query, owneryQuery, _a) {
10761
- if (owneryQuery === void 0) owneryQuery = null;
10762
- var _b = _a === void 0 ? {} : _a, compare = _b.compare, operations = _b.operations;
10763
- var options = {
10764
- compare: compare || equals,
10765
- operations: Object.assign({}, operations || {})
10766
- };
10767
- var _c = createQueryOperations(query, null, options), selfOperations = _c[0], nestedOperations = _c[1];
10768
- var ops = [];
10769
- if (selfOperations.length) ops.push(new NestedOperation([], query, owneryQuery, options, selfOperations));
10770
- ops.push.apply(ops, nestedOperations);
10771
- if (ops.length === 1) return ops[0];
10772
- return new QueryOperation(query, owneryQuery, options, ops);
10773
- };
10774
- var createQueryOperations = function(query, parentKey, options) {
10775
- var selfOperations = [];
10776
- var nestedOperations = [];
10777
- if (!isVanillaObject(query)) {
10778
- selfOperations.push(new EqualsOperation(query, query, options));
10779
- return [selfOperations, nestedOperations];
10780
- }
10781
- for (var key in query) if (options.operations.hasOwnProperty(key)) {
10782
- var op = createNamedOperation(key, query[key], query, options);
10783
- if (op) {
10784
- if (!op.propop && parentKey && !options.operations[parentKey]) throw new Error("Malformed query. ".concat(key, " cannot be matched against property."));
10785
- }
10786
- if (op != null) selfOperations.push(op);
10787
- } else if (key.charAt(0) === "$") throwUnsupportedOperation(key);
10788
- else nestedOperations.push(createNestedOperation(key.split("."), query[key], key, query, options));
10789
- return [selfOperations, nestedOperations];
10790
- };
10791
- var createOperationTester = function(operation) {
10792
- return function(item, key, owner) {
10793
- operation.reset();
10794
- operation.next(item, key, owner);
10795
- return operation.keep;
10796
- };
10797
- };
10798
- var $Ne = function(_super) {
10799
- __extends($Ne, _super);
10800
- function $Ne() {
10801
- var _this = _super !== null && _super.apply(this, arguments) || this;
10802
- _this.propop = true;
10803
- return _this;
10804
- }
10805
- $Ne.prototype.init = function() {
10806
- this._test = createTester(this.params, this.options.compare);
10807
- };
10808
- $Ne.prototype.reset = function() {
10809
- _super.prototype.reset.call(this);
10810
- this.keep = true;
10811
- };
10812
- $Ne.prototype.next = function(item) {
10813
- if (this._test(item)) {
10814
- this.done = true;
10815
- this.keep = false;
10816
- }
10817
- };
10818
- return $Ne;
10819
- }(BaseOperation);
10820
- var $ElemMatch = function(_super) {
10821
- __extends($ElemMatch, _super);
10822
- function $ElemMatch() {
10823
- var _this = _super !== null && _super.apply(this, arguments) || this;
10824
- _this.propop = true;
10825
- return _this;
10826
- }
10827
- $ElemMatch.prototype.init = function() {
10828
- if (!this.params || typeof this.params !== "object") throw new Error("Malformed query. $elemMatch must by an object.");
10829
- this._queryOperation = createQueryOperation(this.params, this.owneryQuery, this.options);
10830
- };
10831
- $ElemMatch.prototype.reset = function() {
10832
- _super.prototype.reset.call(this);
10833
- this._queryOperation.reset();
10834
- };
10835
- $ElemMatch.prototype.next = function(item) {
10836
- if (isArray(item)) {
10837
- for (var i = 0, length_1 = item.length; i < length_1; i++) {
10838
- this._queryOperation.reset();
10839
- var child = item[i];
10840
- this._queryOperation.next(child, i, item, false);
10841
- this.keep = this.keep || this._queryOperation.keep;
10842
- }
10843
- this.done = true;
10844
- } else {
10845
- this.done = false;
10846
- this.keep = false;
10847
- }
10848
- };
10849
- return $ElemMatch;
10850
- }(BaseOperation);
10851
- var $Not = function(_super) {
10852
- __extends($Not, _super);
10853
- function $Not() {
10854
- var _this = _super !== null && _super.apply(this, arguments) || this;
10855
- _this.propop = true;
10856
- return _this;
10857
- }
10858
- $Not.prototype.init = function() {
10859
- this._queryOperation = createQueryOperation(this.params, this.owneryQuery, this.options);
10860
- };
10861
- $Not.prototype.reset = function() {
10862
- _super.prototype.reset.call(this);
10863
- this._queryOperation.reset();
10864
- };
10865
- $Not.prototype.next = function(item, key, owner, root) {
10866
- this._queryOperation.next(item, key, owner, root);
10867
- this.done = this._queryOperation.done;
10868
- this.keep = !this._queryOperation.keep;
10869
- };
10870
- return $Not;
10871
- }(BaseOperation);
10872
- var $Size = function(_super) {
10873
- __extends($Size, _super);
10874
- function $Size() {
10875
- var _this = _super !== null && _super.apply(this, arguments) || this;
10876
- _this.propop = true;
10877
- return _this;
10878
- }
10879
- $Size.prototype.init = function() {};
10880
- $Size.prototype.next = function(item) {
10881
- if (isArray(item) && item.length === this.params) {
10882
- this.done = true;
10883
- this.keep = true;
10884
- }
10885
- };
10886
- return $Size;
10887
- }(BaseOperation);
10888
- var assertGroupNotEmpty = function(values) {
10889
- if (values.length === 0) throw new Error("$and/$or/$nor must be a nonempty array");
10890
- };
10891
- var $Or = function(_super) {
10892
- __extends($Or, _super);
10893
- function $Or() {
10894
- var _this = _super !== null && _super.apply(this, arguments) || this;
10895
- _this.propop = false;
10896
- return _this;
10897
- }
10898
- $Or.prototype.init = function() {
10899
- var _this = this;
10900
- assertGroupNotEmpty(this.params);
10901
- this._ops = this.params.map(function(op) {
10902
- return createQueryOperation(op, null, _this.options);
10903
- });
10904
- };
10905
- $Or.prototype.reset = function() {
10906
- this.done = false;
10907
- this.keep = false;
10908
- for (var i = 0, length_2 = this._ops.length; i < length_2; i++) this._ops[i].reset();
10909
- };
10910
- $Or.prototype.next = function(item, key, owner) {
10911
- var done = false;
10912
- var success = false;
10913
- for (var i = 0, length_3 = this._ops.length; i < length_3; i++) {
10914
- var op = this._ops[i];
10915
- op.next(item, key, owner);
10916
- if (op.keep) {
10917
- done = true;
10918
- success = op.keep;
10919
- break;
10920
- }
10921
- }
10922
- this.keep = success;
10923
- this.done = done;
10924
- };
10925
- return $Or;
10926
- }(BaseOperation);
10927
- var $Nor = function(_super) {
10928
- __extends($Nor, _super);
10929
- function $Nor() {
10930
- var _this = _super !== null && _super.apply(this, arguments) || this;
10931
- _this.propop = false;
10932
- return _this;
10933
- }
10934
- $Nor.prototype.next = function(item, key, owner) {
10935
- _super.prototype.next.call(this, item, key, owner);
10936
- this.keep = !this.keep;
10937
- };
10938
- return $Nor;
10939
- }($Or);
10940
- var $In = function(_super) {
10941
- __extends($In, _super);
10942
- function $In() {
10943
- var _this = _super !== null && _super.apply(this, arguments) || this;
10944
- _this.propop = true;
10945
- return _this;
10946
- }
10947
- $In.prototype.init = function() {
10948
- var _this = this;
10949
- var params = Array.isArray(this.params) ? this.params : [this.params];
10950
- this._testers = params.map(function(value) {
10951
- if (containsOperation(value, _this.options)) throw new Error("cannot nest $ under ".concat(_this.name.toLowerCase()));
10952
- return createTester(value, _this.options.compare);
10953
- });
10954
- };
10955
- $In.prototype.next = function(item, key, owner) {
10956
- var done = false;
10957
- var success = false;
10958
- for (var i = 0, length_4 = this._testers.length; i < length_4; i++) {
10959
- var test = this._testers[i];
10960
- if (test(item)) {
10961
- done = true;
10962
- success = true;
10963
- break;
10964
- }
10965
- }
10966
- this.keep = success;
10967
- this.done = done;
10968
- };
10969
- return $In;
10970
- }(BaseOperation);
10971
- var $Nin = function(_super) {
10972
- __extends($Nin, _super);
10973
- function $Nin(params, ownerQuery, options, name) {
10974
- var _this = _super.call(this, params, ownerQuery, options, name) || this;
10975
- _this.propop = true;
10976
- _this._in = new $In(params, ownerQuery, options, name);
10977
- return _this;
10978
- }
10979
- $Nin.prototype.next = function(item, key, owner, root) {
10980
- this._in.next(item, key, owner);
10981
- if (isArray(owner) && !root) {
10982
- if (this._in.keep) {
10983
- this.keep = false;
10984
- this.done = true;
10985
- } else if (key == owner.length - 1) {
10986
- this.keep = true;
10987
- this.done = true;
10988
- }
10989
- } else {
10990
- this.keep = !this._in.keep;
10991
- this.done = true;
10992
- }
10993
- };
10994
- $Nin.prototype.reset = function() {
10995
- _super.prototype.reset.call(this);
10996
- this._in.reset();
10997
- };
10998
- return $Nin;
10999
- }(BaseOperation);
11000
- var $Exists = function(_super) {
11001
- __extends($Exists, _super);
11002
- function $Exists() {
11003
- var _this = _super !== null && _super.apply(this, arguments) || this;
11004
- _this.propop = true;
11005
- return _this;
11006
- }
11007
- $Exists.prototype.next = function(item, key, owner, root, leaf) {
11008
- if (!leaf) {
11009
- this.done = true;
11010
- this.keep = !this.params;
11011
- } else if (owner.hasOwnProperty(key) === this.params) {
11012
- this.done = true;
11013
- this.keep = true;
11014
- }
11015
- };
11016
- return $Exists;
11017
- }(BaseOperation);
11018
- var $And = function(_super) {
11019
- __extends($And, _super);
11020
- function $And(params, owneryQuery, options, name) {
11021
- var _this = _super.call(this, params, owneryQuery, options, params.map(function(query) {
11022
- return createQueryOperation(query, owneryQuery, options);
11023
- }), name) || this;
11024
- _this.propop = false;
11025
- assertGroupNotEmpty(params);
11026
- return _this;
11027
- }
11028
- $And.prototype.next = function(item, key, owner, root) {
11029
- this.childrenNext(item, key, owner, root);
11030
- };
11031
- return $And;
11032
- }(NamedGroupOperation);
11033
- var $All = function(_super) {
11034
- __extends($All, _super);
11035
- function $All(params, owneryQuery, options, name) {
11036
- var _this = _super.call(this, params, owneryQuery, options, params.map(function(query) {
11037
- return createQueryOperation(query, owneryQuery, options);
11038
- }), name) || this;
11039
- _this.propop = true;
11040
- return _this;
11041
- }
11042
- $All.prototype.next = function(item, key, owner, root) {
11043
- this.childrenNext(item, key, owner, root);
11044
- };
11045
- return $All;
11046
- }(NamedGroupOperation);
11047
- var $eq = function(params, owneryQuery, options) {
11048
- return new EqualsOperation(params, owneryQuery, options);
11049
- };
11050
- var $ne = function(params, owneryQuery, options, name) {
11051
- return new $Ne(params, owneryQuery, options, name);
11052
- };
11053
- var $or = function(params, owneryQuery, options, name) {
11054
- return new $Or(params, owneryQuery, options, name);
11055
- };
11056
- var $nor = function(params, owneryQuery, options, name) {
11057
- return new $Nor(params, owneryQuery, options, name);
11058
- };
11059
- var $elemMatch = function(params, owneryQuery, options, name) {
11060
- return new $ElemMatch(params, owneryQuery, options, name);
11061
- };
11062
- var $nin = function(params, owneryQuery, options, name) {
11063
- return new $Nin(params, owneryQuery, options, name);
11064
- };
11065
- var $in = function(params, owneryQuery, options, name) {
11066
- return new $In(params, owneryQuery, options, name);
11067
- };
11068
- var $lt = numericalOperation(function(params) {
11069
- return function(b) {
11070
- return b != null && b < params;
11071
- };
11072
- });
11073
- var $lte = numericalOperation(function(params) {
11074
- return function(b) {
11075
- return b === params || b <= params;
11076
- };
11077
- });
11078
- var $gt = numericalOperation(function(params) {
11079
- return function(b) {
11080
- return b != null && b > params;
11081
- };
11082
- });
11083
- var $gte = numericalOperation(function(params) {
11084
- return function(b) {
11085
- return b === params || b >= params;
11086
- };
11087
- });
11088
- var $mod = function(_a, owneryQuery, options) {
11089
- var mod = _a[0], equalsValue = _a[1];
11090
- return new EqualsOperation(function(b) {
11091
- return comparable(b) % mod === equalsValue;
11092
- }, owneryQuery, options);
11093
- };
11094
- var $exists = function(params, owneryQuery, options, name) {
11095
- return new $Exists(params, owneryQuery, options, name);
11096
- };
11097
- var $regex = function(pattern, owneryQuery, options) {
11098
- return new EqualsOperation(new RegExp(pattern, owneryQuery.$options), owneryQuery, options);
11099
- };
11100
- var $not = function(params, owneryQuery, options, name) {
11101
- return new $Not(params, owneryQuery, options, name);
11102
- };
11103
- var typeAliases = {
11104
- number: function(v) {
11105
- return typeof v === "number";
11106
- },
11107
- string: function(v) {
11108
- return typeof v === "string";
11109
- },
11110
- bool: function(v) {
11111
- return typeof v === "boolean";
11112
- },
11113
- array: function(v) {
11114
- return Array.isArray(v);
11115
- },
11116
- null: function(v) {
11117
- return v === null;
11118
- },
11119
- timestamp: function(v) {
11120
- return v instanceof Date;
11121
- }
11122
- };
11123
- var $type = function(clazz, owneryQuery, options) {
11124
- return new EqualsOperation(function(b) {
11125
- if (typeof clazz === "string") {
11126
- if (!typeAliases[clazz]) throw new Error("Type alias does not exist");
11127
- return typeAliases[clazz](b);
11128
- }
11129
- return b != null ? b instanceof clazz || b.constructor === clazz : false;
11130
- }, owneryQuery, options);
11131
- };
11132
- var $and = function(params, ownerQuery, options, name) {
11133
- return new $And(params, ownerQuery, options, name);
11134
- };
11135
- var $all = function(params, ownerQuery, options, name) {
11136
- return new $All(params, ownerQuery, options, name);
11137
- };
11138
- var $size = function(params, ownerQuery, options) {
11139
- return new $Size(params, ownerQuery, options, "$size");
11140
- };
11141
- var $options = function() {
11142
- return null;
11143
- };
11144
- var $where = function(params, ownerQuery, options) {
11145
- var test;
11146
- if (isFunction(params)) test = params;
11147
- else if (!process.env.CSP_ENABLED) test = new Function("obj", "return " + params);
11148
- else throw new Error("In CSP mode, sift does not support strings in \"$where\" condition");
11149
- return new EqualsOperation(function(b) {
11150
- return test.bind(b)(b);
11151
- }, ownerQuery, options);
11152
- };
11153
- var defaultOperations = /*#__PURE__*/ Object.freeze({
11154
- __proto__: null,
11155
- $Size,
11156
- $all,
11157
- $and,
11158
- $elemMatch,
11159
- $eq,
11160
- $exists,
11161
- $gt,
11162
- $gte,
11163
- $in,
11164
- $lt,
11165
- $lte,
11166
- $mod,
11167
- $ne,
11168
- $nin,
11169
- $nor,
11170
- $not,
11171
- $options,
11172
- $or,
11173
- $regex,
11174
- $size,
11175
- $type,
11176
- $where
11177
- });
11178
- var createDefaultQueryOperation = function(query, ownerQuery, _a) {
11179
- var _b = _a === void 0 ? {} : _a, compare = _b.compare, operations = _b.operations;
11180
- return createQueryOperation(query, ownerQuery, {
11181
- compare,
11182
- operations: Object.assign({}, defaultOperations, operations || {})
11183
- });
11184
- };
11185
- var createDefaultQueryTester = function(query, options) {
11186
- if (options === void 0) options = {};
11187
- return createOperationTester(createDefaultQueryOperation(query, null, options));
11188
- };
11189
- createDefaultQueryTester.createEqualsOperation;
11190
- //#endregion
11191
10508
  //#region ../sdk/src/shelf.ts
11192
10509
  /** Flat [storageKey, FieldMeta] pairs of the parent table's columns.
11193
10510
  * layout group → flattened; embedded group → prefix `key__`; collection → skipped. */
@@ -11225,43 +10542,6 @@ function assertNoKeylessCompute(items, owner) {
11225
10542
  }
11226
10543
  }
11227
10544
  /**
11228
- * Warns (does not throw) about the ONE composite shape mixed ownership is still wrong for: a
11229
- * MANDATED client-owned stored part beside a server-owned one — one computed-and-stored (the
11230
- * server writes that column) next to a plain stored one (the client writes that one) that the
11231
- * declaration demands a value for.
11232
- *
11233
- * Mixed ownership itself is supported: the write path MATERIALIZES such a composite and
11234
- * computes the server's part even when the write does not carry the field, leaving the
11235
- * client's columns as they were (THE ABSENT-COMPOSITE RULE in
11236
- * `@coffer-org/server/part-injection`). What a MANDATE adds is a demand the materialized value
11237
- * cannot honour: the half-value the server produces on its own — the computed column filled,
11238
- * the client's empty — reads back as `{value: 5, unit: null}` and is rejected by the
11239
- * composite's own zod, yet it is non-null enough to satisfy the required check on the next
11240
- * PATCH. The write path therefore refuses to materialize that one combination, and this names
11241
- * it rather than leaving the author to wonder why the computed part never fills.
11242
- *
11243
- * The mandate is read through `mandatedClientParts`, which counts the FIELD's `required` AND
11244
- * each OVERRIDDEN FILLING's own — `partsRowShape` honours both, so a check that read only the
11245
- * field let `fields: { unit: f.string({ required: true }) }` through silently.
11246
- *
11247
- * Recurses into every group — an embedded group's composite and a collection row's carry
11248
- * exactly the same mandate as a top-level one.
11249
- */
11250
- function warnMixedOwnedParts(items, owner, path = "") {
11251
- for (const it of items) {
11252
- if (hasChildren(it)) {
11253
- warnMixedOwnedParts(it.fields, owner, isStorageGroup(it) ? `${path}${it.key}.` : path);
11254
- continue;
11255
- }
11256
- if (!(hasValue(it) && it.key !== void 0) || !it.type.parts) continue;
11257
- const mixed = mixedOwnedStoredParts(it.type.parts);
11258
- if (!mixed) continue;
11259
- const mandated = mandatedClientParts(it.type.required, it.type.parts);
11260
- if (!mandated.length) continue;
11261
- console.warn(`${owner}: composite '${path}${it.key}' mandates a client-owned stored part (${mandated.join(", ")}) and mixes it with a server-owned stored part (${mixed.server.join(", ")}) — a mandated part is the client's to declare, so the write path does NOT materialize this composite and the computed part stays absent until a client sends the field. Either drop \`required\` (from the field or from the ${mandated.join("/")} filling), or give every stored part a \`value\` (the composite becomes fully server-owned).`);
11262
- }
11263
- }
11264
- /**
11265
10545
  * The declaration-time checks that are about a FIELD LIST, not about a shelf: they read
11266
10546
  * `fields` and nothing else, so they are equally true of an extend's fields — an extend
11267
10547
  * stores composites in its own table through the very same write path (`upsertExtendRecord`
@@ -11275,7 +10555,6 @@ function warnMixedOwnedParts(items, owner, path = "") {
11275
10555
  */
11276
10556
  function checkFieldDeclaration(fields, owner) {
11277
10557
  assertNoKeylessCompute(fields, owner);
11278
- warnMixedOwnedParts(fields, owner);
11279
10558
  }
11280
10559
  function defineShelf(m) {
11281
10560
  const built = materializeDef(m);
@@ -11344,29 +10623,32 @@ var bus_route_default = defineShelf({
11344
10623
  ] },
11345
10624
  fields: {
11346
10625
  name: field.title({ label: "core.fields.name" }),
10626
+ /**
10627
+ * What this route IS, read before anything else: its number, its two ends and the
10628
+ * stop these timetables are measured at. They already drew as one row — the spans
10629
+ * said so — but below the description and with their labels above. A stats cell
10630
+ * inverts that and makes them the record's headline, which is what they are.
10631
+ */
10632
+ route: field.stats({ fields: {
10633
+ route_number: field.int({ label: "transit.bus_route.fields.route_number" }),
10634
+ from: field.string({
10635
+ label: "transit.bus_route.fields.from",
10636
+ rules: { max: 100 }
10637
+ }),
10638
+ to: field.string({
10639
+ label: "transit.bus_route.fields.to",
10640
+ rules: { max: 100 }
10641
+ }),
10642
+ stop: field.string({
10643
+ label: "transit.bus_route.fields.stop",
10644
+ rules: { max: 200 }
10645
+ })
10646
+ } }),
10647
+ hairline: field.divider({}),
11347
10648
  description: field.text({
11348
10649
  label: "transit.bus_route.fields.description",
11349
10650
  rules: { max: 1e3 }
11350
10651
  }),
11351
- route_number: field.int({
11352
- label: "transit.bus_route.fields.route_number",
11353
- ui: { span: 3 }
11354
- }),
11355
- from: field.string({
11356
- label: "transit.bus_route.fields.from",
11357
- rules: { max: 100 },
11358
- ui: { span: 3 }
11359
- }),
11360
- to: field.string({
11361
- label: "transit.bus_route.fields.to",
11362
- rules: { max: 100 },
11363
- ui: { span: 3 }
11364
- }),
11365
- stop: field.string({
11366
- label: "transit.bus_route.fields.stop",
11367
- rules: { max: 200 },
11368
- ui: { span: 3 }
11369
- }),
11370
10652
  weekday_times: field.timetable({
11371
10653
  label: "transit.bus_route.fields.weekday_times",
11372
10654
  ui: { span: 12 }
@@ -11392,6 +10674,8 @@ var src_default = definePlugin({
11392
10674
  id: "transit",
11393
10675
  version: "1.0.0",
11394
10676
  dependsOn: [],
10677
+ label: "transit.plugin.label",
10678
+ description: "transit.plugin.description",
11395
10679
  libraries: [{
11396
10680
  meta: defineLibrary({
11397
10681
  id: "transit",