@gooddata/sdk-code-convertors 11.63.0-alpha.0 → 11.63.0-alpha.2
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/esm/declarativePublisherTypesV2.d.ts +27 -0
- package/esm/declarativePublisherTypesV2.d.ts.map +1 -0
- package/esm/declarativePublisherTypesV2.js +2 -0
- package/esm/fillPublisherIdsV2.d.ts +16 -0
- package/esm/fillPublisherIdsV2.d.ts.map +1 -0
- package/esm/fillPublisherIdsV2.js +149 -0
- package/esm/from/declarativePublisherDocumentPageToYaml.d.ts +3 -10
- package/esm/from/declarativePublisherDocumentPageToYaml.d.ts.map +1 -1
- package/esm/from/declarativePublisherDocumentPageToYaml.js +12 -25
- package/esm/from/declarativePublisherDocumentToYaml.d.ts +5 -5
- package/esm/from/declarativePublisherDocumentToYaml.d.ts.map +1 -1
- package/esm/from/declarativePublisherDocumentToYaml.js +2 -1
- package/esm/from/declarativePublisherEntityToYamlV2.d.ts +52 -0
- package/esm/from/declarativePublisherEntityToYamlV2.d.ts.map +1 -0
- package/esm/from/declarativePublisherEntityToYamlV2.js +216 -0
- package/esm/index.d.ts +6 -1
- package/esm/index.d.ts.map +1 -1
- package/esm/index.js +4 -0
- package/esm/schemas/types.d.ts +17 -1
- package/esm/schemas/types.d.ts.map +1 -1
- package/esm/sdk-code-convertors.d.ts +187 -14
- package/esm/to/yamlPublisherDocumentPageToDeclarative.d.ts +4 -11
- package/esm/to/yamlPublisherDocumentPageToDeclarative.d.ts.map +1 -1
- package/esm/to/yamlPublisherDocumentPageToDeclarative.js +2 -17
- package/esm/to/yamlPublisherDocumentToDeclarative.d.ts +4 -4
- package/esm/to/yamlPublisherDocumentToDeclarative.d.ts.map +1 -1
- package/esm/to/yamlPublisherDocumentToDeclarative.js +2 -1
- package/esm/to/yamlPublisherEntityToDeclarativeV2.d.ts +34 -0
- package/esm/to/yamlPublisherEntityToDeclarativeV2.d.ts.map +1 -0
- package/esm/to/yamlPublisherEntityToDeclarativeV2.js +190 -0
- package/esm/utils/errors.d.ts +6 -1
- package/esm/utils/errors.d.ts.map +1 -1
- package/esm/utils/errors.js +15 -0
- package/esm/utils/keyCase.d.ts +24 -0
- package/esm/utils/keyCase.d.ts.map +1 -0
- package/esm/utils/keyCase.js +28 -0
- package/esm/utils/publisherContentV2.d.ts +25 -0
- package/esm/utils/publisherContentV2.d.ts.map +1 -0
- package/esm/utils/publisherContentV2.js +33 -0
- package/esm/utils/publisherFilters.d.ts +50 -0
- package/esm/utils/publisherFilters.d.ts.map +1 -0
- package/esm/utils/publisherFilters.js +122 -0
- package/esm/utils/publisherPeriodV2.d.ts +7 -0
- package/esm/utils/publisherPeriodV2.d.ts.map +1 -0
- package/esm/utils/publisherPeriodV2.js +34 -0
- package/esm/utils/publisherVersionV2.d.ts +9 -0
- package/esm/utils/publisherVersionV2.d.ts.map +1 -0
- package/esm/utils/publisherVersionV2.js +10 -0
- package/esm/utils/texts.d.ts +1 -0
- package/esm/utils/texts.d.ts.map +1 -1
- package/esm/utils/texts.js +5 -0
- package/esm/validateDeclarativePublisherEntityV2.d.ts +10 -0
- package/esm/validateDeclarativePublisherEntityV2.d.ts.map +1 -0
- package/esm/validateDeclarativePublisherEntityV2.js +34 -0
- package/package.json +6 -6
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
// (C) 2026 GoodData Corporation
|
|
2
|
+
import { idRef, } from "@gooddata/sdk-model";
|
|
3
|
+
import { CoreErrorCode, newError, updateErrorContext } from "../utils/errors.js";
|
|
4
|
+
import { camelKeys } from "../utils/keyCase.js";
|
|
5
|
+
import { pagesOrSectionsV2, unknownLayoutNodeV2 } from "../utils/publisherContentV2.js";
|
|
6
|
+
import { referencesAsStored } from "../utils/publisherFilterRefs.js";
|
|
7
|
+
import { assertDocumentDateFiltersNameDataSet, filtersToDeclarativeV2 } from "../utils/publisherFilters.js";
|
|
8
|
+
import { periodToDeclarativeV2 } from "../utils/publisherPeriodV2.js";
|
|
9
|
+
import { assertPublisherContentVersionV2, publisherContentVersionV2 } from "../utils/publisherVersionV2.js";
|
|
10
|
+
import { yamlIgnoredFilterToDeclarative } from "./yamlDashboardToDeclarative.js";
|
|
11
|
+
function ignoredFilterToDeclarative(id, errorContext) {
|
|
12
|
+
const reference = yamlIgnoredFilterToDeclarative(id);
|
|
13
|
+
if (reference === null) {
|
|
14
|
+
throw newError(CoreErrorCode.ReferenceTypeNotSupported, [id], errorContext);
|
|
15
|
+
}
|
|
16
|
+
return referencesAsStored(reference);
|
|
17
|
+
}
|
|
18
|
+
function visualizationToDeclarative(widget, errorContext) {
|
|
19
|
+
const { visualization, date, filters, ignored_filters, ...rest } = widget;
|
|
20
|
+
return {
|
|
21
|
+
...camelKeys(rest),
|
|
22
|
+
...(visualization === undefined
|
|
23
|
+
? {}
|
|
24
|
+
: { visualization: { identifier: visualization, type: "insight" } }),
|
|
25
|
+
...(date === undefined ? {} : { dateDataSet: { identifier: date, type: "dataSet" } }),
|
|
26
|
+
...(filters === undefined
|
|
27
|
+
? {}
|
|
28
|
+
: { filters: filtersToDeclarativeV2(filters, "widget", errorContext).filters }),
|
|
29
|
+
...(ignored_filters === undefined
|
|
30
|
+
? {}
|
|
31
|
+
: {
|
|
32
|
+
ignoreDocumentFilters: ignored_filters.map((id) => ignoredFilterToDeclarative(id, errorContext)),
|
|
33
|
+
}),
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
function layoutNodeToDeclarative(node, errorContext) {
|
|
37
|
+
switch (node.type) {
|
|
38
|
+
case "row":
|
|
39
|
+
case "column": {
|
|
40
|
+
const { children, ...container } = node;
|
|
41
|
+
return {
|
|
42
|
+
...camelKeys(container),
|
|
43
|
+
children: children.map((child) => layoutNodeToDeclarative(child, errorContext)),
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
case "visualization":
|
|
47
|
+
return visualizationToDeclarative(node, errorContext);
|
|
48
|
+
case "title":
|
|
49
|
+
case "heading":
|
|
50
|
+
case "text":
|
|
51
|
+
case "image":
|
|
52
|
+
case "takeaway":
|
|
53
|
+
return camelKeys(node);
|
|
54
|
+
default:
|
|
55
|
+
throw unknownLayoutNodeV2(node, errorContext);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
function pageBodyToDeclarative(body, errorContext) {
|
|
59
|
+
const { layout, filters, ...rest } = body;
|
|
60
|
+
return {
|
|
61
|
+
...camelKeys(rest),
|
|
62
|
+
layout: layoutNodeToDeclarative(layout, errorContext),
|
|
63
|
+
...(filters === undefined
|
|
64
|
+
? {}
|
|
65
|
+
: { filters: filtersToDeclarativeV2(filters, "page", errorContext).filters }),
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
function documentPageToDeclarative(page, errorContext) {
|
|
69
|
+
const { id, visible, ...body } = page;
|
|
70
|
+
return {
|
|
71
|
+
id,
|
|
72
|
+
...(visible === undefined ? {} : { visible }),
|
|
73
|
+
...pageBodyToDeclarative(body, updateErrorContext(errorContext, { path: [id] })),
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
function sectionToDeclarative(section, errorContext) {
|
|
77
|
+
const { pages, ...rest } = section;
|
|
78
|
+
const pagesContext = updateErrorContext(errorContext, { path: ["sections", section.id, "pages"] });
|
|
79
|
+
return { ...rest, pages: pages.map((page) => documentPageToDeclarative(page, pagesContext)) };
|
|
80
|
+
}
|
|
81
|
+
function defaultsToDeclarative({ period, ...rest }) {
|
|
82
|
+
return {
|
|
83
|
+
...camelKeys(rest),
|
|
84
|
+
...(period === undefined ? {} : { period: periodToDeclarativeV2(period) }),
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
function contentToDeclarative(content, errorContext) {
|
|
88
|
+
const { defaults, filters, pages, sections, ...rest } = content;
|
|
89
|
+
const held = pagesOrSectionsV2({ pages, sections }, errorContext);
|
|
90
|
+
const filtersContext = updateErrorContext(errorContext, { path: ["filters"] });
|
|
91
|
+
const declared = filters === undefined ? undefined : filtersToDeclarativeV2(filters, "document", filtersContext);
|
|
92
|
+
if (declared !== undefined) {
|
|
93
|
+
assertDocumentDateFiltersNameDataSet(declared.filters, filtersContext);
|
|
94
|
+
}
|
|
95
|
+
const base = {
|
|
96
|
+
...(defaults === undefined
|
|
97
|
+
? {}
|
|
98
|
+
: {
|
|
99
|
+
defaults: defaultsToDeclarative(defaults),
|
|
100
|
+
}),
|
|
101
|
+
...declared,
|
|
102
|
+
...camelKeys(rest),
|
|
103
|
+
};
|
|
104
|
+
if (held.sections !== undefined) {
|
|
105
|
+
return {
|
|
106
|
+
...base,
|
|
107
|
+
sections: held.sections.map((section) => sectionToDeclarative(section, errorContext)),
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
const pagesContext = updateErrorContext(errorContext, { path: ["pages"] });
|
|
111
|
+
return { ...base, pages: held.pages.map((page) => documentPageToDeclarative(page, pagesContext)) };
|
|
112
|
+
}
|
|
113
|
+
function entityFields(entity) {
|
|
114
|
+
return {
|
|
115
|
+
title: entity.title,
|
|
116
|
+
...(entity.description === undefined ? {} : { description: entity.description }),
|
|
117
|
+
...(entity.tags === undefined ? {} : { tags: entity.tags }),
|
|
118
|
+
version: publisherContentVersionV2,
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
function documentBody(input, errorContext) {
|
|
122
|
+
assertPublisherContentVersionV2(input, errorContext);
|
|
123
|
+
return {
|
|
124
|
+
type: "document",
|
|
125
|
+
...entityFields(input),
|
|
126
|
+
period: periodToDeclarativeV2(input.period),
|
|
127
|
+
content: contentToDeclarative(input.content, updateErrorContext(errorContext, { path: ["content"] })),
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
function documentTemplateBody(input, errorContext) {
|
|
131
|
+
assertPublisherContentVersionV2(input, errorContext);
|
|
132
|
+
return {
|
|
133
|
+
type: "documentTemplate",
|
|
134
|
+
...entityFields(input),
|
|
135
|
+
content: contentToDeclarative(input.content, updateErrorContext(errorContext, { path: ["content"] })),
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
function pageTemplateBody(input, errorContext) {
|
|
139
|
+
assertPublisherContentVersionV2(input, errorContext);
|
|
140
|
+
return {
|
|
141
|
+
type: "pageTemplate",
|
|
142
|
+
...entityFields(input),
|
|
143
|
+
content: pageBodyToDeclarative(input.content, updateErrorContext(errorContext, { path: ["content"] })),
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
/** An `id:` written without a value reads as null and counts as missing. */
|
|
147
|
+
function refFromId(id) {
|
|
148
|
+
return id === undefined || id === null ? {} : { ref: idRef(id) };
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Converts a v2 document as code to the stored document.
|
|
152
|
+
*
|
|
153
|
+
* @alpha
|
|
154
|
+
*/
|
|
155
|
+
export function yamlPublisherDocumentToDeclarativeV2(input, errorContext) {
|
|
156
|
+
return { id: input.id, ...documentBody(input, errorContext) };
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Converts a v2 document template as code to the stored document template.
|
|
160
|
+
*
|
|
161
|
+
* @alpha
|
|
162
|
+
*/
|
|
163
|
+
export function yamlPublisherDocumentTemplateToDeclarativeV2(input, errorContext) {
|
|
164
|
+
return { id: input.id, ...documentTemplateBody(input, errorContext) };
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* Converts a v2 page template as code to the stored page template.
|
|
168
|
+
*
|
|
169
|
+
* @alpha
|
|
170
|
+
*/
|
|
171
|
+
export function yamlPublisherPageTemplateToDeclarativeV2(input, errorContext) {
|
|
172
|
+
return { id: input.id, ...pageTemplateBody(input, errorContext) };
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* Converts a v2 document as code to the definition the frontend holds: an object reference in place
|
|
176
|
+
* of the bare id. A document written without an id reads back without a reference.
|
|
177
|
+
*
|
|
178
|
+
* @alpha
|
|
179
|
+
*/
|
|
180
|
+
export function yamlPublisherDocumentToDefinitionV2(input, errorContext) {
|
|
181
|
+
return { ...documentBody(input, errorContext), ...refFromId(input.id) };
|
|
182
|
+
}
|
|
183
|
+
/** @alpha */
|
|
184
|
+
export function yamlPublisherDocumentTemplateToDefinitionV2(input, errorContext) {
|
|
185
|
+
return { ...documentTemplateBody(input, errorContext), ...refFromId(input.id) };
|
|
186
|
+
}
|
|
187
|
+
/** @alpha */
|
|
188
|
+
export function yamlPublisherPageTemplateToDefinitionV2(input, errorContext) {
|
|
189
|
+
return { ...pageTemplateBody(input, errorContext), ...refFromId(input.id) };
|
|
190
|
+
}
|
package/esm/utils/errors.d.ts
CHANGED
|
@@ -18,7 +18,12 @@ export declare enum CoreErrorCode {
|
|
|
18
18
|
DuplicateLayerIdentifier = "core.duplicateLayerIdentifier",
|
|
19
19
|
DuplicateTabIdentifier = "core.duplicateTabIdentifier",
|
|
20
20
|
TabsAndRootContentMutuallyExclusive = "core.tabsAndRootContentMutuallyExclusive",
|
|
21
|
-
InvalidIanaTimezoneId = "core.invalidIanaTimezoneId"
|
|
21
|
+
InvalidIanaTimezoneId = "core.invalidIanaTimezoneId",
|
|
22
|
+
UnsupportedContentVersion = "core.unsupportedContentVersion",
|
|
23
|
+
DateFilterWithoutDataSet = "core.dateFilterWithoutDataSet",
|
|
24
|
+
FilterSettingNotStorable = "core.filterSettingNotStorable",
|
|
25
|
+
PagesAndSectionsMutuallyExclusive = "core.pagesAndSectionsMutuallyExclusive",
|
|
26
|
+
PagesOrSectionsRequired = "core.pagesOrSectionsRequired"
|
|
22
27
|
}
|
|
23
28
|
/**
|
|
24
29
|
* @public
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/utils/errors.ts"],"names":[],"mappings":"AAEA;;GAEG;AACH,oBAAY,aAAa;IAErB,0BAA0B,oCAAoC;IAC9D,0BAA0B,oCAAoC;IAC9D,gBAAgB,0BAA0B;IAC1C,yBAAyB,mCAAmC;IAC5D,yBAAyB,mCAAmC;IAC5D,qBAAqB,+BAA+B;IACpD,oBAAoB,8BAA8B;IAClD,yBAAyB,mCAAmC;IAC5D,2BAA2B,qCAAqC;IAChE,yBAAyB,mCAAmC;IAC5D,8BAA8B,wCAAwC;IACtE,kBAAkB,4BAA4B;IAC9C,mBAAmB,6BAA6B;IAChD,wBAAwB,kCAAkC;IAC1D,sBAAsB,gCAAgC;IACtD,mCAAmC,6CAA6C;IAChF,qBAAqB,+BAA+B;
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/utils/errors.ts"],"names":[],"mappings":"AAEA;;GAEG;AACH,oBAAY,aAAa;IAErB,0BAA0B,oCAAoC;IAC9D,0BAA0B,oCAAoC;IAC9D,gBAAgB,0BAA0B;IAC1C,yBAAyB,mCAAmC;IAC5D,yBAAyB,mCAAmC;IAC5D,qBAAqB,+BAA+B;IACpD,oBAAoB,8BAA8B;IAClD,yBAAyB,mCAAmC;IAC5D,2BAA2B,qCAAqC;IAChE,yBAAyB,mCAAmC;IAC5D,8BAA8B,wCAAwC;IACtE,kBAAkB,4BAA4B;IAC9C,mBAAmB,6BAA6B;IAChD,wBAAwB,kCAAkC;IAC1D,sBAAsB,gCAAgC;IACtD,mCAAmC,6CAA6C;IAChF,qBAAqB,+BAA+B;IACpD,yBAAyB,mCAAmC;IAC5D,wBAAwB,kCAAkC;IAC1D,wBAAwB,kCAAkC;IAC1D,iCAAiC,2CAA2C;IAC5E,uBAAuB,iCAAiC;CAC3D;AAED;;GAEG;AACH,eAAO,MAAM,iBAAiB,EAAE,MAAM,CAAC,aAAa,EAAE,MAAM,CAuB3D,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,cAAc,EAAE,MAAM,CAAC,aAAa,EAAE,MAAM,CAuBxD,CAAC;AAEF;;GAEG;AACH,MAAM,WAAW,aAAa;IAC1B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,IAAI,CAAC,EAAE,OAAO,CAAC;CAClB;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAC9B,OAAO,EAAE,aAAa,GAAG,SAAS,EAClC,KAAK,EAAE,OAAO,CAAC,aAAa,CAAC,GAC9B,aAAa,CAaf;AAED;;GAEG;AACH,MAAM,WAAW,UAAW,SAAQ,KAAK;IACrC,IAAI,EAAE,aAAa,CAAC;IACpB,IAAI,EAAE,CAAC,OAAO,cAAc,CAAC,CAAC,MAAM,OAAO,cAAc,CAAC,CAAC;IAC3D,OAAO,CAAC,EAAE,aAAa,CAAC;CAC3B;AAED,wBAAgB,QAAQ,CAAC,IAAI,EAAE,aAAa,EAAE,MAAM,GAAE,KAAK,CAAC,MAAM,CAAM,EAAE,OAAO,CAAC,EAAE,aAAa,cAOhG;AAED,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC,EAAE,aAAa,UAU3F"}
|
package/esm/utils/errors.js
CHANGED
|
@@ -22,6 +22,11 @@ export var CoreErrorCode;
|
|
|
22
22
|
CoreErrorCode["DuplicateTabIdentifier"] = "core.duplicateTabIdentifier";
|
|
23
23
|
CoreErrorCode["TabsAndRootContentMutuallyExclusive"] = "core.tabsAndRootContentMutuallyExclusive";
|
|
24
24
|
CoreErrorCode["InvalidIanaTimezoneId"] = "core.invalidIanaTimezoneId";
|
|
25
|
+
CoreErrorCode["UnsupportedContentVersion"] = "core.unsupportedContentVersion";
|
|
26
|
+
CoreErrorCode["DateFilterWithoutDataSet"] = "core.dateFilterWithoutDataSet";
|
|
27
|
+
CoreErrorCode["FilterSettingNotStorable"] = "core.filterSettingNotStorable";
|
|
28
|
+
CoreErrorCode["PagesAndSectionsMutuallyExclusive"] = "core.pagesAndSectionsMutuallyExclusive";
|
|
29
|
+
CoreErrorCode["PagesOrSectionsRequired"] = "core.pagesOrSectionsRequired";
|
|
25
30
|
})(CoreErrorCode || (CoreErrorCode = {}));
|
|
26
31
|
/**
|
|
27
32
|
* @public
|
|
@@ -44,6 +49,11 @@ export const CoreErrorMessages = {
|
|
|
44
49
|
[CoreErrorCode.DuplicateTabIdentifier]: `Duplicate tab identifier "{0}". Each tab must have a unique identifier within the dashboard.`,
|
|
45
50
|
[CoreErrorCode.TabsAndRootContentMutuallyExclusive]: `Dashboard "{0}" defines both "tabs" and root-level "sections" or "filters". These are mutually exclusive — keep all content inside tabs or at the root, not both.`,
|
|
46
51
|
[CoreErrorCode.InvalidIanaTimezoneId]: `"{0}" is not a valid IANA timezone ID. Use a real timezone such as Europe/Prague or $browserDetected.`,
|
|
52
|
+
[CoreErrorCode.UnsupportedContentVersion]: `Content version "{0}" is not supported. Supported version: "{1}".`,
|
|
53
|
+
[CoreErrorCode.DateFilterWithoutDataSet]: `Date filter "{0}" names no date dataset. A document date filter must name the date dataset it applies to.`,
|
|
54
|
+
[CoreErrorCode.FilterSettingNotStorable]: `Filter "{0}" sets "{1}", which a {2} cannot store.`,
|
|
55
|
+
[CoreErrorCode.PagesAndSectionsMutuallyExclusive]: `Content defines both "pages" and "sections". Keep the pages at the top level or inside sections, not both.`,
|
|
56
|
+
[CoreErrorCode.PagesOrSectionsRequired]: `Content defines neither "pages" nor "sections". Add one of them; an empty document has "pages: []".`,
|
|
47
57
|
};
|
|
48
58
|
/**
|
|
49
59
|
* @public
|
|
@@ -66,6 +76,11 @@ export const CoreErrorTypes = {
|
|
|
66
76
|
[CoreErrorCode.DuplicateTabIdentifier]: "DuplicateTabIdentifier",
|
|
67
77
|
[CoreErrorCode.TabsAndRootContentMutuallyExclusive]: "TabsAndRootContentMutuallyExclusive",
|
|
68
78
|
[CoreErrorCode.InvalidIanaTimezoneId]: "InvalidIanaTimezoneId",
|
|
79
|
+
[CoreErrorCode.UnsupportedContentVersion]: "UnsupportedContentVersion",
|
|
80
|
+
[CoreErrorCode.DateFilterWithoutDataSet]: "DateFilterWithoutDataSet",
|
|
81
|
+
[CoreErrorCode.FilterSettingNotStorable]: "FilterSettingNotStorable",
|
|
82
|
+
[CoreErrorCode.PagesAndSectionsMutuallyExclusive]: "PagesAndSectionsMutuallyExclusive",
|
|
83
|
+
[CoreErrorCode.PagesOrSectionsRequired]: "PagesOrSectionsRequired",
|
|
69
84
|
};
|
|
70
85
|
/**
|
|
71
86
|
* Update error context with new values
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
type SnakeCase<S extends string> = S extends `${infer Head}${infer Tail}` ? `${Head extends Lowercase<Head> ? Head : `_${Lowercase<Head>}`}${SnakeCase<Tail>}` : S;
|
|
2
|
+
type CamelCase<S extends string> = S extends `${infer Head}_${infer Tail}` ? `${Head}${Capitalize<CamelCase<Tail>>}` : S;
|
|
3
|
+
/** @internal */
|
|
4
|
+
export type SnakeKeys<T> = T extends readonly (infer Item)[] ? SnakeKeys<Item>[] : T extends object ? {
|
|
5
|
+
[K in keyof T as K extends string ? SnakeCase<K> : K]: SnakeKeys<T[K]>;
|
|
6
|
+
} : T;
|
|
7
|
+
/** @internal */
|
|
8
|
+
export type CamelKeys<T> = T extends readonly (infer Item)[] ? CamelKeys<Item>[] : T extends object ? {
|
|
9
|
+
[K in keyof T as K extends string ? CamelCase<K> : K]: CamelKeys<T[K]>;
|
|
10
|
+
} : T;
|
|
11
|
+
/**
|
|
12
|
+
* Every key of a plain JSON value, at any depth, in snake_case. Values are kept as they are.
|
|
13
|
+
*
|
|
14
|
+
* @internal
|
|
15
|
+
*/
|
|
16
|
+
export declare function snakeKeys<T>(value: T): SnakeKeys<T>;
|
|
17
|
+
/**
|
|
18
|
+
* Every key of a plain JSON value, at any depth, in camelCase. Values are kept as they are.
|
|
19
|
+
*
|
|
20
|
+
* @internal
|
|
21
|
+
*/
|
|
22
|
+
export declare function camelKeys<T>(value: T): CamelKeys<T>;
|
|
23
|
+
export {};
|
|
24
|
+
//# sourceMappingURL=keyCase.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"keyCase.d.ts","sourceRoot":"","sources":["../../src/utils/keyCase.ts"],"names":[],"mappings":"AAEA,KAAK,SAAS,CAAC,CAAC,SAAS,MAAM,IAAI,CAAC,SAAS,GAAG,MAAM,IAAI,GAAG,MAAM,IAAI,EAAE,GACnE,GAAG,IAAI,SAAS,SAAS,CAAC,IAAI,CAAC,GAAG,IAAI,GAAG,IAAI,SAAS,CAAC,IAAI,CAAC,EAAE,GAAG,SAAS,CAAC,IAAI,CAAC,EAAE,GAClF,CAAC,CAAC;AAER,KAAK,SAAS,CAAC,CAAC,SAAS,MAAM,IAAI,CAAC,SAAS,GAAG,MAAM,IAAI,IAAI,MAAM,IAAI,EAAE,GACpE,GAAG,IAAI,GAAG,UAAU,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,EAAE,GACvC,CAAC,CAAC;AAER,gBAAgB;AAChB,MAAM,MAAM,SAAS,CAAC,CAAC,IAAI,CAAC,SAAS,SAAS,CAAC,MAAM,IAAI,CAAC,EAAE,GACtD,SAAS,CAAC,IAAI,CAAC,EAAE,GACjB,CAAC,SAAS,MAAM,GACd;KAAG,CAAC,IAAI,MAAM,CAAC,IAAI,CAAC,SAAS,MAAM,GAAG,SAAS,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;CAAE,GAC1E,CAAC,CAAC;AAEV,gBAAgB;AAChB,MAAM,MAAM,SAAS,CAAC,CAAC,IAAI,CAAC,SAAS,SAAS,CAAC,MAAM,IAAI,CAAC,EAAE,GACtD,SAAS,CAAC,IAAI,CAAC,EAAE,GACjB,CAAC,SAAS,MAAM,GACd;KAAG,CAAC,IAAI,MAAM,CAAC,IAAI,CAAC,SAAS,MAAM,GAAG,SAAS,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;CAAE,GAC1E,CAAC,CAAC;AAcV;;;;GAIG;AACH,wBAAgB,SAAS,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,GAAG,SAAS,CAAC,CAAC,CAAC,CAKnD;AAED;;;;GAIG;AACH,wBAAgB,SAAS,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,GAAG,SAAS,CAAC,CAAC,CAAC,CAKnD"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
// (C) 2026 GoodData Corporation
|
|
2
|
+
function mapKeys(value, rename) {
|
|
3
|
+
if (Array.isArray(value)) {
|
|
4
|
+
return value.map((item) => mapKeys(item, rename));
|
|
5
|
+
}
|
|
6
|
+
if (value === null || typeof value !== "object") {
|
|
7
|
+
return value;
|
|
8
|
+
}
|
|
9
|
+
return Object.fromEntries(Object.entries(value).map(([key, item]) => [rename(key), mapKeys(item, rename)]));
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Every key of a plain JSON value, at any depth, in snake_case. Values are kept as they are.
|
|
13
|
+
*
|
|
14
|
+
* @internal
|
|
15
|
+
*/
|
|
16
|
+
export function snakeKeys(value) {
|
|
17
|
+
// Sound only while the regex renames exactly as the SnakeCase type does.
|
|
18
|
+
return mapKeys(value, (key) => key.replace(/[A-Z]/g, (letter) => `_${letter.toLowerCase()}`));
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Every key of a plain JSON value, at any depth, in camelCase. Values are kept as they are.
|
|
22
|
+
*
|
|
23
|
+
* @internal
|
|
24
|
+
*/
|
|
25
|
+
export function camelKeys(value) {
|
|
26
|
+
// Sound only while the regex renames exactly as the CamelCase type does.
|
|
27
|
+
return mapKeys(value, (key) => key.replace(/_([a-z0-9])/g, (_, letter) => letter.toUpperCase()));
|
|
28
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { type IErrorContext } from "./errors.js";
|
|
2
|
+
/**
|
|
3
|
+
* The one of `pages` and `sections` that document content holds. Both or neither throws. Both keys
|
|
4
|
+
* written counts as both, whatever their values, as the schema reads it; otherwise a key written
|
|
5
|
+
* without a value, which YAML reads as null, counts as missing.
|
|
6
|
+
*
|
|
7
|
+
* @internal
|
|
8
|
+
*/
|
|
9
|
+
export declare function pagesOrSectionsV2<Pages, Sections>({ pages, sections }: {
|
|
10
|
+
pages?: Pages | null;
|
|
11
|
+
sections?: Sections | null;
|
|
12
|
+
}, errorContext: IErrorContext | undefined): {
|
|
13
|
+
pages: Pages;
|
|
14
|
+
sections?: never;
|
|
15
|
+
} | {
|
|
16
|
+
pages?: never;
|
|
17
|
+
sections: Sections;
|
|
18
|
+
};
|
|
19
|
+
/**
|
|
20
|
+
* The error for a layout node whose type the v2 converters do not know.
|
|
21
|
+
*
|
|
22
|
+
* @internal
|
|
23
|
+
*/
|
|
24
|
+
export declare function unknownLayoutNodeV2(node: never, errorContext: IErrorContext | undefined): Error;
|
|
25
|
+
//# sourceMappingURL=publisherContentV2.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"publisherContentV2.d.ts","sourceRoot":"","sources":["../../src/utils/publisherContentV2.ts"],"names":[],"mappings":"AAEA,OAAO,EAAiB,KAAK,aAAa,EAAY,MAAM,aAAa,CAAC;AAE1E;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,QAAQ,EAC7C,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE;IAAE,KAAK,CAAC,EAAE,KAAK,GAAG,IAAI,CAAC;IAAC,QAAQ,CAAC,EAAE,QAAQ,GAAG,IAAI,CAAA;CAAE,EACzE,YAAY,EAAE,aAAa,GAAG,SAAS,GACxC;IAAE,KAAK,EAAE,KAAK,CAAC;IAAC,QAAQ,CAAC,EAAE,KAAK,CAAA;CAAE,GAAG;IAAE,KAAK,CAAC,EAAE,KAAK,CAAC;IAAC,QAAQ,EAAE,QAAQ,CAAA;CAAE,CAa5E;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,KAAK,EAAE,YAAY,EAAE,aAAa,GAAG,SAAS,GAAG,KAAK,CAI/F"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
// (C) 2026 GoodData Corporation
|
|
2
|
+
import { CoreErrorCode, newError } from "./errors.js";
|
|
3
|
+
/**
|
|
4
|
+
* The one of `pages` and `sections` that document content holds. Both or neither throws. Both keys
|
|
5
|
+
* written counts as both, whatever their values, as the schema reads it; otherwise a key written
|
|
6
|
+
* without a value, which YAML reads as null, counts as missing.
|
|
7
|
+
*
|
|
8
|
+
* @internal
|
|
9
|
+
*/
|
|
10
|
+
export function pagesOrSectionsV2({ pages, sections }, errorContext) {
|
|
11
|
+
if (pages !== undefined && sections !== undefined) {
|
|
12
|
+
throw newError(CoreErrorCode.PagesAndSectionsMutuallyExclusive, [], errorContext);
|
|
13
|
+
}
|
|
14
|
+
const hasPages = pages !== null && pages !== undefined;
|
|
15
|
+
const hasSections = sections !== null && sections !== undefined;
|
|
16
|
+
if (hasSections) {
|
|
17
|
+
return { sections };
|
|
18
|
+
}
|
|
19
|
+
if (hasPages) {
|
|
20
|
+
return { pages };
|
|
21
|
+
}
|
|
22
|
+
throw newError(CoreErrorCode.PagesOrSectionsRequired, [], errorContext);
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* The error for a layout node whose type the v2 converters do not know.
|
|
26
|
+
*
|
|
27
|
+
* @internal
|
|
28
|
+
*/
|
|
29
|
+
export function unknownLayoutNodeV2(node, errorContext) {
|
|
30
|
+
// Unreachable for typed input; stored data and YAML are not checked against the node union.
|
|
31
|
+
const { type } = node;
|
|
32
|
+
return newError(CoreErrorCode.ItemNotSupported, [JSON.stringify({ node: type })], errorContext);
|
|
33
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { type YAMLMap } from "yaml";
|
|
2
|
+
import type { DashboardFilters } from "@gooddata/sdk-code-schemas/v1";
|
|
3
|
+
import { type FilterContextItem, type IDashboardAttributeFilterConfig } from "@gooddata/sdk-model";
|
|
4
|
+
import { type IErrorContext } from "./errors.js";
|
|
5
|
+
/**
|
|
6
|
+
* A document holds its filters the way a dashboard's filter context does, so the same convertor writes
|
|
7
|
+
* them; only the envelope it expects is put around them here.
|
|
8
|
+
*
|
|
9
|
+
* @internal
|
|
10
|
+
*/
|
|
11
|
+
export declare function filtersToYaml(filters: FilterContextItem[] | undefined): YAMLMap | undefined;
|
|
12
|
+
/**
|
|
13
|
+
* A document holds its filters the way a dashboard's filter context does, so they are written and read
|
|
14
|
+
* back by the same convertor; only the envelope it expects is put around them here.
|
|
15
|
+
*
|
|
16
|
+
* @internal
|
|
17
|
+
*/
|
|
18
|
+
export declare function filtersToDeclarative(filters: DashboardFilters | undefined): FilterContextItem[] | undefined;
|
|
19
|
+
/**
|
|
20
|
+
* What holds a v2 filter list. Only a document keeps attribute filter settings (`mode`, `display_as`,
|
|
21
|
+
* `selection_type`), in its `attributeFilterConfigs`.
|
|
22
|
+
*
|
|
23
|
+
* @internal
|
|
24
|
+
*/
|
|
25
|
+
export type PublisherFilterHolderV2 = "document" | "page" | "widget";
|
|
26
|
+
/** @internal */
|
|
27
|
+
export interface IPublisherFiltersV2 {
|
|
28
|
+
filters: FilterContextItem[];
|
|
29
|
+
attributeFilterConfigs?: IDashboardAttributeFilterConfig[];
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Reads a v2 filter list. A setting the v2 shape has nowhere to keep throws instead of being dropped.
|
|
33
|
+
*
|
|
34
|
+
* @internal
|
|
35
|
+
*/
|
|
36
|
+
export declare function filtersToDeclarativeV2(filters: DashboardFilters, holder: PublisherFilterHolderV2, errorContext?: IErrorContext): IPublisherFiltersV2;
|
|
37
|
+
/**
|
|
38
|
+
* Writes a v2 filter list. An empty list is written as an empty map, so it reads back as an empty list.
|
|
39
|
+
*
|
|
40
|
+
* @internal
|
|
41
|
+
*/
|
|
42
|
+
export declare function filtersToYamlV2({ filters, attributeFilterConfigs }: IPublisherFiltersV2, errorContext?: IErrorContext): DashboardFilters;
|
|
43
|
+
/**
|
|
44
|
+
* A document's own date filters each name the date dataset they apply to; the period plays the role
|
|
45
|
+
* of a dashboard's common date filter.
|
|
46
|
+
*
|
|
47
|
+
* @internal
|
|
48
|
+
*/
|
|
49
|
+
export declare function assertDocumentDateFiltersNameDataSet(filters: FilterContextItem[], errorContext?: IErrorContext): void;
|
|
50
|
+
//# sourceMappingURL=publisherFilters.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"publisherFilters.d.ts","sourceRoot":"","sources":["../../src/utils/publisherFilters.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,OAAO,EAAE,MAAM,MAAM,CAAC;AAGpC,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AACtE,OAAO,EACH,KAAK,iBAAiB,EACtB,KAAK,+BAA+B,EAMvC,MAAM,qBAAqB,CAAC;AAQ7B,OAAO,EAAiB,KAAK,aAAa,EAAY,MAAM,aAAa,CAAC;AAI1E;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,iBAAiB,EAAE,GAAG,SAAS,GAAG,OAAO,GAAG,SAAS,CAQ3F;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,gBAAgB,GAAG,SAAS,GAAG,iBAAiB,EAAE,GAAG,SAAS,CAS3G;AAED;;;;;GAKG;AACH,MAAM,MAAM,uBAAuB,GAAG,UAAU,GAAG,MAAM,GAAG,QAAQ,CAAC;AAErE,gBAAgB;AAChB,MAAM,WAAW,mBAAmB;IAChC,OAAO,EAAE,iBAAiB,EAAE,CAAC;IAC7B,sBAAsB,CAAC,EAAE,+BAA+B,EAAE,CAAC;CAC9D;AA0BD;;;;GAIG;AACH,wBAAgB,sBAAsB,CAClC,OAAO,EAAE,gBAAgB,EACzB,MAAM,EAAE,uBAAuB,EAC/B,YAAY,CAAC,EAAE,aAAa,GAC7B,mBAAmB,CAgCrB;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAC3B,EAAE,OAAO,EAAE,sBAAsB,EAAE,EAAE,mBAAmB,EACxD,YAAY,CAAC,EAAE,aAAa,GAC7B,gBAAgB,CA8BlB;AAED;;;;;GAKG;AACH,wBAAgB,oCAAoC,CAChD,OAAO,EAAE,iBAAiB,EAAE,EAC5B,YAAY,CAAC,EAAE,aAAa,GAC7B,IAAI,CASN"}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
// (C) 2026 GoodData Corporation
|
|
2
|
+
import { dashboardFilterLocalIdentifier, isDashboardCommonDateFilter, isDashboardDateFilter, isNoopAllTimeDashboardDateFilter, } from "@gooddata/sdk-model";
|
|
3
|
+
import { declarativeFilterContextToYaml, declarativeFiltersConfigToYaml, } from "../from/declarativeDashboardToYaml.js";
|
|
4
|
+
import { yamlFilterContextToDeclarative } from "../to/yamlDashboardToDeclarative.js";
|
|
5
|
+
import { CoreErrorCode, newError } from "./errors.js";
|
|
6
|
+
import { referencesAsStored, referencesAsWritten } from "./publisherFilterRefs.js";
|
|
7
|
+
import { createFilterContextItemKeyName } from "./yamlUtils.js";
|
|
8
|
+
/**
|
|
9
|
+
* A document holds its filters the way a dashboard's filter context does, so the same convertor writes
|
|
10
|
+
* them; only the envelope it expects is put around them here.
|
|
11
|
+
*
|
|
12
|
+
* @internal
|
|
13
|
+
*/
|
|
14
|
+
export function filtersToYaml(filters) {
|
|
15
|
+
if (!filters?.length) {
|
|
16
|
+
return undefined;
|
|
17
|
+
}
|
|
18
|
+
const { filters: written } = declarativeFilterContextToYaml(undefined, {
|
|
19
|
+
content: { filters: referencesAsWritten(filters), version: "2" },
|
|
20
|
+
});
|
|
21
|
+
return written.items.length === 0 ? undefined : written;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* A document holds its filters the way a dashboard's filter context does, so they are written and read
|
|
25
|
+
* back by the same convertor; only the envelope it expects is put around them here.
|
|
26
|
+
*
|
|
27
|
+
* @internal
|
|
28
|
+
*/
|
|
29
|
+
export function filtersToDeclarative(filters) {
|
|
30
|
+
if (filters === undefined) {
|
|
31
|
+
return undefined;
|
|
32
|
+
}
|
|
33
|
+
// The filter context the shared convertor builds around them is thrown away, so what it is
|
|
34
|
+
// named does not matter; only the filters inside it are what a document stores.
|
|
35
|
+
const { filterContext } = yamlFilterContextToDeclarative("report", filters);
|
|
36
|
+
const content = filterContext.content;
|
|
37
|
+
return content?.filters?.length ? referencesAsStored(content.filters) : undefined;
|
|
38
|
+
}
|
|
39
|
+
function setting(filter, key) {
|
|
40
|
+
return filter[key];
|
|
41
|
+
}
|
|
42
|
+
function changedSetting(filter, key) {
|
|
43
|
+
const value = setting(filter, key);
|
|
44
|
+
return key === "mode" ? value !== undefined && value !== "active" : value !== undefined;
|
|
45
|
+
}
|
|
46
|
+
function lostSettings(filter, holder) {
|
|
47
|
+
switch (setting(filter, "type")) {
|
|
48
|
+
case "filter_group":
|
|
49
|
+
return ["filter_group"];
|
|
50
|
+
case "date_filter":
|
|
51
|
+
return ["title", "mode"].filter((key) => changedSetting(filter, key));
|
|
52
|
+
case "metric_value_filter":
|
|
53
|
+
return ["mode"].filter((key) => changedSetting(filter, key));
|
|
54
|
+
default:
|
|
55
|
+
return holder === "document"
|
|
56
|
+
? []
|
|
57
|
+
: ["mode", "display_as", "selection_type"].filter((key) => changedSetting(filter, key));
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Reads a v2 filter list. A setting the v2 shape has nowhere to keep throws instead of being dropped.
|
|
62
|
+
*
|
|
63
|
+
* @internal
|
|
64
|
+
*/
|
|
65
|
+
export function filtersToDeclarativeV2(filters, holder, errorContext) {
|
|
66
|
+
const entries = Object.entries(filters);
|
|
67
|
+
for (const [key, filter] of entries) {
|
|
68
|
+
const [lost] = lostSettings(filter, holder);
|
|
69
|
+
if (lost !== undefined) {
|
|
70
|
+
throw newError(CoreErrorCode.FilterSettingNotStorable, [key, lost, holder], errorContext);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
const { filterContext, attributeFilterConfigs } = yamlFilterContextToDeclarative("document", filters);
|
|
74
|
+
const read = filterContext.content?.filters ?? [];
|
|
75
|
+
const missing = entries.find(([key]) => !read.some((filter) => dashboardFilterLocalIdentifier(filter) === key));
|
|
76
|
+
if (missing !== undefined) {
|
|
77
|
+
throw newError(CoreErrorCode.ItemNotSupported, [missing[0]], errorContext);
|
|
78
|
+
}
|
|
79
|
+
const unwritable = read.find((filter) => isDashboardCommonDateFilter(filter) && isNoopAllTimeDashboardDateFilter(filter));
|
|
80
|
+
if (unwritable !== undefined) {
|
|
81
|
+
throw newError(CoreErrorCode.ItemNotSupported, [dashboardFilterLocalIdentifier(unwritable) ?? JSON.stringify(unwritable)], errorContext);
|
|
82
|
+
}
|
|
83
|
+
return {
|
|
84
|
+
filters: referencesAsStored(read),
|
|
85
|
+
...(attributeFilterConfigs?.length
|
|
86
|
+
? { attributeFilterConfigs: referencesAsStored(attributeFilterConfigs) }
|
|
87
|
+
: {}),
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Writes a v2 filter list. An empty list is written as an empty map, so it reads back as an empty list.
|
|
92
|
+
*
|
|
93
|
+
* @internal
|
|
94
|
+
*/
|
|
95
|
+
export function filtersToYamlV2({ filters, attributeFilterConfigs }, errorContext) {
|
|
96
|
+
const writtenFilters = referencesAsWritten(filters);
|
|
97
|
+
const { filters: written, filtersMap } = declarativeFilterContextToYaml(undefined, { content: { filters: writtenFilters, version: "2" } }, errorContext);
|
|
98
|
+
const keys = writtenFilters.map((filter) => createFilterContextItemKeyName(filter, "date", errorContext));
|
|
99
|
+
// Two kept filters sharing a key make the writer throw, so a shared key means one of them was skipped.
|
|
100
|
+
const lostFilter = keys.find((key, index) => !Object.hasOwn(filtersMap, key) || keys.indexOf(key) !== index);
|
|
101
|
+
if (lostFilter !== undefined) {
|
|
102
|
+
throw newError(CoreErrorCode.ItemNotSupported, [lostFilter], errorContext);
|
|
103
|
+
}
|
|
104
|
+
const lostConfig = attributeFilterConfigs?.find(({ localIdentifier }) => !Object.hasOwn(filtersMap, localIdentifier));
|
|
105
|
+
if (lostConfig !== undefined) {
|
|
106
|
+
throw newError(CoreErrorCode.ItemNotSupported, [lostConfig.localIdentifier], errorContext);
|
|
107
|
+
}
|
|
108
|
+
declarativeFiltersConfigToYaml(filtersMap, undefined, undefined, referencesAsWritten(attributeFilterConfigs), undefined, errorContext);
|
|
109
|
+
return written.toJSON();
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* A document's own date filters each name the date dataset they apply to; the period plays the role
|
|
113
|
+
* of a dashboard's common date filter.
|
|
114
|
+
*
|
|
115
|
+
* @internal
|
|
116
|
+
*/
|
|
117
|
+
export function assertDocumentDateFiltersNameDataSet(filters, errorContext) {
|
|
118
|
+
const index = filters.findIndex((filter) => isDashboardDateFilter(filter) && !filter.dateFilter.dataSet);
|
|
119
|
+
if (index !== -1) {
|
|
120
|
+
throw newError(CoreErrorCode.DateFilterWithoutDataSet, [dashboardFilterLocalIdentifier(filters[index]) ?? `#${index}`], errorContext);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { PublisherPeriodV2 as AacPublisherPeriodV2 } from "@gooddata/sdk-code-schemas/v1";
|
|
2
|
+
import { type PublisherPeriodV2 } from "@gooddata/sdk-model";
|
|
3
|
+
/** @internal */
|
|
4
|
+
export declare function periodToDeclarativeV2(period: AacPublisherPeriodV2): PublisherPeriodV2;
|
|
5
|
+
/** @internal */
|
|
6
|
+
export declare function periodToYamlV2(period: PublisherPeriodV2): AacPublisherPeriodV2;
|
|
7
|
+
//# sourceMappingURL=publisherPeriodV2.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"publisherPeriodV2.d.ts","sourceRoot":"","sources":["../../src/utils/publisherPeriodV2.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACR,iBAAiB,IAAI,oBAAoB,EAE5C,MAAM,+BAA+B,CAAC;AACvC,OAAO,EAA8B,KAAK,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAsBzF,gBAAgB;AAChB,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,oBAAoB,GAAG,iBAAiB,CAUrF;AAED,gBAAgB;AAChB,wBAAgB,cAAc,CAAC,MAAM,EAAE,iBAAiB,GAAG,oBAAoB,CAK9E"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
// (C) 2026 GoodData Corporation
|
|
2
|
+
const storedGranularities = {
|
|
3
|
+
SECOND: "GDC.time.second",
|
|
4
|
+
MINUTE: "GDC.time.minute",
|
|
5
|
+
HOUR: "GDC.time.hour",
|
|
6
|
+
DAY: "GDC.time.date",
|
|
7
|
+
WEEK_US: "GDC.time.week_us",
|
|
8
|
+
MONTH: "GDC.time.month",
|
|
9
|
+
QUARTER: "GDC.time.quarter",
|
|
10
|
+
YEAR: "GDC.time.year",
|
|
11
|
+
FISCAL_YEAR: "GDC.time.fiscal_year",
|
|
12
|
+
FISCAL_QUARTER: "GDC.time.fiscal_quarter",
|
|
13
|
+
FISCAL_MONTH: "GDC.time.fiscal_month",
|
|
14
|
+
};
|
|
15
|
+
const yamlGranularities = Object.fromEntries(Object.entries(storedGranularities).map(([yaml, stored]) => [stored, yaml]));
|
|
16
|
+
/** @internal */
|
|
17
|
+
export function periodToDeclarativeV2(period) {
|
|
18
|
+
if ("granularity" in period) {
|
|
19
|
+
return {
|
|
20
|
+
type: "relative",
|
|
21
|
+
granularity: storedGranularities[period.granularity],
|
|
22
|
+
from: period.from,
|
|
23
|
+
to: period.to,
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
return { type: "absolute", granularity: "GDC.time.date", from: period.from, to: period.to };
|
|
27
|
+
}
|
|
28
|
+
/** @internal */
|
|
29
|
+
export function periodToYamlV2(period) {
|
|
30
|
+
if (period.type === "relative") {
|
|
31
|
+
return { granularity: yamlGranularities[period.granularity], from: period.from, to: period.to };
|
|
32
|
+
}
|
|
33
|
+
return { from: period.from, to: period.to };
|
|
34
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { type PublisherContentVersionV2 } from "@gooddata/sdk-model";
|
|
2
|
+
import { type IErrorContext } from "./errors.js";
|
|
3
|
+
/** @internal */
|
|
4
|
+
export declare const publisherContentVersionV2: PublisherContentVersionV2;
|
|
5
|
+
/** @internal */
|
|
6
|
+
export declare function assertPublisherContentVersionV2({ version }: {
|
|
7
|
+
version: unknown;
|
|
8
|
+
}, errorContext: IErrorContext | undefined): void;
|
|
9
|
+
//# sourceMappingURL=publisherVersionV2.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"publisherVersionV2.d.ts","sourceRoot":"","sources":["../../src/utils/publisherVersionV2.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,yBAAyB,EAAE,MAAM,qBAAqB,CAAC;AAErE,OAAO,EAAiB,KAAK,aAAa,EAAgC,MAAM,aAAa,CAAC;AAE9F,gBAAgB;AAChB,eAAO,MAAM,yBAAyB,EAAE,yBAA+B,CAAC;AAExE,gBAAgB;AAChB,wBAAgB,+BAA+B,CAC3C,EAAE,OAAO,EAAE,EAAE;IAAE,OAAO,EAAE,OAAO,CAAA;CAAE,EACjC,YAAY,EAAE,aAAa,GAAG,SAAS,GACxC,IAAI,CAQN"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
// (C) 2026 GoodData Corporation
|
|
2
|
+
import { CoreErrorCode, newError, updateErrorContext } from "./errors.js";
|
|
3
|
+
/** @internal */
|
|
4
|
+
export const publisherContentVersionV2 = "2";
|
|
5
|
+
/** @internal */
|
|
6
|
+
export function assertPublisherContentVersionV2({ version }, errorContext) {
|
|
7
|
+
if (version !== publisherContentVersionV2) {
|
|
8
|
+
throw newError(CoreErrorCode.UnsupportedContentVersion, [String(version), publisherContentVersionV2], updateErrorContext(errorContext, { path: ["version"] }));
|
|
9
|
+
}
|
|
10
|
+
}
|
package/esm/utils/texts.d.ts
CHANGED
|
@@ -10,4 +10,5 @@ export declare const PLUGIN_COMMENT: string;
|
|
|
10
10
|
export declare const PUBLISHER_DOCUMENT_COMMENT: string;
|
|
11
11
|
export declare const PUBLISHER_DOCUMENT_TEMPLATE_COMMENT: string;
|
|
12
12
|
export declare const PUBLISHER_PAGE_LAYOUT_COMMENT: string;
|
|
13
|
+
export declare const PUBLISHER_PAGE_TEMPLATE_COMMENT_V2: string;
|
|
13
14
|
//# sourceMappingURL=texts.d.ts.map
|
package/esm/utils/texts.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"texts.d.ts","sourceRoot":"","sources":["../../src/utils/texts.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,eAAe,QAKhB,CAAC;AAEb,eAAO,MAAM,qBAAqB,QAKtB,CAAC;AAEb,eAAO,MAAM,0BAA0B,QAK3B,CAAC;AAEb,eAAO,MAAM,cAAc,QAKf,CAAC;AAEb,eAAO,MAAM,iBAAiB,QAKlB,CAAC;AAEb,eAAO,MAAM,qBAAqB,QAOtB,CAAC;AAEb,eAAO,MAAM,iBAAiB,QAKlB,CAAC;AAEb,eAAO,MAAM,2BAA2B,QAM5B,CAAC;AAEb,eAAO,MAAM,cAAc,QAKf,CAAC;AAEb,eAAO,MAAM,0BAA0B,QAI3B,CAAC;AAEb,eAAO,MAAM,mCAAmC,QAIpC,CAAC;AAEb,eAAO,MAAM,6BAA6B,QAI9B,CAAC"}
|
|
1
|
+
{"version":3,"file":"texts.d.ts","sourceRoot":"","sources":["../../src/utils/texts.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,eAAe,QAKhB,CAAC;AAEb,eAAO,MAAM,qBAAqB,QAKtB,CAAC;AAEb,eAAO,MAAM,0BAA0B,QAK3B,CAAC;AAEb,eAAO,MAAM,cAAc,QAKf,CAAC;AAEb,eAAO,MAAM,iBAAiB,QAKlB,CAAC;AAEb,eAAO,MAAM,qBAAqB,QAOtB,CAAC;AAEb,eAAO,MAAM,iBAAiB,QAKlB,CAAC;AAEb,eAAO,MAAM,2BAA2B,QAM5B,CAAC;AAEb,eAAO,MAAM,cAAc,QAKf,CAAC;AAEb,eAAO,MAAM,0BAA0B,QAI3B,CAAC;AAEb,eAAO,MAAM,mCAAmC,QAIpC,CAAC;AAEb,eAAO,MAAM,6BAA6B,QAI9B,CAAC;AAEb,eAAO,MAAM,kCAAkC,QAInC,CAAC"}
|
package/esm/utils/texts.js
CHANGED
|
@@ -71,3 +71,8 @@ export const PUBLISHER_PAGE_LAYOUT_COMMENT = [
|
|
|
71
71
|
" It places what it draws in a tree of rows and columns, and a slot left",
|
|
72
72
|
" empty here is one whatever uses the page is expected to fill.",
|
|
73
73
|
].join("\n");
|
|
74
|
+
export const PUBLISHER_PAGE_TEMPLATE_COMMENT_V2 = [
|
|
75
|
+
" A page template is one page a document or a document template can copy.",
|
|
76
|
+
" It places widgets in a tree of rows and columns, and a widget left empty",
|
|
77
|
+
" here is one the document is expected to fill.",
|
|
78
|
+
].join("\n");
|