Skip to content

Commit ac294b0

Browse files
committed
wip: retire renderNotification only; renderTemplate and interpolate stay pending a disposition ruling
Claude-Session: https://claude.ai/code/session_01CP5uvqW3aX2Tfwy6YAsNu5 Co-authored-by: Claude <noreply@anthropic.com>
1 parent 85058b6 commit ac294b0

5 files changed

Lines changed: 27 additions & 81 deletions

File tree

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,18 @@
11
---
2-
'@objectstack/plugin-email': patch
32
'@objectstack/service-messaging': patch
43
---
54

6-
fix(plugin-email, service-messaging)!: retire the render exports that take a template body with no save moment (`renderTemplate`, `renderNotification`, `interpolate`)
5+
fix(service-messaging)!: retire `renderNotification`, the render export that takes a notification template body with no save moment
76

8-
The hole-placement rule is judged where a template is saved or registered: the `sys_notification_template` save hooks, and the authoring rule for email templates. Three exports took a template body inline and rendered it at once, with no save moment, so the rule could not see them. They leave the two packages' published entries. Nothing in this repository imported them from either entry. The renderers stay inside the packages: the mail service and the email and sms channels still render every stored template through them, unchanged.
7+
The hole-placement rule for notification templates is judged where a template is saved: the `sys_notification_template` save hooks. `renderNotification` took a template body inline and rendered it at once, with no save moment, so the rule could not see it. It leaves the published entry of `@objectstack/service-messaging`. Nothing in this repository imported it from that entry. The renderer stays inside the package: the email and sms channels still render every stored template through it, unchanged.
98

109
Clause-②: no (narrowing)
1110
Metadata-protocol: none
1211

