@ti-engine/web-framework 1.25.0 → 1.25.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.
package/CHANGELOG.md CHANGED
@@ -2,6 +2,22 @@
2
2
 
3
3
  This document will contain the list of changes made to the framework. The format is based on the [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/) specification.
4
4
 
5
+ ## Version 1.25.1
6
+
7
+ * fix(ti-framework): resolve a label key whose own name contains a literal dot. `getLabel` split the key on every
8
+ dot and descended one object level per segment, so a group storing flat dotted keys — because the key IS a dotted
9
+ path in the consuming application's domain, e.g. audit-log field labels keyed by employee field path
10
+ (`"personal.workSite"`, `"career.roleFamily"`) — could never be reached. The miss was silent: the caller's
11
+ fallback rendered instead, which is why competence's Employee Management audit tab had shown every changed field
12
+ as its raw field path for as long as those labels have existed. Resolution now tries the longest literal key that
13
+ matches at each level, shortens a segment at a time, and backtracks when a matched branch turns out not to hold
14
+ the rest of the key — so a purely nested catalogue resolves exactly as before, a literal dotted key wins over the
15
+ nested path of the same name, and a genuinely absent key still returns the fallback
16
+ * test(ti-framework): cover `tiApplication.getLabel` against the store the browser actually gets. `ti-framework.js`
17
+ is a plain browser script with no module exports, so `test/helpers/ti-framework-sandbox.js` loads it in a Node
18
+ sandbox, fires `alpine:init` and hands back the registered stores — exercising the shipped resolver rather than
19
+ asserting against its source text, which is what let this defect sit unnoticed
20
+
5
21
  ## Version 1.25.0
6
22
 
7
23
  * feat(config-management): surface a `driftTracked` flag on the `getDrift` / `listDrift` payloads, defaulting to
@@ -800,27 +800,69 @@ const configureApplication = () => {
800
800
  const tiToolbox = Alpine.store( "tiToolbox" );
801
801
 
802
802
  /**
803
- * Used to extract a label from a nested labels object.
803
+ * Marker returned by {@link resolveLabel} when a key is not present in the labels object. A dedicated sentinel
804
+ * rather than `undefined` so that backtracking can never be confused by a stored value.
805
+ *
806
+ * @constant
807
+ * @private
808
+ */
809
+ const LABEL_NOT_FOUND = Object.freeze( {} );
810
+
811
+ /**
812
+ * Resolves a label key against a labels object, trying the longest literal key that matches at each level and
813
+ * shortening on a miss.
814
+ * <br/>
815
+ * A labels catalogue is not always purely nested: a group may store flat keys that themselves contain a dot,
816
+ * because the key IS a dotted path in the application's own domain — competence keys its audit-log field labels
817
+ * by employee field path ("personal.workSite", "career.roleFamily"). Descending exactly one object level per dot
818
+ * can never reach those, and the miss is silent: the caller's fallback renders instead. So each level tries the
819
+ * whole remaining key first, shortens a segment at a time, and backtracks whenever a matched branch turns out
820
+ * not to hold the rest of the key.
804
821
  *
805
822
  * @method
806
823
  * @param {Object} labels
807
824
  * @param {String[]} keys
808
- * @param {String} fallback
809
- * @returns {String}
825
+ * @returns {String|Object} The resolved value, or {@link LABEL_NOT_FOUND}.
810
826
  * @private
811
827
  */
812
- const extractLabel = ( labels, keys, fallback ) => {
813
- let key = keys.shift();
814
- if ( labels && typeof labels === "object" && key && Object.prototype.hasOwnProperty.call( labels, key ) ) {
828
+ const resolveLabel = ( labels, keys ) => {
829
+ if ( !labels || typeof labels !== "object" || keys.length === 0 ) {
830
+ return LABEL_NOT_FOUND;
831
+ }
832
+ for ( let length = keys.length; length > 0; length-- ) {
833
+ const key = keys.slice( 0, length ).join( "." );
834
+ if ( !Object.prototype.hasOwnProperty.call( labels, key ) ) {
835
+ continue;
836
+ }
815
837
  const value = labels[ key ];
838
+ const remainder = keys.slice( length );
816
839
  if ( typeof value === "string" ) {
817
- return keys.length === 0 ? value : fallback;
818
- }
819
- if ( value && typeof value === "object" ) {
820
- return extractLabel( value, keys, fallback );
840
+ if ( remainder.length === 0 ) {
841
+ return value;
842
+ }
843
+ } else if ( value && typeof value === "object" ) {
844
+ const resolved = resolveLabel( value, remainder );
845
+ if ( resolved !== LABEL_NOT_FOUND ) {
846
+ return resolved;
847
+ }
821
848
  }
822
849
  }
823
- return fallback;
850
+ return LABEL_NOT_FOUND;
851
+ };
852
+
853
+ /**
854
+ * Used to extract a label from a nested labels object.
855
+ *
856
+ * @method
857
+ * @param {Object} labels
858
+ * @param {String[]} keys
859
+ * @param {String} fallback
860
+ * @returns {String}
861
+ * @private
862
+ */
863
+ const extractLabel = ( labels, keys, fallback ) => {
864
+ const resolved = resolveLabel( labels, keys );
865
+ return ( typeof resolved === "string" ) ? resolved : fallback;
824
866
  };
825
867
 
826
868
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ti-engine/web-framework",
3
- "version": "1.25.0",
3
+ "version": "1.25.1",
4
4
  "description": "A web-framework based on the ti-engine. It provides a customizable ready-to-use web-server microservice and a set of tools for creating web applications. NOTICE: This is still a work in progress and the full architecture, design, and functionality are not available!",
5
5
  "keywords": [
6
6
  "ti-engine",