@opencrvs/toolkit 2.0.0-rc.fef9d21 → 2.0.0-rc.ff1424b

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 (62) hide show
  1. package/create-countryconfig/index.js +103 -0
  2. package/create-countryconfig/package.json +21 -0
  3. package/dist/application-config/index.js +312 -130
  4. package/dist/cli.js +548 -178
  5. package/dist/commons/api/router.d.ts +3390 -241
  6. package/dist/commons/application-config/index.d.ts +17 -4
  7. package/dist/commons/conditionals/conditionals.d.ts +360 -10
  8. package/dist/commons/conditionals/validate.d.ts +52 -2
  9. package/dist/commons/events/ActionConfig.d.ts +28 -2
  10. package/dist/commons/events/ActionDocument.d.ts +6 -0
  11. package/dist/commons/events/ActionInput.d.ts +114 -0
  12. package/dist/commons/events/AdvancedSearchConfig.d.ts +342 -0
  13. package/dist/commons/events/Draft.d.ts +4 -2
  14. package/dist/commons/events/EventDocument.d.ts +3 -0
  15. package/dist/commons/events/EventIndex.d.ts +0 -3
  16. package/dist/commons/events/EventMetadata.d.ts +0 -7
  17. package/dist/commons/events/FieldConfig.d.ts +388 -50
  18. package/dist/commons/events/FieldType.d.ts +1 -0
  19. package/dist/commons/events/FieldTypeMapping.d.ts +1 -1
  20. package/dist/commons/events/FieldValue.d.ts +6 -0
  21. package/dist/commons/events/WorkqueueConfig.d.ts +150 -150
  22. package/dist/commons/events/field.d.ts +53 -1
  23. package/dist/commons/events/index.d.ts +2 -0
  24. package/dist/commons/events/locations.d.ts +38 -1
  25. package/dist/commons/events/mocks.test.utils.d.ts +19 -0
  26. package/dist/commons/events/scopes.d.ts +24 -1
  27. package/dist/commons/events/state/flags.d.ts +16 -0
  28. package/dist/commons/events/state/index.d.ts +0 -4
  29. package/dist/commons/events/state/utils.d.ts +12 -289
  30. package/dist/commons/events/utils.d.ts +13 -2
  31. package/dist/conditionals/index.js +92 -9
  32. package/dist/events/index.js +1204 -290
  33. package/dist/migrations/v2.0/add-birth-certificate-issuance-flag.d.ts.map +1 -1
  34. package/dist/migrations/v2.0/add-birth-certificate-issuance-flag.js +60 -35
  35. package/dist/migrations/v2.0/checkout-upstream-files.d.ts +1 -1
  36. package/dist/migrations/v2.0/checkout-upstream-files.d.ts.map +1 -1
  37. package/dist/migrations/v2.0/checkout-upstream-files.js +1 -2
  38. package/dist/migrations/v2.0/delete-infrastructure-directory.d.ts +9 -1
  39. package/dist/migrations/v2.0/delete-infrastructure-directory.d.ts.map +1 -1
  40. package/dist/migrations/v2.0/delete-infrastructure-directory.js +66 -20
  41. package/dist/migrations/v2.0/fix-accept-requested-registration-function-type.d.ts +3 -0
  42. package/dist/migrations/v2.0/fix-accept-requested-registration-function-type.d.ts.map +1 -0
  43. package/dist/migrations/v2.0/fix-accept-requested-registration-function-type.js +110 -0
  44. package/dist/migrations/v2.0/index.d.ts +5 -3
  45. package/dist/migrations/v2.0/index.d.ts.map +1 -1
  46. package/dist/migrations/v2.0/index.js +546 -176
  47. package/dist/migrations/v2.0/make-built-in-validate-actions-custom.d.ts.map +1 -1
  48. package/dist/migrations/v2.0/make-built-in-validate-actions-custom.js +90 -1
  49. package/dist/migrations/v2.0/merge-infrastructure-directory.d.ts +11 -1
  50. package/dist/migrations/v2.0/merge-infrastructure-directory.d.ts.map +1 -1
  51. package/dist/migrations/v2.0/merge-infrastructure-directory.js +17 -16
  52. package/dist/migrations/v2.0/migrate-scopes.d.ts.map +1 -1
  53. package/dist/migrations/v2.0/migrate-scopes.js +54 -30
  54. package/dist/migrations/v2.0/migrate-workqueue-configs.d.ts.map +1 -1
  55. package/dist/migrations/v2.0/migrate-workqueue-configs.js +140 -59
  56. package/dist/notification/index.js +936 -162
  57. package/dist/scopes/index.d.ts +91 -16
  58. package/dist/scopes/index.js +55 -12
  59. package/opencrvs-toolkit-2.0.0-rc.ff1424b.tgz +0 -0
  60. package/package.json +6 -2
  61. package/tsconfig.tsbuildinfo +1 -1
  62. package/opencrvs-toolkit-2.0.0-rc.fef9d21.tgz +0 -0
@@ -24,8 +24,14 @@ export declare const ApplicationConfig: z.ZodObject<{
24
24
  label: z.ZodObject<import("./events/TranslationConfig").MessageDescriptorZod, z.core.$strip>;
25
25
  }, z.core.$strip>>;
26
26
  PHONE_NUMBER_PATTERN: z.ZodUnion<[z.ZodString, z.ZodCustom<RegExp, RegExp>]>;
