@ai-matrx/records 0.44.1 → 0.45.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,7 +1,7 @@
1
1
  import { g as Timestamp, U as Uuid, h as RecordDocument, i as RecordsResult, j as RecordRead, k as ReadRow, l as Field, m as StoredRecord, N as NewFieldDeclaration, n as FieldPatch, o as RecordRevision, p as ReadValue, q as FieldProposal, r as TableProposal, s as RecordsError, W as WriteConflict, P as PgError, t as StaleWriteDetail, u as PredictedRefusal } from '../field-D0Rr4Cqb.cjs';
2
2
  export { A as ABSENCE_REASONS, v as ACTOR_VOCABULARY, w as AbsenceReason, x as Actor, y as COMPUTE_ON, z as CONTEXT_POLICIES, C as ComputeOn, e as ContextPolicy, D as DELIVERIES, B as Delivery, E as ENTITY_TOKENS, G as EntityToken, H as FIELD_SENSITIVITIES, I as FIELD_SOURCES, J as FRESHNESS, K as FieldBehavior, c as FieldRule, d as FieldSensitivity, b as FieldSource, F as FieldTypeWord, L as ForbiddenEnvelopeWord, M as Freshness, Q as HiddenFieldNotice, V as KERNEL_TABLES, X as KernelTableName, Y as MERGE_FIELD_MODIFIERS, Z as MERGE_FIELD_SEMANTIC_TYPES, _ as MERGE_FIELD_SOURCES, $ as MergeFieldModifier, a0 as MergeFieldSemanticType, a1 as MergeFieldSource, a2 as ON_DELETE, a3 as OVERRIDE_POLICIES, O as OnDelete, a4 as OverridePolicy, a5 as PARITY_FIELD_TYPES, a6 as PER_VALUE_ACCESS_WORDS, a7 as ParityFieldType, a8 as ParityFieldTypeDescriptor, a9 as PerValueAccessWord, aa as ProvenancePointer, ab as RELATION_BINDINGS, ac as RELATION_CARDINALITIES, ad as RELATION_FLAVORS, ae as RETIRED_ACTOR_WORDS, af as RULE_NODE_KINDS, ag as RULE_USES, ah as RecordsErrorCode, ai as RelationBinding, f as RelationCardinality, aj as RelationDisplay, R as RelationFlavor, ak as RetiredActorWord, al as RuleNodeKind, am as RuleUse, an as STORAGE_MODES, ao as STORE_DOORS, ap as STORE_KNOBS, aq as STORE_REFUSAL_CODES, S as StorageMode, ar as StoreDoorName, as as StoreRefusalCode, at as TABLE_DISPLAYS, au as TABLE_ORIGINS, av as TABLE_TYPES, a as TableDisplay, aw as TableOrigin, T as TableType, ax as VALUE_ALTERNATE_KEYS, ay as VALUE_ENVELOPE_KEYS, az as ValueAlternate, aA as ValueAlternateKey, aB as ValueEnvelope, aC as ValueEnvelopeKey, aD as ValueSource, aE as err, aF as isRecordsErr, aG as ok } from '../field-D0Rr4Cqb.cjs';
