@uniformdev/canvas 19.10.0 → 19.11.0

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.ts CHANGED
@@ -139,6 +139,23 @@ interface components$3 {
139
139
  /** @description Last modified date string for this definition (ignored for writes) */
140
140
  updated?: string;
141
141
  };
142
+ /** @description Defines a content type */
143
+ ContentType: {
144
+ id: components$3["schemas"]["PublicIdProperty"];
145
+ /** @description Friendly name of the content type */
146
+ name: string;
147
+ /**
148
+ * @description The public ID of the field whose value should be used to create a display title for entries of this content type in the UI.
149
+ * The field type must support being used as a title field for this to work.
150
+ */
151
+ titleField?: string | null;
152
+ /** @description The fields for this content type. Fields are key-value pairs that can be text, numbers, JSON objects, etc. */
153
+ fields?: components$3["schemas"]["ComponentDefinitionParameter"][];
154
+ /** @description Created date string for this content type (ignored for writes) */
155
+ created?: string;
156
+ /** @description Last modified date string for this content type (ignored for writes) */
157
+ updated?: string;
158
+ };
142
159
  /** @description Defines an editable parameter on a component. */
143
160
  ComponentParameter: {
144
161
  /** @description The value of the parameter. Any JSON-serializable value is acceptable. */
@@ -733,6 +750,23 @@ interface external$8 {
733
750
  /** @description Last modified date string for this definition (ignored for writes) */
734
751
  updated?: string;
735
752
  };
753
+ /** @description Defines a content type */
754
+ ContentType: {
755
+ id: external$8["uniform-canvas-types.swagger.yml"]["components"]["schemas"]["PublicIdProperty"];
756
+ /** @description Friendly name of the content type */
757
+ name: string;
758
+ /**
759
+ * @description The public ID of the field whose value should be used to create a display title for entries of this content type in the UI.
760
+ * The field type must support being used as a title field for this to work.
761
+ */
762
+ titleField?: string | null;
763
+ /** @description The fields for this content type. Fields are key-value pairs that can be text, numbers, JSON objects, etc. */
764
+ fields?: external$8["uniform-canvas-types.swagger.yml"]["components"]["schemas"]["ComponentDefinitionParameter"][];
765
+ /** @description Created date string for this content type (ignored for writes) */
766
+ created?: string;
767
+ /** @description Last modified date string for this content type (ignored for writes) */
768
+ updated?: string;
769
+ };
736
770
  /** @description Defines an editable parameter on a component. */
737
771
  ComponentParameter: {
738
772
  /** @description The value of the parameter. Any JSON-serializable value is acceptable. */
@@ -1580,6 +1614,23 @@ interface external$7 {
1580
1614
  /** @description Last modified date string for this definition (ignored for writes) */
1581
1615
  updated?: string;
1582
1616
  };
1617
+ /** @description Defines a content type */
1618
+ ContentType: {
1619
+ id: external$7["uniform-canvas-types.swagger.yml"]["components"]["schemas"]["PublicIdProperty"];
1620
+ /** @description Friendly name of the content type */
1621
+ name: string;
1622
+ /**
1623
+ * @description The public ID of the field whose value should be used to create a display title for entries of this content type in the UI.
1624
+ * The field type must support being used as a title field for this to work.
1625
+ */
1626
+ titleField?: string | null;
1627
+ /** @description The fields for this content type. Fields are key-value pairs that can be text, numbers, JSON objects, etc. */
1628
+ fields?: external$7["uniform-canvas-types.swagger.yml"]["components"]["schemas"]["ComponentDefinitionParameter"][];
1629
+ /** @description Created date string for this content type (ignored for writes) */
1630
+ created?: string;
1631
+ /** @description Last modified date string for this content type (ignored for writes) */
1632
+ updated?: string;
1633
+ };
1583
1634
  /** @description Defines an editable parameter on a component. */
1584
1635
  ComponentParameter: {
1585
1636
  /** @description The value of the parameter. Any JSON-serializable value is acceptable. */
@@ -2252,6 +2303,23 @@ interface external$6 {
2252
2303
  /** @description Last modified date string for this definition (ignored for writes) */
2253
2304
  updated?: string;
2254
2305
  };
2306
+ /** @description Defines a content type */
2307
+ ContentType: {
2308
+ id: external$6["../../../lambda/functions/uniform-canvas-types.swagger.yml"]["components"]["schemas"]["PublicIdProperty"];
2309
+ /** @description Friendly name of the content type */
2310
+ name: string;
2311
+ /**
2312
+ * @description The public ID of the field whose value should be used to create a display title for entries of this content type in the UI.
2313
+ * The field type must support being used as a title field for this to work.
2314
+ */
2315
+ titleField?: string | null;
2316
+ /** @description The fields for this content type. Fields are key-value pairs that can be text, numbers, JSON objects, etc. */
2317
+ fields?: external$6["../../../lambda/functions/uniform-canvas-types.swagger.yml"]["components"]["schemas"]["ComponentDefinitionParameter"][];
2318
+ /** @description Created date string for this content type (ignored for writes) */
2319
+ created?: string;
2320
+ /** @description Last modified date string for this content type (ignored for writes) */
2321
+ updated?: string;
2322
+ };
2255
2323
  /** @description Defines an editable parameter on a component. */
2256
2324
  ComponentParameter: {
2257
2325
  /** @description The value of the parameter. Any JSON-serializable value is acceptable. */
@@ -3542,6 +3610,23 @@ interface external$5 {
3542
3610
  /** @description Last modified date string for this definition (ignored for writes) */
3543
3611
  updated?: string;
3544
3612
  };
3613
+ /** @description Defines a content type */
3614
+ ContentType: {
3615
+ id: external$5["uniform-canvas-types.swagger.yml"]["components"]["schemas"]["PublicIdProperty"];
3616
+ /** @description Friendly name of the content type */
3617
+ name: string;
3618
+ /**
3619
+ * @description The public ID of the field whose value should be used to create a display title for entries of this content type in the UI.
3620
+ * The field type must support being used as a title field for this to work.
3621
+ */
3622
+ titleField?: string | null;
3623
+ /** @description The fields for this content type. Fields are key-value pairs that can be text, numbers, JSON objects, etc. */
3624
+ fields?: external$5["uniform-canvas-types.swagger.yml"]["components"]["schemas"]["ComponentDefinitionParameter"][];
3625
+ /** @description Created date string for this content type (ignored for writes) */
3626
+ created?: string;
3627
+ /** @description Last modified date string for this content type (ignored for writes) */
3628
+ updated?: string;
3629
+ };
3545
3630
  /** @description Defines an editable parameter on a component. */
3546
3631
  ComponentParameter: {
3547
3632
  /** @description The value of the parameter. Any JSON-serializable value is acceptable. */
@@ -5320,6 +5405,23 @@ interface external$2 {
5320
5405
  /** @description Last modified date string for this definition (ignored for writes) */
5321
5406
  updated?: string;
5322
5407
  };
5408
+ /** @description Defines a content type */
5409
+ ContentType: {
5410
+ id: external$2["uniform-canvas-types.swagger.yml"]["components"]["schemas"]["PublicIdProperty"];
5411
+ /** @description Friendly name of the content type */
5412
+ name: string;
5413
+ /**
5414
+ * @description The public ID of the field whose value should be used to create a display title for entries of this content type in the UI.
5415
+ * The field type must support being used as a title field for this to work.
5416
+ */
5417
+ titleField?: string | null;
5418
+ /** @description The fields for this content type. Fields are key-value pairs that can be text, numbers, JSON objects, etc. */
5419
+ fields?: external$2["uniform-canvas-types.swagger.yml"]["components"]["schemas"]["ComponentDefinitionParameter"][];
5420
+ /** @description Created date string for this content type (ignored for writes) */
5421
+ created?: string;
5422
+ /** @description Last modified date string for this content type (ignored for writes) */
5423
+ updated?: string;
5424
+ };
5323
5425
  /** @description Defines an editable parameter on a component. */
5324
5426
  ComponentParameter: {
5325
5427
  /** @description The value of the parameter. Any JSON-serializable value is acceptable. */
@@ -5856,6 +5958,23 @@ interface external$1 {
5856
5958
  /** @description Last modified date string for this definition (ignored for writes) */
5857
5959
  updated?: string;
5858
5960
  };
5961
+ /** @description Defines a content type */
5962
+ ContentType: {
5963
+ id: external$1["uniform-canvas-types.swagger.yml"]["components"]["schemas"]["PublicIdProperty"];
5964
+ /** @description Friendly name of the content type */
5965
+ name: string;
5966
+ /**
5967
+ * @description The public ID of the field whose value should be used to create a display title for entries of this content type in the UI.
5968
+ * The field type must support being used as a title field for this to work.
5969
+ */
5970
+ titleField?: string | null;
5971
+ /** @description The fields for this content type. Fields are key-value pairs that can be text, numbers, JSON objects, etc. */
5972
+ fields?: external$1["uniform-canvas-types.swagger.yml"]["components"]["schemas"]["ComponentDefinitionParameter"][];
5973
+ /** @description Created date string for this content type (ignored for writes) */
5974
+ created?: string;
5975
+ /** @description Last modified date string for this content type (ignored for writes) */
5976
+ updated?: string;
5977
+ };
5859
5978
  /** @description Defines an editable parameter on a component. */
5860
5979
  ComponentParameter: {
5861
5980
  /** @description The value of the parameter. Any JSON-serializable value is acceptable. */
@@ -6427,6 +6546,23 @@ interface external {
6427
6546
  /** @description Last modified date string for this definition (ignored for writes) */
6428
6547
  updated?: string;
6429
6548
  };
6549
+ /** @description Defines a content type */
6550
+ ContentType: {
6551
+ id: external["uniform-canvas-types.swagger.yml"]["components"]["schemas"]["PublicIdProperty"];
6552
+ /** @description Friendly name of the content type */
6553
+ name: string;
6554
+ /**
6555
+ * @description The public ID of the field whose value should be used to create a display title for entries of this content type in the UI.
6556
+ * The field type must support being used as a title field for this to work.
6557
+ */
6558
+ titleField?: string | null;
6559
+ /** @description The fields for this content type. Fields are key-value pairs that can be text, numbers, JSON objects, etc. */
6560
+ fields?: external["uniform-canvas-types.swagger.yml"]["components"]["schemas"]["ComponentDefinitionParameter"][];
6561
+ /** @description Created date string for this content type (ignored for writes) */
6562
+ created?: string;
6563
+ /** @description Last modified date string for this content type (ignored for writes) */
6564
+ updated?: string;
6565
+ };
6430
6566
  /** @description Defines an editable parameter on a component. */
6431
6567
  ComponentParameter: {
6432
6568
  /** @description The value of the parameter. Any JSON-serializable value is acceptable. */
@@ -7130,6 +7266,15 @@ declare function getComponentJsonPointer(ancestorsAndSelf: Array<ComponentLocati
7130
7266
  withSlots?: boolean | undefined;
7131
7267
  }): string;
7132
7268
 
7269
+ /** Writes colorized logs about composition fetch warnings or errors to the console */
7270
+ declare function logCompositionIssues(prefix: string, issues: CompositionIssue[], colour?: 'red' | 'green' | 'yellow' | 'white'): void;
7271
+
7272
+ /** Writes colorized logs about a composition API fetch to the console */
7273
+ declare function logCompositionResponse(compositionApiResponse: CompositionResolvedGetResponse, duration?: number): void;
7274
+
7275
+ /** Writes colorized logs about a route API response to the console */
7276
+ declare function logRouteResponse(response: RouteGetResponse, duration?: number): void;
7277
+
7133
7278
  interface ContextualEditingWindowData {
7134
7279
  framework?: ReadyMessage['framework'];
7135
7280
  version?: ReadyMessage['version'];
@@ -7545,4 +7690,4 @@ declare function mapSlotToTestVariations(slot: ComponentInstance[] | undefined):
7545
7690
 
7546
7691
  declare const CanvasClientError: typeof ApiClientError;
7547
7692
 
7548
- export { AddComponentMessage, BatchEnhancer, BatchEntry, BatchInvalidationPayload, BindVariablesOptions, BindVariablesResult, BindVariablesToObjectOptions, CANVAS_DRAFT_STATE, CANVAS_ENRICHMENT_TAG_PARAM, CANVAS_INTENT_TAG_PARAM, CANVAS_LOCALE_TAG_PARAM, CANVAS_LOCALIZATION_SLOT, CANVAS_LOCALIZATION_TYPE, CANVAS_PERSONALIZATION_PARAM, CANVAS_PERSONALIZE_SLOT, CANVAS_PERSONALIZE_TYPE, CANVAS_PUBLISHED_STATE, CANVAS_TEST_SLOT, CANVAS_TEST_TYPE, CANVAS_TEST_VARIANT_PARAM, CanvasClient, CanvasClientError, CanvasDefinitions, Channel, ChannelMessage, ChannelSubscription, ChildEnhancerBuilder, ComponentDefinition, ComponentDefinitionDeleteParameters, ComponentDefinitionGetParameters, ComponentDefinitionGetResponse, ComponentDefinitionParameter, ComponentDefinitionPermission, ComponentDefinitionPutParameters, ComponentDefinitionSlot, ComponentDefinitionSlugSettings, ComponentDefinitionVariant, ComponentEnhancer, ComponentEnhancerFunction, ComponentEnhancerOptions, ComponentInstance, ComponentLocationReference, ComponentOverridability, ComponentOverride, ComponentOverrides, ComponentParameter, ComponentParameterContextualEditing, ComponentParameterEnhancer, ComponentParameterEnhancerFunction, ComponentParameterEnhancerOptions, CompositionDataDiagnostic, CompositionDeleteParameters, CompositionDiagnostics, CompositionGetByIdParameters, CompositionGetByNodeIdParameters, CompositionGetByNodePathParameters, CompositionGetBySlugParameters, CompositionGetListResponse, CompositionGetOrderBy, CompositionGetParameters, CompositionGetResponse, CompositionGetValidResponses, CompositionIssue, CompositionPatternIssue, CompositionPutParameters, CompositionRelationshipsClientOptions, CompositionRelationshipsDDefinitionGetResponse, CompositionRelationshipsDefinitionApi, CompositionRelationshipsDefinitionGetParameters, CompositionResolvedGetResponse, CompositionUIStatus, DataElementBindingIssue, DataElementConnectionDefinition, DataResolutionConfigIssue, DataResolutionOption, DataResolutionOptionNegative, DataResolutionOptionPositive, DataResolutionParameters, DataResourceDefinition, DataResourceDefinitions, DataResourceInputIssue, DataResourceIssue, DataResourceVariables, DataSource, DataSourceClient, DataSourceDeleteParameters, DataSourceGetParameters, DataSourceGetResponse, DataSourcePutParameters, DataSourcesGetParameters, DataSourcesGetResponse, DataType, DataTypeClient, DataTypeDeleteParameters, DataTypeGetParameters, DataTypeGetResponse, DataTypePutParameters, DataVariableDefinition, DismissPlaceholderMessage, EDGE_CACHE_DISABLED, EDGE_DEFAULT_CACHE_TTL, EDGE_DEFAULT_L2_CACHE_TTL_IN_HOURS, EDGE_MAX_CACHE_TTL, EDGE_MAX_L2_CACHE_TTL_IN_HOURS, EDGE_MIN_CACHE_TTL, EDGE_MIN_L2_CACHE_TTL_IN_HOURS, EMPTY_COMPOSITION, EnhancerBuilder, EnhancerContext, EnhancerError, EventNames, IN_CONTEXT_EDITOR_COMPONENT_END_ROLE, IN_CONTEXT_EDITOR_COMPONENT_START_ROLE, IN_CONTEXT_EDITOR_EMBED_SCRIPT_ID, IN_CONTEXT_EDITOR_QUERY_STRING_PARAM, IS_RENDERED_BY_UNIFORM_ATTRIBUTE, InvalidationPayload, InvalidationResult, LimitPolicy, MessageHandler, MoveComponentMessage, OverrideIssue, OverrideOptions, PLACEHOLDER_ID, PreviewEventBus, PreviewPanelSettings, ReadyMessage, ReportRenderedCompositionsMessage, ResolvedRouteGetResponse, RootComponentInstance, RouteDynamicInputs, RouteGetParameters, RouteGetResponse, RouteGetResponseComposition, RouteGetResponseEdgehancedComposition, RouteGetResponseNotFound, RouteGetResponseRedirect, SelectComponentMessage, SpecificProjectMap, SubscribeToCompositionOptions, TriggerCompositionActionMessage, UncachedCanvasClient, UniqueBatchEntries, UnsubscribeCallback, UpdateComponentParameterMessage, UpdateCompositionInternalMessage, UpdateCompositionMessage, UpdatePreviewSettingsMessage, UsageTrackingApi, UsageTrackingGetParameters, UsageTrackingGetResponse, UsageTrackingPostParameters, UsageTrackingPostResponse, WalkComponentTreeActions, bindVariables, bindVariablesToObject, compose, createBatchEnhancer, createCanvasChannel, createEventBus, createLimitPolicy, createUniformApiEnhancer, enhance, extractLocales, generateHash, getChannelName, getComponentJsonPointer, getComponentPath, isAddComponentMessage, isDismissPlaceholderMessage, isMovingComponentMessage, isReadyMessage, isReportRenderedCompositionsMessage, isSelectComponentMessage, isSystemComponentDefinition, isTriggerCompositionActionMessage, isUpdateComponentParameterMessage, isUpdateCompositionInternalMessage, isUpdateCompositionMessage, isUpdatePreviewSettingsMessage, localize, mapSlotToPersonalizedVariations, mapSlotToTestVariations, nullLimitPolicy, subscribeToComposition, unstable_CompositionRelationshipClient, unstable_RouteClient, walkComponentTree };
7693
+ export { AddComponentMessage, BatchEnhancer, BatchEntry, BatchInvalidationPayload, BindVariablesOptions, BindVariablesResult, BindVariablesToObjectOptions, CANVAS_DRAFT_STATE, CANVAS_ENRICHMENT_TAG_PARAM, CANVAS_INTENT_TAG_PARAM, CANVAS_LOCALE_TAG_PARAM, CANVAS_LOCALIZATION_SLOT, CANVAS_LOCALIZATION_TYPE, CANVAS_PERSONALIZATION_PARAM, CANVAS_PERSONALIZE_SLOT, CANVAS_PERSONALIZE_TYPE, CANVAS_PUBLISHED_STATE, CANVAS_TEST_SLOT, CANVAS_TEST_TYPE, CANVAS_TEST_VARIANT_PARAM, CanvasClient, CanvasClientError, CanvasDefinitions, Channel, ChannelMessage, ChannelSubscription, ChildEnhancerBuilder, ComponentDefinition, ComponentDefinitionDeleteParameters, ComponentDefinitionGetParameters, ComponentDefinitionGetResponse, ComponentDefinitionParameter, ComponentDefinitionPermission, ComponentDefinitionPutParameters, ComponentDefinitionSlot, ComponentDefinitionSlugSettings, ComponentDefinitionVariant, ComponentEnhancer, ComponentEnhancerFunction, ComponentEnhancerOptions, ComponentInstance, ComponentLocationReference, ComponentOverridability, ComponentOverride, ComponentOverrides, ComponentParameter, ComponentParameterContextualEditing, ComponentParameterEnhancer, ComponentParameterEnhancerFunction, ComponentParameterEnhancerOptions, CompositionDataDiagnostic, CompositionDeleteParameters, CompositionDiagnostics, CompositionGetByIdParameters, CompositionGetByNodeIdParameters, CompositionGetByNodePathParameters, CompositionGetBySlugParameters, CompositionGetListResponse, CompositionGetOrderBy, CompositionGetParameters, CompositionGetResponse, CompositionGetValidResponses, CompositionIssue, CompositionPatternIssue, CompositionPutParameters, CompositionRelationshipsClientOptions, CompositionRelationshipsDDefinitionGetResponse, CompositionRelationshipsDefinitionApi, CompositionRelationshipsDefinitionGetParameters, CompositionResolvedGetResponse, CompositionUIStatus, DataElementBindingIssue, DataElementConnectionDefinition, DataResolutionConfigIssue, DataResolutionOption, DataResolutionOptionNegative, DataResolutionOptionPositive, DataResolutionParameters, DataResourceDefinition, DataResourceDefinitions, DataResourceInputIssue, DataResourceIssue, DataResourceVariables, DataSource, DataSourceClient, DataSourceDeleteParameters, DataSourceGetParameters, DataSourceGetResponse, DataSourcePutParameters, DataSourcesGetParameters, DataSourcesGetResponse, DataType, DataTypeClient, DataTypeDeleteParameters, DataTypeGetParameters, DataTypeGetResponse, DataTypePutParameters, DataVariableDefinition, DismissPlaceholderMessage, EDGE_CACHE_DISABLED, EDGE_DEFAULT_CACHE_TTL, EDGE_DEFAULT_L2_CACHE_TTL_IN_HOURS, EDGE_MAX_CACHE_TTL, EDGE_MAX_L2_CACHE_TTL_IN_HOURS, EDGE_MIN_CACHE_TTL, EDGE_MIN_L2_CACHE_TTL_IN_HOURS, EMPTY_COMPOSITION, EnhancerBuilder, EnhancerContext, EnhancerError, EventNames, IN_CONTEXT_EDITOR_COMPONENT_END_ROLE, IN_CONTEXT_EDITOR_COMPONENT_START_ROLE, IN_CONTEXT_EDITOR_EMBED_SCRIPT_ID, IN_CONTEXT_EDITOR_QUERY_STRING_PARAM, IS_RENDERED_BY_UNIFORM_ATTRIBUTE, InvalidationPayload, InvalidationResult, LimitPolicy, MessageHandler, MoveComponentMessage, OverrideIssue, OverrideOptions, PLACEHOLDER_ID, PreviewEventBus, PreviewPanelSettings, ReadyMessage, ReportRenderedCompositionsMessage, ResolvedRouteGetResponse, RootComponentInstance, RouteDynamicInputs, RouteGetParameters, RouteGetResponse, RouteGetResponseComposition, RouteGetResponseEdgehancedComposition, RouteGetResponseNotFound, RouteGetResponseRedirect, SelectComponentMessage, SpecificProjectMap, SubscribeToCompositionOptions, TriggerCompositionActionMessage, UncachedCanvasClient, UniqueBatchEntries, UnsubscribeCallback, UpdateComponentParameterMessage, UpdateCompositionInternalMessage, UpdateCompositionMessage, UpdatePreviewSettingsMessage, UsageTrackingApi, UsageTrackingGetParameters, UsageTrackingGetResponse, UsageTrackingPostParameters, UsageTrackingPostResponse, WalkComponentTreeActions, bindVariables, bindVariablesToObject, compose, createBatchEnhancer, createCanvasChannel, createEventBus, createLimitPolicy, createUniformApiEnhancer, enhance, extractLocales, generateHash, getChannelName, getComponentJsonPointer, getComponentPath, isAddComponentMessage, isDismissPlaceholderMessage, isMovingComponentMessage, isReadyMessage, isReportRenderedCompositionsMessage, isSelectComponentMessage, isSystemComponentDefinition, isTriggerCompositionActionMessage, isUpdateComponentParameterMessage, isUpdateCompositionInternalMessage, isUpdateCompositionMessage, isUpdatePreviewSettingsMessage, localize, logCompositionIssues, logCompositionResponse, logRouteResponse, mapSlotToPersonalizedVariations, mapSlotToTestVariations, nullLimitPolicy, subscribeToComposition, unstable_CompositionRelationshipClient, unstable_RouteClient, walkComponentTree };
package/dist/index.esm.js CHANGED
@@ -1264,6 +1264,163 @@ var UniqueBatchEntries = class {
1264
1264
  }
1265
1265
  };
1266
1266
 
1267
+ // src/logging/logCompositionIssues.ts
1268
+ import ansicolors from "ansi-colors";
1269
+ var { gray, green, italic, red, white, yellow } = ansicolors;
1270
+ function logCompositionIssues(prefix, issues, colour = "red") {
1271
+ const reversedIssues = [...issues].reverse();
1272
+ const colours = { red, green, yellow, white };
1273
+ console.error(
1274
+ `${colours[colour](prefix)}
1275
+ ${reversedIssues.map(
1276
+ (issue) => `${colours[colour](">")} ${italic(gray(indent(issue.type.toUpperCase(), 7)))} ${renderIssue(issue)}`
1277
+ ).join("\n")}`
1278
+ );
1279
+ }
1280
+ function renderIssue(issue) {
1281
+ var _a;
1282
+ let path;
1283
+ let type;
1284
+ let message = issue.message;
1285
+ let detail;
1286
+ if (issue.type !== "config") {
1287
+ path = issue.componentPath;
1288
+ type = issue.componentType;
1289
+ message = issue.message;
1290
+ }
1291
+ if (issue.type === "binding") {
1292
+ detail = `Binding expression: ${(_a = issue.expression) == null ? void 0 : _a.pointer}`;
1293
+ } else if (issue.type === "data") {
1294
+ detail = `Data resource name: ${issue.dataName}, data type: ${issue.dataType}`;
1295
+ }
1296
+ if (issue.type === "input") {
1297
+ detail = issue.inputName;
1298
+ }
1299
+ let result = `${white(blockify(message))}`;
1300
+ if (detail) {
1301
+ result += `
1302
+ ${indent(" ", 10)}${gray(`${detail}`)}`;
1303
+ }
1304
+ if (path && type) {
1305
+ result += `
1306
+ ${indent(" ", 10)}${gray(`Occurred on component ${type} at slot path ${path}`)}`;
1307
+ }
1308
+ return result;
1309
+ }
1310
+ function indent(str, len) {
1311
+ const indent2 = len != null ? len : 10;
1312
+ return str.padStart(indent2);
1313
+ }
1314
+ function blockify(str, len) {
1315
+ const indentSize = len != null ? len : 10;
1316
+ return str.split("\n").map((line, index) => index === 0 ? line : `${indent(" ", indentSize)}${line}`).join("\n");
1317
+ }
1318
+
1319
+ // src/logging/logCompositionResponse.ts
1320
+ import ansicolors2 from "ansi-colors";
1321
+ var { white: white2 } = ansicolors2;
1322
+ function logCompositionResponse(compositionApiResponse, duration) {
1323
+ var _a, _b;
1324
+ const resErrors = (_a = compositionApiResponse.errors) != null ? _a : [];
1325
+ const resWarnings = (_b = compositionApiResponse.warnings) != null ? _b : [];
1326
+ if (resErrors.length > 0) {
1327
+ logCompositionIssues(
1328
+ `Composition data error${resErrors.length === 1 ? "" : "s"}; some content may be missing`,
1329
+ resErrors,
1330
+ "red"
1331
+ );
1332
+ }
1333
+ if (resWarnings.length > 0) {
1334
+ logCompositionIssues(
1335
+ `Composition data warning${resWarnings.length === 1 ? "" : "s"}; some content may be missing`,
1336
+ resWarnings,
1337
+ "yellow"
1338
+ );
1339
+ }
1340
+ if (compositionApiResponse.diagnostics) {
1341
+ console.log(`
1342
+ Diagnostics`);
1343
+ const { compositionFetch, data } = compositionApiResponse.diagnostics;
1344
+ const table = {
1345
+ [`${white2("Composition")}`]: {
1346
+ "Duration (ms)": resolveDiagnosticsDuration(compositionFetch),
1347
+ "Edge Cached": compositionFetch == null ? void 0 : compositionFetch.cacheHit
1348
+ }
1349
+ };
1350
+ if (data) {
1351
+ data.forEach((d) => {
1352
+ table[d.dataName] = {
1353
+ "Duration (ms)": resolveDiagnosticsDuration(d.performance),
1354
+ "Edge Cached": d.performance.cacheHit,
1355
+ "Retry Count": d.performance.retryCount
1356
+ };
1357
+ });
1358
+ }
1359
+ table["Total Response"] = {
1360
+ "Duration (ms)": duration != null ? duration : "no data"
1361
+ };
1362
+ console.table(table);
1363
+ }
1364
+ }
1365
+ function resolveDiagnosticsDuration(data) {
1366
+ var _a, _b;
1367
+ if (!data) {
1368
+ return "no data";
1369
+ }
1370
+ return (_b = (_a = data.duration) != null ? _a : data.total) != null ? _b : "no data";
1371
+ }
1372
+
1373
+ // src/logging/logCompositionRouteResponse.ts
1374
+ import ansicolors3 from "ansi-colors";
1375
+ var { gray: gray2, green: green2, red: red2, yellow: yellow2 } = ansicolors3;
1376
+ function logRouteCompositionResponse(matched, duration) {
1377
+ var _a, _b;
1378
+ const resErrors = (_a = matched.compositionApiResponse.errors) != null ? _a : [];
1379
+ const resWarnings = (_b = matched.compositionApiResponse.warnings) != null ? _b : [];
1380
+ const colour = resErrors.length > 0 ? red2 : resWarnings.length > 0 ? yellow2 : green2;
1381
+ console.log(`${colour("Matched")} ${matched.type} ${matched.matchedRoute} (${duration}ms)`);
1382
+ if (matched.dynamicInputs) {
1383
+ const entries = Object.entries(matched.dynamicInputs);
1384
+ if (entries.length > 0) {
1385
+ console.log(
1386
+ ` ${gray2("Matched dynamic inputs:\n ")}`,
1387
+ entries.map(([k, v]) => `${k}: ${v}`).join("\n ")
1388
+ );
1389
+ }
1390
+ }
1391
+ logCompositionResponse(matched.compositionApiResponse, duration);
1392
+ }
1393
+
1394
+ // src/logging/logNotFoundRouteResponse.ts
1395
+ import ansicolors4 from "ansi-colors";
1396
+ var { yellow: yellow3 } = ansicolors4;
1397
+ function logNotFoundRouteResponse(_matched, duration) {
1398
+ console.log(`${yellow3("Not found")} no project map or redirect path match (${duration}ms)`);
1399
+ }
1400
+
1401
+ // src/logging/logRedirectRouteResponse.ts
1402
+ import ansicolors5 from "ansi-colors";
1403
+ var { green: green3 } = ansicolors5;
1404
+ function logRedirectRouteResponse(matched, duration) {
1405
+ console.log(
1406
+ `${green3("Matched")} ${matched.type} ${matched.matchedRoute} (${duration}ms)
1407
+ Target: ${matched.redirect.targetUrl}`
1408
+ );
1409
+ }
1410
+
1411
+ // src/logging/logRouteResponse.ts
1412
+ function logRouteResponse(response, duration) {
1413
+ if (response.type === "redirect") {
1414
+ logRedirectRouteResponse(response, duration);
1415
+ return;
1416
+ }
1417
+ if (response.type === "notFound") {
1418
+ logNotFoundRouteResponse(response, duration);
1419
+ return;
1420
+ }
1421
+ logRouteCompositionResponse(response, duration);
1422
+ }
1423
+
1267
1424
  // src/utils/hash.ts
1268
1425
  var generateHash = ({
1269
1426
  composition,
@@ -1767,6 +1924,9 @@ export {
1767
1924
  isUpdateCompositionMessage,
1768
1925
  isUpdatePreviewSettingsMessage,
1769
1926
  localize,
1927
+ logCompositionIssues,
1928
+ logCompositionResponse,
1929
+ logRouteResponse,
1770
1930
  mapSlotToPersonalizedVariations,
1771
1931
  mapSlotToTestVariations,
1772
1932
  nullLimitPolicy,
package/dist/index.js CHANGED
@@ -338,6 +338,9 @@ __export(src_exports, {
338
338
  isUpdateCompositionMessage: () => isUpdateCompositionMessage,
339
339
  isUpdatePreviewSettingsMessage: () => isUpdatePreviewSettingsMessage,
340
340
  localize: () => localize,
341
+ logCompositionIssues: () => logCompositionIssues,
342
+ logCompositionResponse: () => logCompositionResponse,
343
+ logRouteResponse: () => logRouteResponse,
341
344
  mapSlotToPersonalizedVariations: () => mapSlotToPersonalizedVariations,
342
345
  mapSlotToTestVariations: () => mapSlotToTestVariations,
343
346
  nullLimitPolicy: () => nullLimitPolicy,
@@ -1347,6 +1350,163 @@ var UniqueBatchEntries = class {
1347
1350
  }
1348
1351
  };
1349
1352
 
1353
+ // src/logging/logCompositionIssues.ts
1354
+ var import_ansi_colors = __toESM(require("ansi-colors"));
1355
+ var { gray, green, italic, red, white, yellow } = import_ansi_colors.default;
1356
+ function logCompositionIssues(prefix, issues, colour = "red") {
1357
+ const reversedIssues = [...issues].reverse();
1358
+ const colours = { red, green, yellow, white };
1359
+ console.error(
1360
+ `${colours[colour](prefix)}
1361
+ ${reversedIssues.map(
1362
+ (issue) => `${colours[colour](">")} ${italic(gray(indent(issue.type.toUpperCase(), 7)))} ${renderIssue(issue)}`
1363
+ ).join("\n")}`
1364
+ );
1365
+ }
1366
+ function renderIssue(issue) {
1367
+ var _a;
1368
+ let path;
1369
+ let type;
1370
+ let message = issue.message;
1371
+ let detail;
1372
+ if (issue.type !== "config") {
1373
+ path = issue.componentPath;
1374
+ type = issue.componentType;
1375
+ message = issue.message;
1376
+ }
1377
+ if (issue.type === "binding") {
1378
+ detail = `Binding expression: ${(_a = issue.expression) == null ? void 0 : _a.pointer}`;
1379
+ } else if (issue.type === "data") {
1380
+ detail = `Data resource name: ${issue.dataName}, data type: ${issue.dataType}`;
1381
+ }
1382
+ if (issue.type === "input") {
1383
+ detail = issue.inputName;
1384
+ }
1385
+ let result = `${white(blockify(message))}`;
1386
+ if (detail) {
1387
+ result += `
1388
+ ${indent(" ", 10)}${gray(`${detail}`)}`;
1389
+ }
1390
+ if (path && type) {
1391
+ result += `
1392
+ ${indent(" ", 10)}${gray(`Occurred on component ${type} at slot path ${path}`)}`;
1393
+ }
1394
+ return result;
1395
+ }
1396
+ function indent(str, len) {
1397
+ const indent2 = len != null ? len : 10;
1398
+ return str.padStart(indent2);
1399
+ }
1400
+ function blockify(str, len) {
1401
+ const indentSize = len != null ? len : 10;
1402
+ return str.split("\n").map((line, index) => index === 0 ? line : `${indent(" ", indentSize)}${line}`).join("\n");
1403
+ }
1404
+
1405
+ // src/logging/logCompositionResponse.ts
1406
+ var import_ansi_colors2 = __toESM(require("ansi-colors"));
1407
+ var { white: white2 } = import_ansi_colors2.default;
1408
+ function logCompositionResponse(compositionApiResponse, duration) {
1409
+ var _a, _b;
1410
+ const resErrors = (_a = compositionApiResponse.errors) != null ? _a : [];
1411
+ const resWarnings = (_b = compositionApiResponse.warnings) != null ? _b : [];
1412
+ if (resErrors.length > 0) {
1413
+ logCompositionIssues(
1414
+ `Composition data error${resErrors.length === 1 ? "" : "s"}; some content may be missing`,
1415
+ resErrors,
1416
+ "red"
1417
+ );
1418
+ }
1419
+ if (resWarnings.length > 0) {
1420
+ logCompositionIssues(
1421
+ `Composition data warning${resWarnings.length === 1 ? "" : "s"}; some content may be missing`,
1422
+ resWarnings,
1423
+ "yellow"
1424
+ );
1425
+ }
1426
+ if (compositionApiResponse.diagnostics) {
1427
+ console.log(`
1428
+ Diagnostics`);
1429
+ const { compositionFetch, data } = compositionApiResponse.diagnostics;
1430
+ const table = {
1431
+ [`${white2("Composition")}`]: {
1432
+ "Duration (ms)": resolveDiagnosticsDuration(compositionFetch),
1433
+ "Edge Cached": compositionFetch == null ? void 0 : compositionFetch.cacheHit
1434
+ }
1435
+ };
1436
+ if (data) {
1437
+ data.forEach((d) => {
1438
+ table[d.dataName] = {
1439
+ "Duration (ms)": resolveDiagnosticsDuration(d.performance),
1440
+ "Edge Cached": d.performance.cacheHit,
1441
+ "Retry Count": d.performance.retryCount
1442
+ };
1443
+ });
1444
+ }
1445
+ table["Total Response"] = {
1446
+ "Duration (ms)": duration != null ? duration : "no data"
1447
+ };
1448
+ console.table(table);
1449
+ }
1450
+ }
1451
+ function resolveDiagnosticsDuration(data) {
1452
+ var _a, _b;
1453
+ if (!data) {
1454
+ return "no data";
1455
+ }
1456
+ return (_b = (_a = data.duration) != null ? _a : data.total) != null ? _b : "no data";
1457
+ }
1458
+
1459
+ // src/logging/logCompositionRouteResponse.ts
1460
+ var import_ansi_colors3 = __toESM(require("ansi-colors"));
1461
+ var { gray: gray2, green: green2, red: red2, yellow: yellow2 } = import_ansi_colors3.default;
1462
+ function logRouteCompositionResponse(matched, duration) {
1463
+ var _a, _b;
1464
+ const resErrors = (_a = matched.compositionApiResponse.errors) != null ? _a : [];
1465
+ const resWarnings = (_b = matched.compositionApiResponse.warnings) != null ? _b : [];
1466
+ const colour = resErrors.length > 0 ? red2 : resWarnings.length > 0 ? yellow2 : green2;
1467
+ console.log(`${colour("Matched")} ${matched.type} ${matched.matchedRoute} (${duration}ms)`);
1468
+ if (matched.dynamicInputs) {
1469
+ const entries = Object.entries(matched.dynamicInputs);
1470
+ if (entries.length > 0) {
1471
+ console.log(
1472
+ ` ${gray2("Matched dynamic inputs:\n ")}`,
1473
+ entries.map(([k, v]) => `${k}: ${v}`).join("\n ")
1474
+ );
1475
+ }
1476
+ }
1477
+ logCompositionResponse(matched.compositionApiResponse, duration);
1478
+ }
1479
+
1480
+ // src/logging/logNotFoundRouteResponse.ts
1481
+ var import_ansi_colors4 = __toESM(require("ansi-colors"));
1482
+ var { yellow: yellow3 } = import_ansi_colors4.default;
1483
+ function logNotFoundRouteResponse(_matched, duration) {
1484
+ console.log(`${yellow3("Not found")} no project map or redirect path match (${duration}ms)`);
1485
+ }
1486
+
1487
+ // src/logging/logRedirectRouteResponse.ts
1488
+ var import_ansi_colors5 = __toESM(require("ansi-colors"));
1489
+ var { green: green3 } = import_ansi_colors5.default;
1490
+ function logRedirectRouteResponse(matched, duration) {
1491
+ console.log(
1492
+ `${green3("Matched")} ${matched.type} ${matched.matchedRoute} (${duration}ms)
1493
+ Target: ${matched.redirect.targetUrl}`
1494
+ );
1495
+ }
1496
+
1497
+ // src/logging/logRouteResponse.ts
1498
+ function logRouteResponse(response, duration) {
1499
+ if (response.type === "redirect") {
1500
+ logRedirectRouteResponse(response, duration);
1501
+ return;
1502
+ }
1503
+ if (response.type === "notFound") {
1504
+ logNotFoundRouteResponse(response, duration);
1505
+ return;
1506
+ }
1507
+ logRouteCompositionResponse(response, duration);
1508
+ }
1509
+
1350
1510
  // src/utils/hash.ts
1351
1511
  var generateHash = ({
1352
1512
  composition,
@@ -1851,6 +2011,9 @@ var CanvasClientError = import_api6.ApiClientError;
1851
2011
  isUpdateCompositionMessage,
1852
2012
  isUpdatePreviewSettingsMessage,
1853
2013
  localize,
2014
+ logCompositionIssues,
2015
+ logCompositionResponse,
2016
+ logRouteResponse,
1854
2017
  mapSlotToPersonalizedVariations,
1855
2018
  mapSlotToTestVariations,
1856
2019
  nullLimitPolicy,
package/dist/index.mjs CHANGED
@@ -1264,6 +1264,163 @@ var UniqueBatchEntries = class {
1264
1264
  }
1265
1265
  };
1266
1266
 
1267
+ // src/logging/logCompositionIssues.ts
1268
+ import ansicolors from "ansi-colors";
1269
+ var { gray, green, italic, red, white, yellow } = ansicolors;
1270
+ function logCompositionIssues(prefix, issues, colour = "red") {
1271
+ const reversedIssues = [...issues].reverse();
1272
+ const colours = { red, green, yellow, white };
1273
+ console.error(
1274
+ `${colours[colour](prefix)}
1275
+ ${reversedIssues.map(
1276
+ (issue) => `${colours[colour](">")} ${italic(gray(indent(issue.type.toUpperCase(), 7)))} ${renderIssue(issue)}`
1277
+ ).join("\n")}`
1278
+ );
1279
+ }
1280
+ function renderIssue(issue) {
1281
+ var _a;
1282
+ let path;
1283
+ let type;
1284
+ let message = issue.message;
1285
+ let detail;
1286
+ if (issue.type !== "config") {
1287
+ path = issue.componentPath;
1288
+ type = issue.componentType;
1289
+ message = issue.message;
1290
+ }
1291
+ if (issue.type === "binding") {
1292
+ detail = `Binding expression: ${(_a = issue.expression) == null ? void 0 : _a.pointer}`;
1293
+ } else if (issue.type === "data") {
1294
+ detail = `Data resource name: ${issue.dataName}, data type: ${issue.dataType}`;
1295
+ }
1296
+ if (issue.type === "input") {
1297
+ detail = issue.inputName;
1298
+ }
1299
+ let result = `${white(blockify(message))}`;
1300
+ if (detail) {
1301
+ result += `
1302
+ ${indent(" ", 10)}${gray(`${detail}`)}`;
1303
+ }
1304
+ if (path && type) {
1305
+ result += `
1306
+ ${indent(" ", 10)}${gray(`Occurred on component ${type} at slot path ${path}`)}`;
1307
+ }
1308
+ return result;
1309
+ }
1310
+ function indent(str, len) {
1311
+ const indent2 = len != null ? len : 10;
1312
+ return str.padStart(indent2);
1313
+ }
1314
+ function blockify(str, len) {
1315
+ const indentSize = len != null ? len : 10;
1316
+ return str.split("\n").map((line, index) => index === 0 ? line : `${indent(" ", indentSize)}${line}`).join("\n");
1317
+ }
1318
+
1319
+ // src/logging/logCompositionResponse.ts
1320
+ import ansicolors2 from "ansi-colors";
1321
+ var { white: white2 } = ansicolors2;
1322
+ function logCompositionResponse(compositionApiResponse, duration) {
1323
+ var _a, _b;
1324
+ const resErrors = (_a = compositionApiResponse.errors) != null ? _a : [];
1325
+ const resWarnings = (_b = compositionApiResponse.warnings) != null ? _b : [];
1326
+ if (resErrors.length > 0) {
1327
+ logCompositionIssues(
1328
+ `Composition data error${resErrors.length === 1 ? "" : "s"}; some content may be missing`,
1329
+ resErrors,
1330
+ "red"
1331
+ );
1332
+ }
1333
+ if (resWarnings.length > 0) {
1334
+ logCompositionIssues(
1335
+ `Composition data warning${resWarnings.length === 1 ? "" : "s"}; some content may be missing`,
1336
+ resWarnings,
1337
+ "yellow"
1338
+ );
1339
+ }
1340
+ if (compositionApiResponse.diagnostics) {
1341
+ console.log(`
1342
+ Diagnostics`);
1343
+ const { compositionFetch, data } = compositionApiResponse.diagnostics;
1344
+ const table = {
1345
+ [`${white2("Composition")}`]: {
1346
+ "Duration (ms)": resolveDiagnosticsDuration(compositionFetch),
1347
+ "Edge Cached": compositionFetch == null ? void 0 : compositionFetch.cacheHit
1348
+ }
1349
+ };
1350
+ if (data) {
1351
+ data.forEach((d) => {
1352
+ table[d.dataName] = {
1353
+ "Duration (ms)": resolveDiagnosticsDuration(d.performance),
1354
+ "Edge Cached": d.performance.cacheHit,
1355
+ "Retry Count": d.performance.retryCount
1356
+ };
1357
+ });
1358
+ }
1359
+ table["Total Response"] = {
1360
+ "Duration (ms)": duration != null ? duration : "no data"
1361
+ };
1362
+ console.table(table);
1363
+ }
1364
+ }
1365
+ function resolveDiagnosticsDuration(data) {
1366
+ var _a, _b;
1367
+ if (!data) {
1368
+ return "no data";
1369
+ }
1370
+ return (_b = (_a = data.duration) != null ? _a : data.total) != null ? _b : "no data";
1371
+ }
1372
+
1373
+ // src/logging/logCompositionRouteResponse.ts
1374
+ import ansicolors3 from "ansi-colors";
1375
+ var { gray: gray2, green: green2, red: red2, yellow: yellow2 } = ansicolors3;
1376
+ function logRouteCompositionResponse(matched, duration) {
1377
+ var _a, _b;
1378
+ const resErrors = (_a = matched.compositionApiResponse.errors) != null ? _a : [];
1379
+ const resWarnings = (_b = matched.compositionApiResponse.warnings) != null ? _b : [];
1380
+ const colour = resErrors.length > 0 ? red2 : resWarnings.length > 0 ? yellow2 : green2;
1381
+ console.log(`${colour("Matched")} ${matched.type} ${matched.matchedRoute} (${duration}ms)`);
1382
+ if (matched.dynamicInputs) {
1383
+ const entries = Object.entries(matched.dynamicInputs);
1384
+ if (entries.length > 0) {
1385
+ console.log(
1386
+ ` ${gray2("Matched dynamic inputs:\n ")}`,
1387
+ entries.map(([k, v]) => `${k}: ${v}`).join("\n ")
1388
+ );
1389
+ }
1390
+ }
1391
+ logCompositionResponse(matched.compositionApiResponse, duration);
1392
+ }
1393
+
1394
+ // src/logging/logNotFoundRouteResponse.ts
1395
+ import ansicolors4 from "ansi-colors";
1396
+ var { yellow: yellow3 } = ansicolors4;
1397
+ function logNotFoundRouteResponse(_matched, duration) {
1398
+ console.log(`${yellow3("Not found")} no project map or redirect path match (${duration}ms)`);
1399
+ }
1400
+
1401
+ // src/logging/logRedirectRouteResponse.ts
1402
+ import ansicolors5 from "ansi-colors";
1403
+ var { green: green3 } = ansicolors5;
1404
+ function logRedirectRouteResponse(matched, duration) {
1405
+ console.log(
1406
+ `${green3("Matched")} ${matched.type} ${matched.matchedRoute} (${duration}ms)
1407
+ Target: ${matched.redirect.targetUrl}`
1408
+ );
1409
+ }
1410
+
1411
+ // src/logging/logRouteResponse.ts
1412
+ function logRouteResponse(response, duration) {
1413
+ if (response.type === "redirect") {
1414
+ logRedirectRouteResponse(response, duration);
1415
+ return;
1416
+ }
1417
+ if (response.type === "notFound") {
1418
+ logNotFoundRouteResponse(response, duration);
1419
+ return;
1420
+ }
1421
+ logRouteCompositionResponse(response, duration);
1422
+ }
1423
+
1267
1424
  // src/utils/hash.ts
1268
1425
  var generateHash = ({
1269
1426
  composition,
@@ -1767,6 +1924,9 @@ export {
1767
1924
  isUpdateCompositionMessage,
1768
1925
  isUpdatePreviewSettingsMessage,
1769
1926
  localize,
1927
+ logCompositionIssues,
1928
+ logCompositionResponse,
1929
+ logRouteResponse,
1770
1930
  mapSlotToPersonalizedVariations,
1771
1931
  mapSlotToTestVariations,
1772
1932
  nullLimitPolicy,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@uniformdev/canvas",
3
- "version": "19.10.0",
3
+ "version": "19.11.0",
4
4
  "description": "Common functionality and types for Uniform Canvas",
5
5
  "license": "SEE LICENSE IN LICENSE.txt",
6
6
  "main": "./dist/index.js",
@@ -17,16 +17,6 @@
17
17
  }
18
18
  },
19
19
  "types": "./dist/index.d.ts",
20
- "typesVersions": {
21
- "*": {
22
- ".": [
23
- "./dist/index.d.ts"
24
- ],
25
- "cli": [
26
- "./dist/cli/cli.d.ts"
27
- ]
28
- }
29
- },
30
20
  "sideEffects": false,
31
21
  "scripts": {
32
22
  "build": "run-s update-openapi build:ts",
@@ -47,7 +37,8 @@
47
37
  "pusher-js": "8.0.1"
48
38
  },
49
39
  "dependencies": {
50
- "@uniformdev/context": "19.10.0",
40
+ "@uniformdev/context": "19.11.0",
41
+ "ansi-colors": "^4.1.3",
51
42
  "immer": "9.0.21"
52
43
  },
53
44
  "files": [
@@ -56,5 +47,5 @@
56
47
  "publishConfig": {
57
48
  "access": "public"
58
49
  },
59
- "gitHead": "149f942da715ed802545850283f9b99291829a04"
50
+ "gitHead": "25d492fe923f313b517cbc70d3ff13fdcf97fa34"
60
51
  }