react-email-rails 0.1.0 → 0.1.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/bin/build.mjs +75 -0
- package/bin/config.mjs +5 -15
- package/bin/dev.mjs +17 -25
- package/bin/shared.mjs +76 -0
- package/dist/index.d.ts +5 -1
- package/dist/index.js +7 -4
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +2 -1
- package/src/index.ts +16 -5
- package/src/version.ts +1 -1
package/bin/build.mjs
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { createBuilder } from "vite"
|
|
3
|
+
import { fail, isolatedViteConfig, loadReactEmailRailsConfig } from "./shared.mjs"
|
|
4
|
+
import { RENDER_PROTOCOL_VERSION, VERSION } from "../dist/version.js"
|
|
5
|
+
|
|
6
|
+
if (process.argv.includes("--health")) {
|
|
7
|
+
process.stdout.write(
|
|
8
|
+
JSON.stringify({ ok: true, protocolVersion: RENDER_PROTOCOL_VERSION, packageVersion: VERSION }),
|
|
9
|
+
)
|
|
10
|
+
process.exit(0)
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
const args = process.argv.slice(2)
|
|
14
|
+
const readOption = (long, short) => {
|
|
15
|
+
const prefixed = args.find((arg) => arg.startsWith(`${long}=`))
|
|
16
|
+
if (prefixed) return prefixed.slice(long.length + 1)
|
|
17
|
+
|
|
18
|
+
const longIndex = args.indexOf(long)
|
|
19
|
+
if (longIndex !== -1) return args[longIndex + 1]
|
|
20
|
+
|
|
21
|
+
if (!short) return undefined
|
|
22
|
+
const shortIndex = args.indexOf(short)
|
|
23
|
+
return shortIndex === -1 ? undefined : args[shortIndex + 1]
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const root = args.find((arg, index) => {
|
|
27
|
+
if (arg.startsWith("-")) return false
|
|
28
|
+
const previous = args[index - 1]
|
|
29
|
+
return (
|
|
30
|
+
previous !== "--mode" &&
|
|
31
|
+
previous !== "-m" &&
|
|
32
|
+
previous !== "--config" &&
|
|
33
|
+
previous !== "-c" &&
|
|
34
|
+
previous !== "--configLoader" &&
|
|
35
|
+
previous !== "--logLevel" &&
|
|
36
|
+
previous !== "-l"
|
|
37
|
+
)
|
|
38
|
+
})
|
|
39
|
+
const mode = readOption("--mode", "-m") ?? "production"
|
|
40
|
+
const configFile = readOption("--config", "-c")
|
|
41
|
+
const configLoader = readOption("--configLoader")
|
|
42
|
+
const logLevel = readOption("--logLevel", "-l")
|
|
43
|
+
|
|
44
|
+
process.env.NODE_ENV ??= "production"
|
|
45
|
+
|
|
46
|
+
const { userConfig, plugin, vite } = await loadReactEmailRailsConfig({
|
|
47
|
+
command: "build",
|
|
48
|
+
mode,
|
|
49
|
+
root,
|
|
50
|
+
configFile,
|
|
51
|
+
logLevel,
|
|
52
|
+
configLoader,
|
|
53
|
+
})
|
|
54
|
+
|
|
55
|
+
// Build production emails with the same isolation principle as the dev renderer:
|
|
56
|
+
// keep component resolution and transforms, but leave unrelated app plugins out
|
|
57
|
+
// of the email environment so client/global plugin hooks cannot break SSR output.
|
|
58
|
+
const builder = await createBuilder(
|
|
59
|
+
isolatedViteConfig(userConfig, vite, {
|
|
60
|
+
root: root ?? userConfig.root,
|
|
61
|
+
configFile: false,
|
|
62
|
+
mode,
|
|
63
|
+
builder: {},
|
|
64
|
+
plugins: [plugin],
|
|
65
|
+
appType: "custom",
|
|
66
|
+
clearScreen: false,
|
|
67
|
+
logLevel,
|
|
68
|
+
}),
|
|
69
|
+
null,
|
|
70
|
+
)
|
|
71
|
+
|
|
72
|
+
const environment = builder.environments.email
|
|
73
|
+
if (!environment) fail("react-email-rails: email build environment not found")
|
|
74
|
+
|
|
75
|
+
await builder.build(environment)
|
package/bin/config.mjs
CHANGED
|
@@ -1,19 +1,9 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
2
|
+
import { loadReactEmailRailsConfig } from "./shared.mjs"
|
|
3
3
|
|
|
4
|
-
const
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
if (!plugin) {
|
|
10
|
-
process.stderr.write("react-email-rails: reactEmailRails() plugin not found in the Vite config\n")
|
|
11
|
-
process.exit(1)
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
if (!metadata) {
|
|
15
|
-
process.stderr.write("react-email-rails: reactEmailRails() plugin metadata not found\n")
|
|
16
|
-
process.exit(1)
|
|
17
|
-
}
|
|
4
|
+
const { metadata } = await loadReactEmailRailsConfig({
|
|
5
|
+
command: "serve",
|
|
6
|
+
mode: process.env.NODE_ENV ?? "development",
|
|
7
|
+
})
|
|
18
8
|
|
|
19
9
|
process.stdout.write(JSON.stringify(metadata))
|
package/bin/dev.mjs
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { createServer, isRunnableDevEnvironment
|
|
2
|
+
import { createServer, isRunnableDevEnvironment } from "vite"
|
|
3
|
+
import { fail, isolatedViteConfig, loadReactEmailRailsConfig } from "./shared.mjs"
|
|
3
4
|
import { RENDER_PROTOCOL_VERSION, VERSION } from "../dist/version.js"
|
|
4
5
|
|
|
5
6
|
if (process.argv.includes("--health")) {
|
|
@@ -19,40 +20,31 @@ const logger = {
|
|
|
19
20
|
}
|
|
20
21
|
|
|
21
22
|
// Load only this plugin and aliases; host dev-server plugins have global side effects.
|
|
22
|
-
const
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
.find((plugin) => plugin?.name === "react-email-rails")
|
|
27
|
-
|
|
28
|
-
if (!emailPlugin) {
|
|
29
|
-
process.stderr.write("react-email-rails: reactEmailRails() plugin not found in the Vite config\n")
|
|
30
|
-
process.exit(1)
|
|
31
|
-
}
|
|
23
|
+
const { userConfig, plugin, vite } = await loadReactEmailRailsConfig({
|
|
24
|
+
command: "serve",
|
|
25
|
+
mode: "development",
|
|
26
|
+
})
|
|
32
27
|
|
|
33
28
|
// Forward config that affects how components resolve and compile (but not the
|
|
34
29
|
// host's dev-server plugins, which have global side effects), so dev rendering
|
|
35
30
|
// stays close to the production email bundle.
|
|
36
|
-
const server = await createServer(
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
customLogger: logger,
|
|
47
|
-
})
|
|
31
|
+
const server = await createServer(
|
|
32
|
+
isolatedViteConfig(userConfig, vite, {
|
|
33
|
+
configFile: false,
|
|
34
|
+
plugins: [plugin],
|
|
35
|
+
server: { middlewareMode: true },
|
|
36
|
+
appType: "custom",
|
|
37
|
+
clearScreen: false,
|
|
38
|
+
customLogger: logger,
|
|
39
|
+
}),
|
|
40
|
+
)
|
|
48
41
|
|
|
49
42
|
// Render through the same `email` environment the production build uses, so dev
|
|
50
43
|
// and build resolve and compile components identically.
|
|
51
44
|
const environment = server.environments.email
|
|
52
45
|
if (!isRunnableDevEnvironment(environment)) {
|
|
53
46
|
await server.close()
|
|
54
|
-
|
|
55
|
-
process.exit(1)
|
|
47
|
+
fail("react-email-rails: the email environment is not runnable")
|
|
56
48
|
}
|
|
57
49
|
|
|
58
50
|
try {
|
package/bin/shared.mjs
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { loadConfigFromFile, mergeConfig } from "vite"
|
|
2
|
+
|
|
3
|
+
const CONFIG_SYMBOL = Symbol.for("react-email-rails.config")
|
|
4
|
+
const VITE_CONFIG_SYMBOL = Symbol.for("react-email-rails.vite")
|
|
5
|
+
const EMAIL_VITE_CONFIG_KEYS = [
|
|
6
|
+
"assetsInclude",
|
|
7
|
+
"css",
|
|
8
|
+
"define",
|
|
9
|
+
"esbuild",
|
|
10
|
+
"json",
|
|
11
|
+
"oxc",
|
|
12
|
+
"plugins",
|
|
13
|
+
"resolve",
|
|
14
|
+
]
|
|
15
|
+
|
|
16
|
+
export async function loadReactEmailRailsConfig({
|
|
17
|
+
command,
|
|
18
|
+
mode,
|
|
19
|
+
root,
|
|
20
|
+
configFile,
|
|
21
|
+
logLevel,
|
|
22
|
+
configLoader,
|
|
23
|
+
}) {
|
|
24
|
+
const loaded = await loadConfigFromFile(
|
|
25
|
+
{ command, mode },
|
|
26
|
+
configFile,
|
|
27
|
+
root,
|
|
28
|
+
logLevel,
|
|
29
|
+
undefined,
|
|
30
|
+
configLoader,
|
|
31
|
+
)
|
|
32
|
+
const userConfig = loaded?.config ?? {}
|
|
33
|
+
const plugin = (userConfig.plugins ?? [])
|
|
34
|
+
.flat(Infinity)
|
|
35
|
+
.find((plugin) => plugin?.name === "react-email-rails")
|
|
36
|
+
const metadata = plugin?.[CONFIG_SYMBOL]
|
|
37
|
+
|
|
38
|
+
if (!plugin) fail("react-email-rails: reactEmailRails() plugin not found in the Vite config")
|
|
39
|
+
if (!metadata) fail("react-email-rails: reactEmailRails() plugin metadata not found")
|
|
40
|
+
|
|
41
|
+
return {
|
|
42
|
+
userConfig,
|
|
43
|
+
plugin,
|
|
44
|
+
metadata,
|
|
45
|
+
vite: plugin[VITE_CONFIG_SYMBOL] ?? {},
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export function isolatedViteConfig(userConfig, emailViteConfig, baseConfig) {
|
|
50
|
+
const userEsbuild =
|
|
51
|
+
userConfig.esbuild && typeof userConfig.esbuild === "object" ? userConfig.esbuild : {}
|
|
52
|
+
const forwarded = {
|
|
53
|
+
assetsInclude: userConfig.assetsInclude,
|
|
54
|
+
resolve: userConfig.resolve,
|
|
55
|
+
define: userConfig.define,
|
|
56
|
+
css: userConfig.css,
|
|
57
|
+
json: userConfig.json,
|
|
58
|
+
oxc: userConfig.oxc,
|
|
59
|
+
esbuild: { ...userEsbuild, jsx: userEsbuild.jsx ?? "automatic" },
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
return mergeConfig({ ...forwarded, ...baseConfig }, pickEmailViteConfig(emailViteConfig))
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function pickEmailViteConfig(config) {
|
|
66
|
+
return Object.fromEntries(
|
|
67
|
+
EMAIL_VITE_CONFIG_KEYS.flatMap((key) =>
|
|
68
|
+
config && Object.hasOwn(config, key) ? [[key, config[key]]] : [],
|
|
69
|
+
),
|
|
70
|
+
)
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export function fail(message) {
|
|
74
|
+
process.stderr.write(`${message}\n`)
|
|
75
|
+
process.exit(1)
|
|
76
|
+
}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { Plugin } from "vite";
|
|
1
|
+
import type { Plugin, UserConfig } from "vite";
|
|
2
2
|
export type EmailsOption = string | {
|
|
3
3
|
path?: string;
|
|
4
4
|
extension?: string | string[];
|
|
@@ -7,6 +7,10 @@ export type EmailsOption = string | {
|
|
|
7
7
|
export type ReactEmailRailsOptions = {
|
|
8
8
|
emails?: EmailsOption;
|
|
9
9
|
standalone?: boolean;
|
|
10
|
+
vite?: ReactEmailRailsViteOptions;
|
|
11
|
+
};
|
|
12
|
+
export type ReactEmailRailsViteOptions = Pick<UserConfig, "assetsInclude" | "css" | "define" | "esbuild" | "json" | "plugins" | "resolve"> & {
|
|
13
|
+
oxc?: unknown;
|
|
10
14
|
};
|
|
11
15
|
export declare const EMAIL_ENVIRONMENT = "email";
|
|
12
16
|
export declare function reactEmailRails(options?: ReactEmailRailsOptions): Plugin;
|
package/dist/index.js
CHANGED
|
@@ -7,6 +7,7 @@ const RESOLVED_MAIN = `\0${VIRTUAL_MAIN}`;
|
|
|
7
7
|
// The dedicated build environment that emits the server-side email bundle.
|
|
8
8
|
export const EMAIL_ENVIRONMENT = "email";
|
|
9
9
|
const CONFIG_SYMBOL = Symbol.for("react-email-rails.config");
|
|
10
|
+
const VITE_CONFIG_SYMBOL = Symbol.for("react-email-rails.vite");
|
|
10
11
|
const OUT_DIR = "tmp/react-email-rails";
|
|
11
12
|
const BUNDLE_FILE = "emails.js";
|
|
12
13
|
export function reactEmailRails(options = {}) {
|
|
@@ -59,13 +60,12 @@ export function reactEmailRails(options = {}) {
|
|
|
59
60
|
}
|
|
60
61
|
},
|
|
61
62
|
config() {
|
|
62
|
-
// Register a dedicated `email` build environment
|
|
63
|
-
//
|
|
64
|
-
//
|
|
63
|
+
// Register a dedicated `email` build environment. The official
|
|
64
|
+
// react-email-rails-build bin opts into building it with an isolated
|
|
65
|
+
// plugin stack so host app plugins cannot break email SSR builds.
|
|
65
66
|
// The environment is a server consumer. Standalone builds inline Node
|
|
66
67
|
// dependencies by default so Rails runtime images do not need node_modules.
|
|
67
68
|
return {
|
|
68
|
-
builder: {},
|
|
69
69
|
environments: {
|
|
70
70
|
[EMAIL_ENVIRONMENT]: {
|
|
71
71
|
...(standalone ? { resolve: { noExternal: true } } : {}),
|
|
@@ -98,6 +98,9 @@ export function reactEmailRails(options = {}) {
|
|
|
98
98
|
...metadata,
|
|
99
99
|
},
|
|
100
100
|
});
|
|
101
|
+
Object.defineProperty(plugin, VITE_CONFIG_SYMBOL, {
|
|
102
|
+
value: options.vite ?? {},
|
|
103
|
+
});
|
|
101
104
|
return plugin;
|
|
102
105
|
}
|
|
103
106
|
export { RENDER_PROTOCOL_VERSION, VERSION } from "./version.js";
|
package/dist/version.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export declare const VERSION = "0.1.
|
|
1
|
+
export declare const VERSION = "0.1.1";
|
|
2
2
|
export declare const RENDER_PROTOCOL_VERSION = 1;
|
package/dist/version.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export const VERSION = "0.1.
|
|
1
|
+
export const VERSION = "0.1.1";
|
|
2
2
|
export const RENDER_PROTOCOL_VERSION = 1;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-email-rails",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.1",
|
|
4
4
|
"description": "Build and send emails using React and Rails",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -37,6 +37,7 @@
|
|
|
37
37
|
},
|
|
38
38
|
"types": "./dist/index.d.ts",
|
|
39
39
|
"bin": {
|
|
40
|
+
"react-email-rails-build": "./bin/build.mjs",
|
|
40
41
|
"react-email-rails-config": "./bin/config.mjs",
|
|
41
42
|
"react-email-rails-dev": "./bin/dev.mjs"
|
|
42
43
|
},
|
package/src/index.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { Plugin } from "vite"
|
|
1
|
+
import type { Plugin, UserConfig } from "vite"
|
|
2
2
|
|
|
3
3
|
export type EmailsOption =
|
|
4
4
|
| string
|
|
@@ -11,6 +11,14 @@ export type EmailsOption =
|
|
|
11
11
|
export type ReactEmailRailsOptions = {
|
|
12
12
|
emails?: EmailsOption
|
|
13
13
|
standalone?: boolean
|
|
14
|
+
vite?: ReactEmailRailsViteOptions
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export type ReactEmailRailsViteOptions = Pick<
|
|
18
|
+
UserConfig,
|
|
19
|
+
"assetsInclude" | "css" | "define" | "esbuild" | "json" | "plugins" | "resolve"
|
|
20
|
+
> & {
|
|
21
|
+
oxc?: unknown
|
|
14
22
|
}
|
|
15
23
|
|
|
16
24
|
type PluginMetadata = {
|
|
@@ -35,6 +43,7 @@ const RESOLVED_MAIN = `\0${VIRTUAL_MAIN}`
|
|
|
35
43
|
// The dedicated build environment that emits the server-side email bundle.
|
|
36
44
|
export const EMAIL_ENVIRONMENT = "email"
|
|
37
45
|
const CONFIG_SYMBOL = Symbol.for("react-email-rails.config")
|
|
46
|
+
const VITE_CONFIG_SYMBOL = Symbol.for("react-email-rails.vite")
|
|
38
47
|
const OUT_DIR = "tmp/react-email-rails"
|
|
39
48
|
const BUNDLE_FILE = "emails.js"
|
|
40
49
|
|
|
@@ -98,13 +107,12 @@ export function reactEmailRails(options: ReactEmailRailsOptions = {}): Plugin {
|
|
|
98
107
|
},
|
|
99
108
|
|
|
100
109
|
config() {
|
|
101
|
-
// Register a dedicated `email` build environment
|
|
102
|
-
//
|
|
103
|
-
//
|
|
110
|
+
// Register a dedicated `email` build environment. The official
|
|
111
|
+
// react-email-rails-build bin opts into building it with an isolated
|
|
112
|
+
// plugin stack so host app plugins cannot break email SSR builds.
|
|
104
113
|
// The environment is a server consumer. Standalone builds inline Node
|
|
105
114
|
// dependencies by default so Rails runtime images do not need node_modules.
|
|
106
115
|
return {
|
|
107
|
-
builder: {},
|
|
108
116
|
environments: {
|
|
109
117
|
[EMAIL_ENVIRONMENT]: {
|
|
110
118
|
...(standalone ? { resolve: { noExternal: true } } : {}),
|
|
@@ -139,6 +147,9 @@ export function reactEmailRails(options: ReactEmailRailsOptions = {}): Plugin {
|
|
|
139
147
|
...metadata,
|
|
140
148
|
},
|
|
141
149
|
})
|
|
150
|
+
Object.defineProperty(plugin, VITE_CONFIG_SYMBOL, {
|
|
151
|
+
value: options.vite ?? {},
|
|
152
|
+
})
|
|
142
153
|
|
|
143
154
|
return plugin
|
|
144
155
|
}
|
package/src/version.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export const VERSION = "0.1.
|
|
1
|
+
export const VERSION = "0.1.1"
|
|
2
2
|
export const RENDER_PROTOCOL_VERSION = 1
|