3
3
  import { RelationCoordinate, RecordsConfig, Table, TableCapacity, EntityTableFacts, NewEntityFieldDeclaration, EntityFieldRights, EntityRecordRead, EntityRecordsFound, Pipeline, PipelineColumn, PipelineVerdict, PipelineMoveResult, PipelineSpec, PipelineDeclared, StageRuleOnFail, StageRuleEnforcement, StagePending, StagePendingOnBoard, PipelineGate, PipelineGatePreview, FormSummary, BookingSummary, BookingAvailability, BookingDeclared, ImportPlan, ImportPolicy, ImportOpened, ImportBatchResult, ImportFinished, ImportReport, ImportRun, InboundDeclared, InboundAddress, PortalSummary, PortalCard, PortalInvitation, PortalRevocation, PortalPreviewRow, DashboardSummary, DashboardBlock, AggregateFilter, DashboardRunResult, StuckRow, CaptureSheetSummary, CaptureSheetFace, CaptureFileRef, CaptureOutcome, EnrichmentSummary, EnrichDeclared, EnrichDueRow, EnrichCell, EnrichRun, AggregateMeasure, AggregateBucket, AggregateRow, Subscription, MySubscription, SubscriptionSpec, DigestPreview, SavedViewRow, SavedViewSpecIn, DocToken, DocUnresolvedToken, DocTemplateRow, DocRenderRow, DocSignatureRow, RecordHistoryEntry, RecordScopeContext, ConversationScope, ConversationScopeContext, FieldHistoryEntry, RestorePreview, RestoreResult, CommentThreadRead, CommentWritten, AnonTokenBinding, ChecklistSpec, ChecklistDeclared, ChecklistTemplateSummary, ChecklistTemplateShape, ChecklistRunStarted, ChecklistRunStep, ChecklistRunSummary, ChecklistStepCompleted, WorkState, WorkGraph, WorkInstantiation, WorkTurn, WorkAssignmentField, WorkSlotHold, WorkInboxItem, WorkListFlavour, WorkListItem, WorkAssignment, WorkRecordState, WorkApprover, WorkChange, WorkApprovalFiled, WorkApprovalDecision, ExternalPrincipalCard, PublishBinding, ResolvedPublishBinding, MyLevel, RecordsDataSource } from '../index.cjs';