27
- USER_NOTIFICATION_DELIVERY_METHOD: z.ZodString;
28
- INFORMANT_NOTIFICATION_DELIVERY_METHOD: z.ZodString;
27
+ USER_NOTIFICATION_DELIVERY_METHOD: z.ZodEnum<{
28
+ email: "email";
29
+ sms: "sms";
30
+ }>;
31
+ INFORMANT_NOTIFICATION_DELIVERY_METHOD: z.ZodEnum<{
32
+ email: "email";
33
+ sms: "sms";
34
+ }>;
29
35
  SEARCH_DEFAULT_CRITERIA: z.ZodDefault<z.ZodOptional<z.ZodEnum<{
30
36
  NAME: "NAME";
31
37
  EMAIL: "EMAIL";
@@ -46,8 +52,14 @@ export declare const BackgroundConfig: z.ZodObject<{
46
52
  export declare const LoginConfig: z.ZodObject<{
47
53
  COUNTRY: z.ZodString;
48
54
  LANGUAGES: z.ZodArray<z.ZodString>;
49
- USER_NOTIFICATION_DELIVERY_METHOD: z.ZodString;
50
- INFORMANT_NOTIFICATION_DELIVERY_METHOD: z.ZodString;
55
+ USER_NOTIFICATION_DELIVERY_METHOD: z.ZodEnum<{
56
+ email: "email";
57
+ sms: "sms";
58
+ }>;
59
+ INFORMANT_NOTIFICATION_DELIVERY_METHOD: z.ZodEnum<{
60
+ email: "email";
61
+ sms: "sms";
62
+ }>;
51
63
  PHONE_NUMBER_PATTERN: z.ZodUnion<[z.ZodString, z.ZodCustom<RegExp, RegExp>]>;
52
64
  LOGIN_BACKGROUND: z.ZodObject<{
53
65
  backgroundColor: z.ZodOptional<z.ZodString>;
@@ -62,6 +74,7 @@ export declare const ClientConfig: z.ZodObject<{
62
74
  COUNTRY: z.ZodString;
63
75
  LANGUAGES: z.ZodArray<z.ZodString>;
64
76
  SENTRY: z.ZodOptional<z.ZodString>;
77
+ LOGIN_URL: z.ZodOptional<z.ZodString>;
65
78
  REGISTER_BACKGROUND: z.ZodObject<{
66
79
  backgroundColor: z.ZodOptional<z.ZodString>;
67
80
  backgroundImage: z.ZodOptional<z.ZodString>;
@@ -1,12 +1,13 @@
1
1
  import { EventDocument } from '../events/EventDocument';
2
- import { EventState } from '../events/ActionDocument';
2
+ import { ActionUpdate, EventState } from '../events/ActionDocument';
3
3
  import { ITokenPayload as TokenPayload } from '../authentication';
4
4
  import { PartialSchema as AjvJSONSchemaType } from 'ajv/dist/types/json-schema';
5
5
  import { userSerializer } from '../events/serializers/user/serializer';
6
6
  import { UUID } from '../uuid';
7
7
  import { todayDateTimeValueSerializer } from '../events/serializers/date/serializer';
8
8
  import { EventStatus } from '../events/EventMetadata';
9
- import { FieldReference } from '../events/FieldConfig';
9
+ import { CodeToEvaluate, FieldReference } from '../events/FieldConfig';
10
+ import type { ClientFunctionContext } from './validate';
10
11
  /** @knipignore */
11
12
  export type JSONSchema = {
12
13
  $id: string;
@@ -25,7 +26,7 @@ export type EventConditionalParameters = CommonConditionalParameters & {
25
26
  $event: EventDocument;
26
27
  };
27
28
  export type FormConditionalParameters = CommonConditionalParameters & {
28
- $form: EventState | Record<string, unknown>;
29
+ $form: EventState | ActionUpdate;
29
30
  $leafAdminStructureLocationIds?: Array<{
30
31
  id: UUID;
31
32
  }>;
@@ -67,6 +68,12 @@ export declare function not(condition: AjvJSONSchema): JSONSchema;
67
68
  * @returns {JSONSchema} An schema object that always evaluates to false.
68
69
  */
69
70
  export declare function never(): JSONSchema;
71
+ /**
72
+ * Returns an JSON Schema object, which is treated as always valid.
73
+ *
74
+ * @returns {JSONSchema} An schema object that always evaluates to true.
75
+ */
76
+ export declare function always(): JSONSchema;
70
77
  /**
71
78
  * Generate conditional rules for current date
72
79
  */
@@ -86,22 +93,24 @@ export declare const user: typeof userSerializer & {
86
93
  };
87
94
  scope: (scope: import("../scopes").ScopeType) => {
88
95
  attribute: (option: import("../scopes").ScopeOptionKey) => {
89
- $scope: "record.search" | "record.create" | "record.read" | "record.declare" | "record.notify" | "record.edit" | "record.reject" | "record.archive" | "record.review-duplicates" | "record.register" | "record.print-certified-copies" | "record.request-correction" | "record.correct" | "record.unassign-others" | "record.custom-action" | "bypassratelimit" | "record.reindex" | "user.data-seeding" | "integration.create" | "record.import" | "config.update-all" | "attachment.upload" | "profile.electronic-signature" | "user.read-only-my-audit" | "performance.read" | "performance.read-dashboards" | "performance.vital-statistics-export" | "record.confirm-registration" | "record.reject-registration" | "organisation.read-locations" | "user.read" | "user.create" | "user.edit" | "workqueue" | "dashboard.view";
90
- $option: "event" | "placeOfEvent" | "declaredIn" | "declaredBy" | "registeredIn" | "registeredBy" | "accessLevel" | "ids";
96
+ $scope: "record.search" | "record.create" | "record.read" | "record.declare" | "record.notify" | "record.edit" | "record.reject" | "record.archive" | "record.review-duplicates" | "record.register" | "record.print-certified-copies" | "record.request-correction" | "record.correct" | "record.unassign-others" | "record.custom-action" | "bypassratelimit" | "record.reindex" | "user.data-seeding" | "integration.create" | "record.import" | "config.update-all" | "attachment.upload" | "profile.electronic-signature" | "user.read-only-my-audit" | "performance.read" | "performance.read-dashboards" | "performance.vital-statistics-export" | "record.confirm-registration" | "record.reject-registration" | "organisation.read-locations" | "user.read" | "user.create" | "user.edit" | "user.search" | "workqueue" | "dashboard.view";
97
+ $option: "role" | "event" | "placeOfEvent" | "declaredIn" | "declaredBy" | "registeredIn" | "registeredBy" | "accessLevel" | "ids";
91
98
  };
92
99
  };
93
100
  jurisdiction: (jurisdiction: import("../scopes").JurisdictionFilter | {
94
- $scope: "record.search" | "record.create" | "record.read" | "record.declare" | "record.notify" | "record.edit" | "record.reject" | "record.archive" | "record.review-duplicates" | "record.register" | "record.print-certified-copies" | "record.request-correction" | "record.correct" | "record.unassign-others" | "record.custom-action" | "bypassratelimit" | "record.reindex" | "user.data-seeding" | "integration.create" | "record.import" | "config.update-all" | "attachment.upload" | "profile.electronic-signature" | "user.read-only-my-audit" | "performance.read" | "performance.read-dashboards" | "performance.vital-statistics-export" | "record.confirm-registration" | "record.reject-registration" | "organisation.read-locations" | "user.read" | "user.create" | "user.edit" | "workqueue" | "dashboard.view";
95
- $option: "event" | "placeOfEvent" | "declaredIn" | "declaredBy" | "registeredIn" | "registeredBy" | "accessLevel" | "ids";
101
+ $scope: "record.search" | "record.create" | "record.read" | "record.declare" | "record.notify" | "record.edit" | "record.reject" | "record.archive" | "record.review-duplicates" | "record.register" | "record.print-certified-copies" | "record.request-correction" | "record.correct" | "record.unassign-others" | "record.custom-action" | "bypassratelimit" | "record.reindex" | "user.data-seeding" | "integration.create" | "record.import" | "config.update-all" | "attachment.upload" | "profile.electronic-signature" | "user.read-only-my-audit" | "performance.read" | "performance.read-dashboards" | "performance.vital-statistics-export" | "record.confirm-registration" | "record.reject-registration" | "organisation.read-locations" | "user.read" | "user.create" | "user.edit" | "user.search" | "workqueue" | "dashboard.view";
102
+ $option: "role" | "event" | "placeOfEvent" | "declaredIn" | "declaredBy" | "registeredIn" | "registeredBy" | "accessLevel" | "ids";
96
103
  }) => {
97
104
  $jurisdiction: "administrativeArea" | "location" | "all" | {
98
- $scope: "record.search" | "record.create" | "record.read" | "record.declare" | "record.notify" | "record.edit" | "record.reject" | "record.archive" | "record.review-duplicates" | "record.register" | "record.print-certified-copies" | "record.request-correction" | "record.correct" | "record.unassign-others" | "record.custom-action" | "bypassratelimit" | "record.reindex" | "user.data-seeding" | "integration.create" | "record.import" | "config.update-all" | "attachment.upload" | "profile.electronic-signature" | "user.read-only-my-audit" | "performance.read" | "performance.read-dashboards" | "performance.vital-statistics-export" | "record.confirm-registration" | "record.reject-registration" | "organisation.read-locations" | "user.read" | "user.create" | "user.edit" | "workqueue" | "dashboard.view";
99
- $option: "event" | "placeOfEvent" | "declaredIn" | "declaredBy" | "registeredIn" | "registeredBy" | "accessLevel" | "ids";
105
+ $scope: "record.search" | "record.create" | "record.read" | "record.declare" | "record.notify" | "record.edit" | "record.reject" | "record.archive" | "record.review-duplicates" | "record.register" | "record.print-certified-copies" | "record.request-correction" | "record.correct" | "record.unassign-others" | "record.custom-action" | "bypassratelimit" | "record.reindex" | "user.data-seeding" | "integration.create" | "record.import" | "config.update-all" | "attachment.upload" | "profile.electronic-signature" | "user.read-only-my-audit" | "performance.read" | "performance.read-dashboards" | "performance.vital-statistics-export" | "record.confirm-registration" | "record.reject-registration" | "organisation.read-locations" | "user.read" | "user.create" | "user.edit" | "user.search" | "workqueue" | "dashboard.view";
106
+ $option: "role" | "event" | "placeOfEvent" | "declaredIn" | "declaredBy" | "registeredIn" | "registeredBy" | "accessLevel" | "ids";
100
107
  };
101
108
  };
102
109
  };
103
110
  export declare function isFieldReference(value: unknown): value is FieldReference;
104
- export declare function isEventFieldReference(value: unknown): value is FieldReference;
111
+ export declare function isEventFieldReference(value: unknown): value is {
112
+ $$event: string;
113
+ };
105
114
  /** Check if an event flag is present */
106
115
  export declare function flag(flagvalue: string): JSONSchema;
107
116
  /** Check if an event flag is present */
@@ -196,6 +205,37 @@ export declare function createFieldConditionals(fieldId: string): {
196
205
  * )
197
206
  */
198
207
  object: (options: Record<string, any>) => JSONSchema;
208
+ /**
209
+ * Custom client-side validator. The provided function is serialised and executed
210
+ * just-in-time on the client only. External references (e.g. lodash) are not
211
+ * available inside the function body — all logic must be self-contained.
212
+ *
213
+ * @example
214
+ * field('nid').customClientValidator((value) => {
215
+ * // LUHN check — all logic must be inline
216
+ * const digits = String(value).split('').map(Number)
217
+ * // ...
218
+ * return isValid
219
+ * })
220
+ */
221
+ customClientValidator(validationFn: (fieldValue: unknown, context: ClientFunctionContext) => boolean): JSONSchema;
222
+ /**
223
+ * Custom client-side evaluation. Returns a {@link FieldReference} descriptor
224
+ * that can be used as the `value` property or a DATA component entry.
225
+ * The function receives the referenced field's value as the first argument and
226
+ * the full form context as the second; its return value replaces the field reference.
227
+ * The function is serialised and executed just-in-time on the client only.
228
+ * External references (e.g. lodash) are not available inside the function body.
229
+ *
230
+ * For computing a default value without referencing a specific field, use
231
+ * `evaluate(fn)` in the `defaultValue` property instead.
232
+ *
233
+ * @example
234
+ * field('a').customClientEvaluation((aValue, ctx) =>
235
+ * Number(aValue) + Number(ctx.$form.b)
236
+ * )
237
+ */
238
+ customClientEvaluation(computationFn: (fieldValue: unknown, context: ClientFunctionContext) => unknown): CodeToEvaluate;
199
239
  };
200
240
  asDob(): any;
201
241
  asAge(): any;
@@ -255,6 +295,37 @@ export declare function createFieldConditionals(fieldId: string): {
255
295
  * )
256
296
  */
257
297
  object: (options: Record<string, any>) => JSONSchema;
298
+ /**
299
+ * Custom client-side validator. The provided function is serialised and executed
300
+ * just-in-time on the client only. External references (e.g. lodash) are not
301
+ * available inside the function body — all logic must be self-contained.
302
+ *
303
+ * @example
304
+ * field('nid').customClientValidator((value) => {
305
+ * // LUHN check — all logic must be inline
306
+ * const digits = String(value).split('').map(Number)
307
+ * // ...
308
+ * return isValid
309
+ * })
310
+ */
311
+ customClientValidator(validationFn: (fieldValue: unknown, context: ClientFunctionContext) => boolean): JSONSchema;
312
+ /**
313
+ * Custom client-side evaluation. Returns a {@link FieldReference} descriptor
314
+ * that can be used as the `value` property or a DATA component entry.
315
+ * The function receives the referenced field's value as the first argument and
316
+ * the full form context as the second; its return value replaces the field reference.
317
+ * The function is serialised and executed just-in-time on the client only.
318
+ * External references (e.g. lodash) are not available inside the function body.
319
+ *
320
+ * For computing a default value without referencing a specific field, use
321
+ * `evaluate(fn)` in the `defaultValue` property instead.
322
+ *
323
+ * @example
324
+ * field('a').customClientEvaluation((aValue, ctx) =>
325
+ * Number(aValue) + Number(ctx.$form.b)
326
+ * )
327
+ */
328
+ customClientEvaluation(computationFn: (fieldValue: unknown, context: ClientFunctionContext) => unknown): CodeToEvaluate;
258
329
  };
259
330
  getByPath(fieldPath: string[]): {
260
331
  $$subfield: string[];
@@ -328,6 +399,37 @@ export declare function createFieldConditionals(fieldId: string): {
328
399
  * )
329
400
  */
330
401
  object: (options: Record<string, any>) => JSONSchema;
402
+ /**
403
+ * Custom client-side validator. The provided function is serialised and executed
404
+ * just-in-time on the client only. External references (e.g. lodash) are not
405
+ * available inside the function body — all logic must be self-contained.
406
+ *
407
+ * @example
408
+ * field('nid').customClientValidator((value) => {
409
+ * // LUHN check — all logic must be inline
410
+ * const digits = String(value).split('').map(Number)
411
+ * // ...
412
+ * return isValid
413
+ * })
414
+ */
415
+ customClientValidator(validationFn: (fieldValue: unknown, context: ClientFunctionContext) => boolean): JSONSchema;
416
+ /**
417
+ * Custom client-side evaluation. Returns a {@link FieldReference} descriptor
418
+ * that can be used as the `value` property or a DATA component entry.
419
+ * The function receives the referenced field's value as the first argument and
420
+ * the full form context as the second; its return value replaces the field reference.
421
+ * The function is serialised and executed just-in-time on the client only.
422
+ * External references (e.g. lodash) are not available inside the function body.
423
+ *
424
+ * For computing a default value without referencing a specific field, use
425
+ * `evaluate(fn)` in the `defaultValue` property instead.
426
+ *
427
+ * @example
428
+ * field('a').customClientEvaluation((aValue, ctx) =>
429
+ * Number(aValue) + Number(ctx.$form.b)
430
+ * )
431
+ */
432
+ customClientEvaluation(computationFn: (fieldValue: unknown, context: ClientFunctionContext) => unknown): CodeToEvaluate;
331
433
  };
332
434
  getByPath(fieldPath: string[]): any;
333
435
  asDob(): {
@@ -396,6 +498,37 @@ export declare function createFieldConditionals(fieldId: string): {
396
498
  * )
397
499
  */
398
500
  object: (options: Record<string, any>) => JSONSchema;
501
+ /**
502
+ * Custom client-side validator. The provided function is serialised and executed
503
+ * just-in-time on the client only. External references (e.g. lodash) are not
504
+ * available inside the function body — all logic must be self-contained.
505
+ *
506
+ * @example
507
+ * field('nid').customClientValidator((value) => {
508
+ * // LUHN check — all logic must be inline
509
+ * const digits = String(value).split('').map(Number)
510
+ * // ...
511
+ * return isValid
512
+ * })
513
+ */
514
+ customClientValidator(validationFn: (fieldValue: unknown, context: ClientFunctionContext) => boolean): JSONSchema;
515
+ /**
516
+ * Custom client-side evaluation. Returns a {@link FieldReference} descriptor
517
+ * that can be used as the `value` property or a DATA component entry.
518
+ * The function receives the referenced field's value as the first argument and
519
+ * the full form context as the second; its return value replaces the field reference.
520
+ * The function is serialised and executed just-in-time on the client only.
521
+ * External references (e.g. lodash) are not available inside the function body.
522
+ *
523
+ * For computing a default value without referencing a specific field, use
524
+ * `evaluate(fn)` in the `defaultValue` property instead.
525
+ *
526
+ * @example
527
+ * field('a').customClientEvaluation((aValue, ctx) =>
528
+ * Number(aValue) + Number(ctx.$form.b)
529
+ * )
530
+ */
531
+ customClientEvaluation(computationFn: (fieldValue: unknown, context: ClientFunctionContext) => unknown): CodeToEvaluate;
399
532
  };
400
533
  asAge(): {
401
534
  $$subfield: string[];
@@ -463,6 +596,37 @@ export declare function createFieldConditionals(fieldId: string): {
463
596
  * )
464
597
  */
465
598
  object: (options: Record<string, any>) => JSONSchema;
599
+ /**
600
+ * Custom client-side validator. The provided function is serialised and executed
601
+ * just-in-time on the client only. External references (e.g. lodash) are not
602
+ * available inside the function body — all logic must be self-contained.
603
+ *
604
+ * @example
605
+ * field('nid').customClientValidator((value) => {
606
+ * // LUHN check — all logic must be inline
607
+ * const digits = String(value).split('').map(Number)
608
+ * // ...
609
+ * return isValid
610
+ * })
611
+ */
612
+ customClientValidator(validationFn: (fieldValue: unknown, context: ClientFunctionContext) => boolean): JSONSchema;
613
+ /**
614
+ * Custom client-side evaluation. Returns a {@link FieldReference} descriptor
615
+ * that can be used as the `value` property or a DATA component entry.
616
+ * The function receives the referenced field's value as the first argument and
617
+ * the full form context as the second; its return value replaces the field reference.
618
+ * The function is serialised and executed just-in-time on the client only.
619
+ * External references (e.g. lodash) are not available inside the function body.
620
+ *
621
+ * For computing a default value without referencing a specific field, use
622
+ * `evaluate(fn)` in the `defaultValue` property instead.
623
+ *
624
+ * @example
625
+ * field('a').customClientEvaluation((aValue, ctx) =>
626
+ * Number(aValue) + Number(ctx.$form.b)
627
+ * )
628
+ */
629
+ customClientEvaluation(computationFn: (fieldValue: unknown, context: ClientFunctionContext) => unknown): CodeToEvaluate;
466
630
  };
467
631
  isAfter(): {
468
632
  days: (days: number) => {
@@ -520,6 +684,37 @@ export declare function createFieldConditionals(fieldId: string): {
520
684
  * )
521
685
  */
522
686
  object: (options: Record<string, any>) => JSONSchema;
687
+ /**
688
+ * Custom client-side validator. The provided function is serialised and executed
689
+ * just-in-time on the client only. External references (e.g. lodash) are not
690
+ * available inside the function body — all logic must be self-contained.
691
+ *
692
+ * @example
693
+ * field('nid').customClientValidator((value) => {
694
+ * // LUHN check — all logic must be inline
695
+ * const digits = String(value).split('').map(Number)
696
+ * // ...
697
+ * return isValid
698
+ * })
699
+ */
700
+ customClientValidator(validationFn: (fieldValue: unknown, context: ClientFunctionContext) => boolean): JSONSchema;
701
+ /**
702
+ * Custom client-side evaluation. Returns a {@link FieldReference} descriptor
703
+ * that can be used as the `value` property or a DATA component entry.
704
+ * The function receives the referenced field's value as the first argument and
705
+ * the full form context as the second; its return value replaces the field reference.
706
+ * The function is serialised and executed just-in-time on the client only.
707
+ * External references (e.g. lodash) are not available inside the function body.
708
+ *
709
+ * For computing a default value without referencing a specific field, use
710
+ * `evaluate(fn)` in the `defaultValue` property instead.
711
+ *
712
+ * @example
713
+ * field('a').customClientEvaluation((aValue, ctx) =>
714
+ * Number(aValue) + Number(ctx.$form.b)
715
+ * )
716
+ */
717
+ customClientEvaluation(computationFn: (fieldValue: unknown, context: ClientFunctionContext) => unknown): CodeToEvaluate;
523
718
  };
524
719
  asDob(): {
525
720
  $$subfield: string[];
@@ -594,6 +789,37 @@ export declare function createFieldConditionals(fieldId: string): {
594
789
  * )
595
790
  */
596
791
  object: (options: Record<string, any>) => JSONSchema;
792
+ /**
793
+ * Custom client-side validator. The provided function is serialised and executed
794
+ * just-in-time on the client only. External references (e.g. lodash) are not
795
+ * available inside the function body — all logic must be self-contained.
796
+ *
797
+ * @example
798
+ * field('nid').customClientValidator((value) => {
799
+ * // LUHN check — all logic must be inline
800
+ * const digits = String(value).split('').map(Number)
801
+ * // ...
802
+ * return isValid
803
+ * })
804
+ */
805
+ customClientValidator(validationFn: (fieldValue: unknown, context: ClientFunctionContext) => boolean): JSONSchema;
806
+ /**
807
+ * Custom client-side evaluation. Returns a {@link FieldReference} descriptor
808
+ * that can be used as the `value` property or a DATA component entry.
809
+ * The function receives the referenced field's value as the first argument and
810
+ * the full form context as the second; its return value replaces the field reference.
811
+ * The function is serialised and executed just-in-time on the client only.
812
+ * External references (e.g. lodash) are not available inside the function body.
813
+ *
814
+ * For computing a default value without referencing a specific field, use
815
+ * `evaluate(fn)` in the `defaultValue` property instead.
816
+ *
817
+ * @example
818
+ * field('a').customClientEvaluation((aValue, ctx) =>
819
+ * Number(aValue) + Number(ctx.$form.b)
820
+ * )
821
+ */
822
+ customClientEvaluation(computationFn: (fieldValue: unknown, context: ClientFunctionContext) => unknown): CodeToEvaluate;
597
823
  };
598
824
  asDob(): any;
599
825
  asAge(): any;
@@ -653,6 +879,37 @@ export declare function createFieldConditionals(fieldId: string): {
653
879
  * )
654
880
  */
655
881
  object: (options: Record<string, any>) => JSONSchema;
882
+ /**
883
+ * Custom client-side validator. The provided function is serialised and executed
884
+ * just-in-time on the client only. External references (e.g. lodash) are not
885
+ * available inside the function body — all logic must be self-contained.
886
+ *
887
+ * @example
888
+ * field('nid').customClientValidator((value) => {
889
+ * // LUHN check — all logic must be inline
890
+ * const digits = String(value).split('').map(Number)
891
+ * // ...
892
+ * return isValid
893
+ * })
894
+ */
895
+ customClientValidator(validationFn: (fieldValue: unknown, context: ClientFunctionContext) => boolean): JSONSchema;
896
+ /**
897
+ * Custom client-side evaluation. Returns a {@link FieldReference} descriptor
898
+ * that can be used as the `value` property or a DATA component entry.
899
+ * The function receives the referenced field's value as the first argument and
900
+ * the full form context as the second; its return value replaces the field reference.
901
+ * The function is serialised and executed just-in-time on the client only.
902
+ * External references (e.g. lodash) are not available inside the function body.
903
+ *
904
+ * For computing a default value without referencing a specific field, use
905
+ * `evaluate(fn)` in the `defaultValue` property instead.
906
+ *
907
+ * @example
908
+ * field('a').customClientEvaluation((aValue, ctx) =>
909
+ * Number(aValue) + Number(ctx.$form.b)
910
+ * )
911
+ */
912
+ customClientEvaluation(computationFn: (fieldValue: unknown, context: ClientFunctionContext) => unknown): CodeToEvaluate;
656
913
  };
657
914
  asAge(): {
658
915
  $$subfield: string[];
@@ -727,6 +984,37 @@ export declare function createFieldConditionals(fieldId: string): {
727
984
  * )
728
985
  */
729
986
  object: (options: Record<string, any>) => JSONSchema;
987
+ /**
988
+ * Custom client-side validator. The provided function is serialised and executed
989
+ * just-in-time on the client only. External references (e.g. lodash) are not
990
+ * available inside the function body — all logic must be self-contained.
991
+ *
992
+ * @example
993
+ * field('nid').customClientValidator((value) => {
994
+ * // LUHN check — all logic must be inline
995
+ * const digits = String(value).split('').map(Number)
996
+ * // ...
997
+ * return isValid
998
+ * })
999
+ */
1000
+ customClientValidator(validationFn: (fieldValue: unknown, context: ClientFunctionContext) => boolean): JSONSchema;
1001
+ /**
1002
+ * Custom client-side evaluation. Returns a {@link FieldReference} descriptor
1003
+ * that can be used as the `value` property or a DATA component entry.
1004
+ * The function receives the referenced field's value as the first argument and
1005
+ * the full form context as the second; its return value replaces the field reference.
1006
+ * The function is serialised and executed just-in-time on the client only.
1007
+ * External references (e.g. lodash) are not available inside the function body.
1008
+ *
1009
+ * For computing a default value without referencing a specific field, use
1010
+ * `evaluate(fn)` in the `defaultValue` property instead.
1011
+ *
1012
+ * @example
1013
+ * field('a').customClientEvaluation((aValue, ctx) =>
1014
+ * Number(aValue) + Number(ctx.$form.b)
1015
+ * )
1016
+ */
1017
+ customClientEvaluation(computationFn: (fieldValue: unknown, context: ClientFunctionContext) => unknown): CodeToEvaluate;
730
1018
  };
731
1019
  asDob(): any;
732
1020
  asAge(): any;
@@ -786,6 +1074,37 @@ export declare function createFieldConditionals(fieldId: string): {
786
1074
  * )
787
1075
  */
788
1076
  object: (options: Record<string, any>) => JSONSchema;
1077
+ /**
1078
+ * Custom client-side validator. The provided function is serialised and executed
1079
+ * just-in-time on the client only. External references (e.g. lodash) are not
1080
+ * available inside the function body — all logic must be self-contained.
1081
+ *
1082
+ * @example
1083
+ * field('nid').customClientValidator((value) => {
1084
+ * // LUHN check — all logic must be inline
1085
+ * const digits = String(value).split('').map(Number)
1086
+ * // ...
1087
+ * return isValid
1088
+ * })
1089
+ */
1090
+ customClientValidator(validationFn: (fieldValue: unknown, context: ClientFunctionContext) => boolean): JSONSchema;
1091
+ /**
1092
+ * Custom client-side evaluation. Returns a {@link FieldReference} descriptor
1093
+ * that can be used as the `value` property or a DATA component entry.
1094
+ * The function receives the referenced field's value as the first argument and
1095
+ * the full form context as the second; its return value replaces the field reference.
1096
+ * The function is serialised and executed just-in-time on the client only.
1097
+ * External references (e.g. lodash) are not available inside the function body.
1098
+ *
1099
+ * For computing a default value without referencing a specific field, use
1100
+ * `evaluate(fn)` in the `defaultValue` property instead.
1101
+ *
1102
+ * @example
1103
+ * field('a').customClientEvaluation((aValue, ctx) =>
1104
+ * Number(aValue) + Number(ctx.$form.b)
1105
+ * )
1106
+ */
1107
+ customClientEvaluation(computationFn: (fieldValue: unknown, context: ClientFunctionContext) => unknown): CodeToEvaluate;
789
1108
  };
790
1109
  isAfter(): {
791
1110
  days: (days: number) => {
@@ -843,6 +1162,37 @@ export declare function createFieldConditionals(fieldId: string): {
843
1162
  * )
844
1163
  */
845
1164
  object: (options: Record<string, any>) => JSONSchema;
1165
+ /**
1166
+ * Custom client-side validator. The provided function is serialised and executed
1167
+ * just-in-time on the client only. External references (e.g. lodash) are not
1168
+ * available inside the function body — all logic must be self-contained.
1169
+ *
1170
+ * @example
1171
+ * field('nid').customClientValidator((value) => {
1172
+ * // LUHN check — all logic must be inline
1173
+ * const digits = String(value).split('').map(Number)
1174
+ * // ...
1175
+ * return isValid
1176
+ * })
1177
+ */
1178
+ customClientValidator(validationFn: (fieldValue: unknown, context: ClientFunctionContext) => boolean): JSONSchema;
1179
+ /**
1180
+ * Custom client-side evaluation. Returns a {@link FieldReference} descriptor
1181
+ * that can be used as the `value` property or a DATA component entry.
1182
+ * The function receives the referenced field's value as the first argument and
1183
+ * the full form context as the second; its return value replaces the field reference.
1184
+ * The function is serialised and executed just-in-time on the client only.
1185
+ * External references (e.g. lodash) are not available inside the function body.
1186
+ *
1187
+ * For computing a default value without referencing a specific field, use
1188
+ * `evaluate(fn)` in the `defaultValue` property instead.
1189
+ *
1190
+ * @example
1191
+ * field('a').customClientEvaluation((aValue, ctx) =>
1192
+ * Number(aValue) + Number(ctx.$form.b)
1193
+ * )
1194
+ */
1195
+ customClientEvaluation(computationFn: (fieldValue: unknown, context: ClientFunctionContext) => unknown): CodeToEvaluate;
846
1196
  };
847
1197
  export {};
848
1198
  //# sourceMappingURL=conditionals.d.ts.map
@@ -12,6 +12,54 @@ import { ActionType } from '../events/ActionType';
12
12
  import { EventConfig } from '../events/EventConfig';
13
13
  import { EventDocument } from '../events/EventDocument';
14
14
  import { EventIndex } from '../events/EventIndex';
15
+ import { Location } from '../events/locations';
16
+ import { SystemVariables } from '../events/TemplateConfig';
17
+ /** Returns today's date as an ISO date string (YYYY-MM-DD). */
18
+ export declare function todayISO(): string;
19
+ /**
20
+ * Context passed to every serialised client-side function ({@link runClientFunction}).
21
+ *
22
+ * `$user` (full {@link ITokenPayload}, validator paths) and `user` (a
23
+ * {@link SystemVariables} subset for template substitution, default-value
24
+ * path) are distinct sources, not duplicates.
25
+ */
26
+ export type ClientFunctionContext = {
27
+ $form: EventState | ActionUpdate;
28
+ $now: string;
29
+ $online: boolean;
30
+ $user?: ITokenPayload;
31
+ $event?: EventDocument;
32
+ $leafAdminStructureLocationIds: Array<{
33
+ id: UUID;
34
+ }>;
35
+ user?: SystemVariables['user'];
36
+ $window?: SystemVariables['$window'];
37
+ locations?: Location[];
38
+ adminLevelIds?: string[];
39
+ $flags?: string[];
40
+ $status?: string;
41
+ };
42
+ type CompiledClientFunction = (data: FieldValue | undefined, context: ClientFunctionContext) => unknown;
43
+ /**
44
+ * Deserialises a serialised function string (produced by `.toString()`) into a callable.
45
+ * Results are cached by code string so each unique function body is compiled at most once.
46
+ * Runs in a clean scope — no access to outer closures or external imports.
47
+ */
48
+ export declare function compileClientFunction(code: string): CompiledClientFunction;
49
+ export declare function buildClientFunctionContext(input: {
50
+ form: EventState | ActionUpdate;
51
+ validatorContext?: ValidatorContext;
52
+ systemVariables?: SystemVariables;
53
+ /**
54
+ * In real use cases, there can be hundreds of thousands of locations.
55
+ * Make sure that the context contains only the locations that are needed for validation.
56
+ * E.g. if the user is a leaf admin, only the leaf locations under their admin structure are needed.
57
+ * Loading few megabytes of locations to memory just for validation is not efficient and will choke the application.
58
+ */
59
+ locations?: Location[];
60
+ adminLevelIds?: string[];
61
+ }): ClientFunctionContext;
62
+ export declare function runClientFunction(code: string, data: FieldValue | undefined, context: ClientFunctionContext): unknown;
15
63
  /**
16
64
  * Precompiles action conditional schemas from the event configurations to improve performance of condition validation later on.
17
65
  * Best called once on application startup before any condition validation is done.
@@ -20,14 +68,15 @@ export declare function precompileActionSchemas(eventConfigurations: EventConfig
20
68
  export declare function validate(schema: JSONSchema, data: ConditionalParameters): boolean;
21
69
  export declare function validateValue(schema: JSONSchema, data: unknown): boolean;
22
70
  export declare function isOnline(): boolean;
23
- export declare function isConditionMet(conditional: JSONSchema, values: EventState | ActionUpdate, context: ValidatorContext, eventIndex?: EventIndex): boolean;
24
- export declare function areConditionsMet(conditions: FieldConditional[], values: Record<string, FieldValue>, context: ValidatorContext, event: EventIndex): boolean;
71
+ export declare function isConditionMet(conditional: JSONSchema, values: EventState | ActionUpdate, context: ValidatorContext): boolean;
72
+ export declare function areConditionsMet(conditions: FieldConditional[], values: Record<string, FieldValue>, context: ValidatorContext, _event: EventIndex): boolean;
25
73
  export type ValidatorContext = {
26
74
  user?: ITokenPayload;
27
75
  leafAdminStructureLocationIds?: Array<{
28
76
  id: UUID;
29
77
  }>;
30
78
  event?: EventDocument;
79
+ baseFormState?: EventState;
31
80
  };
32
81
  export declare function isFieldVisible(field: FieldConfig, form: Partial<ActionUpdate | EventState>, context: ValidatorContext): boolean;
33
82
  export declare function isFieldEnabled(field: FieldConfig, form: ActionUpdate | EventState, context: ValidatorContext): boolean;
@@ -112,4 +161,5 @@ export declare function runFieldValidations({ field: config, form, value, contex
112
161
  }>>;
113
162
  export declare function getValidatorsForField(fieldId: FieldConfig['id'], validations: NonNullable<FieldConfig['validation']>): NonNullable<FieldConfig['validation']>;
114
163
  export declare function areCertificateConditionsMet(conditions: FieldConditional[], values: ConditionalParameters): boolean;
164
+ export {};
115
165
  //# sourceMappingURL=validate.d.ts.map
@@ -85,6 +85,32 @@ export declare const ActionConfig: z.ZodDiscriminatedUnion<[z.ZodObject<{
85
85
  fields: z.ZodArray<z.ZodType<FieldConfig, import("./FieldConfig").FieldConfigInput, z.core.$ZodTypeInternals<FieldConfig, import("./FieldConfig").FieldConfigInput>>>;
86
86
  }, z.core.$strip>;
87
87
  conditionals: z.ZodOptional<z.ZodNever>;
88
+ }, z.core.$strip>, z.ZodObject<{
89
+ label: z.ZodObject<import("./TranslationConfig").MessageDescriptorZod, z.core.$strip>;
90
+ flags: z.ZodDefault<z.ZodOptional<z.ZodArray<z.ZodObject<{
91
+ id: z.ZodUnion<[z.ZodUnion<[z.ZodString, z.ZodEnum<{
92
+ readonly INCOMPLETE: "incomplete";
93
+ readonly REJECTED: "rejected";
94
+ readonly CORRECTION_REQUESTED: "correction-requested";
95
+ readonly POTENTIAL_DUPLICATE: "potential-duplicate";
96
+ readonly EDIT_IN_PROGRESS: "edit-in-progress";
97
+ }>]>, z.ZodString]>;
98
+ operation: z.ZodEnum<{
99
+ add: "add";
100
+ remove: "remove";
101
+ }>;
102
+ conditional: z.ZodOptional<z.ZodAny>;
103
+ }, z.core.$strip>>>>;
104
+ supportingCopy: z.ZodOptional<z.ZodObject<import("./TranslationConfig").MessageDescriptorZod, z.core.$strip>>;
105
+ icon: z.ZodOptional<z.ZodString>;
106
+ conditionals: z.ZodOptional<z.ZodArray<z.ZodDiscriminatedUnion<[z.ZodObject<{
107
+ type: z.ZodLiteral<"SHOW">;
108
+ conditional: z.ZodAny;
109
+ }, z.core.$strip>, z.ZodObject<{
110
+ type: z.ZodLiteral<"ENABLE">;
111
+ conditional: z.ZodAny;
112
+ }, z.core.$strip>], "type">>>;
113
+ type: z.ZodLiteral<"NOTIFY">;
88
114
  }, z.core.$strip>, z.ZodObject<{
89
115
  label: z.ZodObject<import("./TranslationConfig").MessageDescriptorZod, z.core.$strip>;
90
116
  flags: z.ZodDefault<z.ZodOptional<z.ZodArray<z.ZodObject<{
@@ -388,8 +414,8 @@ export declare const actionConfigTypes: Set<ActionConfigTypes>;
388
414
  *
389
415
  * These are not the same as the broader workflow `action.type` values.
390
416
  * `ActionConfigTypes` includes only the action kinds that can be defined
391
- * in the country configuration (e.g. DECLARE, VALIDATE, CUSTOM), and
392
- * excludes workflow-only types such as CREATE or NOTIFY.
417
+ * in the country configuration (e.g. NOTIFY, DECLARE, VALIDATE, CUSTOM), and
418
+ * excludes workflow-only types such as CREATE.
393
419
  */
394
420
  export type ActionConfigTypes = ActionConfig['type'];
395
421
  export declare const DeclarationActionConfig: z.ZodDiscriminatedUnion<[z.ZodObject<{