@kelpie/schemas 0.8.0 → 0.10.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.
Files changed (91) hide show
  1. package/dist/company.d.ts +8 -0
  2. package/dist/company.d.ts.map +1 -1
  3. package/dist/company.js +4 -0
  4. package/dist/company.js.map +1 -1
  5. package/dist/consentPurpose.d.ts +49 -0
  6. package/dist/consentPurpose.d.ts.map +1 -0
  7. package/dist/consentPurpose.js +40 -0
  8. package/dist/consentPurpose.js.map +1 -0
  9. package/dist/customField.d.ts +99 -0
  10. package/dist/customField.d.ts.map +1 -0
  11. package/dist/customField.js +133 -0
  12. package/dist/customField.js.map +1 -0
  13. package/dist/deal.d.ts +8 -0
  14. package/dist/deal.d.ts.map +1 -1
  15. package/dist/deal.js +4 -0
  16. package/dist/deal.js.map +1 -1
  17. package/dist/enquiry.d.ts +43 -0
  18. package/dist/enquiry.d.ts.map +1 -0
  19. package/dist/enquiry.js +47 -0
  20. package/dist/enquiry.js.map +1 -0
  21. package/dist/form.d.ts +117 -2
  22. package/dist/form.d.ts.map +1 -1
  23. package/dist/form.js +102 -1
  24. package/dist/form.js.map +1 -1
  25. package/dist/formSubmission.d.ts +29 -0
  26. package/dist/formSubmission.d.ts.map +1 -1
  27. package/dist/formSubmission.js +34 -0
  28. package/dist/formSubmission.js.map +1 -1
  29. package/dist/importExport.d.ts +28 -4
  30. package/dist/importExport.d.ts.map +1 -1
  31. package/dist/importExport.js +24 -1
  32. package/dist/importExport.js.map +1 -1
  33. package/dist/index.d.ts +15 -5
  34. package/dist/index.d.ts.map +1 -1
  35. package/dist/index.js +7 -2
  36. package/dist/index.js.map +1 -1
  37. package/dist/list.d.ts +10 -0
  38. package/dist/list.d.ts.map +1 -1
  39. package/dist/list.js +6 -0
  40. package/dist/list.js.map +1 -1
  41. package/dist/names.d.ts +43 -0
  42. package/dist/names.d.ts.map +1 -0
  43. package/dist/names.js +35 -0
  44. package/dist/names.js.map +1 -0
  45. package/dist/opportunity.d.ts +10 -0
  46. package/dist/opportunity.d.ts.map +1 -1
  47. package/dist/opportunity.js +7 -0
  48. package/dist/opportunity.js.map +1 -1
  49. package/dist/partnership.d.ts +8 -0
  50. package/dist/partnership.d.ts.map +1 -1
  51. package/dist/partnership.js +4 -0
  52. package/dist/partnership.js.map +1 -1
  53. package/dist/person.d.ts +42 -1
  54. package/dist/person.d.ts.map +1 -1
  55. package/dist/person.js +23 -0
  56. package/dist/person.js.map +1 -1
  57. package/dist/personConsent.d.ts +31 -0
  58. package/dist/personConsent.d.ts.map +1 -0
  59. package/dist/personConsent.js +27 -0
  60. package/dist/personConsent.js.map +1 -0
  61. package/dist/raise.d.ts +8 -0
  62. package/dist/raise.d.ts.map +1 -1
  63. package/dist/raise.js +4 -0
  64. package/dist/raise.js.map +1 -1
  65. package/dist/sampleData.d.ts +1 -0
  66. package/dist/sampleData.d.ts.map +1 -1
  67. package/dist/sampleData.js +2 -0
  68. package/dist/sampleData.js.map +1 -1
  69. package/dist/values.d.ts +86 -8
  70. package/dist/values.d.ts.map +1 -1
  71. package/dist/values.js +140 -3
  72. package/dist/values.js.map +1 -1
  73. package/package.json +1 -1
  74. package/src/company.ts +13 -0
  75. package/src/consentPurpose.ts +95 -0
  76. package/src/customField.ts +211 -0
  77. package/src/deal.ts +13 -0
  78. package/src/enquiry.ts +94 -0
  79. package/src/form.ts +230 -2
  80. package/src/formSubmission.ts +63 -0
  81. package/src/importExport.ts +44 -5
  82. package/src/index.ts +70 -2
  83. package/src/list.ts +16 -0
  84. package/src/names.ts +49 -0
  85. package/src/opportunity.ts +18 -0
  86. package/src/partnership.ts +13 -0
  87. package/src/person.ts +69 -1
  88. package/src/personConsent.ts +60 -0
  89. package/src/raise.ts +13 -0
  90. package/src/sampleData.ts +3 -0
  91. package/src/values.ts +169 -3