4
- export { AggregateOperation, AggregateWindow, BookingWindow, CaptureField, CaptureQuestion, CaptureQueue, CaptureQueueCounts, CaptureQueueOptions, CaptureQueuePorts, CaptureQueueStore, CaptureSyncReport, ChecklistRequirement, ChecklistRequirementKind, ChecklistRoleSpec, ChecklistStepSpec, ChecklistTrigger, ChecklistTriggerKind, ChoiceOption, CustomFieldTableType, DashboardBlockKind, DashboardBlockResult, DocSignatureCheck, EnrichAlternate, EnrichSource, Enrichment, EntityFieldValue, EntityRecordMatch, HistoryActor, HistoryActorKind, HistoryChange, Home, ImportColumnPlan, ImportOutcome, ImportProposal, MergeField, MergeFieldProvenance, MergeFieldResolution, MergeFieldTransform, MissingBehavior, PERMISSION_LEVELS, PIPELINE_RULE_KINDS, PermissionLevel, PipelineMissingField, PipelineRule, PipelineRuleKind, PipelineStage, PortalPrincipal, PortalTableExposure, QueuedCapture, QueuedCaptureFile, QueuedCaptureState, QuietHours, REFUSALS_WORTH_REPEATING, RecordComment, RecordScopeComment, RecordScopeField, RecordScopeHistoryEntry, RecordScopeRelation, RecordScopeWithheld, RecordsActor, RecordsChangeSink, RecordsErrorSink, RecordsFilter, RecordsRealtimePort, RecordsResolverPort, RecordsResponse, RecordsTableQuery, RegisteredTable, Relation, RelationCarries, RelationProperties, RelationTarget, ResolutionTriple, Rule, RuleAnswer, RuleExpression, STAGE_RULE_ENFORCEMENT, STAGE_RULE_ON_FAIL, StageRuleWarning, SubscriptionBlock, SubscriptionCadence, WorkDueState, WorkInboxKind, WorkOrigin, WorkTemplateNode, WorkTemplateRelation, asPermissionLevel, atLeast, bookingPath, choiceSlug, choiceValuesOf, choicesOf, forgetAllOps, highestLevel, holdsARetiredChoice, indexedDbStore, isDecided, isOwnOp, isTheChosen, looksLikeAnId, mayDrag, measureKey, memoryStore, mintClientKey, mintOpId, openCaptureQueue, optionKey, optionLabel, portalPath, publicFormPath, rememberedOpCount, scopeChip } from '../index.cjs';
4
+ export { AggregateOperation, AggregateWindow, BookingWindow, CaptureField, CaptureQuestion, CaptureQueue, CaptureQueueCounts, CaptureQueueOptions, CaptureQueuePorts, CaptureQueueStore, CaptureSyncReport, ChecklistRequirement, ChecklistRequirementKind, ChecklistRoleSpec, ChecklistStepSpec, ChecklistTrigger, ChecklistTriggerKind, ChoiceOption, ChoiceOptions, CoerceOptions, Coerced, CoercedAnswers, CoercibleField, CustomFieldTableType, DashboardBlockKind, DashboardBlockResult, DocSignatureCheck, EnrichAlternate, EnrichSource, Enrichment, EntityFieldValue, EntityRecordMatch, FIELD_KINDS, FieldKind, HistoryActor, HistoryActorKind, HistoryChange, Home, ImportColumnPlan, ImportOutcome, ImportProposal, KernelTargets, MergeField, MergeFieldProvenance, MergeFieldResolution, MergeFieldTransform, MissingBehavior, PERMISSION_LEVELS, PIPELINE_RULE_KINDS, PermissionLevel, PipelineMissingField, PipelineRule, PipelineRuleKind, PipelineStage, PortalPrincipal, PortalTableExposure, QueuedCapture, QueuedCaptureFile, QueuedCaptureState, QuietHours, REFUSALS_WORTH_REPEATING, RecordComment, RecordScopeComment, RecordScopeField, RecordScopeHistoryEntry, RecordScopeRelation, RecordScopeWithheld, RecordsActor, RecordsChangeSink, RecordsErrorSink, RecordsFilter, RecordsRealtimePort, RecordsResolverPort, RecordsResponse, RecordsTableQuery, RegisteredTable, Relation, RelationCarries, RelationProperties, RelationTarget, ResolutionTriple, Rule, RuleAnswer, RuleExpression, STAGE_RULE_ENFORCEMENT, STAGE_RULE_ON_FAIL, StageRuleWarning, SubscriptionBlock, SubscriptionCadence, WorkDueState, WorkInboxKind, WorkOrigin, WorkTemplateNode, WorkTemplateRelation, asPermissionLevel, atLeast, bookingPath, choiceSlug, choiceValuesOf, choicesOf, coerceTypedAnswer, coerceTypedAnswers, coercionLabel, fieldKindFor, forgetAllOps, highestLevel, holdsARetiredChoice, indexedDbStore, isDecided, isOwnOp, isTheChosen, looksLikeAnId, mayDrag, measureKey, memoryStore, mintClientKey, mintOpId, openCaptureQueue, optionKey, optionLabel, portalPath, publicFormPath, rememberedOpCount, scopeChip } from '../index.cjs';
5
5
 
