@timeax/digital-service-engine 0.2.0 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -112,6 +112,11 @@ type ValidatorOptions = {
112
112
  selectedOptionKeys?: string[];
113
113
  globalUtilityGuard?: boolean;
114
114
  policies?: DynamicRule[];
115
+ /**
116
+ * Global/base rate policy used by validation and service filtering.
117
+ * This is intentionally separate from fallbackSettings.ratePolicy.
118
+ */
119
+ ratePolicy?: RatePolicy;
115
120
  fallbackSettings?: FallbackSettings;
116
121
  };
117
122
  type RatePolicy = {
@@ -380,6 +385,7 @@ interface Builder {
380
385
  getProps(): ServiceProps;
381
386
  /** Service map for validation/rules */
382
387
  getServiceMap(): DgpServiceMap;
388
+ getOptions(): BuilderOptions;
383
389
  getConstraints(): {
384
390
  id: string;
385
391
  label: string;
@@ -1832,6 +1838,9 @@ declare class Editor {
1832
1838
  usedServiceIds: Array<number | string>;
1833
1839
  effectiveConstraints?: Partial<Record<"refill" | "cancel" | "dripfeed", boolean>>;
1834
1840
  policies?: unknown;
1841
+ ratePolicy?: RatePolicy;
1842
+ fallbackSettings?: FallbackSettings;
1843
+ /** Backward-compatible alias */
1835
1844
  fallback?: FallbackSettings;
1836
1845
  }): ServiceCheck[];
1837
1846
  private moduleCtx;
@@ -1908,6 +1917,8 @@ type CanvasProviderWorkspaceProps = {
1908
1917
  children: ReactNode;
1909
1918
  builderOpts?: BuilderOptions;
1910
1919
  canvasOpts?: CanvasOptions & CanvasBackendOptions;
1920
+ ratePolicy?: RatePolicy;
1921
+ fallbackSettings?: FallbackSettings;
1911
1922
  attachToWorkspace?: boolean;
1912
1923
  };
1913
1924
  type CanvasProviderProps = CanvasProviderManagedProps | CanvasProviderWorkspaceProps;
@@ -2244,6 +2255,10 @@ interface WorkspaceProps {
2244
2255
  readonly autosaveMs?: WorkspaceProviderProps["autosaveMs"];
2245
2256
  /** Auto-run autosave when dirty (default true) */
2246
2257
  readonly autoAutosave?: WorkspaceProviderProps["autoAutosave"];
2258
+ /** Global/base rate policy (separate from fallbackSettings.ratePolicy). */
2259
+ readonly ratePolicy?: RatePolicy;
2260
+ /** Fallback flow settings. */
2261
+ readonly fallbackSettings?: FallbackSettings;
2247
2262
  readonly tools?: ToolsConfig;
2248
2263
  readonly children: (tools?: ToolsConfig) => React.ReactNode;
2249
2264
  }
@@ -112,6 +112,11 @@ type ValidatorOptions = {
112
112
  selectedOptionKeys?: string[];
113
113
  globalUtilityGuard?: boolean;
114
114
  policies?: DynamicRule[];
115
+ /**
116
+ * Global/base rate policy used by validation and service filtering.
117
+ * This is intentionally separate from fallbackSettings.ratePolicy.
118
+ */
119
+ ratePolicy?: RatePolicy;
115
120
  fallbackSettings?: FallbackSettings;
116
121
  };
117
122
  type RatePolicy = {
@@ -380,6 +385,7 @@ interface Builder {
380
385
  getProps(): ServiceProps;
381
386
  /** Service map for validation/rules */
382
387
  getServiceMap(): DgpServiceMap;
388
+ getOptions(): BuilderOptions;
383
389
  getConstraints(): {
384
390
  id: string;
385
391
  label: string;
@@ -1832,6 +1838,9 @@ declare class Editor {
1832
1838
  usedServiceIds: Array<number | string>;
1833
1839
  effectiveConstraints?: Partial<Record<"refill" | "cancel" | "dripfeed", boolean>>;
1834
1840
  policies?: unknown;
1841
+ ratePolicy?: RatePolicy;
1842
+ fallbackSettings?: FallbackSettings;
1843
+ /** Backward-compatible alias */
1835
1844
  fallback?: FallbackSettings;
1836
1845
  }): ServiceCheck[];
1837
1846
  private moduleCtx;
@@ -1908,6 +1917,8 @@ type CanvasProviderWorkspaceProps = {
1908
1917
  children: ReactNode;
1909
1918
  builderOpts?: BuilderOptions;
1910
1919
  canvasOpts?: CanvasOptions & CanvasBackendOptions;
1920
+ ratePolicy?: RatePolicy;
1921
+ fallbackSettings?: FallbackSettings;
1911
1922
  attachToWorkspace?: boolean;
1912
1923
  };
1913
1924
  type CanvasProviderProps = CanvasProviderManagedProps | CanvasProviderWorkspaceProps;
@@ -2244,6 +2255,10 @@ interface WorkspaceProps {
2244
2255
  readonly autosaveMs?: WorkspaceProviderProps["autosaveMs"];
2245
2256
  /** Auto-run autosave when dirty (default true) */
2246
2257
  readonly autoAutosave?: WorkspaceProviderProps["autoAutosave"];
2258
+ /** Global/base rate policy (separate from fallbackSettings.ratePolicy). */
2259
+ readonly ratePolicy?: RatePolicy;
2260
+ /** Fallback flow settings. */
2261
+ readonly fallbackSettings?: FallbackSettings;
2247
2262
  readonly tools?: ToolsConfig;
2248
2263
  readonly children: (tools?: ToolsConfig) => React.ReactNode;
2249
2264
  }
@@ -4721,15 +4721,13 @@ function rateOk(svcMap, candidate, primary, policy) {
4721
4721
 
4722
4722
  // src/core/validate/steps/rates.ts
4723
4723
  function validateRates(v) {
4724
- var _a, _b, _c, _d;
4725
- const ratePolicy = normalizeRatePolicy(
4726
- (_a = v.options.fallbackSettings) == null ? void 0 : _a.ratePolicy
4727
- );
4724
+ var _a, _b, _c;
4725
+ const ratePolicy = normalizeRatePolicy(v.options.ratePolicy);
4728
4726
  for (const f of v.fields) {
4729
4727
  if (!isMultiField(f)) continue;
4730
4728
  const baseRates = [];
4731
- for (const o of (_b = f.options) != null ? _b : []) {
4732
- const role = (_d = (_c = o.pricing_role) != null ? _c : f.pricing_role) != null ? _d : "base";
4729
+ for (const o of (_a = f.options) != null ? _a : []) {
4730
+ const role = (_c = (_b = o.pricing_role) != null ? _b : f.pricing_role) != null ? _c : "base";
4733
4731
  if (role !== "base") continue;
4734
4732
  const sid = o.service_id;
4735
4733
  if (!isServiceIdRef(sid)) continue;
@@ -5503,6 +5501,38 @@ function applyPolicies(errors, props, serviceMap, policies, fieldsVisibleUnder,
5503
5501
  }
5504
5502
  }
5505
5503
 
5504
+ // src/core/governance.ts
5505
+ var DEFAULT_FALLBACK_SETTINGS = {
5506
+ requireConstraintFit: true,
5507
+ ratePolicy: { kind: "lte_primary", pct: 5 },
5508
+ selectionStrategy: "priority",
5509
+ mode: "strict"
5510
+ };
5511
+ function resolveGlobalRatePolicy(options) {
5512
+ return normalizeRatePolicy(options.ratePolicy);
5513
+ }
5514
+ function resolveFallbackSettings(options) {
5515
+ var _a;
5516
+ return {
5517
+ ...DEFAULT_FALLBACK_SETTINGS,
5518
+ ...(_a = options.fallbackSettings) != null ? _a : {}
5519
+ };
5520
+ }
5521
+ function mergeValidatorOptions(defaults = {}, overrides = {}) {
5522
+ var _a, _b, _c, _d;
5523
+ const mergedFallbackSettings = {
5524
+ ...(_a = defaults.fallbackSettings) != null ? _a : {},
5525
+ ...(_b = overrides.fallbackSettings) != null ? _b : {}
5526
+ };
5527
+ return {
5528
+ ...defaults,
5529
+ ...overrides,
5530
+ policies: (_c = overrides.policies) != null ? _c : defaults.policies,
5531
+ ratePolicy: (_d = overrides.ratePolicy) != null ? _d : defaults.ratePolicy,
5532
+ fallbackSettings: Object.keys(mergedFallbackSettings).length > 0 ? mergedFallbackSettings : void 0
5533
+ };
5534
+ }
5535
+
5506
5536
  // src/core/builder.ts
5507
5537
  import { cloneDeep as cloneDeep2 } from "lodash-es";
5508
5538
  function createBuilder(opts = {}) {
@@ -5745,7 +5775,7 @@ var BuilderImpl = class {
5745
5775
  return out;
5746
5776
  }
5747
5777
  errors() {
5748
- return validate(this.props, this.options);
5778
+ return validate(this.props, mergeValidatorOptions({}, this.options));
5749
5779
  }
5750
5780
  getOptions() {
5751
5781
  return cloneDeep2(this.options);
@@ -6032,11 +6062,14 @@ function readVisibilitySimOpts(ctx) {
6032
6062
  };
6033
6063
  }
6034
6064
  function validate(props, ctx = {}) {
6035
- var _a, _b, _c, _d;
6065
+ var _a, _b, _c;
6066
+ const options = mergeValidatorOptions({}, ctx);
6067
+ const fallbackSettings = resolveFallbackSettings(options);
6068
+ const ratePolicy = resolveGlobalRatePolicy(options);
6036
6069
  const errors = [];
6037
- const serviceMap = (_a = ctx.serviceMap) != null ? _a : {};
6070
+ const serviceMap = (_a = options.serviceMap) != null ? _a : {};
6038
6071
  const selectedKeys = new Set(
6039
- (_b = ctx.selectedOptionKeys) != null ? _b : []
6072
+ (_b = options.selectedOptionKeys) != null ? _b : []
6040
6073
  );
6041
6074
  const tags = Array.isArray(props.filters) ? props.filters : [];
6042
6075
  const fields = Array.isArray(props.fields) ? props.fields : [];
@@ -6046,8 +6079,12 @@ function validate(props, ctx = {}) {
6046
6079
  for (const f of fields) fieldById.set(f.id, f);
6047
6080
  const v = {
6048
6081
  props,
6049
- nodeMap: (_c = ctx.nodeMap) != null ? _c : buildNodeMap(props),
6050
- options: ctx,
6082
+ nodeMap: (_c = options.nodeMap) != null ? _c : buildNodeMap(props),
6083
+ options: {
6084
+ ...options,
6085
+ ratePolicy,
6086
+ fallbackSettings
6087
+ },
6051
6088
  errors,
6052
6089
  serviceMap,
6053
6090
  selectedKeys,
@@ -6062,7 +6099,7 @@ function validate(props, ctx = {}) {
6062
6099
  validateIdentity(v);
6063
6100
  validateOptionMaps(v);
6064
6101
  v.fieldsVisibleUnder = createFieldsVisibleUnder(v);
6065
- const visSim = readVisibilitySimOpts(ctx);
6102
+ const visSim = readVisibilitySimOpts(options);
6066
6103
  validateVisibility(v, visSim);
6067
6104
  applyPolicies(
6068
6105
  v.errors,
@@ -6083,7 +6120,7 @@ function validate(props, ctx = {}) {
6083
6120
  builder,
6084
6121
  services: serviceMap,
6085
6122
  tagId: tag.id,
6086
- ratePolicy: (_d = ctx.fallbackSettings) == null ? void 0 : _d.ratePolicy,
6123
+ ratePolicy,
6087
6124
  invalidFieldIds: v.invalidRateFieldIds
6088
6125
  });
6089
6126
  for (const diag of diags) {
@@ -6652,18 +6689,23 @@ function createNodeIndex(builder) {
6652
6689
 
6653
6690
  // src/core/service-filter.ts
6654
6691
  function filterServicesForVisibleGroup(input, deps) {
6655
- var _a, _b, _c, _d, _e, _f;
6692
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k;
6656
6693
  const svcMap = (_c = (_b = (_a = deps.builder).getServiceMap) == null ? void 0 : _b.call(_a)) != null ? _c : {};
6694
+ const builderOptions = (_e = (_d = deps.builder).getOptions) == null ? void 0 : _e.call(_d);
6657
6695
  const { context } = input;
6658
6696
  const usedSet = new Set(context.usedServiceIds.map(String));
6659
6697
  const primary = context.usedServiceIds[0];
6698
+ const explicitFallbackSettings = (_f = context.fallbackSettings) != null ? _f : context.fallback;
6699
+ const resolvedRatePolicy = normalizeRatePolicy(
6700
+ (_h = (_g = context.ratePolicy) != null ? _g : explicitFallbackSettings == null ? void 0 : explicitFallbackSettings.ratePolicy) != null ? _h : builderOptions == null ? void 0 : builderOptions.ratePolicy
6701
+ );
6702
+ const fallbackSettingsSource = explicitFallbackSettings != null ? explicitFallbackSettings : builderOptions == null ? void 0 : builderOptions.fallbackSettings;
6660
6703
  const fb = {
6661
- requireConstraintFit: true,
6662
- ratePolicy: { kind: "lte_primary", pct: 5 },
6663
- selectionStrategy: "priority",
6664
- mode: "strict",
6665
- ...(_d = context.fallback) != null ? _d : {}
6704
+ ...DEFAULT_FALLBACK_SETTINGS,
6705
+ ...fallbackSettingsSource != null ? fallbackSettingsSource : {},
6706
+ ratePolicy: resolvedRatePolicy
6666
6707
  };
6708
+ const policySource = (_j = (_i = context.policies) != null ? _i : builderOptions == null ? void 0 : builderOptions.policies) != null ? _j : [];
6667
6709
  const visibleServiceIds = context.selectedButtons === void 0 ? void 0 : collectVisibleServiceIds(
6668
6710
  deps.builder,
6669
6711
  context.tagId,
@@ -6688,11 +6730,11 @@ function filterServicesForVisibleGroup(input, deps) {
6688
6730
  const fitsConstraints = constraintFitOk(
6689
6731
  svcMap,
6690
6732
  cap.id,
6691
- (_e = context.effectiveConstraints) != null ? _e : {}
6733
+ (_k = context.effectiveConstraints) != null ? _k : {}
6692
6734
  );
6693
6735
  const passesRate2 = primary == null ? true : rateOk(svcMap, id, primary, fb);
6694
6736
  const polRes = evaluatePoliciesRaw(
6695
- (_f = context.policies) != null ? _f : [],
6737
+ policySource,
6696
6738
  [...context.usedServiceIds, id],
6697
6739
  svcMap,
6698
6740
  context.tagId,
@@ -8376,6 +8418,8 @@ function filterServicesForVisibleGroup2(ctx, candidates, input) {
8376
8418
  usedServiceIds: input.usedServiceIds,
8377
8419
  effectiveConstraints: input.effectiveConstraints,
8378
8420
  policies: input.policies,
8421
+ ratePolicy: input.ratePolicy,
8422
+ fallbackSettings: input.fallbackSettings,
8379
8423
  fallback: input.fallback
8380
8424
  }
8381
8425
  };
@@ -9797,6 +9841,8 @@ function CanvasProviderWorkspaceRuntime({
9797
9841
  children,
9798
9842
  builderOpts,
9799
9843
  canvasOpts,
9844
+ ratePolicy,
9845
+ fallbackSettings,
9800
9846
  attachToWorkspace = true
9801
9847
  }) {
9802
9848
  const ws = useWorkspaceMaybe();
@@ -9815,11 +9861,23 @@ function CanvasProviderWorkspaceRuntime({
9815
9861
  const resolvedBuilderOpts = useMemo13(() => {
9816
9862
  const svc = ws.services.data;
9817
9863
  const hasMap = svc != null && typeof svc === "object" && !Array.isArray(svc);
9818
- return hasMap ? {
9864
+ const policies = ws.policies.policies.data;
9865
+ return {
9819
9866
  ...builderOpts != null ? builderOpts : {},
9820
- serviceMap: svc
9821
- } : builderOpts;
9822
- }, [builderOpts, ws.services.data]);
9867
+ ...hasMap ? {
9868
+ serviceMap: svc
9869
+ } : {},
9870
+ policies: policies != null ? policies : void 0,
9871
+ ratePolicy: ratePolicy != null ? ratePolicy : builderOpts == null ? void 0 : builderOpts.ratePolicy,
9872
+ fallbackSettings: fallbackSettings != null ? fallbackSettings : builderOpts == null ? void 0 : builderOpts.fallbackSettings
9873
+ };
9874
+ }, [
9875
+ builderOpts,
9876
+ fallbackSettings,
9877
+ ratePolicy,
9878
+ ws.policies.policies.data,
9879
+ ws.services.data
9880
+ ]);
9823
9881
  if (canMountCanvas) {
9824
9882
  hasMountedOnceRef.current = true;
9825
9883
  }
@@ -10157,7 +10215,7 @@ function useCanvasOwned(initialProps, canvasOpts, builderOpts) {
10157
10215
  } else if (((_a = window.SITE) == null ? void 0 : _a.env) !== "production") {
10158
10216
  if (builderOptsRef.current !== builderOpts) {
10159
10217
  console.warn(
10160
- "[useCanvasOwned] builderOpts changed after init; new values are ignored. If you need to recreate the builder, remount the hook (e.g. change a React key)."
10218
+ "[useCanvasOwned] builderOpts changed after init. Reactive keys (serviceMap/policies/ratePolicy/fallbackSettings/selectedOptionKeys) are applied via setOptions(); other keys may still require remounting to fully reinitialize."
10161
10219
  );
10162
10220
  builderOptsRef.current = builderOpts;
10163
10221
  }
@@ -10169,6 +10227,23 @@ function useCanvasOwned(initialProps, canvasOpts, builderOpts) {
10169
10227
  loadedOnceRef.current = true;
10170
10228
  }
10171
10229
  }, [initialProps]);
10230
+ useEffect7(() => {
10231
+ if (!builderOpts) return;
10232
+ builder.setOptions({
10233
+ serviceMap: builderOpts.serviceMap,
10234
+ policies: builderOpts.policies,
10235
+ ratePolicy: builderOpts.ratePolicy,
10236
+ fallbackSettings: builderOpts.fallbackSettings,
10237
+ selectedOptionKeys: builderOpts.selectedOptionKeys
10238
+ });
10239
+ }, [
10240
+ builder,
10241
+ builderOpts == null ? void 0 : builderOpts.fallbackSettings,
10242
+ builderOpts == null ? void 0 : builderOpts.policies,
10243
+ builderOpts == null ? void 0 : builderOpts.ratePolicy,
10244
+ builderOpts == null ? void 0 : builderOpts.selectedOptionKeys,
10245
+ builderOpts == null ? void 0 : builderOpts.serviceMap
10246
+ ]);
10172
10247
  const lastCanvasOptsRef = useRef6();
10173
10248
  const stableCanvasOpts = useMemo13(() => {
10174
10249
  var _a2;
@@ -10494,18 +10569,18 @@ function useErrors(opts = {}) {
10494
10569
  setValidating(true);
10495
10570
  schedule(
10496
10571
  () => {
10497
- var _a2, _b2;
10572
+ var _a2, _b2, _c2, _d2, _e2;
10498
10573
  if (token !== runTokenRef.current) return;
10499
10574
  try {
10500
10575
  const props = api.editor.getProps();
10501
- const res = validate(props);
10576
+ const res = validate(props, (_c2 = (_b2 = (_a2 = api.builder).getOptions) == null ? void 0 : _b2.call(_a2)) != null ? _c2 : {});
10502
10577
  if (token !== runTokenRef.current) return;
10503
10578
  setValidation(toValidationRows(res != null ? res : []));
10504
10579
  } catch (err) {
10505
10580
  if (token !== runTokenRef.current) return;
10506
10581
  pushLog({
10507
- message: (_a2 = err == null ? void 0 : err.message) != null ? _a2 : "validate() threw",
10508
- code: (_b2 = err == null ? void 0 : err.code) != null ? _b2 : "validate_throw",
10582
+ message: (_d2 = err == null ? void 0 : err.message) != null ? _d2 : "validate() threw",
10583
+ code: (_e2 = err == null ? void 0 : err.code) != null ? _e2 : "validate_throw",
10509
10584
  meta: err
10510
10585
  });
10511
10586
  setValidation([]);
@@ -11967,6 +12042,8 @@ function Workspace(props) {
11967
12042
  liveDebounceMs,
11968
12043
  autosaveMs,
11969
12044
  autoAutosave,
12045
+ ratePolicy,
12046
+ fallbackSettings,
11970
12047
  tools,
11971
12048
  children
11972
12049
  } = props;
@@ -11982,7 +12059,14 @@ function Workspace(props) {
11982
12059
  liveDebounceMs,
11983
12060
  autosaveMs,
11984
12061
  autoAutosave,
11985
- children: /* @__PURE__ */ jsx3(CanvasProvider, { children: children(tools) })
12062
+ children: /* @__PURE__ */ jsx3(
12063
+ CanvasProvider,
12064
+ {
12065
+ ratePolicy,
12066
+ fallbackSettings,
12067
+ children: children(tools)
12068
+ }
12069
+ )
11986
12070
  }
11987
12071
  );
11988
12072
  }