13-
<!-- adr-0087: not-required (runtime-export-retired @objectstack/plugin-email#renderTemplate, @objectstack/service-messaging#renderNotification, @objectstack/service-messaging#interpolate) Three runtime functions leave two published package entries; no key of any metadata schema, no object definition and no stored shape is added, removed, renamed or re-shaped, so there is nothing for `objectstack migrate meta` to rewrite and no tombstone. A TypeScript consumer meets the break at its own import, and the lines below name the door to use instead. -->
12+
<!-- adr-0087: not-required (runtime-export-retired @objectstack/service-messaging#renderNotification) One runtime function leaves a published package entry; no key of any metadata schema, no object definition and no stored shape is added, removed, renamed or re-shaped, so there is nothing for `objectstack migrate meta` to rewrite and no tombstone. A TypeScript consumer meets the break at its own import, and the line below names the door to use instead. -->
1413

15-
**BREAKING** (three runtime exports are removed). It ships as `patch` because the metadata protocol does not move. There is no staged window.
14+
**BREAKING** (a runtime export is removed). It ships as `patch` because the metadata protocol does not move. There is no staged window.
1615

17-
- FROM `renderTemplate` imported from `@objectstack/plugin-email` TO a template saved or registered as an `email_template` and rendered by name through the mail service: `renderTemplate({ template, data, locale })` on the `email` service (render only) or `sendTemplate` (render and send).
18-
- FROM `renderNotification` imported from `@objectstack/service-messaging` TO a `sys_notification_template` row for the topic, channel and locale, which the delivering channel renders when the notification is emitted.
19-
- FROM `interpolate` imported from `@objectstack/service-messaging` TO the subject or plain-text body of a `sys_notification_template` row, rendered the same way by the delivering channel.
16+
- FROM `renderNotification` TO a `sys_notification_template` row for the topic, channel and locale, which the delivering channel renders when the notification is emitted.
2017

21-
Unchanged: `requireVars` and `htmlToText` in `@objectstack/plugin-email`, and the mail service's `setTemplateLoader`; `NotificationTemplateStore`, `TEMPLATE_OBJECT`, `DEFAULT_LOCALE` and the template types in `@objectstack/service-messaging`; and how every stored template renders.
18+
Unchanged: `interpolate` (the plain-text face, which the placement rule judges at no door), `NotificationTemplateStore`, `TEMPLATE_OBJECT`, `DEFAULT_LOCALE` and the template types; and how every stored template renders.

‎packages/plugins/plugin-email/src/index.ts‎

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -85,12 +85,7 @@ export {
8585
type AttachmentReclaimOutcome,
8686
type ReclaimAttachmentContentOptions,
8787
} from './attachment-reclaim.js';
88-
// [#25190] `renderTemplate` (the HTML-face renderer) is not on this entry: it
89-
// took a template body inline and rendered it with no save moment, so the
90-
// hole-placement rule judged where a template is saved or registered could not
91-
// see it (ruling 6335348115 on #25082, F2 B3). A template is rendered from the
92-
// mail service by NAME: `IEmailService.renderTemplate` / `sendTemplate`.
93-
export { requireVars, htmlToText } from './template-engine.js';
88+
export { renderTemplate, requireVars, htmlToText } from './template-engine.js';
9489
export {
9590
ResendTransport,
9691
PostmarkTransport,

‎packages/plugins/plugin-email/src/render-export-retired.pin.test.ts‎

Lines changed: 0 additions & 49 deletions
This file was deleted.

‎packages/services/service-messaging/src/index.ts‎

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -88,14 +88,16 @@ export type {
8888

8989
// Templates + renderer (ADR-0030 P3)
9090
//
91-
// [#25190] The renderer itself (`renderNotification`, and `interpolate`, its
92-
// plain-text face) is not on this entry: both took a template body inline and
93-
// rendered it with no save moment, so the hole-placement rule the template
94-
// object's save hooks run could not see them (ruling 6335348115 on #25082,
95-
// F2 B3). A notification template is a `sys_notification_template` row, judged
96-
// when it is saved and rendered by the channels that deliver it.
91+
// [#25190] `renderNotification` is not on this entry: it took a template body
92+
// inline and rendered its html face with no save moment, so the hole-placement
93+
// rule the template object's save hooks run could not see it (ruling
94+
// 6335348115 on #25082, F2 B3). A notification template is a
95+
// `sys_notification_template` row, judged when it is saved and rendered by the
96+
// channels that deliver it. `interpolate` stays: it renders a plain-text face,
97+
// which that rule judges at no door.
9798
export {
9899
NotificationTemplateStore,
100+
interpolate,
99101
TEMPLATE_OBJECT,
100102
DEFAULT_LOCALE,
101103
} from './template-renderer.js';

‎packages/services/service-messaging/src/render-export-retired.pin.test.ts‎

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,31 @@
11
// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.
22

33
/**
4-
* #25190 — `renderNotification` and `interpolate`, the renderer that took a
5-
* template body inline, are retired from this package's published entry
6-
* (ruling 6335348115 on #25082, F2 B3; ADR-0087 `runtime-export-retired`). The
7-
* hole-placement rule is judged by the `sys_notification_template` save hooks,
8-
* and a body handed straight to either function was never saved, so they were
9-
* the one door the rule could not see.
4+
* #25190 — `renderNotification`, the renderer that took a template body inline,
5+
* is retired from this package's published entry (ruling 6335348115 on #25082,
6+
* F2 B3; ADR-0087 `runtime-export-retired`). The hole-placement rule is judged
7+
* by the `sys_notification_template` save hooks, and a body handed straight to
8+
* it was never saved, so it was the one door the rule could not see.
9+
* `interpolate` stays on the entry: it renders a plain-text face, which the
10+
* rule judges at no door.
1011
*
11-
* Pinned both ways: the entry no longer names them (the template store and the
12+
* Pinned both ways: the entry no longer names it (the template store and the
1213
* channels stay), and a stored template row still renders through a channel
1314
* built from the entry — the html body with every hole encoded, the subject
14-
* (`interpolate`'s plain-text face) verbatim.
15+
* (the plain-text face) verbatim.
1516
*/
1617

1718
import { describe, it, expect } from 'vitest';
1819
import * as entry from './index.js';
1920

2021
describe('service-messaging entry: the body-taking renderer is retired (#25190)', () => {
21-
it('the published entry does not export renderNotification or interpolate', () => {
22+
it('the published entry does not export renderNotification', () => {
2223
expect('renderNotification' in entry).toBe(false);
23-
expect('interpolate' in entry).toBe(false);
2424
});
2525

26-
it('THE CONTROL: the entry still exports the template store and the channels that render', () => {
26+
it('THE CONTROL: the entry still exports the template store, the plain-text face and the channels that render', () => {
2727
expect(typeof entry.NotificationTemplateStore).toBe('function');
28+
expect(typeof entry.interpolate).toBe('function');
2829
expect(entry.TEMPLATE_OBJECT).toBe('sys_notification_template');
2930
expect(typeof entry.createEmailChannel).toBe('function');
3031
expect(typeof entry.createSmsChannel).toBe('function');

0 commit comments

Comments
 (0)