6
6
  /**
7
7
  * DOOR-8. As-of on EITHER clock, and they are different questions:
@@ -1,7 +1,7 @@
1
1
  import { g as Timestamp, U as Uuid, h as RecordDocument, i as RecordsResult, j as RecordRead, k as ReadRow, l as Field, m as StoredRecord, N as NewFieldDeclaration, n as FieldPatch, o as RecordRevision, p as ReadValue, q as FieldProposal, r as TableProposal, s as RecordsError, W as WriteConflict, P as PgError, t as StaleWriteDetail, u as PredictedRefusal } from '../field-D0Rr4Cqb.js';
2
2
  export { A as ABSENCE_REASONS, v as ACTOR_VOCABULARY, w as AbsenceReason, x as Actor, y as COMPUTE_ON, z as CONTEXT_POLICIES, C as ComputeOn, e as ContextPolicy, D as DELIVERIES, B as Delivery, E as ENTITY_TOKENS, G as EntityToken, H as FIELD_SENSITIVITIES, I as FIELD_SOURCES, J as FRESHNESS, K as FieldBehavior, c as FieldRule, d as FieldSensitivity, b as FieldSource, F as FieldTypeWord, L as ForbiddenEnvelopeWord, M as Freshness, Q as HiddenFieldNotice, V as KERNEL_TABLES, X as KernelTableName, Y as MERGE_FIELD_MODIFIERS, Z as MERGE_FIELD_SEMANTIC_TYPES, _ as MERGE_FIELD_SOURCES, $ as MergeFieldModifier, a0 as MergeFieldSemanticType, a1 as MergeFieldSource, a2 as ON_DELETE, a3 as OVERRIDE_POLICIES, O as OnDelete, a4 as OverridePolicy, a5 as PARITY_FIELD_TYPES, a6 as PER_VALUE_ACCESS_WORDS, a7 as ParityFieldType, a8 as ParityFieldTypeDescriptor, a9 as PerValueAccessWord, aa as ProvenancePointer, ab as RELATION_BINDINGS, ac as RELATION_CARDINALITIES, ad as RELATION_FLAVORS, ae as RETIRED_ACTOR_WORDS, af as RULE_NODE_KINDS, ag as RULE_USES, ah as RecordsErrorCode, ai as RelationBinding, f as RelationCardinality, aj as RelationDisplay, R as RelationFlavor, ak as RetiredActorWord, al as RuleNodeKind, am as RuleUse, an as STORAGE_MODES, ao as STORE_DOORS, ap as STORE_KNOBS, aq as STORE_REFUSAL_CODES, S as StorageMode, ar as StoreDoorName, as as StoreRefusalCode, at as TABLE_DISPLAYS, au as TABLE_ORIGINS, av as TABLE_TYPES, a as TableDisplay, aw as TableOrigin, T as TableType, ax as VALUE_ALTERNATE_KEYS, ay as VALUE_ENVELOPE_KEYS, az as ValueAlternate, aA as ValueAlternateKey, aB as ValueEnvelope, aC as ValueEnvelopeKey, aD as ValueSource, aE as err, aF as isRecordsErr, aG as ok } from '../field-D0Rr4Cqb.js';
3
3
  import { RelationCoordinate, RecordsConfig, Table, TableCapacity, EntityTableFacts, NewEntityFieldDeclaration, EntityFieldRights, EntityRecordRead, EntityRecordsFound, Pipeline, PipelineColumn, PipelineVerdict, PipelineMoveResult, PipelineSpec, PipelineDeclared, StageRuleOnFail, StageRuleEnforcement, StagePending, StagePendingOnBoard, PipelineGate, PipelineGatePreview, FormSummary, BookingSummary, BookingAvailability, BookingDeclared, ImportPlan, ImportPolicy, ImportOpened, ImportBatchResult, ImportFinished, ImportReport, ImportRun, InboundDeclared, InboundAddress, PortalSummary, PortalCard, PortalInvitation, PortalRevocation, PortalPreviewRow, DashboardSummary, DashboardBlock, AggregateFilter, DashboardRunResult, StuckRow, CaptureSheetSummary, CaptureSheetFace, CaptureFileRef, CaptureOutcome, EnrichmentSummary, EnrichDeclared, EnrichDueRow, EnrichCell, EnrichRun, AggregateMeasure, AggregateBucket, AggregateRow, Subscription, MySubscription, SubscriptionSpec, DigestPreview, SavedViewRow, SavedViewSpecIn, DocToken, DocUnresolvedToken, DocTemplateRow, DocRenderRow, DocSignatureRow, RecordHistoryEntry, RecordScopeContext, ConversationScope, ConversationScopeContext, FieldHistoryEntry, RestorePreview, RestoreResult, CommentThreadRead, CommentWritten, AnonTokenBinding, ChecklistSpec, ChecklistDeclared, ChecklistTemplateSummary, ChecklistTemplateShape, ChecklistRunStarted, ChecklistRunStep, ChecklistRunSummary, ChecklistStepCompleted, WorkState, WorkGraph, WorkInstantiation, WorkTurn, WorkAssignmentField, WorkSlotHold, WorkInboxItem, WorkListFlavour, WorkListItem, WorkAssignment, WorkRecordState, WorkApprover, WorkChange, WorkApprovalFiled, WorkApprovalDecision, ExternalPrincipalCard, PublishBinding, ResolvedPublishBinding, MyLevel, RecordsDataSource } from '../index.js';
4
- export { AggregateOperation, AggregateWindow, BookingWindow, CaptureField, CaptureQuestion, CaptureQueue, CaptureQueueCounts, CaptureQueueOptions, CaptureQueuePorts, CaptureQueueStore, CaptureSyncReport, ChecklistRequirement, ChecklistRequirementKind, ChecklistRoleSpec, ChecklistStepSpec, ChecklistTrigger, ChecklistTriggerKind, ChoiceOption, CustomFieldTableType, DashboardBlockKind, DashboardBlockResult, DocSignatureCheck, EnrichAlternate, EnrichSource, Enrichment, EntityFieldValue, EntityRecordMatch, HistoryActor, HistoryActorKind, HistoryChange, Home, ImportColumnPlan, ImportOutcome, ImportProposal, MergeField, MergeFieldProvenance, MergeFieldResolution, MergeFieldTransform, MissingBehavior, PERMISSION_LEVELS, PIPELINE_RULE_KINDS, PermissionLevel, PipelineMissingField, PipelineRule, PipelineRuleKind, PipelineStage, PortalPrincipal, PortalTableExposure, QueuedCapture, QueuedCaptureFile, QueuedCaptureState, QuietHours, REFUSALS_WORTH_REPEATING, RecordComment, RecordScopeComment, RecordScopeField, RecordScopeHistoryEntry, RecordScopeRelation, RecordScopeWithheld, RecordsActor, RecordsChangeSink, RecordsErrorSink, RecordsFilter, RecordsRealtimePort, RecordsResolverPort, RecordsResponse, RecordsTableQuery, RegisteredTable, Relation, RelationCarries, RelationProperties, RelationTarget, ResolutionTriple, Rule, RuleAnswer, RuleExpression, STAGE_RULE_ENFORCEMENT, STAGE_RULE_ON_FAIL, StageRuleWarning, SubscriptionBlock, SubscriptionCadence, WorkDueState, WorkInboxKind, WorkOrigin, WorkTemplateNode, WorkTemplateRelation, asPermissionLevel, atLeast, bookingPath, choiceSlug, choiceValuesOf, choicesOf, forgetAllOps, highestLevel, holdsARetiredChoice, indexedDbStore, isDecided, isOwnOp, isTheChosen, looksLikeAnId, mayDrag, measureKey, memoryStore, mintClientKey, mintOpId, openCaptureQueue, optionKey, optionLabel, portalPath, publicFormPath, rememberedOpCount, scopeChip } from '../index.js';
4
+ export { AggregateOperation, AggregateWindow, BookingWindow, CaptureField, CaptureQuestion, CaptureQueue, CaptureQueueCounts, CaptureQueueOptions, CaptureQueuePorts, CaptureQueueStore, CaptureSyncReport, ChecklistRequirement, ChecklistRequirementKind, ChecklistRoleSpec, ChecklistStepSpec, ChecklistTrigger, ChecklistTriggerKind, ChoiceOption, ChoiceOptions, CoerceOptions, Coerced, CoercedAnswers, CoercibleField, CustomFieldTableType, DashboardBlockKind, DashboardBlockResult, DocSignatureCheck, EnrichAlternate, EnrichSource, Enrichment, EntityFieldValue, EntityRecordMatch, FIELD_KINDS, FieldKind, HistoryActor, HistoryActorKind, HistoryChange, Home, ImportColumnPlan, ImportOutcome, ImportProposal, KernelTargets, MergeField, MergeFieldProvenance, MergeFieldResolution, MergeFieldTransform, MissingBehavior, PERMISSION_LEVELS, PIPELINE_RULE_KINDS, PermissionLevel, PipelineMissingField, PipelineRule, PipelineRuleKind, PipelineStage, PortalPrincipal, PortalTableExposure, QueuedCapture, QueuedCaptureFile, QueuedCaptureState, QuietHours, REFUSALS_WORTH_REPEATING, RecordComment, RecordScopeComment, RecordScopeField, RecordScopeHistoryEntry, RecordScopeRelation, RecordScopeWithheld, RecordsActor, RecordsChangeSink, RecordsErrorSink, RecordsFilter, RecordsRealtimePort, RecordsResolverPort, RecordsResponse, RecordsTableQuery, RegisteredTable, Relation, RelationCarries, RelationProperties, RelationTarget, ResolutionTriple, Rule, RuleAnswer, RuleExpression, STAGE_RULE_ENFORCEMENT, STAGE_RULE_ON_FAIL, StageRuleWarning, SubscriptionBlock, SubscriptionCadence, WorkDueState, WorkInboxKind, WorkOrigin, WorkTemplateNode, WorkTemplateRelation, asPermissionLevel, atLeast, bookingPath, choiceSlug, choiceValuesOf, choicesOf, coerceTypedAnswer, coerceTypedAnswers, coercionLabel, fieldKindFor, forgetAllOps, highestLevel, holdsARetiredChoice, indexedDbStore, isDecided, isOwnOp, isTheChosen, looksLikeAnId, mayDrag, measureKey, memoryStore, mintClientKey, mintOpId, openCaptureQueue, optionKey, optionLabel, portalPath, publicFormPath, rememberedOpCount, scopeChip } from '../index.js';
5
5
 
6
6
  /**
7
7
  * DOOR-8. As-of on EITHER clock, and they are different questions:
@@ -124,6 +124,209 @@ function looksLikeAnId(value) {
124
124
  return typeof value === "string" && UUID.test(value);
125
125
  }
126
126
 
127
+ // src/coerce.ts
128
+ var FIELD_KINDS = [
129
+ "attachment",
130
+ "checkbox",
131
+ "currency",
132
+ "datetime",
133
+ "email",
134
+ "formula",
135
+ "json",
136
+ "long_text",
137
+ "lookup",
138
+ "member",
139
+ "multi_select",
140
+ "number",
141
+ "percent",
142
+ "phone",
143
+ "relation",
144
+ "rollup",
145
+ "select",
146
+ "text",
147
+ "url"
148
+ ];
149
+ function fieldKindFor(field, kernel) {
150
+ const format = (field.format ?? "").toLowerCase();
151
+ const config = field.config ?? {};
152
+ switch (field.type) {
153
+ case "boolean":
154
+ return "checkbox";
155
+ case "text":
156
+ if (format === "email") return "email";
157
+ if (format === "phone") return "phone";
158
+ if (format === "url") return "url";
159
+ if (format === "json" || config["json"] === true) return "json";
160
+ if (format === "long" || config["multiline"] === true) return "long_text";
161
+ return "text";
162
+ case "range": {
163
+ const kind = String(config["kind"] ?? "number");
164
+ if (kind === "date" || kind === "datetime") return "datetime";
165
+ if (format === "currency") return "currency";
166
+ if (format === "percent" || field.unit === "%") return "percent";
167
+ return "number";
168
+ }
169
+ case "list":
170
+ return field.multi ? "multi_select" : "select";
171
+ case "relation": {
172
+ const parity = String(config["parity"] ?? "");
173
+ if (parity === "attachment" || parity === "member") return parity;
174
+ if (kernel?.file && field.relation_target === kernel.file) return "attachment";
175
+ if (kernel?.person && field.relation_target === kernel.person) return "member";
176
+ return "relation";
177
+ }
178
+ case "formula": {
179
+ const via = config["via"];
180
+ if (via && config["agg"]) return "rollup";
181
+ if (via) return "lookup";
182
+ return "formula";
183
+ }
184
+ default:
185
+ return "text";
186
+ }
187
+ }
188
+ var TRUE_WORDS = /* @__PURE__ */ new Set(["true", "yes", "y", "1", "\u2713", "x", "checked", "on"]);
189
+ var FALSE_WORDS = /* @__PURE__ */ new Set(["false", "no", "n", "0", "", "unchecked", "off"]);
190
+ function coercionLabel(field) {
191
+ const label = (field.label ?? "").trim();
192
+ if (label !== "") return label;
193
+ const name = (field.name ?? "").trim();
194
+ if (name !== "") return name;
195
+ return field.key.replace(/[_-]+/g, " ").replace(/\b\w/g, (c) => c.toUpperCase()).trim();
196
+ }
197
+ function coerceTypedAnswer(field, raw, opts = {}) {
198
+ const label = opts.label ?? coercionLabel(field);
199
+ const text = raw.trim();
200
+ const kind = fieldKindFor(field, opts.kernel);
201
+ if (text === "" && kind !== "checkbox") return { value: null };
202
+ switch (kind) {
203
+ case "checkbox": {
204
+ const word = text.toLowerCase();
205
+ if (TRUE_WORDS.has(word)) return { value: true };
206
+ if (FALSE_WORDS.has(word)) return { value: word === "" ? null : false };
207
+ return {
208
+ refusal: `${label} is a tick box, so it takes yes or no \u2014 \u201C${raw}\u201D is neither. Write TRUE/FALSE, yes/no or 1/0.`
209
+ };
210
+ }
211
+ case "number":
212
+ case "currency":
213
+ case "percent": {
214
+ const negative = /^\(.*\)$/.test(text);
215
+ const bare = text.replace(/^\(|\)$/g, "").replace(/[\s,]/g, "").replace(/^[^\d.\-+]+/, "").replace(/[^\d.\-+eE]+$/, "");
216
+ const n = Number(bare);
217
+ if (bare === "" || Number.isNaN(n)) {
218
+ return {
219
+ refusal: `${label} holds a number, and \u201C${raw}\u201D is not one. Write digits \u2014 a currency symbol, a percent sign, commas and brackets for a negative are all fine.`
220
+ };
221
+ }
222
+ return { value: negative ? -n : n };
223
+ }
224
+ case "datetime": {
225
+ const wantsTime = String(field.config?.["kind"] ?? "date") === "datetime";
226
+ const plainDay = /^\s*(\d{4})-(\d{2})-(\d{2})\s*$/.exec(raw);
227
+ if (!wantsTime && plainDay) return { value: `${plainDay[1]}-${plainDay[2]}-${plainDay[3]}` };
228
+ const at = Date.parse(text);
229
+ if (Number.isNaN(at)) {
230
+ return {
231
+ refusal: `${label} holds a date, and \u201C${raw}\u201D is not one this can read. Write it as 2026-09-21, or the way your spreadsheet writes dates.`
232
+ };
233
+ }
234
+ const parsed = new Date(at);
235
+ if (wantsTime) return { value: parsed.toISOString() };
236
+ const y = parsed.getFullYear();
237
+ const m = String(parsed.getMonth() + 1).padStart(2, "0");
238
+ const d = String(parsed.getDate()).padStart(2, "0");
239
+ return { value: `${y}-${m}-${d}` };
240
+ }
241
+ case "json": {
242
+ try {
243
+ return { value: JSON.parse(text) };
244
+ } catch {
245
+ return {
246
+ refusal: `${label} holds a document, and \u201C${raw}\u201D is not valid JSON. Write the whole object, braces and all.`
247
+ };
248
+ }
249
+ }
250
+ case "select":
251
+ case "multi_select": {
252
+ if (!opts.options) {
253
+ return {
254
+ refusal: `${label} is a list and its options have not been read yet, so nothing can be matched to \u201C${raw}\u201D. Try again once the column's choices have loaded.`
255
+ };
256
+ }
257
+ const wanted = kind === "multi_select" ? text.split(/[,;]/).map((w) => w.trim()).filter((w) => w.length > 0) : [text];
258
+ if (wanted.length === 0) return { value: kind === "multi_select" ? [] : null };
259
+ const matched = [];
260
+ const unmatched = [];
261
+ for (const word of wanted) {
262
+ const hit = opts.options.byWord.get(word.toLowerCase());
263
+ if (hit === void 0) unmatched.push(word);
264
+ else matched.push(hit);
265
+ }
266
+ if (unmatched.length > 0) {
267
+ const offered = opts.options.labels.length > 0 ? opts.options.labels.join(", ") : "it has none yet";
268
+ return {
269
+ refusal: `${label} does not have ${unmatched.map((w) => `\u201C${w}\u201D`).join(" or ")} among its options. It offers: ${offered}.`,
270
+ unmatched
271
+ };
272
+ }
273
+ return { value: kind === "multi_select" ? matched : matched[0] };
274
+ }
275
+ // AN IDENTITY IS NOT A WORD. Writing the word would put a string where an
276
+ // id belongs, and every filter, colour and rollup built on that column
277
+ // would stop agreeing with it. So it is refused and the person is told
278
+ // which control does hold it.
279
+ case "member":
280
+ return {
281
+ refusal: `${label} names a person in this organization, so it is chosen rather than typed. Open it and pick them.`
282
+ };
283
+ case "attachment":
284
+ return {
285
+ refusal: `${label} holds a file, which cannot arrive as typed-in text. Open it and attach the file.`
286
+ };
287
+ case "relation":
288
+ return {
289
+ refusal: `${label} points at another record, so it is chosen rather than typed. Open it and pick the record.`
290
+ };
291
+ case "formula":
292
+ case "lookup":
293
+ case "rollup":
294
+ return {
295
+ refusal: `${label} is worked out by the system, so nothing can be written into it.`
296
+ };
297
+ default:
298
+ return { value: raw };
299
+ }
300
+ }
301
+ function coerceTypedAnswers(fields, answers, opts = {}) {
302
+ const byKey = new Map(fields.map((f) => [f.key, f]));
303
+ const values = {};
304
+ const refusals = {};
305
+ const unknownKeys = [];
306
+ for (const [key, given] of Object.entries(answers)) {
307
+ const field = byKey.get(key);
308
+ if (!field) {
309
+ unknownKeys.push(key);
310
+ values[key] = given;
311
+ continue;
312
+ }
313
+ if (typeof given !== "string") {
314
+ values[key] = given;
315
+ continue;
316
+ }
317
+ const opt = {};
318
+ const choices = opts.options?.get(key);
319
+ if (choices) opt.options = choices;
320
+ if (opts.kernel) opt.kernel = opts.kernel;
321
+ const label = opts.labels?.[key];
322
+ if (label) opt.label = label;
323
+ const answered = coerceTypedAnswer(field, given, opt);
324
+ if ("refusal" in answered) refusals[key] = answered.refusal;
325
+ else values[key] = answered.value;
326
+ }
327
+ return { values, refusals, unknownKeys };
328
+ }
329
+
127
330
  // src/pipeline.ts
128
331
  var PIPELINE_RULE_KINDS = ["moves", "requires", "who", "limit", "entry"];
129
332
  var STAGE_RULE_ON_FAIL = ["refuse", "require_approval"];
@@ -5082,6 +5285,7 @@ export {
5082
5285
  DELIVERIES,
5083
5286
  DOORS,
5084
5287
  ENTITY_TOKENS,
5288
+ FIELD_KINDS,
5085
5289
  FIELD_SENSITIVITIES,
5086
5290
  FIELD_SOURCES,
5087
5291
  FRESHNESS,
@@ -5122,6 +5326,9 @@ export {
5122
5326
  choiceSlug,
5123
5327
  choiceValuesOf,
5124
5328
  choicesOf,
5329
+ coerceTypedAnswer,
5330
+ coerceTypedAnswers,
5331
+ coercionLabel,
5125
5332
  createRecordsClient,
5126
5333
  doorAbsent,
5127
5334
  doorCensus,
@@ -5129,6 +5336,7 @@ export {
5129
5336
  err,
5130
5337
  exportCsv,
5131
5338
  exportXlsx,
5339
+ fieldKindFor,
5132
5340
  forgetAllOps,
5133
5341
  highestLevel,
5134
5342
  holdsARetiredChoice,