@nxgt/mail-config 0.1.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/LICENSE +21 -0
- package/README.md +239 -0
- package/dist/index.d.ts +72 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +173 -0
- package/dist/index.js.map +11 -0
- package/dist/layer.d.ts +10 -0
- package/dist/layer.d.ts.map +1 -0
- package/docs/README.md +14 -0
- package/docs/guide/config.md +305 -0
- package/docs/guide/plugins.md +280 -0
- package/docs/guide/production.md +168 -0
- package/docs/roadmap.md +76 -0
- package/docs/troubleshooting.md +497 -0
- package/package.json +58 -0
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
# Production
|
|
2
|
+
|
|
3
|
+
This page is for adding a production build next to the everyday one: the same
|
|
4
|
+
project config, with the HTML minified, written somewhere else, with whatever
|
|
5
|
+
else only production needs.
|
|
6
|
+
|
|
7
|
+
```ts
|
|
8
|
+
// maizzle.config.production.ts
|
|
9
|
+
import { productionConfig } from '@nxgt/mail-config';
|
|
10
|
+
import config from './maizzle.config';
|
|
11
|
+
|
|
12
|
+
export default productionConfig(config, { output: { path: 'dist-production' } });
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
```json
|
|
16
|
+
{
|
|
17
|
+
"scripts": {
|
|
18
|
+
"dev": "maizzle serve",
|
|
19
|
+
"build": "maizzle build -c maizzle.config.production.ts"
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
Maizzle 6 has no environments. `maizzle build -c <file>` loads that file and
|
|
25
|
+
no other — not `maizzle.config.ts` beside it — so the production file imports
|
|
26
|
+
the project config and builds on it.
|
|
27
|
+
|
|
28
|
+
## The signature
|
|
29
|
+
|
|
30
|
+
```ts
|
|
31
|
+
import type { MaizzleConfig } from '@maizzle/framework';
|
|
32
|
+
|
|
33
|
+
function productionConfig(
|
|
34
|
+
config: MaizzleConfig & { readonly plugins?: never },
|
|
35
|
+
overrides?: MaizzleConfig & { readonly plugins?: never },
|
|
36
|
+
): MaizzleConfig;
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
Neither argument may carry `plugins`: every plugin is listed in the project
|
|
40
|
+
config, and `plugins` in either one is a type error as well as a `TypeError`
|
|
41
|
+
at load time.
|
|
42
|
+
|
|
43
|
+
| Parameter | Type | Default | Effect |
|
|
44
|
+
| --- | --- | --- | --- |
|
|
45
|
+
| `config` | `MaizzleConfig` | — | The project config: what `maizzle.config.ts` exports, that is **what `defineMailConfig` answered** |
|
|
46
|
+
| `overrides` | `MaizzleConfig` | `{}` | Layered last: wins over the project and over the minification |
|
|
47
|
+
|
|
48
|
+
It answers three layers, lowest first — `config`, then
|
|
49
|
+
`{ html: { minify: true } }` (left out when the project already set minify
|
|
50
|
+
options, [below](#what-it-changes)), then `overrides` — merged by the same
|
|
51
|
+
rules as `defineMailConfig`, the overrides as a plugin is: objects merge,
|
|
52
|
+
arrays replace, their `components.source`, `vite.plugins` and `vue.plugins`
|
|
53
|
+
are added to the project's, their build events run after the project's. See
|
|
54
|
+
[The project config](config.md#how-two-layers-merge). Neither argument is
|
|
55
|
+
changed.
|
|
56
|
+
|
|
57
|
+
## What it changes
|
|
58
|
+
|
|
59
|
+
Only `html.minify`. Everything else is the project's:
|
|
60
|
+
|
|
61
|
+
```ts
|
|
62
|
+
import { defineMailConfig, productionConfig } from '@nxgt/mail-config';
|
|
63
|
+
|
|
64
|
+
const config = defineMailConfig({ output: { path: 'dist' } });
|
|
65
|
+
|
|
66
|
+
productionConfig(config);
|
|
67
|
+
// { plaintext: true, output: { path: 'dist' }, html: { minify: true } }
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
When the project config already sets `html.minify` to an object of options,
|
|
71
|
+
they are kept: `minify: true` would replace them.
|
|
72
|
+
|
|
73
|
+
```ts
|
|
74
|
+
const config = defineMailConfig({
|
|
75
|
+
html: { minify: { lineLengthLimit: 1000 }, decodeEntities: false },
|
|
76
|
+
});
|
|
77
|
+
productionConfig(config).html;
|
|
78
|
+
// { minify: { lineLengthLimit: 1000 }, decodeEntities: false }
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
Minifying with no output path of its own writes over the everyday build in
|
|
82
|
+
`dist/`. Give production its own folder, as above, when both are kept.
|
|
83
|
+
|
|
84
|
+
## Overrides
|
|
85
|
+
|
|
86
|
+
Anything a Maizzle config holds. The minifier's options, for one:
|
|
87
|
+
|
|
88
|
+
```ts
|
|
89
|
+
productionConfig(config, {
|
|
90
|
+
output: { path: 'dist-production' },
|
|
91
|
+
html: { minify: { lineLengthLimit: 1000 } },
|
|
92
|
+
});
|
|
93
|
+
// { plaintext: true, output: { path: 'dist-production' }, html: { minify: { lineLengthLimit: 1000 } } }
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
A list in `overrides` is added to the project's, never replaces it — a Vite
|
|
97
|
+
plugin only production needs, say:
|
|
98
|
+
|
|
99
|
+
```ts
|
|
100
|
+
const report = { name: 'report' }; // a Vite plugin of yours
|
|
101
|
+
|
|
102
|
+
productionConfig(config, { vite: { plugins: [report] } });
|
|
103
|
+
// vite.plugins: the project's (and its plugins'), then report
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
A build event in `overrides` runs **after** the project's — and after every
|
|
107
|
+
plugin's, which the project config already chains:
|
|
108
|
+
|
|
109
|
+
```ts
|
|
110
|
+
import { defineMailConfig, productionConfig } from '@nxgt/mail-config';
|
|
111
|
+
|
|
112
|
+
const config = defineMailConfig({ afterTransform: ({ html }) => `${html}p` });
|
|
113
|
+
|
|
114
|
+
export default productionConfig(config, {
|
|
115
|
+
afterTransform: ({ html }) => `${html}!`, // receives the project's output: '…p' becomes '…p!'
|
|
116
|
+
});
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
A realistic one: fail the production build when an e-mail is heavier than an
|
|
120
|
+
inbox will show in full.
|
|
121
|
+
|
|
122
|
+
```ts
|
|
123
|
+
// maizzle.config.production.ts
|
|
124
|
+
import { productionConfig } from '@nxgt/mail-config';
|
|
125
|
+
import config from './maizzle.config';
|
|
126
|
+
|
|
127
|
+
const limit = 100 * 1024; // some clients clip an e-mail past about 100 KB
|
|
128
|
+
|
|
129
|
+
export default productionConfig(config, {
|
|
130
|
+
output: { path: 'dist-production' },
|
|
131
|
+
afterTransform: ({ template, html }) => {
|
|
132
|
+
const size = new TextEncoder().encode(html).length;
|
|
133
|
+
if (size > limit) {
|
|
134
|
+
throw new Error(`${template.path.name}: ${size} bytes, over the ${limit}-byte limit`);
|
|
135
|
+
}
|
|
136
|
+
},
|
|
137
|
+
});
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
Returning nothing keeps the HTML as it was; throwing fails the build.
|
|
141
|
+
|
|
142
|
+
## Errors
|
|
143
|
+
|
|
144
|
+
A bare `TypeError`, when `maizzle.config.production.ts` loads:
|
|
145
|
+
|
|
146
|
+
| Message | Cause |
|
|
147
|
+
| --- | --- |
|
|
148
|
+
| `productionConfig: config must be the project config, as productionConfig(config, overrides)` | `config` is missing, `null`, an array, or not an object |
|
|
149
|
+
| `productionConfig: config lists plugins — pass what defineMailConfig answered, not its argument` | `config` still has `plugins`: it is the object given to `defineMailConfig`, not what it answered |
|
|
150
|
+
| `productionConfig: overrides must be an object` | `overrides` is `null`, an array, or not an object |
|
|
151
|
+
| `productionConfig: overrides list plugins — list every plugin in the project config` | `overrides` sets `plugins`. Plugins are layered once, in the project config; what only production needs goes in the overrides as plain config keys, which merge as a plugin's would |
|
|
152
|
+
| `productionConfig: afterBuild must be a function` | `overrides` sets a build event to something other than a function |
|
|
153
|
+
|
|
154
|
+
The second one comes from exporting the argument instead of the result:
|
|
155
|
+
|
|
156
|
+
```ts
|
|
157
|
+
// maizzle.config.ts — wrong: exports the input, not a Maizzle config
|
|
158
|
+
const input = { plugins: [brand] };
|
|
159
|
+
export default input;
|
|
160
|
+
|
|
161
|
+
// right
|
|
162
|
+
export default defineMailConfig({ plugins: [brand] });
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
## See also
|
|
166
|
+
|
|
167
|
+
- [The project config](config.md) — the merge rules and the chained events.
|
|
168
|
+
- [Writing a plugin](plugins.md) — what a plugin can add, in both builds.
|
package/docs/roadmap.md
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
# Roadmap
|
|
2
|
+
|
|
3
|
+
Where `@nxgt/mail-config` is heading. A direction, not a commitment: there are
|
|
4
|
+
no dates here, and the version something shipped in is the only number.
|
|
5
|
+
|
|
6
|
+
## Now
|
|
7
|
+
|
|
8
|
+
Nothing between releases.
|
|
9
|
+
|
|
10
|
+
## Next
|
|
11
|
+
|
|
12
|
+
Nothing yet.
|
|
13
|
+
|
|
14
|
+
## Later
|
|
15
|
+
|
|
16
|
+
Nothing yet. A request is welcome as an
|
|
17
|
+
[issue](https://github.com/softistx/nxgt-mail/issues).
|
|
18
|
+
|
|
19
|
+
## Not planned
|
|
20
|
+
|
|
21
|
+
- **A preview server or a CLI of our own** — `maizzle serve` is the preview
|
|
22
|
+
and `maizzle build` the build. This package writes the config those commands
|
|
23
|
+
read; it never replaces them.
|
|
24
|
+
- **Environments beyond Maizzle's `-c` config files** — Maizzle has no
|
|
25
|
+
environments: `maizzle build -c <file>` loads that one file. A second config
|
|
26
|
+
file that imports the first, as `productionConfig` does, is the whole
|
|
27
|
+
mechanism; there is no `NODE_ENV` switch or environment map to learn.
|
|
28
|
+
- **A plugin that brings other plugins** — refused with an error. Every plugin
|
|
29
|
+
is listed in your project, so their order, and which one's key wins, is read
|
|
30
|
+
in one place.
|
|
31
|
+
- **Joining every array** — only `components.source`, `vite.plugins` and
|
|
32
|
+
`vue.plugins` are joined. Every other array replaces the one under it, as in
|
|
33
|
+
Maizzle, so a list your project sets is the list you get.
|
|
34
|
+
- **Last handler wins** — Maizzle's own merge keeps only the last
|
|
35
|
+
`beforeRender` (or any other event); here every layer's handler runs, in
|
|
36
|
+
order. A plugin silently disabling another's hook is the bug this package
|
|
37
|
+
exists to remove.
|
|
38
|
+
- **`moduleResolution: "nodenext"` as a contract** — bundler resolution
|
|
39
|
+
(`"moduleResolution": "bundler"`) is what is supported and tested, as Bun,
|
|
40
|
+
every bundler and Maizzle's own config loader resolve. `nodenext` may work;
|
|
41
|
+
it is not promised.
|
|
42
|
+
|
|
43
|
+
## Shipped
|
|
44
|
+
|
|
45
|
+
The last ten, newest first, each with the version it came in. Everything
|
|
46
|
+
before is in the [CHANGELOG](../CHANGELOG.md).
|
|
47
|
+
|
|
48
|
+
- **A base Maizzle config, v0.1.0** — `defineMailConfig({ plugins, ...project })` for
|
|
49
|
+
the `maizzle.config.ts` of a normal Maizzle 6 project (`maizzle serve`,
|
|
50
|
+
`maizzle build`, unchanged). It turns plain text on (`baseConfig`), and
|
|
51
|
+
leaves everything else to Maizzle's defaults.
|
|
52
|
+
- **Plugins that do not drop each other, v0.1.0** — a plugin is a partial Maizzle
|
|
53
|
+
config with a `name`, layered base, then each plugin in order, then your
|
|
54
|
+
project, whose keys win. Every build event (`beforeCreate` to `afterBuild`)
|
|
55
|
+
runs each layer's handler in that order, and `components.source`,
|
|
56
|
+
`vite.plugins` and `vue.plugins` are joined, so two plugins that each bring
|
|
57
|
+
components keep both.
|
|
58
|
+
- **Checking a plugin where it is written, v0.1.0** — `defineMailPlugin(plugin)`: a
|
|
59
|
+
package that exports a plugin gets a missing name or a handler that is not a
|
|
60
|
+
function reported in its own code, not in the project that uses it.
|
|
61
|
+
- **A production config, v0.1.0** — `productionConfig(config, overrides)` for
|
|
62
|
+
`maizzle.config.production.ts`: your project config, the HTML minified,
|
|
63
|
+
then your overrides, built with `maizzle build -c
|
|
64
|
+
maizzle.config.production.ts`.
|
|
65
|
+
- **i18n as a plugin, `@nxgt/mail-i18n` v0.1.0** — `i18n({ locales,
|
|
66
|
+
fallbackLocale })`, listed in `plugins` — see
|
|
67
|
+
[its roadmap](https://github.com/softistx/nxgt-mail/blob/develop/packages/mail-i18n/docs/roadmap.md).
|
|
68
|
+
- **UI components as a plugin, `@nxgt/mail-ui` v0.1.0** — `ui({ brand, theme
|
|
69
|
+
})`, listed in `plugins`: e-mail components in the style of
|
|
70
|
+
`@nxgt/material-vue`, each replaceable by name in your project — see
|
|
71
|
+
[its roadmap](https://github.com/softistx/nxgt-mail/blob/develop/packages/mail-ui/docs/roadmap.md).
|
|
72
|
+
- **A starter project, with v0.1.0** — the official Maizzle starter with
|
|
73
|
+
`defineMailConfig`, the i18n and the UI plugins wired in as the READMEs
|
|
74
|
+
say, built, rendered in `en` and `fr` and served in CI, so the snippets are
|
|
75
|
+
known to work: [`examples/starter`](https://github.com/softistx/nxgt-mail/tree/develop/examples/starter).
|
|
76
|
+
In the repository; its README says how to start your own from npm.
|