@uniformdev/canvas 19.35.2 → 19.35.3-alpha.82
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/dist/index.d.mts +9349 -0
- package/dist/index.d.ts +1137 -105
- package/dist/index.esm.js +231 -84
- package/dist/index.js +238 -87
- package/dist/index.mjs +231 -84
- package/package.json +3 -3
package/dist/index.js
CHANGED
@@ -283,7 +283,7 @@ __export(src_exports, {
|
|
283
283
|
ATTRIBUTE_PARAMETER_TYPE: () => ATTRIBUTE_PARAMETER_TYPE,
|
284
284
|
ATTRIBUTE_PARAMETER_VALUE: () => ATTRIBUTE_PARAMETER_VALUE,
|
285
285
|
ATTRIBUTE_PLACEHOLDER: () => ATTRIBUTE_PLACEHOLDER,
|
286
|
-
ApiClientError: () =>
|
286
|
+
ApiClientError: () => import_api7.ApiClientError,
|
287
287
|
BatchEntry: () => BatchEntry,
|
288
288
|
CANVAS_DRAFT_STATE: () => CANVAS_DRAFT_STATE,
|
289
289
|
CANVAS_ENRICHMENT_TAG_PARAM: () => CANVAS_ENRICHMENT_TAG_PARAM,
|
@@ -300,6 +300,7 @@ __export(src_exports, {
|
|
300
300
|
CANVAS_TEST_VARIANT_PARAM: () => CANVAS_TEST_VARIANT_PARAM,
|
301
301
|
CanvasClient: () => CanvasClient,
|
302
302
|
CanvasClientError: () => CanvasClientError,
|
303
|
+
CategoryClient: () => CategoryClient,
|
303
304
|
ChildEnhancerBuilder: () => ChildEnhancerBuilder,
|
304
305
|
DataSourceClient: () => DataSourceClient,
|
305
306
|
DataTypeClient: () => DataTypeClient,
|
@@ -320,6 +321,7 @@ __export(src_exports, {
|
|
320
321
|
PLACEHOLDER_ID: () => PLACEHOLDER_ID,
|
321
322
|
RouteClient: () => RouteClient,
|
322
323
|
UncachedCanvasClient: () => UncachedCanvasClient,
|
324
|
+
UncachedCategoryClient: () => UncachedCategoryClient,
|
323
325
|
UniqueBatchEntries: () => UniqueBatchEntries,
|
324
326
|
bindVariables: () => bindVariables,
|
325
327
|
bindVariablesToObject: () => bindVariablesToObject,
|
@@ -329,6 +331,7 @@ __export(src_exports, {
|
|
329
331
|
createEventBus: () => createEventBus,
|
330
332
|
createLimitPolicy: () => createLimitPolicy,
|
331
333
|
createUniformApiEnhancer: () => createUniformApiEnhancer,
|
334
|
+
createVariableReference: () => createVariableReference,
|
332
335
|
enhance: () => enhance,
|
333
336
|
extractLocales: () => extractLocales,
|
334
337
|
generateHash: () => generateHash,
|
@@ -354,6 +357,7 @@ __export(src_exports, {
|
|
354
357
|
mapSlotToPersonalizedVariations: () => mapSlotToPersonalizedVariations,
|
355
358
|
mapSlotToTestVariations: () => mapSlotToTestVariations,
|
356
359
|
nullLimitPolicy: () => nullLimitPolicy,
|
360
|
+
parseVariableExpression: () => parseVariableExpression,
|
357
361
|
subscribeToComposition: () => subscribeToComposition,
|
358
362
|
unstable_CompositionRelationshipClient: () => unstable_CompositionRelationshipClient,
|
359
363
|
walkComponentTree: () => walkComponentTree
|
@@ -649,10 +653,53 @@ var UncachedCanvasClient = class extends CanvasClient {
|
|
649
653
|
}
|
650
654
|
};
|
651
655
|
|
652
|
-
// src/
|
656
|
+
// src/CategoryClient.ts
|
653
657
|
var import_api2 = require("@uniformdev/context/api");
|
658
|
+
var CATEGORIES_URL = "/api/v1/categories";
|
659
|
+
var CategoryClient = class extends import_api2.ApiClient {
|
660
|
+
constructor(options) {
|
661
|
+
if (!options.limitPolicy) {
|
662
|
+
options.limitPolicy = createLimitPolicy({});
|
663
|
+
}
|
664
|
+
super(options);
|
665
|
+
}
|
666
|
+
/** Fetches all categories created in given project */
|
667
|
+
async getCategories(options) {
|
668
|
+
const { projectId } = this.options;
|
669
|
+
const fetchUri = this.createUrl("/api/v1/categories", { ...options, projectId });
|
670
|
+
return await this.apiClient(fetchUri);
|
671
|
+
}
|
672
|
+
/** Updates or creates a category, also used to re-order them */
|
673
|
+
async upsertCategories(categories) {
|
674
|
+
const { projectId } = this.options;
|
675
|
+
const fetchUri = this.createUrl(CATEGORIES_URL);
|
676
|
+
return await this.apiClient(fetchUri, {
|
677
|
+
method: "PUT",
|
678
|
+
body: JSON.stringify({ categories, projectId }),
|
679
|
+
expectNoContent: true
|
680
|
+
});
|
681
|
+
}
|
682
|
+
/** Deletes a category */
|
683
|
+
async removeCategory(options) {
|
684
|
+
const { projectId } = this.options;
|
685
|
+
const fetchUri = this.createUrl(CATEGORIES_URL);
|
686
|
+
return await this.apiClient(fetchUri, {
|
687
|
+
method: "DELETE",
|
688
|
+
body: JSON.stringify({ projectId, categoryId: options.categoryId }),
|
689
|
+
expectNoContent: true
|
690
|
+
});
|
691
|
+
}
|
692
|
+
};
|
693
|
+
var UncachedCategoryClient = class extends CategoryClient {
|
694
|
+
constructor(options) {
|
695
|
+
super({ ...options, bypassCache: true });
|
696
|
+
}
|
697
|
+
};
|
698
|
+
|
699
|
+
// src/CompositionRelationshipClient.ts
|
700
|
+
var import_api3 = require("@uniformdev/context/api");
|
654
701
|
var COMPOSITION_RELATIONSHIP_URL = "/api/v1/composition-relationships";
|
655
|
-
var unstable_CompositionRelationshipClient = class extends
|
702
|
+
var unstable_CompositionRelationshipClient = class extends import_api3.ApiClient {
|
656
703
|
constructor(options) {
|
657
704
|
super(options);
|
658
705
|
this.getDefinitionsRelationships = async ({
|
@@ -713,10 +760,10 @@ var unstable_CompositionRelationshipClient = class extends import_api2.ApiClient
|
|
713
760
|
};
|
714
761
|
|
715
762
|
// src/DataSourceClient.ts
|
716
|
-
var
|
763
|
+
var import_api4 = require("@uniformdev/context/api");
|
717
764
|
var dataSourceUrl = "/api/v1/data-source";
|
718
765
|
var dataSourcesUrl = "/api/v1/data-sources";
|
719
|
-
var DataSourceClient = class extends
|
766
|
+
var DataSourceClient = class extends import_api4.ApiClient {
|
720
767
|
constructor(options) {
|
721
768
|
super(options);
|
722
769
|
}
|
@@ -753,9 +800,9 @@ var DataSourceClient = class extends import_api3.ApiClient {
|
|
753
800
|
};
|
754
801
|
|
755
802
|
// src/DataTypeClient.ts
|
756
|
-
var
|
803
|
+
var import_api5 = require("@uniformdev/context/api");
|
757
804
|
var _url;
|
758
|
-
var _DataTypeClient = class _DataTypeClient extends
|
805
|
+
var _DataTypeClient = class _DataTypeClient extends import_api5.ApiClient {
|
759
806
|
constructor(options) {
|
760
807
|
super(options);
|
761
808
|
}
|
@@ -1672,9 +1719,9 @@ function subscribeToComposition({
|
|
1672
1719
|
}
|
1673
1720
|
|
1674
1721
|
// src/RouteClient.ts
|
1675
|
-
var
|
1722
|
+
var import_api6 = require("@uniformdev/context/api");
|
1676
1723
|
var ROUTE_URL = "/api/v1/route";
|
1677
|
-
var RouteClient = class extends
|
1724
|
+
var RouteClient = class extends import_api6.ApiClient {
|
1678
1725
|
constructor(options) {
|
1679
1726
|
var _a;
|
1680
1727
|
if (!options.limitPolicy) {
|
@@ -1691,80 +1738,6 @@ var RouteClient = class extends import_api5.ApiClient {
|
|
1691
1738
|
}
|
1692
1739
|
};
|
1693
1740
|
|
1694
|
-
// src/utils/bindVariables.ts
|
1695
|
-
function bindVariables({
|
1696
|
-
variables,
|
1697
|
-
value,
|
1698
|
-
errorPrefix = "Variable",
|
1699
|
-
handleBinding
|
1700
|
-
}) {
|
1701
|
-
let boundCount = 0;
|
1702
|
-
const errors = [];
|
1703
|
-
const defaultHandleBinding = (variableName, variables2, errors2) => {
|
1704
|
-
const variableValue = variables2[variableName];
|
1705
|
-
if (variableValue === void 0) {
|
1706
|
-
errors2.push(`${errorPrefix} "${variableName}" is not defined`);
|
1707
|
-
return "";
|
1708
|
-
}
|
1709
|
-
return variableValue;
|
1710
|
-
};
|
1711
|
-
const result = value.replace(/(?<!\\)\${([^}]+)}/g, (_match, variableName) => {
|
1712
|
-
const variableValue = (handleBinding != null ? handleBinding : defaultHandleBinding)(variableName, variables, errors);
|
1713
|
-
boundCount++;
|
1714
|
-
return variableValue;
|
1715
|
-
});
|
1716
|
-
return { result, boundCount, errors: errors.length > 0 ? errors : void 0 };
|
1717
|
-
}
|
1718
|
-
|
1719
|
-
// src/utils/bindVariablesToObject.ts
|
1720
|
-
var import_immer = require("immer");
|
1721
|
-
function bindVariablesToObject(options) {
|
1722
|
-
return bindVariablesToObjectRecursive(options);
|
1723
|
-
}
|
1724
|
-
function bindVariablesToObjectRecursive({
|
1725
|
-
value,
|
1726
|
-
recursivePath,
|
1727
|
-
...bindVariablesOptions
|
1728
|
-
}) {
|
1729
|
-
let boundCount = 0;
|
1730
|
-
const errors = [];
|
1731
|
-
if (typeof value === "string") {
|
1732
|
-
return bindVariables({ ...bindVariablesOptions, value });
|
1733
|
-
}
|
1734
|
-
if (typeof value !== "object" || value === null) {
|
1735
|
-
return { boundCount: 0, result: value };
|
1736
|
-
}
|
1737
|
-
const result = (0, import_immer.produce)(value, (draft) => {
|
1738
|
-
Object.entries(draft).forEach(([property, oldValue]) => {
|
1739
|
-
const currentObjectPath = recursivePath ? `${recursivePath}.${property}` : property;
|
1740
|
-
if (typeof oldValue === "string") {
|
1741
|
-
const bindResult = bindVariables({ ...bindVariablesOptions, value: oldValue });
|
1742
|
-
if (oldValue !== bindResult.result || bindResult.errors) {
|
1743
|
-
boundCount += bindResult.boundCount;
|
1744
|
-
draft[property] = bindResult.result;
|
1745
|
-
if (bindResult.errors) {
|
1746
|
-
errors.push(...bindResult.errors.map((e) => `${currentObjectPath}: ${e}`));
|
1747
|
-
}
|
1748
|
-
}
|
1749
|
-
return;
|
1750
|
-
}
|
1751
|
-
const childBind = bindVariablesToObjectRecursive({
|
1752
|
-
...bindVariablesOptions,
|
1753
|
-
value: oldValue,
|
1754
|
-
recursivePath: currentObjectPath
|
1755
|
-
});
|
1756
|
-
if (childBind.boundCount || childBind.errors) {
|
1757
|
-
boundCount += childBind.boundCount;
|
1758
|
-
draft[property] = childBind.result;
|
1759
|
-
if (childBind.errors) {
|
1760
|
-
errors.push(...childBind.errors.map((e) => `${currentObjectPath}: ${e}`));
|
1761
|
-
}
|
1762
|
-
}
|
1763
|
-
});
|
1764
|
-
});
|
1765
|
-
return { boundCount, result, errors: errors.length > 0 ? errors : void 0 };
|
1766
|
-
}
|
1767
|
-
|
1768
1741
|
// src/utils/createApiEnhancer.ts
|
1769
1742
|
var createUniformApiEnhancer = ({ apiUrl }) => {
|
1770
1743
|
return async (message) => {
|
@@ -1812,8 +1785,8 @@ var getParameterAttributes = ({
|
|
1812
1785
|
[ATTRIBUTE_PARAMETER_VALUE]: String(value != null ? value : ""),
|
1813
1786
|
[ATTRIBUTE_PARAMETER_TYPE]: type,
|
1814
1787
|
[ATTRIBUTE_PLACEHOLDER]: placeholder,
|
1815
|
-
[ATTRIBUTE_MULTILINE]: isMultiline,
|
1816
|
-
contentEditable: isEditable
|
1788
|
+
[ATTRIBUTE_MULTILINE]: type === "text" ? isMultiline : void 0,
|
1789
|
+
contentEditable: type === "text" ? isEditable : void 0
|
1817
1790
|
};
|
1818
1791
|
};
|
1819
1792
|
|
@@ -1854,9 +1827,183 @@ function mapSlotToTestVariations(slot) {
|
|
1854
1827
|
});
|
1855
1828
|
}
|
1856
1829
|
|
1830
|
+
// src/utils/variables/parseVariableExpression.ts
|
1831
|
+
var escapeCharacter = "\\";
|
1832
|
+
var variablePrefix = "${";
|
1833
|
+
var variableSuffix = "}";
|
1834
|
+
function parseVariableExpression(serialized, onToken) {
|
1835
|
+
let bufferStartIndex = 0;
|
1836
|
+
let bufferEndIndex = 0;
|
1837
|
+
let tokenCount = 0;
|
1838
|
+
const handleToken = (token, type) => {
|
1839
|
+
tokenCount++;
|
1840
|
+
return onToken == null ? void 0 : onToken(token, type);
|
1841
|
+
};
|
1842
|
+
let state = "text";
|
1843
|
+
for (let index = 0; index < serialized.length; index++) {
|
1844
|
+
const char = serialized[index];
|
1845
|
+
if (bufferStartIndex > bufferEndIndex) {
|
1846
|
+
bufferEndIndex = bufferStartIndex;
|
1847
|
+
}
|
1848
|
+
if (char === variablePrefix[0] && serialized[index + 1] === variablePrefix[1]) {
|
1849
|
+
if (serialized[index - 1] === escapeCharacter) {
|
1850
|
+
bufferEndIndex -= escapeCharacter.length;
|
1851
|
+
if (handleToken(serialized.substring(bufferStartIndex, bufferEndIndex), "text") === false) {
|
1852
|
+
return tokenCount;
|
1853
|
+
}
|
1854
|
+
bufferStartIndex = index;
|
1855
|
+
bufferEndIndex = index + 1;
|
1856
|
+
continue;
|
1857
|
+
}
|
1858
|
+
state = "variable";
|
1859
|
+
if (bufferEndIndex > bufferStartIndex) {
|
1860
|
+
if (handleToken(serialized.substring(bufferStartIndex, bufferEndIndex), "text") === false) {
|
1861
|
+
return tokenCount;
|
1862
|
+
}
|
1863
|
+
bufferStartIndex = bufferEndIndex;
|
1864
|
+
}
|
1865
|
+
index += variablePrefix.length - 1;
|
1866
|
+
bufferStartIndex += variablePrefix.length;
|
1867
|
+
continue;
|
1868
|
+
}
|
1869
|
+
if (char === variableSuffix && state === "variable") {
|
1870
|
+
state = "text";
|
1871
|
+
if (bufferEndIndex > bufferStartIndex) {
|
1872
|
+
if (handleToken(serialized.substring(bufferStartIndex, bufferEndIndex), "variable") === false) {
|
1873
|
+
return tokenCount;
|
1874
|
+
}
|
1875
|
+
bufferStartIndex = bufferEndIndex + variableSuffix.length;
|
1876
|
+
}
|
1877
|
+
continue;
|
1878
|
+
}
|
1879
|
+
bufferEndIndex++;
|
1880
|
+
}
|
1881
|
+
if (bufferEndIndex > bufferStartIndex) {
|
1882
|
+
if (state === "variable") {
|
1883
|
+
state = "text";
|
1884
|
+
bufferStartIndex -= variablePrefix.length;
|
1885
|
+
}
|
1886
|
+
handleToken(serialized.substring(bufferStartIndex), state);
|
1887
|
+
}
|
1888
|
+
return tokenCount;
|
1889
|
+
}
|
1890
|
+
|
1891
|
+
// src/utils/variables/bindVariables.ts
|
1892
|
+
function bindVariables({
|
1893
|
+
variables,
|
1894
|
+
value,
|
1895
|
+
errorPrefix = "Variable",
|
1896
|
+
handleBinding
|
1897
|
+
}) {
|
1898
|
+
let boundCount = 0;
|
1899
|
+
let tokenCount = 0;
|
1900
|
+
const errors = [];
|
1901
|
+
const defaultHandleBinding = (variableName, variables2, errors2) => {
|
1902
|
+
const variableValue = variables2[variableName];
|
1903
|
+
if (variableValue === void 0) {
|
1904
|
+
errors2.push(`${errorPrefix} "${variableName}" is not defined`);
|
1905
|
+
return "";
|
1906
|
+
}
|
1907
|
+
return variableValue;
|
1908
|
+
};
|
1909
|
+
const result = [];
|
1910
|
+
parseVariableExpression(value, (token, tokenType) => {
|
1911
|
+
tokenCount++;
|
1912
|
+
if (tokenType === "text") {
|
1913
|
+
result.push(token);
|
1914
|
+
return;
|
1915
|
+
}
|
1916
|
+
const variableValue = (handleBinding != null ? handleBinding : defaultHandleBinding)(token, variables, errors);
|
1917
|
+
boundCount++;
|
1918
|
+
result.push(variableValue);
|
1919
|
+
});
|
1920
|
+
return {
|
1921
|
+
result: tokenCount === 1 ? result[0] : result.join(""),
|
1922
|
+
boundCount,
|
1923
|
+
errors: errors.length > 0 ? errors : void 0
|
1924
|
+
};
|
1925
|
+
}
|
1926
|
+
|
1927
|
+
// src/utils/variables/bindVariablesToObject.ts
|
1928
|
+
var import_immer = require("immer");
|
1929
|
+
|
1930
|
+
// src/utils/variables/createVariableReference.ts
|
1931
|
+
function createVariableReference(variableName) {
|
1932
|
+
return `\${${variableName}}`;
|
1933
|
+
}
|
1934
|
+
|
1935
|
+
// src/utils/variables/bindVariablesToObject.ts
|
1936
|
+
function bindVariablesToObject(options) {
|
1937
|
+
return bindVariablesToObjectRecursive(options);
|
1938
|
+
}
|
1939
|
+
function bindVariablesToObjectRecursive({
|
1940
|
+
value,
|
1941
|
+
recursivePath,
|
1942
|
+
...bindVariablesOptions
|
1943
|
+
}) {
|
1944
|
+
let boundCount = 0;
|
1945
|
+
const errors = [];
|
1946
|
+
if (typeof value === "string") {
|
1947
|
+
return bindVariables({ ...bindVariablesOptions, value });
|
1948
|
+
}
|
1949
|
+
if (typeof value !== "object" || value === null) {
|
1950
|
+
return { boundCount: 0, result: value };
|
1951
|
+
}
|
1952
|
+
const richTextNodeResult = handleRichTextNodeBinding(value, bindVariablesOptions);
|
1953
|
+
if (richTextNodeResult !== void 0) {
|
1954
|
+
return richTextNodeResult;
|
1955
|
+
}
|
1956
|
+
const result = (0, import_immer.produce)(value, (draft) => {
|
1957
|
+
Object.entries(draft).forEach(([property, oldValue]) => {
|
1958
|
+
const currentObjectPath = recursivePath ? `${recursivePath}.${property}` : property;
|
1959
|
+
if (typeof oldValue === "string") {
|
1960
|
+
const bindResult = bindVariables({ ...bindVariablesOptions, value: oldValue });
|
1961
|
+
if (oldValue !== bindResult.result || bindResult.errors) {
|
1962
|
+
boundCount += bindResult.boundCount;
|
1963
|
+
draft[property] = bindResult.result;
|
1964
|
+
if (bindResult.errors) {
|
1965
|
+
errors.push(...bindResult.errors.map((e) => `${currentObjectPath}: ${e}`));
|
1966
|
+
}
|
1967
|
+
}
|
1968
|
+
return;
|
1969
|
+
}
|
1970
|
+
const childBind = bindVariablesToObjectRecursive({
|
1971
|
+
...bindVariablesOptions,
|
1972
|
+
value: oldValue,
|
1973
|
+
recursivePath: currentObjectPath
|
1974
|
+
});
|
1975
|
+
if (childBind.boundCount || childBind.errors) {
|
1976
|
+
boundCount += childBind.boundCount;
|
1977
|
+
draft[property] = childBind.result;
|
1978
|
+
if (childBind.errors) {
|
1979
|
+
errors.push(...childBind.errors);
|
1980
|
+
}
|
1981
|
+
}
|
1982
|
+
});
|
1983
|
+
});
|
1984
|
+
return { boundCount, result, errors: errors.length > 0 ? errors : void 0 };
|
1985
|
+
}
|
1986
|
+
function handleRichTextNodeBinding(object, options) {
|
1987
|
+
if ("type" in object && object.type === "variable" && "reference" in object && typeof object.reference === "string" && "version" in object && object.version === 1) {
|
1988
|
+
const value = createVariableReference(object.reference);
|
1989
|
+
const bindResult = bindVariables({ ...options, value });
|
1990
|
+
const bindResultAsTextNode = {
|
1991
|
+
detail: 0,
|
1992
|
+
format: 0,
|
1993
|
+
mode: "normal",
|
1994
|
+
style: "",
|
1995
|
+
text: bindResult.result,
|
1996
|
+
type: "text",
|
1997
|
+
version: 1
|
1998
|
+
};
|
1999
|
+
return { ...bindResult, result: bindResultAsTextNode };
|
2000
|
+
}
|
2001
|
+
return void 0;
|
2002
|
+
}
|
2003
|
+
|
1857
2004
|
// src/index.ts
|
1858
|
-
var
|
1859
|
-
var CanvasClientError =
|
2005
|
+
var import_api7 = require("@uniformdev/context/api");
|
2006
|
+
var CanvasClientError = import_api7.ApiClientError;
|
1860
2007
|
// Annotate the CommonJS export names for ESM import in node:
|
1861
2008
|
0 && (module.exports = {
|
1862
2009
|
ATTRIBUTE_COMPONENT_ID,
|
@@ -1882,6 +2029,7 @@ var CanvasClientError = import_api6.ApiClientError;
|
|
1882
2029
|
CANVAS_TEST_VARIANT_PARAM,
|
1883
2030
|
CanvasClient,
|
1884
2031
|
CanvasClientError,
|
2032
|
+
CategoryClient,
|
1885
2033
|
ChildEnhancerBuilder,
|
1886
2034
|
DataSourceClient,
|
1887
2035
|
DataTypeClient,
|
@@ -1902,6 +2050,7 @@ var CanvasClientError = import_api6.ApiClientError;
|
|
1902
2050
|
PLACEHOLDER_ID,
|
1903
2051
|
RouteClient,
|
1904
2052
|
UncachedCanvasClient,
|
2053
|
+
UncachedCategoryClient,
|
1905
2054
|
UniqueBatchEntries,
|
1906
2055
|
bindVariables,
|
1907
2056
|
bindVariablesToObject,
|
@@ -1911,6 +2060,7 @@ var CanvasClientError = import_api6.ApiClientError;
|
|
1911
2060
|
createEventBus,
|
1912
2061
|
createLimitPolicy,
|
1913
2062
|
createUniformApiEnhancer,
|
2063
|
+
createVariableReference,
|
1914
2064
|
enhance,
|
1915
2065
|
extractLocales,
|
1916
2066
|
generateHash,
|
@@ -1936,6 +2086,7 @@ var CanvasClientError = import_api6.ApiClientError;
|
|
1936
2086
|
mapSlotToPersonalizedVariations,
|
1937
2087
|
mapSlotToTestVariations,
|
1938
2088
|
nullLimitPolicy,
|
2089
|
+
parseVariableExpression,
|
1939
2090
|
subscribeToComposition,
|
1940
2091
|
unstable_CompositionRelationshipClient,
|
1941
2092
|
walkComponentTree
|