@timeax/digital-service-engine 0.3.5 → 0.3.6

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.
@@ -175,7 +175,7 @@ type NodeRef = {
175
175
  };
176
176
  type NodeMap = Map<string, NodeRef>;
177
177
 
178
- type ValidationCode = "root_missing" | "cycle_in_tags" | "bad_bind_reference" | "duplicate_id" | "duplicate_tag_label" | "duplicate_field_name" | "label_missing" | "duplicate_visible_label" | "bad_option_key" | "option_include_exclude_conflict" | "service_field_missing_service_id" | "user_input_field_has_service_option" | "rate_mismatch_across_base" | "rate_coherence_violation" | "utility_without_base" | "unsupported_constraint" | "constraint_contradiction" | "custom_component_missing" | "policy_violation" | "field_unbound" | "constraint_overridden" | "unsupported_constraint_option" | "custom_component_unresolvable" | "quantity_multiple_markers" | "utility_with_service_id" | "utility_missing_rate" | "utility_invalid_mode" | "fallback_bad_node" | "fallback_unknown_service" | "fallback_cycle" | "fallback_no_primary" | "fallback_rate_violation" | "fallback_constraint_mismatch" | "fallback_no_tag_context" | "field_validation_invalid_rule" | "field_validation_invalid_op" | "field_validation_eval_missing_code" | "field_validation_between_missing_bounds" | "field_validation_match_missing_pattern" | "multiple_order_kinds_selected";
178
+ type ValidationCode = "root_missing" | "cycle_in_tags" | "bad_bind_reference" | "duplicate_id" | "duplicate_tag_label" | "duplicate_field_name" | "label_missing" | "duplicate_visible_label" | "bad_option_key" | "bad_option_effect_key" | "bad_option_effect_target" | "bad_option_effect_option" | "option_include_exclude_conflict" | "visibility_dependency_cycle" | "service_field_missing_service_id" | "user_input_field_has_service_option" | "rate_mismatch_across_base" | "rate_coherence_violation" | "utility_without_base" | "unsupported_constraint" | "constraint_contradiction" | "custom_component_missing" | "policy_violation" | "field_unbound" | "constraint_overridden" | "unsupported_constraint_option" | "custom_component_unresolvable" | "quantity_multiple_markers" | "utility_with_service_id" | "utility_missing_rate" | "utility_invalid_mode" | "fallback_bad_node" | "fallback_unknown_service" | "fallback_cycle" | "fallback_no_primary" | "fallback_rate_violation" | "fallback_constraint_mismatch" | "fallback_no_tag_context" | "field_validation_invalid_rule" | "field_validation_invalid_op" | "field_validation_eval_missing_code" | "field_validation_between_missing_bounds" | "field_validation_match_missing_pattern" | "multiple_order_kinds_selected";
179
179
  type ValidationError = {
180
180
  code: ValidationCode;
181
181
  message: string;
@@ -408,6 +408,22 @@ type FieldOption = {
408
408
  service_id?: ServiceIdRef;
409
409
  pricing_role?: PricingRole;
410
410
  meta?: Record<string, unknown> & UtilityMark & WithQuantityDefault;
411
+ children?: FieldOption[];
412
+ };
413
+ type OptionEffectForButton = {
414
+ /**
415
+ * If true, selecting this button/option may force the target field visible.
416
+ * If false/missing, the option filter only applies when the target field is already visible.
417
+ */
418
+ forceVisible?: boolean;
419
+ /**
420
+ * If present, only these option ids remain visible.
421
+ */
422
+ include?: string[];
423
+ /**
424
+ * Removed after include is applied.
425
+ */
426
+ exclude?: string[];
411
427
  };
412
428
  type Field = BaseFieldUI & {
413
429
  id: string;
@@ -461,6 +477,7 @@ type ServiceProps = {
461
477
  fields: Field[];
462
478
  includes_for_buttons?: Record<string, string[]>;
463
479
  excludes_for_buttons?: Record<string, string[]>;
480
+ option_effects_for_buttons?: Record<string, Record<string, OptionEffectForButton>>;
464
481
  schema_version?: string;
465
482
  fallbacks?: ServiceFallback;
466
483
  name?: string;
@@ -535,6 +552,12 @@ declare function validate(props: ServiceProps, ctx?: ValidatorOptions): Validati
535
552
  */
536
553
  declare function validateAsync(props: ServiceProps, ctx?: ValidatorOptions): Promise<ValidationError[]>;
537
554
 
555
+ type ResolvedVisibility = {
556
+ fieldIds: string[];
557
+ optionsByFieldId: Record<string, string[]>;
558
+ forcedFieldIds: string[];
559
+ };
560
+
538
561
  /** Options you can set on the builder (used for validation/visibility) */
539
562
  type BuilderOptions = Omit<ValidatorOptions, "serviceMap"> & {
540
563
  serviceMap?: DgpServiceMap;
@@ -560,6 +583,8 @@ interface Builder {
560
583
  * NOTE: keys are “button ids”: either option.id or field.id for option-less buttons.
561
584
  */
562
585
  visibleFields(tagId: string, selectedOptionKeys?: string[]): string[];
586
+ /** Compute field ids plus option visibility under a tag. */
587
+ resolveVisibility(tagId: string, selectedOptionKeys?: string[]): ResolvedVisibility;
563
588
  /** Update builder options (validator context etc.) */
564
589
  setOptions(patch: Partial<BuilderOptions>): void;
565
590
  /** Access the current props (already normalised) */
@@ -580,6 +605,26 @@ interface Builder {
580
605
  }
581
606
  declare function createBuilder(opts?: BuilderOptions): Builder;
582
607
 
608
+ type OptionVisit = {
609
+ field: Field;
610
+ fieldId: string;
611
+ option: FieldOption;
612
+ optionId: string;
613
+ depth: number;
614
+ parentId?: string;
615
+ };
616
+ declare function walkFieldOptions(field: Field): OptionVisit[];
617
+ declare function walkOptions(props: ServiceProps): OptionVisit[];
618
+ declare function fieldOptionIds(field: Field): string[];
619
+ declare function fieldOptionIdSet(field: Field): Set<string>;
620
+ declare function findFieldOption(field: Field | undefined, optionId: string): FieldOption | undefined;
621
+ declare function findOptionOwnerField(fields: Iterable<Field>, optionId: string): Field | undefined;
622
+ declare function optionOwnerMap(fields: Iterable<Field>): Map<string, {
623
+ fieldId: string;
624
+ option: FieldOption;
625
+ }>;
626
+ declare function filterFieldOptionsById(options: readonly FieldOption[] | undefined, allowed: ReadonlySet<string>): FieldOption[] | undefined;
627
+
583
628
  type FailedFallbackContext = {
584
629
  scope: "node" | "global";
585
630
  nodeId?: string;
@@ -820,10 +865,7 @@ type BuildOrderSelection = {
820
865
  formValuesByFieldId: Record<string, Scalar | Scalar[]>;
821
866
  optionSelectionsByFieldId: Record<string, string[]>;
822
867
  selectedKeys?: string[];
823
- optionTraversalOrder?: Array<{
824
- fieldId: string;
825
- optionId: string;
826
- }>;
868
+ optionTraversalOrder?: string[];
827
869
  };
828
870
 
829
871
  declare function buildOrderSnapshot(props: ServiceProps, builder: Builder, selection: BuildOrderSelection, services: DgpServiceMap, settings?: BuildOrderSnapshotSettings): OrderSnapshot;
@@ -863,4 +905,4 @@ interface FallbackEditor {
863
905
  }
864
906
  declare function createFallbackEditor(options?: FallbackEditorOptions): FallbackEditor;
865
907
 
866
- export { type AncestryHit, type AnyNode, type Builder, type BuilderOptions, type FailedFallbackContext, type FallbackEditor, type FieldNode, type FilterServicesForVisibleGroupInput, type FilterServicesForVisibleGroupResult, type NodeIndex, type NodeKind, type NormaliseOptions, type OptionNode, type RateCoherenceDiagnostic, type RelKind, type ServiceCheck, type TagNode, type TriggerEffectMap, type TriggerEffects, type UnknownNode, type WithAncestry, buildOrderSnapshot, buildTriggerEffectMap, collectFailedFallbacks, createBuilder, createFallbackEditor, createNodeIndex, filterServicesForVisibleGroup, getAssignedServiceIds, getEligibleFallbacks, getFallbackRegistrationInfo, isRefExcludedBySelectedKeys, normalise, normalizeFieldValidation, resolveServiceFallback, validate, validateAsync, validateRateCoherenceDeep };
908
+ export { type AncestryHit, type AnyNode, type Builder, type BuilderOptions, type FailedFallbackContext, type FallbackEditor, type FieldNode, type FilterServicesForVisibleGroupInput, type FilterServicesForVisibleGroupResult, type NodeIndex, type NodeKind, type NormaliseOptions, type OptionNode, type OptionVisit, type RateCoherenceDiagnostic, type RelKind, type ServiceCheck, type TagNode, type TriggerEffectMap, type TriggerEffects, type UnknownNode, type WithAncestry, buildOrderSnapshot, buildTriggerEffectMap, collectFailedFallbacks, createBuilder, createFallbackEditor, createNodeIndex, fieldOptionIdSet, fieldOptionIds, filterFieldOptionsById, filterServicesForVisibleGroup, findFieldOption, findOptionOwnerField, getAssignedServiceIds, getEligibleFallbacks, getFallbackRegistrationInfo, isRefExcludedBySelectedKeys, normalise, normalizeFieldValidation, optionOwnerMap, resolveServiceFallback, validate, validateAsync, validateRateCoherenceDeep, walkFieldOptions, walkOptions };
@@ -175,7 +175,7 @@ type NodeRef = {
175
175
  };
176
176
  type NodeMap = Map<string, NodeRef>;
177
177
 
178
- type ValidationCode = "root_missing" | "cycle_in_tags" | "bad_bind_reference" | "duplicate_id" | "duplicate_tag_label" | "duplicate_field_name" | "label_missing" | "duplicate_visible_label" | "bad_option_key" | "option_include_exclude_conflict" | "service_field_missing_service_id" | "user_input_field_has_service_option" | "rate_mismatch_across_base" | "rate_coherence_violation" | "utility_without_base" | "unsupported_constraint" | "constraint_contradiction" | "custom_component_missing" | "policy_violation" | "field_unbound" | "constraint_overridden" | "unsupported_constraint_option" | "custom_component_unresolvable" | "quantity_multiple_markers" | "utility_with_service_id" | "utility_missing_rate" | "utility_invalid_mode" | "fallback_bad_node" | "fallback_unknown_service" | "fallback_cycle" | "fallback_no_primary" | "fallback_rate_violation" | "fallback_constraint_mismatch" | "fallback_no_tag_context" | "field_validation_invalid_rule" | "field_validation_invalid_op" | "field_validation_eval_missing_code" | "field_validation_between_missing_bounds" | "field_validation_match_missing_pattern" | "multiple_order_kinds_selected";
178
+ type ValidationCode = "root_missing" | "cycle_in_tags" | "bad_bind_reference" | "duplicate_id" | "duplicate_tag_label" | "duplicate_field_name" | "label_missing" | "duplicate_visible_label" | "bad_option_key" | "bad_option_effect_key" | "bad_option_effect_target" | "bad_option_effect_option" | "option_include_exclude_conflict" | "visibility_dependency_cycle" | "service_field_missing_service_id" | "user_input_field_has_service_option" | "rate_mismatch_across_base" | "rate_coherence_violation" | "utility_without_base" | "unsupported_constraint" | "constraint_contradiction" | "custom_component_missing" | "policy_violation" | "field_unbound" | "constraint_overridden" | "unsupported_constraint_option" | "custom_component_unresolvable" | "quantity_multiple_markers" | "utility_with_service_id" | "utility_missing_rate" | "utility_invalid_mode" | "fallback_bad_node" | "fallback_unknown_service" | "fallback_cycle" | "fallback_no_primary" | "fallback_rate_violation" | "fallback_constraint_mismatch" | "fallback_no_tag_context" | "field_validation_invalid_rule" | "field_validation_invalid_op" | "field_validation_eval_missing_code" | "field_validation_between_missing_bounds" | "field_validation_match_missing_pattern" | "multiple_order_kinds_selected";
179
179
  type ValidationError = {
180
180
  code: ValidationCode;
181
181
  message: string;
@@ -408,6 +408,22 @@ type FieldOption = {
408
408
  service_id?: ServiceIdRef;
409
409
  pricing_role?: PricingRole;
410
410
  meta?: Record<string, unknown> & UtilityMark & WithQuantityDefault;
411
+ children?: FieldOption[];
412
+ };
413
+ type OptionEffectForButton = {
414
+ /**
415
+ * If true, selecting this button/option may force the target field visible.
416
+ * If false/missing, the option filter only applies when the target field is already visible.
417
+ */
418
+ forceVisible?: boolean;
419
+ /**
420
+ * If present, only these option ids remain visible.
421
+ */
422
+ include?: string[];
423
+ /**
424
+ * Removed after include is applied.
425
+ */
426
+ exclude?: string[];
411
427
  };
412
428
  type Field = BaseFieldUI & {
413
429
  id: string;
@@ -461,6 +477,7 @@ type ServiceProps = {
461
477
  fields: Field[];
462
478
  includes_for_buttons?: Record<string, string[]>;
463
479
  excludes_for_buttons?: Record<string, string[]>;
480
+ option_effects_for_buttons?: Record<string, Record<string, OptionEffectForButton>>;
464
481
  schema_version?: string;
465
482
  fallbacks?: ServiceFallback;
466
483
  name?: string;
@@ -535,6 +552,12 @@ declare function validate(props: ServiceProps, ctx?: ValidatorOptions): Validati
535
552
  */
536
553
  declare function validateAsync(props: ServiceProps, ctx?: ValidatorOptions): Promise<ValidationError[]>;
537
554
 
555
+ type ResolvedVisibility = {
556
+ fieldIds: string[];
557
+ optionsByFieldId: Record<string, string[]>;
558
+ forcedFieldIds: string[];
559
+ };
560
+
538
561
  /** Options you can set on the builder (used for validation/visibility) */
539
562
  type BuilderOptions = Omit<ValidatorOptions, "serviceMap"> & {
540
563
  serviceMap?: DgpServiceMap;
@@ -560,6 +583,8 @@ interface Builder {
560
583
  * NOTE: keys are “button ids”: either option.id or field.id for option-less buttons.
561
584
  */
562
585
  visibleFields(tagId: string, selectedOptionKeys?: string[]): string[];
586
+ /** Compute field ids plus option visibility under a tag. */
587
+ resolveVisibility(tagId: string, selectedOptionKeys?: string[]): ResolvedVisibility;
563
588
  /** Update builder options (validator context etc.) */
564
589
  setOptions(patch: Partial<BuilderOptions>): void;
565
590
  /** Access the current props (already normalised) */
@@ -580,6 +605,26 @@ interface Builder {
580
605
  }
581
606
  declare function createBuilder(opts?: BuilderOptions): Builder;
582
607
 
608
+ type OptionVisit = {
609
+ field: Field;
610
+ fieldId: string;
611
+ option: FieldOption;
612
+ optionId: string;
613
+ depth: number;
614
+ parentId?: string;
615
+ };
616
+ declare function walkFieldOptions(field: Field): OptionVisit[];
617
+ declare function walkOptions(props: ServiceProps): OptionVisit[];
618
+ declare function fieldOptionIds(field: Field): string[];
619
+ declare function fieldOptionIdSet(field: Field): Set<string>;
620
+ declare function findFieldOption(field: Field | undefined, optionId: string): FieldOption | undefined;
621
+ declare function findOptionOwnerField(fields: Iterable<Field>, optionId: string): Field | undefined;
622
+ declare function optionOwnerMap(fields: Iterable<Field>): Map<string, {
623
+ fieldId: string;
624
+ option: FieldOption;
625
+ }>;
626
+ declare function filterFieldOptionsById(options: readonly FieldOption[] | undefined, allowed: ReadonlySet<string>): FieldOption[] | undefined;
627
+
583
628
  type FailedFallbackContext = {
584
629
  scope: "node" | "global";
585
630
  nodeId?: string;
@@ -820,10 +865,7 @@ type BuildOrderSelection = {
820
865
  formValuesByFieldId: Record<string, Scalar | Scalar[]>;
821
866
  optionSelectionsByFieldId: Record<string, string[]>;
822
867
  selectedKeys?: string[];
823
- optionTraversalOrder?: Array<{
824
- fieldId: string;
825
- optionId: string;
826
- }>;
868
+ optionTraversalOrder?: string[];
827
869
  };
828
870
 
829
871
  declare function buildOrderSnapshot(props: ServiceProps, builder: Builder, selection: BuildOrderSelection, services: DgpServiceMap, settings?: BuildOrderSnapshotSettings): OrderSnapshot;
@@ -863,4 +905,4 @@ interface FallbackEditor {
863
905
  }
864
906
  declare function createFallbackEditor(options?: FallbackEditorOptions): FallbackEditor;
865
907
 
866
- export { type AncestryHit, type AnyNode, type Builder, type BuilderOptions, type FailedFallbackContext, type FallbackEditor, type FieldNode, type FilterServicesForVisibleGroupInput, type FilterServicesForVisibleGroupResult, type NodeIndex, type NodeKind, type NormaliseOptions, type OptionNode, type RateCoherenceDiagnostic, type RelKind, type ServiceCheck, type TagNode, type TriggerEffectMap, type TriggerEffects, type UnknownNode, type WithAncestry, buildOrderSnapshot, buildTriggerEffectMap, collectFailedFallbacks, createBuilder, createFallbackEditor, createNodeIndex, filterServicesForVisibleGroup, getAssignedServiceIds, getEligibleFallbacks, getFallbackRegistrationInfo, isRefExcludedBySelectedKeys, normalise, normalizeFieldValidation, resolveServiceFallback, validate, validateAsync, validateRateCoherenceDeep };
908
+ export { type AncestryHit, type AnyNode, type Builder, type BuilderOptions, type FailedFallbackContext, type FallbackEditor, type FieldNode, type FilterServicesForVisibleGroupInput, type FilterServicesForVisibleGroupResult, type NodeIndex, type NodeKind, type NormaliseOptions, type OptionNode, type OptionVisit, type RateCoherenceDiagnostic, type RelKind, type ServiceCheck, type TagNode, type TriggerEffectMap, type TriggerEffects, type UnknownNode, type WithAncestry, buildOrderSnapshot, buildTriggerEffectMap, collectFailedFallbacks, createBuilder, createFallbackEditor, createNodeIndex, fieldOptionIdSet, fieldOptionIds, filterFieldOptionsById, filterServicesForVisibleGroup, findFieldOption, findOptionOwnerField, getAssignedServiceIds, getEligibleFallbacks, getFallbackRegistrationInfo, isRefExcludedBySelectedKeys, normalise, normalizeFieldValidation, optionOwnerMap, resolveServiceFallback, validate, validateAsync, validateRateCoherenceDeep, walkFieldOptions, walkOptions };