@singleton-sd/post-kit-editor 0.6.0 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +65 -10
- package/dist/email-template-editor.d.ts +1 -1
- package/dist/email-template-editor.js +37 -30
- package/dist/email-template-editor.js.map +1 -1
- package/dist/save-send/actions.d.ts +70 -0
- package/dist/save-send/actions.js +75 -0
- package/dist/save-send/actions.js.map +1 -0
- package/package.json +4 -2
package/README.md
CHANGED
|
@@ -25,14 +25,25 @@ import {
|
|
|
25
25
|
EmailTemplateEditor,
|
|
26
26
|
type TemplateSourceFiles,
|
|
27
27
|
type SerializedTemplateSource,
|
|
28
|
+
type ValidationIssue,
|
|
28
29
|
} from '@singleton-sd/post-kit-editor';
|
|
29
30
|
|
|
30
|
-
export function TemplateAdminPage({
|
|
31
|
+
export function TemplateAdminPage({
|
|
32
|
+
template,
|
|
33
|
+
loading,
|
|
34
|
+
loadError,
|
|
35
|
+
}: {
|
|
36
|
+
template: TemplateSourceFiles;
|
|
37
|
+
loading?: boolean;
|
|
38
|
+
loadError?: string;
|
|
39
|
+
}) {
|
|
31
40
|
return (
|
|
32
41
|
<EmailTemplateEditor
|
|
33
42
|
template={template}
|
|
34
43
|
availableVariables={[{ name: 'name', description: 'Recipient display name' }]}
|
|
35
|
-
|
|
44
|
+
loading={loading}
|
|
45
|
+
loadError={loadError}
|
|
46
|
+
onSave={async (serialized: SerializedTemplateSource, files: TemplateSourceFiles) => {
|
|
36
47
|
// Commit serialized.templateJson / metadataJson / previewJson to the
|
|
37
48
|
// consumer repository (e.g. via the app's own server endpoint).
|
|
38
49
|
const res = await fetch('/api/templates', {
|
|
@@ -47,10 +58,9 @@ export function TemplateAdminPage({ template }: { template: TemplateSourceFiles
|
|
|
47
58
|
}}
|
|
48
59
|
onSendTest={async (serialized, _files, recipient) => {
|
|
49
60
|
// Browser → your trusted server only. The server uses
|
|
50
|
-
// @singleton-sd/post-kit-client with
|
|
51
|
-
//
|
|
52
|
-
//
|
|
53
|
-
// browser code.
|
|
61
|
+
// @singleton-sd/post-kit-client with secrets from Azure Key Vault
|
|
62
|
+
// (production) or local `.env` (development). Never embed a
|
|
63
|
+
// long-lived PostKit API key in browser code.
|
|
54
64
|
const res = await fetch('/api/templates/send-test', {
|
|
55
65
|
method: 'POST',
|
|
56
66
|
headers: { 'Content-Type': 'application/json' },
|
|
@@ -63,6 +73,9 @@ export function TemplateAdminPage({ template }: { template: TemplateSourceFiles
|
|
|
63
73
|
onDirtyChange={(dirty) => {
|
|
64
74
|
// Optional: guard in-app navigation while dirty.
|
|
65
75
|
}}
|
|
76
|
+
onValidationChange={(issues: ValidationIssue[]) => {
|
|
77
|
+
// Optional: mirror validation in the host chrome.
|
|
78
|
+
}}
|
|
66
79
|
onPreviewRendered={(html) => {
|
|
67
80
|
console.log('preview bytes', html.length);
|
|
68
81
|
}}
|
|
@@ -72,6 +85,39 @@ export function TemplateAdminPage({ template }: { template: TemplateSourceFiles
|
|
|
72
85
|
}
|
|
73
86
|
```
|
|
74
87
|
|
|
88
|
+
A copy-pasteable single-file integration (plus synthetic sample JSON) lives in
|
|
89
|
+
[`examples/minimal/`](./examples/minimal/).
|
|
90
|
+
|
|
91
|
+
## Props
|
|
92
|
+
|
|
93
|
+
| Prop | Type | Required | Description |
|
|
94
|
+
| --- | --- | --- | --- |
|
|
95
|
+
| `template` | `TemplateSourceFiles` | yes | Seeded working triple (`templateJson`, `metadata`, `previewData`). |
|
|
96
|
+
| `onSave` | `(serialized, files) => SaveResult \| void \| Promise<…>` | yes | Persist working files. Receives serialized Git strings **and** structured files. |
|
|
97
|
+
| `onSendTest` | `(serialized, files, recipient) => SendTestResult \| void \| Promise<…>` | no | When set, shows Send-test chrome. Must route through the consumer’s trusted server. |
|
|
98
|
+
| `availableVariables` | `TemplateVariable[]` | no | Catalogue entries offered to the editing user. |
|
|
99
|
+
| `onDirtyChange` | `(dirty: boolean) => void` | no | Fires when working state diverges from the seeded `template` (resets after successful save). |
|
|
100
|
+
| `onValidationChange` | `(issues: ValidationIssue[]) => void` | no | Current validation issues whenever they change. |
|
|
101
|
+
| `onPreviewRendered` | `(html: string) => void` | no | Successful preview HTML (e.g. open-in-new-tab without recompiling). |
|
|
102
|
+
| `loading` | `boolean` | no | Non-interactive loading shell while the host fetches files. |
|
|
103
|
+
| `loadError` | `string` | no | Non-interactive error shell with the host’s message. |
|
|
104
|
+
| `className` | `string` | no | Extra class on the root element. |
|
|
105
|
+
|
|
106
|
+
Also exported: `loadTemplateSource`, `serializeTemplateSource`,
|
|
107
|
+
`validateTemplate`, `hasValidationErrors`, `EDITOR_CLASS_PREFIX`, and related
|
|
108
|
+
types.
|
|
109
|
+
|
|
110
|
+
## What this package does not do
|
|
111
|
+
|
|
112
|
+
- **No persistence** — it never writes to disk, Git, or object storage. `onSave`
|
|
113
|
+
is the only way contents leave the editor.
|
|
114
|
+
- **No sending** — it never calls PostKit or any mail transport. `onSendTest`
|
|
115
|
+
(when provided) is a consumer callback only.
|
|
116
|
+
- **No credentials** — there are no API-key / token props. Secrets stay on the
|
|
117
|
+
consumer’s trusted server (Key Vault / env), never in browser bundles.
|
|
118
|
+
- **No publish pipeline** — compilation and content hashing belong to
|
|
119
|
+
`@singleton-sd/post-kit-compiler` in CI or server tooling.
|
|
120
|
+
|
|
75
121
|
## Persistence is consumer-supplied
|
|
76
122
|
|
|
77
123
|
Save serializes the working state with `serializeTemplateSource()` and passes
|
|
@@ -82,8 +128,9 @@ failure messages (no unhandled rejections).
|
|
|
82
128
|
|
|
83
129
|
Send-test chrome appears **only** when `onSendTest` is provided. The editor
|
|
84
130
|
validates a non-empty, plausible recipient address, then invokes the callback
|
|
85
|
-
with the same serialized payload. Test delivery must go
|
|
86
|
-
trusted server (typically `@singleton-sd/post-kit-client`
|
|
131
|
+
with the same serialized payload plus the recipient. Test delivery must go
|
|
132
|
+
through the consumer's trusted server (typically `@singleton-sd/post-kit-client`
|
|
133
|
+
server-side).
|
|
87
134
|
|
|
88
135
|
Optional `onDirtyChange` fires when working state diverges from the seeded
|
|
89
136
|
`template` prop and resets after a successful save.
|
|
@@ -143,12 +190,16 @@ against the resulting HTML string:
|
|
|
143
190
|
```tsx
|
|
144
191
|
import { renderToStaticMarkup } from 'react-dom/server';
|
|
145
192
|
|
|
146
|
-
const html = renderToStaticMarkup(
|
|
193
|
+
const html = renderToStaticMarkup(
|
|
194
|
+
<EmailTemplateEditor template={template} onSave={() => {}} />,
|
|
195
|
+
);
|
|
147
196
|
```
|
|
148
197
|
|
|
149
198
|
Specs live next to the code as `src/**/*.spec.tsx`. Behaviour that needs
|
|
150
199
|
interaction is factored into pure functions (preview rows, save/send helpers)
|
|
151
|
-
that can be tested without a DOM.
|
|
200
|
+
that can be tested without a DOM. The end-to-end suite (`src/e2e.spec.tsx`)
|
|
201
|
+
drives load → edit → validate → save / send-test through those helpers plus SSR
|
|
202
|
+
markup.
|
|
152
203
|
|
|
153
204
|
## Development
|
|
154
205
|
|
|
@@ -157,3 +208,7 @@ pnpm test # type-check + run tests
|
|
|
157
208
|
pnpm build # emit CommonJS to dist/
|
|
158
209
|
pnpm lint # covered by root eslint
|
|
159
210
|
```
|
|
211
|
+
|
|
212
|
+
`examples/` is documentation-only: it is not listed in the package `files`
|
|
213
|
+
array and is outside `src/`, so it is neither published to npm nor emitted into
|
|
214
|
+
`dist/`.
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { SaveResult, SendTestResult, SerializedTemplateSource } from './save-send/types';
|
|
2
2
|
import type { TemplateSourceFiles, TemplateVariable } from './types';
|
|
3
3
|
import { type ValidationIssue } from './validation/validate';
|
|
4
4
|
export declare const EDITOR_CLASS_PREFIX = "pk-editor-";
|
|
@@ -13,7 +13,7 @@ const PreviewDataEditor_1 = require("./preview/PreviewDataEditor");
|
|
|
13
13
|
const PreviewPane_1 = require("./preview/PreviewPane");
|
|
14
14
|
const dirty_1 = require("./save-send/dirty");
|
|
15
15
|
const SaveSendBar_1 = require("./save-send/SaveSendBar");
|
|
16
|
-
const
|
|
16
|
+
const actions_1 = require("./save-send/actions");
|
|
17
17
|
const ValidationSummary_1 = require("./validation/ValidationSummary");
|
|
18
18
|
const validate_1 = require("./validation/validate");
|
|
19
19
|
const VariableCatalogue_1 = require("./variables/VariableCatalogue");
|
|
@@ -95,68 +95,75 @@ function EmailTemplateEditorInner({ template, availableVariables, onSave, onSend
|
|
|
95
95
|
}, []);
|
|
96
96
|
const busy = saveFeedback.status === 'pending' || sendFeedback.status === 'pending';
|
|
97
97
|
const handleSave = (0, react_1.useCallback)(() => {
|
|
98
|
-
|
|
98
|
+
const started = (0, actions_1.startSaveAction)({
|
|
99
|
+
busy,
|
|
100
|
+
validationBlocked,
|
|
101
|
+
files: workingFiles,
|
|
102
|
+
});
|
|
103
|
+
if (started.status === 'noop') {
|
|
99
104
|
return;
|
|
100
105
|
}
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
payload = (0, types_1.buildSavePayload)(workingFiles);
|
|
104
|
-
}
|
|
105
|
-
catch (error) {
|
|
106
|
-
setSaveFeedback({
|
|
107
|
-
status: 'failure',
|
|
108
|
-
message: error instanceof Error ? error.message : String(error),
|
|
109
|
-
});
|
|
106
|
+
if (started.status === 'serialize-error') {
|
|
107
|
+
setSaveFeedback({ status: 'failure', message: started.message });
|
|
110
108
|
return;
|
|
111
109
|
}
|
|
112
110
|
const generation = templateGenerationRef.current;
|
|
113
111
|
setSaveFeedback({ status: 'pending' });
|
|
114
112
|
void (async () => {
|
|
115
|
-
const result = await (0,
|
|
116
|
-
|
|
113
|
+
const result = await (0, actions_1.finishSaveAction)({
|
|
114
|
+
payload: started.payload,
|
|
115
|
+
isGenerationCurrent: () => generation === templateGenerationRef.current,
|
|
116
|
+
onSave,
|
|
117
|
+
});
|
|
118
|
+
if (result.status === 'stale') {
|
|
117
119
|
return;
|
|
118
120
|
}
|
|
119
|
-
if (result.
|
|
120
|
-
setSeedFiles(
|
|
121
|
+
if (result.status === 'success') {
|
|
122
|
+
setSeedFiles(result.files);
|
|
121
123
|
setSaveFeedback({ status: 'success', message: result.message });
|
|
122
124
|
}
|
|
123
125
|
else {
|
|
124
126
|
setSaveFeedback({
|
|
125
127
|
status: 'failure',
|
|
126
|
-
message: result.message
|
|
128
|
+
message: result.message,
|
|
127
129
|
});
|
|
128
130
|
}
|
|
129
131
|
})();
|
|
130
132
|
}, [busy, onSave, validationBlocked, workingFiles]);
|
|
131
133
|
const handleSendTest = (0, react_1.useCallback)((recipient) => {
|
|
132
|
-
|
|
134
|
+
const started = (0, actions_1.startSendTestAction)({
|
|
135
|
+
busy,
|
|
136
|
+
validationBlocked,
|
|
137
|
+
sendTestEnabled: typeof onSendTest === 'function',
|
|
138
|
+
files: workingFiles,
|
|
139
|
+
recipient,
|
|
140
|
+
});
|
|
141
|
+
if (started.status === 'noop') {
|
|
133
142
|
return;
|
|
134
143
|
}
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
payload = (0, types_1.buildSavePayload)(workingFiles);
|
|
138
|
-
}
|
|
139
|
-
catch (error) {
|
|
140
|
-
setSendFeedback({
|
|
141
|
-
status: 'failure',
|
|
142
|
-
message: error instanceof Error ? error.message : String(error),
|
|
143
|
-
});
|
|
144
|
+
if (started.status === 'recipient-error' || started.status === 'serialize-error') {
|
|
145
|
+
setSendFeedback({ status: 'failure', message: started.message });
|
|
144
146
|
return;
|
|
145
147
|
}
|
|
146
148
|
const generation = templateGenerationRef.current;
|
|
147
149
|
setSendFeedback({ status: 'pending' });
|
|
148
150
|
void (async () => {
|
|
149
|
-
const result = await (0,
|
|
150
|
-
|
|
151
|
+
const result = await (0, actions_1.finishSendTestAction)({
|
|
152
|
+
payload: started.payload,
|
|
153
|
+
recipient: started.recipient,
|
|
154
|
+
isGenerationCurrent: () => generation === templateGenerationRef.current,
|
|
155
|
+
onSendTest: onSendTest,
|
|
156
|
+
});
|
|
157
|
+
if (result.status === 'stale') {
|
|
151
158
|
return;
|
|
152
159
|
}
|
|
153
|
-
if (result.
|
|
160
|
+
if (result.status === 'success') {
|
|
154
161
|
setSendFeedback({ status: 'success', message: result.message });
|
|
155
162
|
}
|
|
156
163
|
else {
|
|
157
164
|
setSendFeedback({
|
|
158
165
|
status: 'failure',
|
|
159
|
-
message: result.message
|
|
166
|
+
message: result.message,
|
|
160
167
|
});
|
|
161
168
|
}
|
|
162
169
|
})();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"email-template-editor.js","sourceRoot":"","sources":["../src/email-template-editor.tsx"],"names":[],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"email-template-editor.js","sourceRoot":"","sources":["../src/email-template-editor.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import type { TemplateSourceFiles } from '../types';
|
|
2
|
+
import { type SaveResult, type SendTestResult, type SerializedTemplateSource } from './types';
|
|
3
|
+
export type SavePayload = {
|
|
4
|
+
serialized: SerializedTemplateSource;
|
|
5
|
+
files: TemplateSourceFiles;
|
|
6
|
+
};
|
|
7
|
+
export type StartSaveResult = {
|
|
8
|
+
status: 'noop';
|
|
9
|
+
} | {
|
|
10
|
+
status: 'serialize-error';
|
|
11
|
+
message: string;
|
|
12
|
+
} | {
|
|
13
|
+
status: 'ready';
|
|
14
|
+
payload: SavePayload;
|
|
15
|
+
};
|
|
16
|
+
export type FinishSaveResult = {
|
|
17
|
+
status: 'stale';
|
|
18
|
+
} | {
|
|
19
|
+
status: 'success';
|
|
20
|
+
files: TemplateSourceFiles;
|
|
21
|
+
message?: string;
|
|
22
|
+
} | {
|
|
23
|
+
status: 'failure';
|
|
24
|
+
message: string;
|
|
25
|
+
};
|
|
26
|
+
export type StartSendTestResult = {
|
|
27
|
+
status: 'noop';
|
|
28
|
+
} | {
|
|
29
|
+
status: 'recipient-error';
|
|
30
|
+
message: string;
|
|
31
|
+
} | {
|
|
32
|
+
status: 'serialize-error';
|
|
33
|
+
message: string;
|
|
34
|
+
} | {
|
|
35
|
+
status: 'ready';
|
|
36
|
+
payload: SavePayload;
|
|
37
|
+
recipient: string;
|
|
38
|
+
};
|
|
39
|
+
export type FinishSendTestResult = {
|
|
40
|
+
status: 'stale';
|
|
41
|
+
} | {
|
|
42
|
+
status: 'success';
|
|
43
|
+
message?: string;
|
|
44
|
+
} | {
|
|
45
|
+
status: 'failure';
|
|
46
|
+
message: string;
|
|
47
|
+
};
|
|
48
|
+
export declare function startSaveAction(input: {
|
|
49
|
+
busy: boolean;
|
|
50
|
+
validationBlocked: boolean;
|
|
51
|
+
files: TemplateSourceFiles;
|
|
52
|
+
}): StartSaveResult;
|
|
53
|
+
export declare function finishSaveAction(input: {
|
|
54
|
+
payload: SavePayload;
|
|
55
|
+
isGenerationCurrent: () => boolean;
|
|
56
|
+
onSave: (serialized: SerializedTemplateSource, files: TemplateSourceFiles) => Promise<SaveResult | void> | SaveResult | void;
|
|
57
|
+
}): Promise<FinishSaveResult>;
|
|
58
|
+
export declare function startSendTestAction(input: {
|
|
59
|
+
busy: boolean;
|
|
60
|
+
validationBlocked: boolean;
|
|
61
|
+
sendTestEnabled: boolean;
|
|
62
|
+
files: TemplateSourceFiles;
|
|
63
|
+
recipient: string;
|
|
64
|
+
}): StartSendTestResult;
|
|
65
|
+
export declare function finishSendTestAction(input: {
|
|
66
|
+
payload: SavePayload;
|
|
67
|
+
recipient: string;
|
|
68
|
+
isGenerationCurrent: () => boolean;
|
|
69
|
+
onSendTest: (serialized: SerializedTemplateSource, files: TemplateSourceFiles, recipient: string) => Promise<SendTestResult | void> | SendTestResult | void;
|
|
70
|
+
}): Promise<FinishSendTestResult>;
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.startSaveAction = startSaveAction;
|
|
4
|
+
exports.finishSaveAction = finishSaveAction;
|
|
5
|
+
exports.startSendTestAction = startSendTestAction;
|
|
6
|
+
exports.finishSendTestAction = finishSendTestAction;
|
|
7
|
+
const recipient_1 = require("./recipient");
|
|
8
|
+
const types_1 = require("./types");
|
|
9
|
+
function startSaveAction(input) {
|
|
10
|
+
if (input.busy || input.validationBlocked) {
|
|
11
|
+
return { status: 'noop' };
|
|
12
|
+
}
|
|
13
|
+
try {
|
|
14
|
+
return { status: 'ready', payload: (0, types_1.buildSavePayload)(input.files) };
|
|
15
|
+
}
|
|
16
|
+
catch (error) {
|
|
17
|
+
return {
|
|
18
|
+
status: 'serialize-error',
|
|
19
|
+
message: error instanceof Error ? error.message : String(error),
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
async function finishSaveAction(input) {
|
|
24
|
+
const result = await (0, types_1.invokeConsumerAction)(() => input.onSave(input.payload.serialized, input.payload.files));
|
|
25
|
+
if (!input.isGenerationCurrent()) {
|
|
26
|
+
return { status: 'stale' };
|
|
27
|
+
}
|
|
28
|
+
if (result.ok) {
|
|
29
|
+
return {
|
|
30
|
+
status: 'success',
|
|
31
|
+
files: input.payload.files,
|
|
32
|
+
message: result.message,
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
return {
|
|
36
|
+
status: 'failure',
|
|
37
|
+
message: result.message ?? 'Save failed.',
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
function startSendTestAction(input) {
|
|
41
|
+
if (input.busy || input.validationBlocked || !input.sendTestEnabled) {
|
|
42
|
+
return { status: 'noop' };
|
|
43
|
+
}
|
|
44
|
+
const recipientError = (0, recipient_1.validateSendTestRecipient)(input.recipient);
|
|
45
|
+
if (recipientError) {
|
|
46
|
+
return { status: 'recipient-error', message: recipientError };
|
|
47
|
+
}
|
|
48
|
+
try {
|
|
49
|
+
return {
|
|
50
|
+
status: 'ready',
|
|
51
|
+
payload: (0, types_1.buildSavePayload)(input.files),
|
|
52
|
+
recipient: input.recipient.trim(),
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
catch (error) {
|
|
56
|
+
return {
|
|
57
|
+
status: 'serialize-error',
|
|
58
|
+
message: error instanceof Error ? error.message : String(error),
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
async function finishSendTestAction(input) {
|
|
63
|
+
const result = await (0, types_1.invokeConsumerAction)(() => input.onSendTest(input.payload.serialized, input.payload.files, input.recipient));
|
|
64
|
+
if (!input.isGenerationCurrent()) {
|
|
65
|
+
return { status: 'stale' };
|
|
66
|
+
}
|
|
67
|
+
if (result.ok) {
|
|
68
|
+
return { status: 'success', message: result.message };
|
|
69
|
+
}
|
|
70
|
+
return {
|
|
71
|
+
status: 'failure',
|
|
72
|
+
message: result.message ?? 'Send test failed.',
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
//# sourceMappingURL=actions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"actions.js","sourceRoot":"","sources":["../../src/save-send/actions.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@singleton-sd/post-kit-editor",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "React admin editor component for PostKit email templates",
|
|
6
6
|
"license": "MIT",
|
|
@@ -24,7 +24,9 @@
|
|
|
24
24
|
"!dist/**/*.spec.js.map",
|
|
25
25
|
"!dist/**/*.spec.d.ts",
|
|
26
26
|
"!dist/**/*.spec.d.ts.map",
|
|
27
|
-
"!dist/fixtures/**"
|
|
27
|
+
"!dist/fixtures/**",
|
|
28
|
+
"!examples",
|
|
29
|
+
"!examples/**"
|
|
28
30
|
],
|
|
29
31
|
"dependencies": {
|
|
30
32
|
"@usewaypoint/block-avatar": "^0.0.3",
|