package/src/values.ts CHANGED
@@ -90,6 +90,7 @@ export const EXTENSIBLE_RECORD_TYPES = [
90
90
  'opportunity',
91
91
  'partnership',
92
92
  'raise',
93
+ 'enquiry',
93
94
  'role',
94
95
  'candidate',
95
96
  ] as const
@@ -110,6 +111,7 @@ export const RECORD_TARGET_TYPES = [
110
111
  'opportunity',
111
112
  'partnership',
112
113
  'raise',
114
+ 'enquiry',
113
115
  'candidate',
114
116
  ] as const
115
117
 
@@ -123,6 +125,7 @@ export const RECORD_TARGET_TYPE_LABELS: Readonly<Record<RecordTargetType, string
123
125
  opportunity: 'Opportunity',
124
126
  partnership: 'Partnership',
125
127
  raise: 'Raise',
128
+ enquiry: 'Enquiry',
126
129
  candidate: 'Candidate',
127
130
  }
128
131
 
@@ -142,6 +145,7 @@ export const SEARCH_COLLECTIONS = [
142
145
  'person',
143
146
  'role',
144
147
  'company',
148
+ 'enquiry',
145
149
  'deal',
146
150
  'opportunity',
147
151
  'raise',
@@ -207,16 +211,23 @@ export const INTERVIEW_STAGE_LABELS: Readonly<Record<InterviewStage, string>> =
207
211
  export const FIRST_INTERVIEW_STAGE: InterviewStage = INTERVIEW_STAGES[0]
208
212
 
209
213
  /**
210
- * The four pipelines whose board columns live in `pipeline_stages`. A Deal moves
214
+ * The five pipelines whose board columns live in `pipeline_stages`. A Deal moves
211
215
  * through `deal` stages and so on; the kinds are fixed even though the stages
212
216
  * within each are workspace-configurable.
213
217
  */
214
- export const PIPELINE_KINDS = ['deal', 'opportunity', 'raise', 'partnership'] as const
218
+ export const PIPELINE_KINDS = [
219
+ 'enquiry',
220
+ 'deal',
221
+ 'opportunity',
222
+ 'raise',
223
+ 'partnership',
224
+ ] as const
215
225
 
216
226
  export type PipelineKind = (typeof PIPELINE_KINDS)[number]
217
227
 
218
228
  /** Display names for `PIPELINE_KINDS`. "Fundraising" is what the nav calls a Raise. */
219
229
  export const PIPELINE_KIND_LABELS: Readonly<Record<PipelineKind, string>> = {
230
+ enquiry: 'Enquiry',
220
231
  deal: 'Deal',
221
232
  opportunity: 'Opportunity',
222
233
  raise: 'Fundraising',
@@ -313,24 +324,46 @@ export type FormStatus = (typeof FORM_STATUSES)[number]
313
324
  * uploads, multi-page forms and branching out of scope, and every type here is
314
325
  * one `<input>`, `<textarea>` or `<select>`.
315
326
  */
316
- export const FORM_FIELD_TYPES = ['text', 'email', 'textarea', 'select'] as const
327
+ export const FORM_FIELD_TYPES = ['text', 'email', 'textarea', 'select', 'consent', 'notice'] as const
317
328
 
318
329
  export type FormFieldType = (typeof FORM_FIELD_TYPES)[number]
319
330
 
331
+ /**
332
+ * The field types whose answer is stored as a boolean, not a string. A
333
+ * `consent` field renders as a checkbox whose label carries the consent
334
+ * statement; the answer records whether the visitor ticked it.
335
+ */
336
+ export const FORM_BOOLEAN_FIELD_TYPES = ['consent'] as const
337
+
338
+ export type FormBooleanFieldType = (typeof FORM_BOOLEAN_FIELD_TYPES)[number]
339
+
320
340
  /**
321
341
  * Where a field's answer lands on submit.
322
342
  *
323
343
  * `position.title` rather than a person field, because a job title belongs to the
324
344
  * Person↔Company link and nowhere else. `submission` stores the answer without
325
345
  * writing any CRM record, which is what a free-text "How can we help?" wants.
346
+ *
347
+ * A form asks for a name the way its author wants it asked: one `person.name`
348
+ * box, or the `person.first_name` / `person.last_name` pair most sign-up forms
349
+ * use. Mapping the pair and no `person.name` composes the display name from the
350
+ * two, so neither arrangement makes a nameless person. `salutation` and `suffix`
351
+ * are storable on a Person but are not offered here — a public form asking for
352
+ * them is rare enough that the choice is not worth the room in this list.
326
353
  */
327
354
  export const FORM_FIELD_MAP_TARGETS = [
328
355
  'person.name',
356
+ 'person.first_name',
357
+ 'person.last_name',
329
358
  'person.email',
359
+ 'person.consent',
330
360
  'company.name',
331
361
  'company.domain',
332
362
  'position.title',
363
+ 'enquiry.name',
333
364
  'deal.name',
365
+ 'opportunity.name',
366
+ 'partnership.name',
334
367
  'submission',
335
368
  ] as const
336
369
 
@@ -338,14 +371,23 @@ export type FormFieldMapTarget = (typeof FORM_FIELD_MAP_TARGETS)[number]
338
371
 
339
372
  export const FORM_FIELD_MAP_TARGET_LABELS: Readonly<Record<FormFieldMapTarget, string>> = {
340
373
  'person.name': 'Person · name',
374
+ 'person.first_name': 'Person · first name',
375
+ 'person.last_name': 'Person · last name',
341
376
  'person.email': 'Person · email',
377
+ 'person.consent': 'Person · consent',
342
378
  'company.name': 'Company · name',
343
379
  'company.domain': 'Company · domain',
344
380
  'position.title': 'Position · title',
381
+ 'enquiry.name': 'Enquiry · name',
345
382
  'deal.name': 'Deal · name',
383
+ 'opportunity.name': 'Opportunity · name',
384
+ 'partnership.name': 'Partnership · name',
346
385
  submission: 'Submission only',
347
386
  }
348
387
 
388
+ /** The map target for a consent field. Repeats per purpose, unlike `person.email`. */
389
+ export const PERSON_CONSENT_TARGET: FormFieldMapTarget = 'person.consent'
390
+
349
391
  /** The one mapping a form cannot process without, and may carry at most once. */
350
392
  export const PERSON_EMAIL_TARGET: FormFieldMapTarget = 'person.email'
351
393
 
@@ -359,6 +401,16 @@ export const FORM_OPTION_VALUE_TYPES = ['string', 'number', 'boolean'] as const
359
401
 
360
402
  export type FormOptionValueType = (typeof FORM_OPTION_VALUE_TYPES)[number]
361
403
 
404
+ /**
405
+ * Each post-submit action lands one of these on the submission's `action_log`.
406
+ * `ok` = the action ran; `skipped` = its precondition was absent (a company
407
+ * list on a submit that never resolved one); `error` = the savepoint rolled
408
+ * back so the rest of the submit could continue.
409
+ */
410
+ export const FORM_ACTION_STATUSES = ['ok', 'skipped', 'error'] as const
411
+
412
+ export type FormActionStatus = (typeof FORM_ACTION_STATUSES)[number]
413
+
362
414
  /**
363
415
  * The domain events a webhook can subscribe to.
364
416
  *
@@ -415,6 +467,7 @@ export const AGENT_TASK_TARGET_TYPES = [
415
467
  'opportunity',
416
468
  'partnership',
417
469
  'raise',
470
+ 'enquiry',
418
471
  'candidate',
419
472
  'role',
420
473
  'handbook',
@@ -444,3 +497,116 @@ export const AGENT_RUN_STATUS_LABELS: Readonly<Record<AgentRunStatus, string>> =
444
497
  succeeded: 'Succeeded',
445
498
  failed: 'Failed',
446
499
  }
500
+
501
+ /**
502
+ * The seven record types a workspace may attach custom field definitions to.
503
+ *
504
+ * The ones that already carry `tags` and agent-oriented fields on the record
505
+ * itself. Role and Candidate are absent on purpose: hiring state hangs off the
506
+ * Candidate link and a Role is a header rather than a rich record, so the demand
507
+ * signal for custom fields on either has not landed. Kept separate from
508
+ * `RECORD_TARGET_TYPES` and `EXTENSIBLE_RECORD_TYPES` so a later addition here
509
+ * cannot silently widen either of those.
510
+ */
511
+ export const CUSTOM_FIELD_OBJECT_TYPES = [
512
+ 'person',
513
+ 'company',
514
+ 'deal',
515
+ 'opportunity',
516
+ 'partnership',
517
+ 'raise',
518
+ 'enquiry',
519
+ ] as const
520
+
521
+ export type CustomFieldObjectType = (typeof CUSTOM_FIELD_OBJECT_TYPES)[number]
522
+
523
+ export const CUSTOM_FIELD_OBJECT_TYPE_LABELS: Readonly<Record<CustomFieldObjectType, string>> = {
524
+ person: 'Person',
525
+ company: 'Company',
526
+ deal: 'Deal',
527
+ opportunity: 'Opportunity',
528
+ partnership: 'Partnership',
529
+ raise: 'Raise',
530
+ enquiry: 'Enquiry',
531
+ }
532
+
533
+ /**
534
+ * The nine editor types a custom field can carry.
535
+ *
536
+ * Deliberately distinct from `FORM_FIELD_TYPES`: a form asks a stranger for four
537
+ * kinds of text over one submit; a custom field is a first-class attribute on a
538
+ * record with numeric, date, boolean and currency answers. Sharing one list
539
+ * would drag either surface toward the other's shape.
540
+ *
541
+ * `record_reference` is intentionally absent from v1 — it needs the polymorphic
542
+ * existence check and delete-transaction cleanup that Phase 2 owns.
543
+ */
544
+ export const CUSTOM_FIELD_TYPES = [
545
+ 'text',
546
+ 'long_text',
547
+ 'number',
548
+ 'currency',
549
+ 'date',
550
+ 'checkbox',
551
+ 'select',
552
+ 'multi_select',
553
+ 'url',
554
+ ] as const
555
+
556
+ export type CustomFieldType = (typeof CUSTOM_FIELD_TYPES)[number]
557
+
558
+ export const CUSTOM_FIELD_TYPE_LABELS: Readonly<Record<CustomFieldType, string>> = {
559
+ text: 'Text',
560
+ long_text: 'Long text',
561
+ number: 'Number',
562
+ currency: 'Currency',
563
+ date: 'Date',
564
+ checkbox: 'Checkbox',
565
+ select: 'Select',
566
+ multi_select: 'Multi-select',
567
+ url: 'URL',
568
+ }
569
+
570
+ /**
571
+ * The custom-field types whose definition carries an `options` list. Every
572
+ * other type stores its `options` as `[]` and any non-empty write is `422`.
573
+ */
574
+ export const CUSTOM_FIELD_TYPES_WITH_OPTIONS = ['select', 'multi_select'] as const
575
+
576
+ export type CustomFieldTypeWithOptions = (typeof CUSTOM_FIELD_TYPES_WITH_OPTIONS)[number]
577
+
578
+ /**
579
+ * The default a consent purpose starts with, and what a person without an
580
+ * explicit `person_consents` row inherits for that purpose. `unknown` is the
581
+ * safest default — silence about a person's wishes is not a grant.
582
+ */
583
+ export const CONSENT_PURPOSE_STATUSES = ['unknown', 'granted', 'withdrawn'] as const
584
+
585
+ export type ConsentPurposeStatus = (typeof CONSENT_PURPOSE_STATUSES)[number]
586
+
587
+ export const CONSENT_PURPOSE_STATUS_LABELS: Readonly<Record<ConsentPurposeStatus, string>> = {
588
+ unknown: 'Unknown',
589
+ granted: 'Granted',
590
+ withdrawn: 'Withdrawn',
591
+ }
592
+
593
+ /**
594
+ * The explicit status on a `person_consents` row. `unknown` is deliberately
595
+ * absent: no row is the unknown, so a stored row always carries a decision.
596
+ */
597
+ export const CONSENT_STATUSES = ['granted', 'withdrawn'] as const
598
+
599
+ export type ConsentStatus = (typeof CONSENT_STATUSES)[number]
600
+
601
+ export const CONSENT_STATUS_LABELS: Readonly<Record<ConsentStatus, string>> = {
602
+ granted: 'Granted',
603
+ withdrawn: 'Withdrawn',
604
+ }
605
+
606
+ /**
607
+ * Where a `person_consents` row came from. `form:<form_id>` and `list:<list_id>`
608
+ * are prefixed so the origin is inspectable; `import` and `manual` need no id.
609
+ */
610
+ export const CONSENT_SOURCE_KINDS = ['form', 'list', 'import', 'manual'] as const
611
+
612
+ export type ConsentSourceKind = (typeof CONSENT_SOURCE_KINDS)[number]