Skip to content
Closed
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
* Removes the non-functional `uniqueUsername` route from the `user` module
* Updated dependencies to address deprecation warnings.

* Modifies the `annotateAreaForExternalFront()` method of the `@apostrophecms/template` module to accept a per-module `annotateWidgetForExternalFront()` method. This allows widgets to send project-level options alongside the per-area options to external frontends.

## 4.21.0 (2025-09-03)

Expand Down
27 changes: 19 additions & 8 deletions modules/@apostrophecms/template/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -432,8 +432,8 @@ module.exports = {
const parse = config.parse
? config.parse
: function (parser, nodes, lexer) {
// Default parser gets comma separated arguments,
// assumes no body
// Default parser gets comma separated arguments,
// assumes no body

// get the tag token
const token = parser.nextToken();
Expand Down Expand Up @@ -696,7 +696,7 @@ module.exports = {
_.extend(args, data);

if (req.aposError) {
// A 500-worthy error occurred already, i.e. in `pageBeforeSend`
// A 500-worthy error occurred already, i.e. in `pageBeforeSend`
telemetry.handleError(span, req.aposError);
span.end();
return error(req.aposError);
Expand Down Expand Up @@ -739,8 +739,8 @@ module.exports = {
span.setStatus({ code: telemetry.api.SpanStatusCode.OK });
return content;
} catch (e) {
// The page template threw an exception. Log where it
// occurred for easier debugging
// The page template threw an exception. Log where it
// occurred for easier debugging
telemetry.handleError(span, e);
return error(e);
} finally {
Expand Down Expand Up @@ -1289,7 +1289,7 @@ module.exports = {
// and `choices` properties, and guaranteeing that `items` exists,
// at least as an empty array.

annotateAreaForExternalFront(field, area) {
async annotateAreaForExternalFront(field, area) {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this really need to be async? It's a major performance hit when multiplied by every area and then every widget, and there's no async work being done to look up options. Also I don't think you changed anything where it's called, so there's probably just a promise showing up there?

My starting assumption is that this annotation work should not be async. It's meant to be very lightweight to minimize the impact of using an external frontend.

area.field = field;
area.options = field.options;
// Really widget configurations, but the method name is already set in
Expand All @@ -1303,11 +1303,22 @@ module.exports = {
label: options.addLabel || manager.label || `No label for ${name}`
};
}).filter(choice => !!choice);

area.items ||= [];
if (area._docId) {
for (const item of area.items) {
for (const item of area.items) {
// Add _docId if area has one
if (area._docId) {
item._docId = area._docId;
}

// Annotate each individual widget with its options
// Each widget must elect into this by creating an
// `annotateWidgetForExternalFront() method.
const manager = self.apos.area.getManager?.(item.type) ||
self.apos.area.widgetManagers?.[item.type];

const widgetOptions = await manager.annotateWidgetForExternalFront() || {};
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should not be async either.

item._options = widgetOptions;
}
}
};
Expand Down
5 changes: 5 additions & 0 deletions modules/@apostrophecms/widget-type/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -449,7 +449,12 @@ module.exports = {
}
return true;
});
},

annotateWidgetForExternalFront() {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Noticing this is already not async (and that's good), I think "async" in the area annotation method might have been a discarded early thought that hung around?

return {};
}

};
},
extendMethods(self) {
Expand Down