@umbraco-cms/mcp-dev 17.0.0 → 17.0.1-beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +782 -13
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +887 -118
- package/dist/index.js.map +1 -1
- package/package.json +3 -1
package/dist/index.cjs
CHANGED
|
@@ -7597,7 +7597,7 @@ var UmbracoManagementClient2 = (_class2 = class {
|
|
|
7597
7597
|
// package.json
|
|
7598
7598
|
var package_default = {
|
|
7599
7599
|
name: "@umbraco-cms/mcp-dev",
|
|
7600
|
-
version: "17.0.
|
|
7600
|
+
version: "17.0.1-beta.1",
|
|
7601
7601
|
type: "module",
|
|
7602
7602
|
description: "A model context protocol (MCP) server for Umbraco CMS",
|
|
7603
7603
|
main: "index.js",
|
|
@@ -7620,6 +7620,8 @@ var package_default = {
|
|
|
7620
7620
|
"eval-mcp:create-document-type": "npx mcp-server-tester@1.4.0 evals tests/e2e/create-document-type/create-document-type.yaml --server-config tests/e2e/create-document-type/create-document-type-config.json",
|
|
7621
7621
|
"eval-mcp:create-document-copy": "npx mcp-server-tester@1.4.0 evals tests/e2e/create-document-copy/create-document-copy.yaml --server-config tests/e2e/create-document-copy/create-document-copy-config.json",
|
|
7622
7622
|
"eval-mcp:create-document-with-template": "npx mcp-server-tester@1.4.0 evals tests/e2e/create-document-with-template/create-document-with-template.yaml --server-config tests/e2e/create-document-with-template/create-document-with-template-config.json",
|
|
7623
|
+
"eval-mcp:update-document-properties": "npx mcp-server-tester@1.4.0 evals tests/e2e/update-document-properties/update-document-properties.yaml --server-config tests/e2e/update-document-properties/update-document-properties-config.json",
|
|
7624
|
+
"eval-mcp:update-block-property": "npx mcp-server-tester@1.4.0 evals tests/e2e/update-block-property/update-block-property.yaml --server-config tests/e2e/update-block-property/update-block-property-config.json",
|
|
7623
7625
|
"eval-mcp:all": "npm run eval-mcp:basic && npm run eval-mcp:create-data-type && npm run eval-mcp:create-document-type && npm run eval-mcp:create-blog-post"
|
|
7624
7626
|
},
|
|
7625
7627
|
engines: {
|
|
@@ -19544,9 +19546,19 @@ var move_to_recycle_bin_default = MoveDocumentToRecycleBinTool;
|
|
|
19544
19546
|
|
|
19545
19547
|
var UpdateDocumentTool = CreateUmbracoTool(
|
|
19546
19548
|
"update-document",
|
|
19547
|
-
`Updates a document by Id
|
|
19548
|
-
|
|
19549
|
-
|
|
19549
|
+
`Updates a document by Id. USE AS LAST RESORT ONLY.
|
|
19550
|
+
|
|
19551
|
+
IMPORTANT: Prefer these specialized tools instead:
|
|
19552
|
+
- update-document-properties: For updating individual property values (simpler, safer)
|
|
19553
|
+
- update-block-property: For updating properties within BlockList/BlockGrid/RichText blocks
|
|
19554
|
+
|
|
19555
|
+
Only use this tool when you need to update document-level metadata (template, variants)
|
|
19556
|
+
or when the specialized tools cannot handle your specific use case.
|
|
19557
|
+
|
|
19558
|
+
If you must use this tool:
|
|
19559
|
+
- Always read the current document value first
|
|
19560
|
+
- Only update the required values
|
|
19561
|
+
- Don't miss any properties from the original document`,
|
|
19550
19562
|
{
|
|
19551
19563
|
id: putDocumentByIdParams.shape.id,
|
|
19552
19564
|
data: _zod.z.object(putDocumentByIdBody.shape)
|
|
@@ -19567,6 +19579,761 @@ var UpdateDocumentTool = CreateUmbracoTool(
|
|
|
19567
19579
|
);
|
|
19568
19580
|
var update_document_default = UpdateDocumentTool;
|
|
19569
19581
|
|
|
19582
|
+
// src/umb-management-api/tools/document/put/update-document-properties.ts
|
|
19583
|
+
|
|
19584
|
+
|
|
19585
|
+
// src/umb-management-api/tools/document/put/helpers/document-type-properties-resolver.ts
|
|
19586
|
+
async function getAllDocumentTypeProperties(documentTypeId) {
|
|
19587
|
+
const client = UmbracoManagementClient2.getClient();
|
|
19588
|
+
const visitedIds = /* @__PURE__ */ new Set();
|
|
19589
|
+
const properties = [];
|
|
19590
|
+
async function resolveDocumentType(docTypeId) {
|
|
19591
|
+
if (visitedIds.has(docTypeId)) {
|
|
19592
|
+
return;
|
|
19593
|
+
}
|
|
19594
|
+
visitedIds.add(docTypeId);
|
|
19595
|
+
const docType = await client.getDocumentTypeById(docTypeId);
|
|
19596
|
+
for (const prop of docType.properties) {
|
|
19597
|
+
if (!properties.some((p) => p.alias === prop.alias)) {
|
|
19598
|
+
properties.push({
|
|
19599
|
+
alias: prop.alias,
|
|
19600
|
+
name: prop.name,
|
|
19601
|
+
dataTypeId: prop.dataType.id,
|
|
19602
|
+
variesByCulture: prop.variesByCulture,
|
|
19603
|
+
variesBySegment: prop.variesBySegment
|
|
19604
|
+
});
|
|
19605
|
+
}
|
|
19606
|
+
}
|
|
19607
|
+
for (const composition of docType.compositions) {
|
|
19608
|
+
await resolveDocumentType(composition.documentType.id);
|
|
19609
|
+
}
|
|
19610
|
+
}
|
|
19611
|
+
await resolveDocumentType(documentTypeId);
|
|
19612
|
+
return properties;
|
|
19613
|
+
}
|
|
19614
|
+
function validateCultureSegment(prop, def) {
|
|
19615
|
+
if (!def.variesByCulture && prop.culture) {
|
|
19616
|
+
return `Property '${prop.alias}' does not vary by culture, but culture '${prop.culture}' was provided`;
|
|
19617
|
+
}
|
|
19618
|
+
if (def.variesByCulture && !prop.culture) {
|
|
19619
|
+
return `Property '${prop.alias}' varies by culture - culture is required`;
|
|
19620
|
+
}
|
|
19621
|
+
if (!def.variesBySegment && prop.segment) {
|
|
19622
|
+
return `Property '${prop.alias}' does not vary by segment, but segment '${prop.segment}' was provided`;
|
|
19623
|
+
}
|
|
19624
|
+
if (def.variesBySegment && !prop.segment) {
|
|
19625
|
+
return `Property '${prop.alias}' varies by segment - segment is required`;
|
|
19626
|
+
}
|
|
19627
|
+
return null;
|
|
19628
|
+
}
|
|
19629
|
+
|
|
19630
|
+
// src/umb-management-api/tools/document/put/helpers/property-value-validator.ts
|
|
19631
|
+
var EDITOR_FORMAT_MAP = {
|
|
19632
|
+
// Editors with allowed values validation
|
|
19633
|
+
"Umbraco.DropDown.Flexible": { valueType: "string[]", allowedValuesKey: "items", validateAllowedValues: true },
|
|
19634
|
+
"Umbraco.RadioButtonList": { valueType: "string", allowedValuesKey: "items", validateAllowedValues: true },
|
|
19635
|
+
"Umbraco.CheckBoxList": { valueType: "string[]", allowedValuesKey: "items", validateAllowedValues: true },
|
|
19636
|
+
"Umbraco.ColorPicker": { valueType: "object", allowedValuesKey: "items", validateAllowedValues: true },
|
|
19637
|
+
// Editors with format-only validation
|
|
19638
|
+
"Umbraco.TextBox": { valueType: "string" },
|
|
19639
|
+
"Umbraco.TextArea": { valueType: "string" },
|
|
19640
|
+
"Umbraco.Integer": { valueType: "number" },
|
|
19641
|
+
"Umbraco.Decimal": { valueType: "number" },
|
|
19642
|
+
"Umbraco.TrueFalse": { valueType: "boolean" },
|
|
19643
|
+
"Umbraco.Tags": { valueType: "string[]" },
|
|
19644
|
+
"Umbraco.MultipleTextstring": { valueType: "string[]" },
|
|
19645
|
+
"Umbraco.DateTime": { valueType: "string" },
|
|
19646
|
+
"Umbraco.EmailAddress": { valueType: "string" },
|
|
19647
|
+
"Umbraco.MarkdownEditor": { valueType: "string" },
|
|
19648
|
+
"Umbraco.ColorPicker.EyeDropper": { valueType: "string" }
|
|
19649
|
+
};
|
|
19650
|
+
function validateValueType(value, expectedType, propertyAlias, editorAlias) {
|
|
19651
|
+
if (value === null || value === void 0) {
|
|
19652
|
+
return null;
|
|
19653
|
+
}
|
|
19654
|
+
switch (expectedType) {
|
|
19655
|
+
case "string":
|
|
19656
|
+
if (typeof value !== "string") {
|
|
19657
|
+
return `Property '${propertyAlias}': Value must be a string for ${editorAlias} editor, got ${typeof value}`;
|
|
19658
|
+
}
|
|
19659
|
+
break;
|
|
19660
|
+
case "string[]":
|
|
19661
|
+
if (!Array.isArray(value)) {
|
|
19662
|
+
return `Property '${propertyAlias}': Value must be an array for ${editorAlias} editor, got ${typeof value}`;
|
|
19663
|
+
}
|
|
19664
|
+
if (!value.every((item) => typeof item === "string")) {
|
|
19665
|
+
return `Property '${propertyAlias}': All array items must be strings for ${editorAlias} editor`;
|
|
19666
|
+
}
|
|
19667
|
+
break;
|
|
19668
|
+
case "number":
|
|
19669
|
+
if (typeof value !== "number") {
|
|
19670
|
+
return `Property '${propertyAlias}': Value must be a number for ${editorAlias} editor, got ${typeof value}`;
|
|
19671
|
+
}
|
|
19672
|
+
break;
|
|
19673
|
+
case "boolean":
|
|
19674
|
+
if (typeof value !== "boolean") {
|
|
19675
|
+
return `Property '${propertyAlias}': Value must be a boolean for ${editorAlias} editor, got ${typeof value}`;
|
|
19676
|
+
}
|
|
19677
|
+
break;
|
|
19678
|
+
case "object":
|
|
19679
|
+
if (typeof value !== "object" || Array.isArray(value)) {
|
|
19680
|
+
return `Property '${propertyAlias}': Value must be an object for ${editorAlias} editor, got ${Array.isArray(value) ? "array" : typeof value}`;
|
|
19681
|
+
}
|
|
19682
|
+
break;
|
|
19683
|
+
}
|
|
19684
|
+
return null;
|
|
19685
|
+
}
|
|
19686
|
+
function extractAllowedValues(dataType, configKey) {
|
|
19687
|
+
const configItem = dataType.values.find((v) => v.alias === configKey);
|
|
19688
|
+
if (!configItem || !configItem.value) {
|
|
19689
|
+
return null;
|
|
19690
|
+
}
|
|
19691
|
+
const value = configItem.value;
|
|
19692
|
+
if (Array.isArray(value)) {
|
|
19693
|
+
if (value.every((item) => typeof item === "string")) {
|
|
19694
|
+
return value;
|
|
19695
|
+
}
|
|
19696
|
+
if (value.every((item) => typeof item === "object" && item !== null && "value" in item)) {
|
|
19697
|
+
return value.map((item) => item.value);
|
|
19698
|
+
}
|
|
19699
|
+
}
|
|
19700
|
+
return null;
|
|
19701
|
+
}
|
|
19702
|
+
function validateAllowedValues(value, allowedValues, propertyAlias, editorAlias, valueType) {
|
|
19703
|
+
const errors = [];
|
|
19704
|
+
if (value === null || value === void 0) {
|
|
19705
|
+
return errors;
|
|
19706
|
+
}
|
|
19707
|
+
if (editorAlias === "Umbraco.ColorPicker" && typeof value === "object" && value !== null && "value" in value) {
|
|
19708
|
+
const colorValue = value.value;
|
|
19709
|
+
if (!allowedValues.includes(colorValue)) {
|
|
19710
|
+
errors.push(`Property '${propertyAlias}': Color value '${colorValue}' is not in allowed values: [${allowedValues.map((v) => `'${v}'`).join(", ")}]`);
|
|
19711
|
+
}
|
|
19712
|
+
return errors;
|
|
19713
|
+
}
|
|
19714
|
+
if (valueType === "string[]" && Array.isArray(value)) {
|
|
19715
|
+
for (const item of value) {
|
|
19716
|
+
if (!allowedValues.includes(item)) {
|
|
19717
|
+
errors.push(`Property '${propertyAlias}': Value '${item}' is not in allowed values: [${allowedValues.map((v) => `'${v}'`).join(", ")}]`);
|
|
19718
|
+
}
|
|
19719
|
+
}
|
|
19720
|
+
return errors;
|
|
19721
|
+
}
|
|
19722
|
+
if (valueType === "string" && typeof value === "string") {
|
|
19723
|
+
if (!allowedValues.includes(value)) {
|
|
19724
|
+
errors.push(`Property '${propertyAlias}': Value '${value}' is not in allowed values: [${allowedValues.map((v) => `'${v}'`).join(", ")}]`);
|
|
19725
|
+
}
|
|
19726
|
+
return errors;
|
|
19727
|
+
}
|
|
19728
|
+
return errors;
|
|
19729
|
+
}
|
|
19730
|
+
function validatePropertyValue(dataType, value, propertyAlias) {
|
|
19731
|
+
const errors = [];
|
|
19732
|
+
const editorAlias = dataType.editorAlias;
|
|
19733
|
+
const formatConfig = EDITOR_FORMAT_MAP[editorAlias];
|
|
19734
|
+
if (!formatConfig) {
|
|
19735
|
+
return { isValid: true, errors: [] };
|
|
19736
|
+
}
|
|
19737
|
+
const typeError = validateValueType(value, formatConfig.valueType, propertyAlias, editorAlias);
|
|
19738
|
+
if (typeError) {
|
|
19739
|
+
errors.push(typeError);
|
|
19740
|
+
return { isValid: false, errors };
|
|
19741
|
+
}
|
|
19742
|
+
if (formatConfig.validateAllowedValues && formatConfig.allowedValuesKey) {
|
|
19743
|
+
const allowedValues = extractAllowedValues(dataType, formatConfig.allowedValuesKey);
|
|
19744
|
+
if (allowedValues && allowedValues.length > 0) {
|
|
19745
|
+
const allowedValueErrors = validateAllowedValues(
|
|
19746
|
+
value,
|
|
19747
|
+
allowedValues,
|
|
19748
|
+
propertyAlias,
|
|
19749
|
+
editorAlias,
|
|
19750
|
+
formatConfig.valueType
|
|
19751
|
+
);
|
|
19752
|
+
errors.push(...allowedValueErrors);
|
|
19753
|
+
}
|
|
19754
|
+
}
|
|
19755
|
+
return {
|
|
19756
|
+
isValid: errors.length === 0,
|
|
19757
|
+
errors
|
|
19758
|
+
};
|
|
19759
|
+
}
|
|
19760
|
+
async function validatePropertiesBeforeSave(properties) {
|
|
19761
|
+
const client = UmbracoManagementClient2.getClient();
|
|
19762
|
+
const errors = [];
|
|
19763
|
+
const dataTypeCache = /* @__PURE__ */ new Map();
|
|
19764
|
+
async function getCachedDataType(dataTypeId) {
|
|
19765
|
+
if (!dataTypeCache.has(dataTypeId)) {
|
|
19766
|
+
try {
|
|
19767
|
+
const dataType = await client.getDataTypeById(dataTypeId);
|
|
19768
|
+
dataTypeCache.set(dataTypeId, dataType);
|
|
19769
|
+
} catch (error) {
|
|
19770
|
+
console.error(`Failed to fetch Data Type ${dataTypeId}:`, error);
|
|
19771
|
+
return null;
|
|
19772
|
+
}
|
|
19773
|
+
}
|
|
19774
|
+
return _nullishCoalesce(dataTypeCache.get(dataTypeId), () => ( null));
|
|
19775
|
+
}
|
|
19776
|
+
for (const prop of properties) {
|
|
19777
|
+
if (!prop.dataTypeId) {
|
|
19778
|
+
continue;
|
|
19779
|
+
}
|
|
19780
|
+
const dataType = await getCachedDataType(prop.dataTypeId);
|
|
19781
|
+
if (!dataType) {
|
|
19782
|
+
continue;
|
|
19783
|
+
}
|
|
19784
|
+
const validation = validatePropertyValue(dataType, prop.value, prop.alias);
|
|
19785
|
+
if (!validation.isValid) {
|
|
19786
|
+
errors.push(...validation.errors);
|
|
19787
|
+
}
|
|
19788
|
+
}
|
|
19789
|
+
return {
|
|
19790
|
+
isValid: errors.length === 0,
|
|
19791
|
+
errors
|
|
19792
|
+
};
|
|
19793
|
+
}
|
|
19794
|
+
|
|
19795
|
+
// src/umb-management-api/tools/document/put/helpers/property-matching.ts
|
|
19796
|
+
function matchesProperty(value, alias, culture, segment) {
|
|
19797
|
+
return value.alias === alias && (_nullishCoalesce(value.culture, () => ( null))) === (_nullishCoalesce(culture, () => ( null))) && (_nullishCoalesce(value.segment, () => ( null))) === (_nullishCoalesce(segment, () => ( null)));
|
|
19798
|
+
}
|
|
19799
|
+
function getPropertyKey(alias, culture, segment) {
|
|
19800
|
+
let key = alias;
|
|
19801
|
+
if (culture) key += `[${culture}]`;
|
|
19802
|
+
if (segment) key += `[${segment}]`;
|
|
19803
|
+
return key;
|
|
19804
|
+
}
|
|
19805
|
+
|
|
19806
|
+
// src/umb-management-api/tools/document/put/update-document-properties.ts
|
|
19807
|
+
var propertySchema2 = _zod.z.object({
|
|
19808
|
+
alias: _zod.z.string().min(1).describe("The property alias to update or add"),
|
|
19809
|
+
value: _zod.z.any().nullish().describe("The new value for the property"),
|
|
19810
|
+
culture: _zod.z.string().nullish().describe("Optional culture code for variant properties (e.g., 'en-US')"),
|
|
19811
|
+
segment: _zod.z.string().nullish().describe("Optional segment identifier for variant properties")
|
|
19812
|
+
});
|
|
19813
|
+
var updateDocumentPropertiesSchema = {
|
|
19814
|
+
id: _zod.z.string().uuid().describe("The unique identifier of the document to update"),
|
|
19815
|
+
properties: _zod.z.array(propertySchema2).min(1).describe("Array of properties to update or add - at least one property is required")
|
|
19816
|
+
};
|
|
19817
|
+
var UpdateDocumentPropertiesTool = CreateUmbracoTool(
|
|
19818
|
+
"update-document-properties",
|
|
19819
|
+
`Updates or adds property values on a document without requiring the full document JSON payload.
|
|
19820
|
+
|
|
19821
|
+
This tool simplifies property updates by handling the read-modify-write cycle internally.
|
|
19822
|
+
You can update existing properties, add new properties, or do both in a single call.
|
|
19823
|
+
|
|
19824
|
+
Key features:
|
|
19825
|
+
- Update existing properties or add new ones
|
|
19826
|
+
- Property must exist on the document type (including compositions)
|
|
19827
|
+
- Full i18n support with culture and segment parameters
|
|
19828
|
+
- Automatic validation of property aliases against document type
|
|
19829
|
+
- Culture/segment requirements validated against property variance flags
|
|
19830
|
+
- Returns detailed error messages with available properties
|
|
19831
|
+
|
|
19832
|
+
Example usage:
|
|
19833
|
+
- Update a single property: { id: "...", properties: [{ alias: "title", value: "New Title" }] }
|
|
19834
|
+
- Add a new property: { id: "...", properties: [{ alias: "author", value: "John Doe" }] }
|
|
19835
|
+
- Update with culture: { id: "...", properties: [{ alias: "title", value: "Nuevo T\xEDtulo", culture: "es-ES" }] }
|
|
19836
|
+
- Mix update and add: { id: "...", properties: [{ alias: "title", value: "New" }, { alias: "newProp", value: "Value" }] }`,
|
|
19837
|
+
updateDocumentPropertiesSchema,
|
|
19838
|
+
async (model) => {
|
|
19839
|
+
const client = UmbracoManagementClient2.getClient();
|
|
19840
|
+
const currentDocument = await client.getDocumentById(model.id);
|
|
19841
|
+
const invalidAliases = [];
|
|
19842
|
+
const varianceErrors = [];
|
|
19843
|
+
const propertiesToUpdate = [];
|
|
19844
|
+
const propertiesToAdd = [];
|
|
19845
|
+
let documentTypeProperties = null;
|
|
19846
|
+
const getDocumentTypeProperties = async () => {
|
|
19847
|
+
if (documentTypeProperties === null) {
|
|
19848
|
+
try {
|
|
19849
|
+
documentTypeProperties = await getAllDocumentTypeProperties(currentDocument.documentType.id);
|
|
19850
|
+
} catch (error) {
|
|
19851
|
+
console.error("Failed to fetch document type properties:", error);
|
|
19852
|
+
documentTypeProperties = [];
|
|
19853
|
+
}
|
|
19854
|
+
}
|
|
19855
|
+
return documentTypeProperties;
|
|
19856
|
+
};
|
|
19857
|
+
for (const prop of model.properties) {
|
|
19858
|
+
const existsOnDocument = currentDocument.values.some(
|
|
19859
|
+
(v) => matchesProperty(v, prop.alias, prop.culture, prop.segment)
|
|
19860
|
+
);
|
|
19861
|
+
if (existsOnDocument) {
|
|
19862
|
+
propertiesToUpdate.push({
|
|
19863
|
+
alias: prop.alias,
|
|
19864
|
+
value: prop.value,
|
|
19865
|
+
culture: prop.culture,
|
|
19866
|
+
segment: prop.segment
|
|
19867
|
+
});
|
|
19868
|
+
} else {
|
|
19869
|
+
const docTypeProperties = await getDocumentTypeProperties();
|
|
19870
|
+
const propertyDef = docTypeProperties.find((p) => p.alias === prop.alias);
|
|
19871
|
+
if (propertyDef) {
|
|
19872
|
+
const validationError = validateCultureSegment(prop, propertyDef);
|
|
19873
|
+
if (validationError) {
|
|
19874
|
+
varianceErrors.push(validationError);
|
|
19875
|
+
} else {
|
|
19876
|
+
propertiesToAdd.push({
|
|
19877
|
+
alias: prop.alias,
|
|
19878
|
+
value: prop.value,
|
|
19879
|
+
culture: prop.culture,
|
|
19880
|
+
segment: prop.segment
|
|
19881
|
+
});
|
|
19882
|
+
}
|
|
19883
|
+
} else if (docTypeProperties.length > 0) {
|
|
19884
|
+
invalidAliases.push(getPropertyKey(prop.alias, prop.culture, prop.segment));
|
|
19885
|
+
} else {
|
|
19886
|
+
invalidAliases.push(getPropertyKey(prop.alias, prop.culture, prop.segment));
|
|
19887
|
+
}
|
|
19888
|
+
}
|
|
19889
|
+
}
|
|
19890
|
+
if (varianceErrors.length > 0) {
|
|
19891
|
+
return {
|
|
19892
|
+
content: [{
|
|
19893
|
+
type: "text",
|
|
19894
|
+
text: JSON.stringify({
|
|
19895
|
+
success: false,
|
|
19896
|
+
error: "Culture/segment validation failed",
|
|
19897
|
+
message: varianceErrors.join("; "),
|
|
19898
|
+
errors: varianceErrors,
|
|
19899
|
+
availableProperties: (_nullishCoalesce(documentTypeProperties, () => ( []))).map((p) => ({
|
|
19900
|
+
alias: p.alias,
|
|
19901
|
+
name: p.name,
|
|
19902
|
+
variesByCulture: p.variesByCulture,
|
|
19903
|
+
variesBySegment: p.variesBySegment
|
|
19904
|
+
}))
|
|
19905
|
+
}, null, 2)
|
|
19906
|
+
}]
|
|
19907
|
+
};
|
|
19908
|
+
}
|
|
19909
|
+
if (invalidAliases.length > 0) {
|
|
19910
|
+
const docTypeProps = _nullishCoalesce(documentTypeProperties, () => ( []));
|
|
19911
|
+
const availableProperties = docTypeProps.length > 0 ? docTypeProps.map((p) => ({
|
|
19912
|
+
alias: p.alias,
|
|
19913
|
+
name: p.name,
|
|
19914
|
+
variesByCulture: p.variesByCulture,
|
|
19915
|
+
variesBySegment: p.variesBySegment
|
|
19916
|
+
})) : currentDocument.values.map((v) => ({
|
|
19917
|
+
alias: v.alias,
|
|
19918
|
+
culture: _nullishCoalesce(v.culture, () => ( null)),
|
|
19919
|
+
segment: _nullishCoalesce(v.segment, () => ( null)),
|
|
19920
|
+
editorAlias: v.editorAlias
|
|
19921
|
+
}));
|
|
19922
|
+
return {
|
|
19923
|
+
content: [{
|
|
19924
|
+
type: "text",
|
|
19925
|
+
text: JSON.stringify({
|
|
19926
|
+
success: false,
|
|
19927
|
+
error: "Invalid property aliases",
|
|
19928
|
+
message: `The following properties do not exist on this document type: ${invalidAliases.join(", ")}`,
|
|
19929
|
+
invalidAliases,
|
|
19930
|
+
availableProperties
|
|
19931
|
+
}, null, 2)
|
|
19932
|
+
}]
|
|
19933
|
+
};
|
|
19934
|
+
}
|
|
19935
|
+
const allPropertiesToValidate = [...propertiesToUpdate, ...propertiesToAdd];
|
|
19936
|
+
if (allPropertiesToValidate.length > 0) {
|
|
19937
|
+
const docTypeProps = await getDocumentTypeProperties();
|
|
19938
|
+
const propsToValidate = allPropertiesToValidate.map((p) => {
|
|
19939
|
+
const def = docTypeProps.find((d) => d.alias === p.alias);
|
|
19940
|
+
return { alias: p.alias, value: p.value, dataTypeId: _nullishCoalesce(_optionalChain([def, 'optionalAccess', _50 => _50.dataTypeId]), () => ( "")) };
|
|
19941
|
+
}).filter((p) => p.dataTypeId);
|
|
19942
|
+
if (propsToValidate.length > 0) {
|
|
19943
|
+
const valueValidation = await validatePropertiesBeforeSave(propsToValidate);
|
|
19944
|
+
if (!valueValidation.isValid) {
|
|
19945
|
+
return {
|
|
19946
|
+
content: [{
|
|
19947
|
+
type: "text",
|
|
19948
|
+
text: JSON.stringify({
|
|
19949
|
+
success: false,
|
|
19950
|
+
error: "Property value validation failed",
|
|
19951
|
+
errors: valueValidation.errors
|
|
19952
|
+
}, null, 2)
|
|
19953
|
+
}]
|
|
19954
|
+
};
|
|
19955
|
+
}
|
|
19956
|
+
}
|
|
19957
|
+
}
|
|
19958
|
+
const updatedValues = currentDocument.values.map((existingValue) => {
|
|
19959
|
+
const updateProp = propertiesToUpdate.find(
|
|
19960
|
+
(p) => matchesProperty(existingValue, p.alias, p.culture, p.segment)
|
|
19961
|
+
);
|
|
19962
|
+
if (updateProp) {
|
|
19963
|
+
return {
|
|
19964
|
+
alias: existingValue.alias,
|
|
19965
|
+
culture: existingValue.culture,
|
|
19966
|
+
segment: existingValue.segment,
|
|
19967
|
+
value: updateProp.value
|
|
19968
|
+
};
|
|
19969
|
+
}
|
|
19970
|
+
return {
|
|
19971
|
+
alias: existingValue.alias,
|
|
19972
|
+
culture: existingValue.culture,
|
|
19973
|
+
segment: existingValue.segment,
|
|
19974
|
+
value: existingValue.value
|
|
19975
|
+
};
|
|
19976
|
+
});
|
|
19977
|
+
for (const newProp of propertiesToAdd) {
|
|
19978
|
+
updatedValues.push({
|
|
19979
|
+
alias: newProp.alias,
|
|
19980
|
+
culture: _nullishCoalesce(newProp.culture, () => ( null)),
|
|
19981
|
+
segment: _nullishCoalesce(newProp.segment, () => ( null)),
|
|
19982
|
+
value: newProp.value
|
|
19983
|
+
});
|
|
19984
|
+
}
|
|
19985
|
+
const variants = currentDocument.variants.map((v) => ({
|
|
19986
|
+
culture: v.culture,
|
|
19987
|
+
segment: v.segment,
|
|
19988
|
+
name: v.name
|
|
19989
|
+
}));
|
|
19990
|
+
const updatePayload = {
|
|
19991
|
+
values: updatedValues,
|
|
19992
|
+
variants,
|
|
19993
|
+
template: currentDocument.template
|
|
19994
|
+
};
|
|
19995
|
+
await client.putDocumentById(model.id, updatePayload);
|
|
19996
|
+
const updatedDocument = await client.getDocumentById(model.id);
|
|
19997
|
+
const updatedPropertyKeys = propertiesToUpdate.map(
|
|
19998
|
+
(p) => getPropertyKey(p.alias, p.culture, p.segment)
|
|
19999
|
+
);
|
|
20000
|
+
const addedPropertyKeys = propertiesToAdd.map(
|
|
20001
|
+
(p) => getPropertyKey(p.alias, p.culture, p.segment)
|
|
20002
|
+
);
|
|
20003
|
+
const totalCount = propertiesToUpdate.length + propertiesToAdd.length;
|
|
20004
|
+
let message = `Successfully processed ${totalCount} property value(s)`;
|
|
20005
|
+
if (propertiesToUpdate.length > 0 && propertiesToAdd.length > 0) {
|
|
20006
|
+
message = `Successfully updated ${propertiesToUpdate.length} and added ${propertiesToAdd.length} property value(s)`;
|
|
20007
|
+
} else if (propertiesToAdd.length > 0) {
|
|
20008
|
+
message = `Successfully added ${propertiesToAdd.length} property value(s)`;
|
|
20009
|
+
} else {
|
|
20010
|
+
message = `Successfully updated ${propertiesToUpdate.length} property value(s)`;
|
|
20011
|
+
}
|
|
20012
|
+
return {
|
|
20013
|
+
content: [{
|
|
20014
|
+
type: "text",
|
|
20015
|
+
text: JSON.stringify({
|
|
20016
|
+
success: true,
|
|
20017
|
+
message,
|
|
20018
|
+
updatedProperties: updatedPropertyKeys,
|
|
20019
|
+
addedProperties: addedPropertyKeys,
|
|
20020
|
+
document: updatedDocument
|
|
20021
|
+
}, null, 2)
|
|
20022
|
+
}]
|
|
20023
|
+
};
|
|
20024
|
+
},
|
|
20025
|
+
(user) => user.fallbackPermissions.includes(UmbracoDocumentPermissions.Update)
|
|
20026
|
+
);
|
|
20027
|
+
var update_document_properties_default = UpdateDocumentPropertiesTool;
|
|
20028
|
+
|
|
20029
|
+
// src/umb-management-api/tools/document/put/update-block-property.ts
|
|
20030
|
+
|
|
20031
|
+
|
|
20032
|
+
// src/umb-management-api/tools/document/put/helpers/block-discovery.ts
|
|
20033
|
+
function isRichTextValue(value) {
|
|
20034
|
+
if (!value || typeof value !== "object") {
|
|
20035
|
+
return false;
|
|
20036
|
+
}
|
|
20037
|
+
if (!("markup" in value)) {
|
|
20038
|
+
return false;
|
|
20039
|
+
}
|
|
20040
|
+
if (!value.blocks || typeof value.blocks !== "object") {
|
|
20041
|
+
return false;
|
|
20042
|
+
}
|
|
20043
|
+
return Array.isArray(value.blocks.contentData) && Array.isArray(value.blocks.settingsData);
|
|
20044
|
+
}
|
|
20045
|
+
function isBlockStructure(value) {
|
|
20046
|
+
if (!value || typeof value !== "object") {
|
|
20047
|
+
return false;
|
|
20048
|
+
}
|
|
20049
|
+
return Array.isArray(value.contentData) && Array.isArray(value.settingsData);
|
|
20050
|
+
}
|
|
20051
|
+
function discoverAllBlockArrays(value, path4 = "root") {
|
|
20052
|
+
const results = [];
|
|
20053
|
+
if (!value || typeof value !== "object") {
|
|
20054
|
+
return results;
|
|
20055
|
+
}
|
|
20056
|
+
if (isRichTextValue(value)) {
|
|
20057
|
+
const nestedResults = discoverAllBlockArrays(value.blocks, `${path4}.blocks`);
|
|
20058
|
+
results.push(...nestedResults);
|
|
20059
|
+
return results;
|
|
20060
|
+
}
|
|
20061
|
+
if (isBlockStructure(value)) {
|
|
20062
|
+
results.push({
|
|
20063
|
+
contentData: value.contentData,
|
|
20064
|
+
settingsData: value.settingsData,
|
|
20065
|
+
path: path4
|
|
20066
|
+
});
|
|
20067
|
+
value.contentData.forEach((block, index) => {
|
|
20068
|
+
if (block.values && Array.isArray(block.values)) {
|
|
20069
|
+
block.values.forEach((prop, propIndex) => {
|
|
20070
|
+
const propPath = `${path4}.contentData[${index}].values[${propIndex}](${prop.alias})`;
|
|
20071
|
+
if (isRichTextValue(prop.value)) {
|
|
20072
|
+
const nestedResults = discoverAllBlockArrays(prop.value.blocks, `${propPath}.blocks`);
|
|
20073
|
+
results.push(...nestedResults);
|
|
20074
|
+
} else if (isBlockStructure(prop.value)) {
|
|
20075
|
+
const nestedResults = discoverAllBlockArrays(prop.value, propPath);
|
|
20076
|
+
results.push(...nestedResults);
|
|
20077
|
+
}
|
|
20078
|
+
});
|
|
20079
|
+
}
|
|
20080
|
+
});
|
|
20081
|
+
value.settingsData.forEach((block, index) => {
|
|
20082
|
+
if (block.values && Array.isArray(block.values)) {
|
|
20083
|
+
block.values.forEach((prop, propIndex) => {
|
|
20084
|
+
const propPath = `${path4}.settingsData[${index}].values[${propIndex}](${prop.alias})`;
|
|
20085
|
+
if (isRichTextValue(prop.value)) {
|
|
20086
|
+
const nestedResults = discoverAllBlockArrays(prop.value.blocks, `${propPath}.blocks`);
|
|
20087
|
+
results.push(...nestedResults);
|
|
20088
|
+
} else if (isBlockStructure(prop.value)) {
|
|
20089
|
+
const nestedResults = discoverAllBlockArrays(prop.value, propPath);
|
|
20090
|
+
results.push(...nestedResults);
|
|
20091
|
+
}
|
|
20092
|
+
});
|
|
20093
|
+
}
|
|
20094
|
+
});
|
|
20095
|
+
}
|
|
20096
|
+
return results;
|
|
20097
|
+
}
|
|
20098
|
+
function findBlockByKey(discoveredArrays, contentKey, blockType) {
|
|
20099
|
+
for (const discovered of discoveredArrays) {
|
|
20100
|
+
const array = blockType === "content" ? discovered.contentData : discovered.settingsData;
|
|
20101
|
+
const block = array.find((b) => b.key === contentKey);
|
|
20102
|
+
if (block) {
|
|
20103
|
+
return { block, arrayRef: array, path: discovered.path };
|
|
20104
|
+
}
|
|
20105
|
+
}
|
|
20106
|
+
return null;
|
|
20107
|
+
}
|
|
20108
|
+
|
|
20109
|
+
// src/umb-management-api/tools/document/put/update-block-property.ts
|
|
20110
|
+
var blockPropertyUpdateSchema = _zod.z.object({
|
|
20111
|
+
alias: _zod.z.string().min(1).describe("The property alias within the block to update"),
|
|
20112
|
+
value: _zod.z.any().nullish().describe("The new value for the property"),
|
|
20113
|
+
culture: _zod.z.string().nullish().describe("Optional culture code for variant block properties"),
|
|
20114
|
+
segment: _zod.z.string().nullish().describe("Optional segment identifier for variant block properties")
|
|
20115
|
+
});
|
|
20116
|
+
var blockUpdateSchema = _zod.z.object({
|
|
20117
|
+
contentKey: _zod.z.string().uuid().describe("The unique key (UUID) identifying the block"),
|
|
20118
|
+
blockType: _zod.z.enum(["content", "settings"]).describe("'content' for contentData, 'settings' for settingsData"),
|
|
20119
|
+
properties: _zod.z.array(blockPropertyUpdateSchema).min(1).describe("Properties to update within this block")
|
|
20120
|
+
});
|
|
20121
|
+
var updateBlockPropertySchema = {
|
|
20122
|
+
documentId: _zod.z.string().uuid().describe("The document containing the block"),
|
|
20123
|
+
propertyAlias: _zod.z.string().min(1).describe("Document property alias containing BlockList/BlockGrid"),
|
|
20124
|
+
culture: _zod.z.string().nullish().describe("Optional culture for variant document properties"),
|
|
20125
|
+
segment: _zod.z.string().nullish().describe("Optional segment for variant document properties"),
|
|
20126
|
+
updates: _zod.z.array(blockUpdateSchema).min(1).describe("Array of block updates")
|
|
20127
|
+
};
|
|
20128
|
+
var UpdateBlockPropertyTool = CreateUmbracoTool(
|
|
20129
|
+
"update-block-property",
|
|
20130
|
+
`Updates or adds property values within BlockList, BlockGrid, or RichText block content.
|
|
20131
|
+
|
|
20132
|
+
This tool enables targeted updates to individual block properties without sending the entire JSON payload.
|
|
20133
|
+
You can update existing properties, add new properties, or do both in a single call.
|
|
20134
|
+
It automatically handles deep traversal of nested block structures (e.g., RichText blocks containing nested blocks).
|
|
20135
|
+
|
|
20136
|
+
Key features:
|
|
20137
|
+
- Update existing properties or add new ones to blocks
|
|
20138
|
+
- Property must exist on the Element Type (including compositions)
|
|
20139
|
+
- Support for both content and settings blocks
|
|
20140
|
+
- Batch updates to multiple blocks in a single call
|
|
20141
|
+
- Deep traversal of nested block structures
|
|
20142
|
+
- Full i18n support with culture and segment parameters
|
|
20143
|
+
- Culture/segment requirements validated against property variance flags
|
|
20144
|
+
|
|
20145
|
+
Example usage:
|
|
20146
|
+
- Update a block property: { documentId: "...", propertyAlias: "mainContent", updates: [{ contentKey: "block-uuid", blockType: "content", properties: [{ alias: "title", value: "New Title" }] }] }
|
|
20147
|
+
- Add a new property to block: { documentId: "...", propertyAlias: "mainContent", updates: [{ contentKey: "block-uuid", blockType: "content", properties: [{ alias: "newProp", value: "Value" }] }] }
|
|
20148
|
+
- Update with culture: { documentId: "...", propertyAlias: "mainContent", culture: "es-ES", updates: [...] }
|
|
20149
|
+
- Batch update multiple blocks: { documentId: "...", propertyAlias: "mainContent", updates: [{ contentKey: "uuid1", ... }, { contentKey: "uuid2", ... }] }`,
|
|
20150
|
+
updateBlockPropertySchema,
|
|
20151
|
+
async (model) => {
|
|
20152
|
+
const client = UmbracoManagementClient2.getClient();
|
|
20153
|
+
const currentDocument = await client.getDocumentById(model.documentId);
|
|
20154
|
+
const documentProperty = currentDocument.values.find(
|
|
20155
|
+
(v) => matchesProperty(v, model.propertyAlias, model.culture, model.segment)
|
|
20156
|
+
);
|
|
20157
|
+
if (!documentProperty) {
|
|
20158
|
+
const availableAliases = currentDocument.values.map((v) => ({
|
|
20159
|
+
alias: v.alias,
|
|
20160
|
+
culture: _nullishCoalesce(v.culture, () => ( null)),
|
|
20161
|
+
segment: _nullishCoalesce(v.segment, () => ( null)),
|
|
20162
|
+
editorAlias: v.editorAlias
|
|
20163
|
+
}));
|
|
20164
|
+
return {
|
|
20165
|
+
content: [{
|
|
20166
|
+
type: "text",
|
|
20167
|
+
text: JSON.stringify({
|
|
20168
|
+
success: false,
|
|
20169
|
+
error: "Property not found",
|
|
20170
|
+
message: `Property '${getPropertyKey(model.propertyAlias, model.culture, model.segment)}' does not exist on this document`,
|
|
20171
|
+
availableProperties: availableAliases
|
|
20172
|
+
}, null, 2)
|
|
20173
|
+
}]
|
|
20174
|
+
};
|
|
20175
|
+
}
|
|
20176
|
+
const discoveredArrays = discoverAllBlockArrays(documentProperty.value, `property(${model.propertyAlias})`);
|
|
20177
|
+
if (discoveredArrays.length === 0) {
|
|
20178
|
+
return {
|
|
20179
|
+
content: [{
|
|
20180
|
+
type: "text",
|
|
20181
|
+
text: JSON.stringify({
|
|
20182
|
+
success: false,
|
|
20183
|
+
error: "No block structure found",
|
|
20184
|
+
message: `Property '${model.propertyAlias}' does not contain a BlockList, BlockGrid, or RichText block structure`,
|
|
20185
|
+
propertyValue: documentProperty.value
|
|
20186
|
+
}, null, 2)
|
|
20187
|
+
}]
|
|
20188
|
+
};
|
|
20189
|
+
}
|
|
20190
|
+
const results = [];
|
|
20191
|
+
const notFoundBlocks = [];
|
|
20192
|
+
const elementTypePropertiesCache = /* @__PURE__ */ new Map();
|
|
20193
|
+
const getElementTypeProperties = async (contentTypeKey) => {
|
|
20194
|
+
if (!elementTypePropertiesCache.has(contentTypeKey)) {
|
|
20195
|
+
try {
|
|
20196
|
+
const properties = await getAllDocumentTypeProperties(contentTypeKey);
|
|
20197
|
+
elementTypePropertiesCache.set(contentTypeKey, properties);
|
|
20198
|
+
} catch (error) {
|
|
20199
|
+
console.error(`Failed to fetch Element Type properties for ${contentTypeKey}:`, error);
|
|
20200
|
+
elementTypePropertiesCache.set(contentTypeKey, []);
|
|
20201
|
+
}
|
|
20202
|
+
}
|
|
20203
|
+
return elementTypePropertiesCache.get(contentTypeKey);
|
|
20204
|
+
};
|
|
20205
|
+
for (const update of model.updates) {
|
|
20206
|
+
const foundBlock = findBlockByKey(discoveredArrays, update.contentKey, update.blockType);
|
|
20207
|
+
if (!foundBlock) {
|
|
20208
|
+
notFoundBlocks.push({ contentKey: update.contentKey, blockType: update.blockType });
|
|
20209
|
+
results.push({
|
|
20210
|
+
success: false,
|
|
20211
|
+
contentKey: update.contentKey,
|
|
20212
|
+
message: `Block with contentKey '${update.contentKey}' not found in ${update.blockType}Data`
|
|
20213
|
+
});
|
|
20214
|
+
continue;
|
|
20215
|
+
}
|
|
20216
|
+
const warnings = [];
|
|
20217
|
+
const errors = [];
|
|
20218
|
+
let updatedCount = 0;
|
|
20219
|
+
let addedCount = 0;
|
|
20220
|
+
const elementTypeProperties = await getElementTypeProperties(foundBlock.block.contentTypeKey);
|
|
20221
|
+
if (elementTypeProperties.length > 0) {
|
|
20222
|
+
const propsToValidate = update.properties.map((p) => {
|
|
20223
|
+
const def = elementTypeProperties.find((d) => d.alias === p.alias);
|
|
20224
|
+
return { alias: p.alias, value: p.value, dataTypeId: _nullishCoalesce(_optionalChain([def, 'optionalAccess', _51 => _51.dataTypeId]), () => ( "")) };
|
|
20225
|
+
}).filter((p) => p.dataTypeId);
|
|
20226
|
+
if (propsToValidate.length > 0) {
|
|
20227
|
+
const valueValidation = await validatePropertiesBeforeSave(propsToValidate);
|
|
20228
|
+
if (!valueValidation.isValid) {
|
|
20229
|
+
errors.push(...valueValidation.errors);
|
|
20230
|
+
}
|
|
20231
|
+
}
|
|
20232
|
+
}
|
|
20233
|
+
for (const propUpdate of update.properties) {
|
|
20234
|
+
const blockProperty = foundBlock.block.values.find(
|
|
20235
|
+
(v) => matchesProperty(v, propUpdate.alias, propUpdate.culture, propUpdate.segment)
|
|
20236
|
+
);
|
|
20237
|
+
if (blockProperty) {
|
|
20238
|
+
blockProperty.value = propUpdate.value;
|
|
20239
|
+
updatedCount++;
|
|
20240
|
+
} else {
|
|
20241
|
+
const propertyDef = elementTypeProperties.find((p) => p.alias === propUpdate.alias);
|
|
20242
|
+
if (propertyDef) {
|
|
20243
|
+
const validationError = validateCultureSegment(propUpdate, propertyDef);
|
|
20244
|
+
if (validationError) {
|
|
20245
|
+
errors.push(validationError);
|
|
20246
|
+
} else {
|
|
20247
|
+
foundBlock.block.values.push({
|
|
20248
|
+
alias: propUpdate.alias,
|
|
20249
|
+
culture: _nullishCoalesce(propUpdate.culture, () => ( null)),
|
|
20250
|
+
segment: _nullishCoalesce(propUpdate.segment, () => ( null)),
|
|
20251
|
+
value: propUpdate.value
|
|
20252
|
+
});
|
|
20253
|
+
addedCount++;
|
|
20254
|
+
}
|
|
20255
|
+
} else if (elementTypeProperties.length > 0) {
|
|
20256
|
+
errors.push(
|
|
20257
|
+
`Property '${getPropertyKey(propUpdate.alias, propUpdate.culture, propUpdate.segment)}' does not exist on Element Type`
|
|
20258
|
+
);
|
|
20259
|
+
} else {
|
|
20260
|
+
warnings.push(
|
|
20261
|
+
`Property '${getPropertyKey(propUpdate.alias, propUpdate.culture, propUpdate.segment)}' not found in block (could not validate against Element Type)`
|
|
20262
|
+
);
|
|
20263
|
+
}
|
|
20264
|
+
}
|
|
20265
|
+
}
|
|
20266
|
+
const totalProcessed = updatedCount + addedCount;
|
|
20267
|
+
let message;
|
|
20268
|
+
if (updatedCount > 0 && addedCount > 0) {
|
|
20269
|
+
message = `Updated ${updatedCount} and added ${addedCount} properties in block at ${foundBlock.path}`;
|
|
20270
|
+
} else if (addedCount > 0) {
|
|
20271
|
+
message = `Added ${addedCount} properties in block at ${foundBlock.path}`;
|
|
20272
|
+
} else if (updatedCount > 0) {
|
|
20273
|
+
message = `Updated ${updatedCount} properties in block at ${foundBlock.path}`;
|
|
20274
|
+
} else {
|
|
20275
|
+
message = `No properties were processed in block at ${foundBlock.path}`;
|
|
20276
|
+
}
|
|
20277
|
+
results.push({
|
|
20278
|
+
success: totalProcessed > 0 || errors.length === 0,
|
|
20279
|
+
contentKey: update.contentKey,
|
|
20280
|
+
message,
|
|
20281
|
+
updatedCount: updatedCount > 0 ? updatedCount : void 0,
|
|
20282
|
+
addedCount: addedCount > 0 ? addedCount : void 0,
|
|
20283
|
+
warnings: warnings.length > 0 ? warnings : void 0,
|
|
20284
|
+
errors: errors.length > 0 ? errors : void 0
|
|
20285
|
+
});
|
|
20286
|
+
}
|
|
20287
|
+
if (notFoundBlocks.length === model.updates.length) {
|
|
20288
|
+
const allBlocks = discoveredArrays.flatMap((d) => [
|
|
20289
|
+
...d.contentData.map((b) => ({ key: b.key, type: "content", path: d.path })),
|
|
20290
|
+
...d.settingsData.map((b) => ({ key: b.key, type: "settings", path: d.path }))
|
|
20291
|
+
]);
|
|
20292
|
+
return {
|
|
20293
|
+
content: [{
|
|
20294
|
+
type: "text",
|
|
20295
|
+
text: JSON.stringify({
|
|
20296
|
+
success: false,
|
|
20297
|
+
error: "Blocks not found",
|
|
20298
|
+
message: "None of the specified blocks were found in the document",
|
|
20299
|
+
notFoundBlocks,
|
|
20300
|
+
availableBlocks: allBlocks
|
|
20301
|
+
}, null, 2)
|
|
20302
|
+
}]
|
|
20303
|
+
};
|
|
20304
|
+
}
|
|
20305
|
+
const updatedValues = currentDocument.values.map((existingValue) => ({
|
|
20306
|
+
alias: existingValue.alias,
|
|
20307
|
+
culture: existingValue.culture,
|
|
20308
|
+
segment: existingValue.segment,
|
|
20309
|
+
value: existingValue.value
|
|
20310
|
+
}));
|
|
20311
|
+
const variants = currentDocument.variants.map((v) => ({
|
|
20312
|
+
culture: v.culture,
|
|
20313
|
+
segment: v.segment,
|
|
20314
|
+
name: v.name
|
|
20315
|
+
}));
|
|
20316
|
+
const updatePayload = {
|
|
20317
|
+
values: updatedValues,
|
|
20318
|
+
variants,
|
|
20319
|
+
template: currentDocument.template
|
|
20320
|
+
};
|
|
20321
|
+
await client.putDocumentById(model.documentId, updatePayload);
|
|
20322
|
+
return {
|
|
20323
|
+
content: [{
|
|
20324
|
+
type: "text",
|
|
20325
|
+
text: JSON.stringify({
|
|
20326
|
+
success: true,
|
|
20327
|
+
message: `Successfully processed ${model.updates.length} block update(s)`,
|
|
20328
|
+
results
|
|
20329
|
+
}, null, 2)
|
|
20330
|
+
}]
|
|
20331
|
+
};
|
|
20332
|
+
},
|
|
20333
|
+
(user) => user.fallbackPermissions.includes(UmbracoDocumentPermissions.Update)
|
|
20334
|
+
);
|
|
20335
|
+
var update_block_property_default = UpdateBlockPropertyTool;
|
|
20336
|
+
|
|
19570
20337
|
// src/umb-management-api/tools/document/items/get/get-root.ts
|
|
19571
20338
|
var GetDocumentRootTool = CreateUmbracoTool(
|
|
19572
20339
|
"get-document-root",
|
|
@@ -19740,6 +20507,8 @@ var DocumentCollection = {
|
|
|
19740
20507
|
tools.push(sort_document_default());
|
|
19741
20508
|
tools.push(unpublish_document_default());
|
|
19742
20509
|
tools.push(update_document_default());
|
|
20510
|
+
tools.push(update_document_properties_default());
|
|
20511
|
+
tools.push(update_block_property_default());
|
|
19743
20512
|
tools.push(put_document_domains_default());
|
|
19744
20513
|
tools.push(put_document_notifications_default());
|
|
19745
20514
|
tools.push(put_document_public_access_default());
|
|
@@ -20165,7 +20934,7 @@ function getExtensionFromMimeType(mimeType) {
|
|
|
20165
20934
|
return extension ? `.${extension}` : void 0;
|
|
20166
20935
|
}
|
|
20167
20936
|
function validateMediaTypeForSvg(filePath, fileUrl, fileName, mediaTypeName) {
|
|
20168
|
-
const isSvg = _optionalChain([filePath, 'optionalAccess',
|
|
20937
|
+
const isSvg = _optionalChain([filePath, 'optionalAccess', _52 => _52.toLowerCase, 'call', _53 => _53(), 'access', _54 => _54.endsWith, 'call', _55 => _55(".svg")]) || _optionalChain([fileUrl, 'optionalAccess', _56 => _56.toLowerCase, 'call', _57 => _57(), 'access', _58 => _58.endsWith, 'call', _59 => _59(".svg")]) || fileName.toLowerCase().endsWith(".svg");
|
|
20169
20938
|
if (isSvg && mediaTypeName === MEDIA_TYPE_IMAGE) {
|
|
20170
20939
|
console.warn(`SVG detected - using ${MEDIA_TYPE_VECTOR_GRAPHICS} media type instead of ${MEDIA_TYPE_IMAGE}`);
|
|
20171
20940
|
return MEDIA_TYPE_VECTOR_GRAPHICS;
|
|
@@ -20322,8 +21091,8 @@ async function uploadMediaFile(client, params) {
|
|
|
20322
21091
|
});
|
|
20323
21092
|
} catch (error) {
|
|
20324
21093
|
const err = error;
|
|
20325
|
-
const errorData = _optionalChain([err, 'access',
|
|
20326
|
-
throw new Error(`Failed to upload temporary file: ${_optionalChain([err, 'access',
|
|
21094
|
+
const errorData = _optionalChain([err, 'access', _60 => _60.response, 'optionalAccess', _61 => _61.data]) ? typeof err.response.data === "string" ? err.response.data : JSON.stringify(err.response.data) : err.message;
|
|
21095
|
+
throw new Error(`Failed to upload temporary file: ${_optionalChain([err, 'access', _62 => _62.response, 'optionalAccess', _63 => _63.status]) || "Unknown error"} - ${errorData}`);
|
|
20327
21096
|
}
|
|
20328
21097
|
const valueStructure = buildValueStructure(validatedMediaTypeName, params.temporaryFileId);
|
|
20329
21098
|
try {
|
|
@@ -20342,7 +21111,7 @@ async function uploadMediaFile(client, params) {
|
|
|
20342
21111
|
});
|
|
20343
21112
|
} catch (error) {
|
|
20344
21113
|
const err = error;
|
|
20345
|
-
throw new Error(`Failed to create media item: ${_optionalChain([err, 'access',
|
|
21114
|
+
throw new Error(`Failed to create media item: ${_optionalChain([err, 'access', _64 => _64.response, 'optionalAccess', _65 => _65.status]) || "Unknown error"} - ${JSON.stringify(_optionalChain([err, 'access', _66 => _66.response, 'optionalAccess', _67 => _67.data])) || err.message}`);
|
|
20346
21115
|
}
|
|
20347
21116
|
return params.name;
|
|
20348
21117
|
} finally {
|
|
@@ -21547,7 +22316,7 @@ var update_folder_default4 = UpdateMediaTypeFolderTool;
|
|
|
21547
22316
|
|
|
21548
22317
|
// src/umb-management-api/tools/media-type/post/create-media-type.ts
|
|
21549
22318
|
|
|
21550
|
-
var
|
|
22319
|
+
var propertySchema3 = postMediaTypeBody.shape.properties;
|
|
21551
22320
|
var containerSchema = postMediaTypeBody.shape.containers;
|
|
21552
22321
|
var allowedMediaTypeSchema = postMediaTypeBody.shape.allowedMediaTypes;
|
|
21553
22322
|
var compositionSchema = postMediaTypeBody.shape.compositions;
|
|
@@ -21561,7 +22330,7 @@ var createMediaTypeSchema = _zod.z.object({
|
|
|
21561
22330
|
variesByCulture: _zod.z.boolean(),
|
|
21562
22331
|
variesBySegment: _zod.z.boolean(),
|
|
21563
22332
|
isElement: _zod.z.boolean(),
|
|
21564
|
-
properties:
|
|
22333
|
+
properties: propertySchema3,
|
|
21565
22334
|
containers: containerSchema,
|
|
21566
22335
|
id: _zod.z.string().uuid().nullish(),
|
|
21567
22336
|
parentId: _zod.z.string().uuid().optional(),
|
|
@@ -26176,8 +26945,8 @@ var mapTools = (server, user, tools, config) => {
|
|
|
26176
26945
|
return tools.forEach((tool) => {
|
|
26177
26946
|
const userHasPermission = tool.enabled === void 0 || tool.enabled(user);
|
|
26178
26947
|
if (!userHasPermission) return;
|
|
26179
|
-
if (_optionalChain([config, 'access',
|
|
26180
|
-
if (_optionalChain([config, 'access',
|
|
26948
|
+
if (_optionalChain([config, 'access', _68 => _68.disabledTools, 'optionalAccess', _69 => _69.includes, 'call', _70 => _70(tool.name)])) return;
|
|
26949
|
+
if (_optionalChain([config, 'access', _71 => _71.enabledTools, 'optionalAccess', _72 => _72.length]) && !config.enabledTools.includes(tool.name)) return;
|
|
26181
26950
|
server.tool(tool.name, tool.description, tool.schema, tool.handler);
|
|
26182
26951
|
});
|
|
26183
26952
|
};
|
|
@@ -26198,7 +26967,7 @@ function resolveDependencies(requestedNames, collections) {
|
|
|
26198
26967
|
const collectionMap = new Map(collections.map((c) => [c.metadata.name, c]));
|
|
26199
26968
|
function addDependencies(collectionName) {
|
|
26200
26969
|
const collection = collectionMap.get(collectionName);
|
|
26201
|
-
if (_optionalChain([collection, 'optionalAccess',
|
|
26970
|
+
if (_optionalChain([collection, 'optionalAccess', _73 => _73.metadata, 'access', _74 => _74.dependencies])) {
|
|
26202
26971
|
collection.metadata.dependencies.forEach((dep) => {
|
|
26203
26972
|
if (!result.has(dep)) {
|
|
26204
26973
|
result.add(dep);
|