@ti-engine/web-framework 1.24.2 → 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,31 @@
|
|
|
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
|
+
|
|
21
|
+
## Version 1.25.0
|
|
22
|
+
|
|
23
|
+
* feat(config-management): surface a `driftTracked` flag on the `getDrift` / `listDrift` payloads, defaulting to
|
|
24
|
+
`true` and set to `false` by a document registering `metadata.driftTracked: false`. Drift compares a stored value
|
|
25
|
+
against the file default shipped in the image, which is meaningful for vendor-shipped product content and
|
|
26
|
+
meaningless for a document holding customer data — that always differs, forever, and would drown a signal that
|
|
27
|
+
otherwise means "a release changed something this deployment is not serving". Consumers now filter on data rather
|
|
28
|
+
than on a hardcoded key list (CA-107)
|
|
29
|
+
|
|
5
30
|
## Version 1.24.2
|
|
6
31
|
|
|
7
32
|
Dependency maintenance only — no framework code changed.
|
|
@@ -800,27 +800,69 @@ const configureApplication = () => {
|
|
|
800
800
|
const tiToolbox = Alpine.store( "tiToolbox" );
|
|
801
801
|
|
|
802
802
|
/**
|
|
803
|
-
*
|
|
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
|
-
* @
|
|
809
|
-
* @returns {String}
|
|
825
|
+
* @returns {String|Object} The resolved value, or {@link LABEL_NOT_FOUND}.
|
|
810
826
|
* @private
|
|
811
827
|
*/
|
|
812
|
-
const
|
|
813
|
-
|
|
814
|
-
|
|
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
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
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
|
|
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
|
/**
|
|
@@ -326,7 +326,7 @@ class ConfigService {
|
|
|
326
326
|
*
|
|
327
327
|
* @method
|
|
328
328
|
* @param {string} configKey
|
|
329
|
-
* @returns {Promise<{configKey: string, status: string, counts: Object, entries: Array, storedVersion: number, editable: boolean, label: string}>}
|
|
329
|
+
* @returns {Promise<{configKey: string, status: string, counts: Object, entries: Array, storedVersion: number, editable: boolean, driftTracked: boolean, label: string}>}
|
|
330
330
|
* @throws {TiException.E_WEB_INVALID_REQUEST_PARAMETERS} If the document is not registered.
|
|
331
331
|
* @public
|
|
332
332
|
*/
|
|
@@ -344,6 +344,7 @@ class ConfigService {
|
|
|
344
344
|
entries: diff.entries,
|
|
345
345
|
storedVersion: current ? current.version : 0,
|
|
346
346
|
editable: metadata.editable !== false,
|
|
347
|
+
driftTracked: metadata.driftTracked !== false,
|
|
347
348
|
label: metadata.label || configKey
|
|
348
349
|
};
|
|
349
350
|
} );
|
|
@@ -367,6 +368,7 @@ class ConfigService {
|
|
|
367
368
|
counts: drift.counts,
|
|
368
369
|
storedVersion: drift.storedVersion,
|
|
369
370
|
editable: drift.editable,
|
|
371
|
+
driftTracked: drift.driftTracked,
|
|
370
372
|
label: drift.label
|
|
371
373
|
} ) );
|
|
372
374
|
} ) );
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ti-engine/web-framework",
|
|
3
|
-
"version": "1.
|
|
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",
|
|
@@ -198,7 +198,7 @@ declare class ConfigService {
|
|
|
198
198
|
*
|
|
199
199
|
* @method
|
|
200
200
|
* @param {string} configKey
|
|
201
|
-
* @returns {Promise<{configKey: string, status: string, counts: Object, entries: Array, storedVersion: number, editable: boolean, label: string}>}
|
|
201
|
+
* @returns {Promise<{configKey: string, status: string, counts: Object, entries: Array, storedVersion: number, editable: boolean, driftTracked: boolean, label: string}>}
|
|
202
202
|
* @throws {TiException.E_WEB_INVALID_REQUEST_PARAMETERS} If the document is not registered.
|
|
203
203
|
* @public
|
|
204
204
|
*/
|
|
@@ -209,6 +209,7 @@ declare class ConfigService {
|
|
|
209
209
|
entries: any[];
|
|
210
210
|
storedVersion: number;
|
|
211
211
|
editable: boolean;
|
|
212
|
+
driftTracked: boolean;
|
|
212
213
|
label: string;
|
|
213
214
|
}>;
|
|
214
215
|
/**
|