promote-email-templates 0.0.19 → 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/.react-email/.eslintrc.js +52 -0
- package/.react-email/.prettierignore +3 -0
- package/.react-email/.prettierrc.js +8 -0
- package/.react-email/license.md +7 -0
- package/.react-email/next.config.js +36 -0
- package/.react-email/package.json +1 -0
- package/.react-email/postcss.config.js +8 -0
- package/.react-email/readme.md +44 -0
- package/.react-email/src/actions/get-email-path-from-slug.ts +26 -0
- package/.react-email/src/actions/get-emails-directory-metadata.spec.ts +73 -0
- package/.react-email/src/actions/get-emails-directory-metadata.ts +91 -0
- package/.react-email/src/actions/render-email-by-path.tsx +59 -0
- package/.react-email/src/app/favicon.ico +0 -0
- package/.react-email/src/app/globals.css +35 -0
- package/.react-email/src/app/inter.ts +7 -0
- package/.react-email/src/app/layout.tsx +36 -0
- package/.react-email/src/app/logo.png +0 -0
- package/.react-email/src/app/page.tsx +47 -0
- package/.react-email/src/app/preview/[...slug]/page.tsx +65 -0
- package/.react-email/src/app/preview/[...slug]/preview.tsx +141 -0
- package/.react-email/src/app/preview/[...slug]/rendering-error.tsx +40 -0
- package/.react-email/src/components/button.tsx +90 -0
- package/.react-email/src/components/code-container.tsx +145 -0
- package/.react-email/src/components/code.tsx +112 -0
- package/.react-email/src/components/heading.tsx +113 -0
- package/.react-email/src/components/icons/icon-arrow-down.tsx +16 -0
- package/.react-email/src/components/icons/icon-base.tsx +24 -0
- package/.react-email/src/components/icons/icon-button.tsx +23 -0
- package/.react-email/src/components/icons/icon-check.tsx +19 -0
- package/.react-email/src/components/icons/icon-clipboard.tsx +40 -0
- package/.react-email/src/components/icons/icon-download.tsx +19 -0
- package/.react-email/src/components/icons/icon-file.tsx +19 -0
- package/.react-email/src/components/icons/icon-folder-open.tsx +19 -0
- package/.react-email/src/components/icons/icon-folder.tsx +18 -0
- package/.react-email/src/components/icons/icon-hide-sidebar.tsx +23 -0
- package/.react-email/src/components/icons/icon-monitor.tsx +19 -0
- package/.react-email/src/components/icons/icon-phone.tsx +26 -0
- package/.react-email/src/components/icons/icon-source.tsx +19 -0
- package/.react-email/src/components/index.ts +7 -0
- package/.react-email/src/components/logo.tsx +64 -0
- package/.react-email/src/components/send.tsx +135 -0
- package/.react-email/src/components/shell.tsx +115 -0
- package/.react-email/src/components/sidebar/index.ts +1 -0
- package/.react-email/src/components/sidebar/sidebar-directory-children.tsx +134 -0
- package/.react-email/src/components/sidebar/sidebar-directory.tsx +106 -0
- package/.react-email/src/components/sidebar/sidebar.tsx +45 -0
- package/.react-email/src/components/text.tsx +99 -0
- package/.react-email/src/components/tooltip-content.tsx +32 -0
- package/.react-email/src/components/tooltip.tsx +19 -0
- package/.react-email/src/components/topbar.tsx +161 -0
- package/.react-email/src/contexts/emails.tsx +127 -0
- package/.react-email/src/hooks/use-hot-reload.ts +35 -0
- package/.react-email/src/hooks/use-rendering-metadata.ts +36 -0
- package/.react-email/src/utils/cn.ts +6 -0
- package/.react-email/src/utils/constants.ts +6 -0
- package/.react-email/src/utils/copy-text-to-clipboard.ts +7 -0
- package/.react-email/src/utils/emails-directory-absolute-path.ts +34 -0
- package/.react-email/src/utils/get-email-component.ts +108 -0
- package/.react-email/src/utils/improve-error-with-sourcemap.ts +55 -0
- package/.react-email/src/utils/index.ts +5 -0
- package/.react-email/src/utils/language-map.ts +7 -0
- package/.react-email/src/utils/static-node-modules-for-vm.ts +92 -0
- package/.react-email/src/utils/types/as.ts +26 -0
- package/.react-email/src/utils/types/email-template.ts +8 -0
- package/.react-email/src/utils/types/error-object.ts +11 -0
- package/.react-email/src/utils/types/hot-reload-change.ts +6 -0
- package/.react-email/src/utils/types/hot-reload-event.ts +6 -0
- package/.react-email/src/utils/unreachable.ts +8 -0
- package/.react-email/tailwind.config.ts +94 -0
- package/dist/index.d.mts +238 -83
- package/dist/index.d.ts +238 -83
- package/dist/index.js +364 -105
- package/dist/index.mjs +360 -105
- package/package.json +1 -1
- package/emails/admin/abort-order-request.tsx +0 -58
- package/emails/admin/index.ts +0 -2
- package/emails/admin/revert-payment-request-admin.tsx +0 -54
- package/emails/all/index.ts +0 -1
- package/emails/all/welcome.tsx +0 -104
- package/emails/brand/evidences-accepted-brand.tsx +0 -59
- package/emails/brand/evidences-submitted-brand.tsx +0 -65
- package/emails/brand/index.ts +0 -6
- package/emails/brand/new-order-created-brand.tsx +0 -74
- package/emails/brand/order-accepted-brand.tsx +0 -63
- package/emails/brand/order-cancelled-brand.tsx +0 -68
- package/emails/brand/order-rejected-brand.tsx +0 -79
- package/emails/creator/evidences-approved-creator.tsx +0 -62
- package/emails/creator/evidences-rejected-creator.tsx +0 -74
- package/emails/creator/index.ts +0 -5
- package/emails/creator/new-order-created-creator.tsx +0 -70
- package/emails/creator/order-cancelled-creator.tsx +0 -69
- package/emails/creator/order-payment-creator.tsx +0 -58
- package/emails/index.ts +0 -5
- package/emails/shared/components/base-head.tsx +0 -19
- package/emails/shared/components/comment-component.tsx +0 -32
- package/emails/shared/components/footer.tsx +0 -84
- package/emails/shared/components/header.tsx +0 -24
- package/emails/shared/components/new-order-info.tsx +0 -60
- package/emails/shared/components/payment-amount.tsx +0 -37
- package/emails/shared/components/user-Info.tsx +0 -55
- package/emails/shared/index.ts +0 -3
- package/emails/shared/styles.ts +0 -72
- package/emails/shared/types.ts +0 -179
- package/emails/shared/values.ts +0 -19
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { createContext, useContext, useEffect, useState } from 'react';
|
|
3
|
+
import {
|
|
4
|
+
getEmailsDirectoryMetadata,
|
|
5
|
+
type EmailsDirectory,
|
|
6
|
+
} from '../actions/get-emails-directory-metadata';
|
|
7
|
+
import { useHotreload } from '../hooks/use-hot-reload';
|
|
8
|
+
import {
|
|
9
|
+
emailsDirRelativePath,
|
|
10
|
+
emailsDirectoryAbsolutePath,
|
|
11
|
+
normalizePath,
|
|
12
|
+
pathSeparator,
|
|
13
|
+
} from '../utils/emails-directory-absolute-path';
|
|
14
|
+
import {
|
|
15
|
+
renderEmailByPath,
|
|
16
|
+
type EmailRenderingResult,
|
|
17
|
+
} from '../actions/render-email-by-path';
|
|
18
|
+
import { getEmailPathFromSlug } from '../actions/get-email-path-from-slug';
|
|
19
|
+
|
|
20
|
+
const EmailsContext = createContext<
|
|
21
|
+
| {
|
|
22
|
+
emailsDirectoryMetadata: EmailsDirectory;
|
|
23
|
+
/**
|
|
24
|
+
* Uses the hot reloaded bundled build and rendering email result
|
|
25
|
+
*/
|
|
26
|
+
useEmailRenderingResult: (
|
|
27
|
+
emailPath: string,
|
|
28
|
+
serverEmailRenderedResult: EmailRenderingResult,
|
|
29
|
+
) => EmailRenderingResult;
|
|
30
|
+
}
|
|
31
|
+
| undefined
|
|
32
|
+
>(undefined);
|
|
33
|
+
|
|
34
|
+
export const useEmails = () => {
|
|
35
|
+
const providerValue = useContext(EmailsContext);
|
|
36
|
+
|
|
37
|
+
if (typeof providerValue === 'undefined') {
|
|
38
|
+
throw new Error(
|
|
39
|
+
'Cannot call `useEmail()` outside of an EmailsContext provider!',
|
|
40
|
+
);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
return providerValue;
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
export const EmailsProvider = (props: {
|
|
47
|
+
initialEmailsDirectoryMetadata: EmailsDirectory;
|
|
48
|
+
children: React.ReactNode;
|
|
49
|
+
}) => {
|
|
50
|
+
const [emailsDirectoryMetadata, setEmailsDirectoryMetadata] =
|
|
51
|
+
useState<EmailsDirectory>(props.initialEmailsDirectoryMetadata);
|
|
52
|
+
|
|
53
|
+
const [renderingResultPerEmailPath, setRenderingResultPerEmailPath] =
|
|
54
|
+
useState<Record<string, EmailRenderingResult>>({});
|
|
55
|
+
|
|
56
|
+
if (process.env.NEXT_PUBLIC_IS_BUILDING !== 'true') {
|
|
57
|
+
// this will not change on runtime so it doesn't violate
|
|
58
|
+
// the rules of hooks
|
|
59
|
+
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
60
|
+
useHotreload(async (changes) => {
|
|
61
|
+
const metadata = await getEmailsDirectoryMetadata(
|
|
62
|
+
emailsDirectoryAbsolutePath,
|
|
63
|
+
);
|
|
64
|
+
if (metadata) {
|
|
65
|
+
setEmailsDirectoryMetadata(metadata);
|
|
66
|
+
} else {
|
|
67
|
+
throw new Error(
|
|
68
|
+
'Hot reloading: unable to find the emails directory to update the sidebar',
|
|
69
|
+
);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
for await (const change of changes) {
|
|
73
|
+
const normalizedEmailsDirRelativePath = normalizePath(
|
|
74
|
+
emailsDirRelativePath,
|
|
75
|
+
);
|
|
76
|
+
const slugForChangedEmail =
|
|
77
|
+
// filename ex: emails/apple-receipt.tsx
|
|
78
|
+
// so we need to remove the "emails/" because it isn't used
|
|
79
|
+
// on the slug parameter for the preview page
|
|
80
|
+
change.filename
|
|
81
|
+
.replace(`${normalizedEmailsDirRelativePath}${pathSeparator}`, '')
|
|
82
|
+
.replace(normalizedEmailsDirRelativePath, '');
|
|
83
|
+
|
|
84
|
+
const pathForChangedEmail =
|
|
85
|
+
await getEmailPathFromSlug(slugForChangedEmail);
|
|
86
|
+
|
|
87
|
+
const lastResult = renderingResultPerEmailPath[pathForChangedEmail];
|
|
88
|
+
|
|
89
|
+
if (typeof lastResult !== 'undefined') {
|
|
90
|
+
const renderingResult = await renderEmailByPath(pathForChangedEmail);
|
|
91
|
+
|
|
92
|
+
setRenderingResultPerEmailPath((map) => ({
|
|
93
|
+
...map,
|
|
94
|
+
[pathForChangedEmail]: renderingResult,
|
|
95
|
+
}));
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
return (
|
|
102
|
+
<EmailsContext.Provider
|
|
103
|
+
value={{
|
|
104
|
+
emailsDirectoryMetadata,
|
|
105
|
+
useEmailRenderingResult: (emailPath, serverEmailRenderedResult) => {
|
|
106
|
+
useEffect(() => {
|
|
107
|
+
if (typeof renderingResultPerEmailPath[emailPath] === 'undefined') {
|
|
108
|
+
setRenderingResultPerEmailPath((map) => ({
|
|
109
|
+
...map,
|
|
110
|
+
[emailPath]: serverEmailRenderedResult,
|
|
111
|
+
}));
|
|
112
|
+
}
|
|
113
|
+
}, [serverEmailRenderedResult, emailPath]);
|
|
114
|
+
|
|
115
|
+
if (typeof renderingResultPerEmailPath[emailPath] !== 'undefined') {
|
|
116
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
117
|
+
return renderingResultPerEmailPath[emailPath]!;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
return serverEmailRenderedResult;
|
|
121
|
+
},
|
|
122
|
+
}}
|
|
123
|
+
>
|
|
124
|
+
{props.children}
|
|
125
|
+
</EmailsContext.Provider>
|
|
126
|
+
);
|
|
127
|
+
};
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { useEffect, useRef } from 'react';
|
|
3
|
+
import { type Socket, io } from 'socket.io-client';
|
|
4
|
+
import type { HotReloadChange } from '../utils/types/hot-reload-change';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Hook that detects any "reload" event sent from the CLI's web socket
|
|
8
|
+
* and calls the received parameter callback
|
|
9
|
+
*/
|
|
10
|
+
export const useHotreload = (
|
|
11
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
12
|
+
onShouldReload: (changes: HotReloadChange[]) => any,
|
|
13
|
+
) => {
|
|
14
|
+
const socketRef = useRef<Socket | null>(null);
|
|
15
|
+
|
|
16
|
+
useEffect(() => {
|
|
17
|
+
if (process.env.NODE_ENV === 'production') {
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
if (!socketRef.current) {
|
|
22
|
+
socketRef.current = io();
|
|
23
|
+
}
|
|
24
|
+
const socket = socketRef.current;
|
|
25
|
+
|
|
26
|
+
socket.on('reload', (changes: HotReloadChange[]) => {
|
|
27
|
+
console.debug('Reloading...');
|
|
28
|
+
void onShouldReload(changes);
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
return () => {
|
|
32
|
+
socket.off();
|
|
33
|
+
};
|
|
34
|
+
}, [onShouldReload]);
|
|
35
|
+
};
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { useEffect } from 'react';
|
|
2
|
+
import type {
|
|
3
|
+
EmailRenderingResult,
|
|
4
|
+
RenderedEmailMetadata,
|
|
5
|
+
} from '../actions/render-email-by-path';
|
|
6
|
+
|
|
7
|
+
const lastRenderingMetadataPerEmailPath = {} as Record<
|
|
8
|
+
string,
|
|
9
|
+
RenderedEmailMetadata
|
|
10
|
+
>;
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Returns the rendering metadata if the given `renderingResult`
|
|
14
|
+
* does not error. If it does error it returns the last value it had for the hook.
|
|
15
|
+
*/
|
|
16
|
+
export const useRenderingMetadata = (
|
|
17
|
+
emailPath: string,
|
|
18
|
+
renderingResult: EmailRenderingResult,
|
|
19
|
+
initialRenderingMetadata?: EmailRenderingResult,
|
|
20
|
+
): RenderedEmailMetadata | undefined => {
|
|
21
|
+
useEffect(() => {
|
|
22
|
+
if ('markup' in renderingResult) {
|
|
23
|
+
lastRenderingMetadataPerEmailPath[emailPath] = renderingResult;
|
|
24
|
+
} else if (
|
|
25
|
+
typeof initialRenderingMetadata !== 'undefined' &&
|
|
26
|
+
'markup' in initialRenderingMetadata &&
|
|
27
|
+
typeof lastRenderingMetadataPerEmailPath[emailPath] === 'undefined'
|
|
28
|
+
) {
|
|
29
|
+
lastRenderingMetadataPerEmailPath[emailPath] = initialRenderingMetadata;
|
|
30
|
+
}
|
|
31
|
+
}, [renderingResult, emailPath, initialRenderingMetadata]);
|
|
32
|
+
|
|
33
|
+
return 'error' in renderingResult
|
|
34
|
+
? lastRenderingMetadataPerEmailPath[emailPath]
|
|
35
|
+
: renderingResult;
|
|
36
|
+
};
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/* eslint-disable @typescript-eslint/no-non-null-assertion */
|
|
2
|
+
export const emailsDirRelativePath =
|
|
3
|
+
process.env.NEXT_PUBLIC_EMAILS_DIR_RELATIVE_PATH ?? 'emails';
|
|
4
|
+
|
|
5
|
+
export const userProjectLocation =
|
|
6
|
+
process.env.NEXT_PUBLIC_USER_PROJECT_LOCATION!;
|
|
7
|
+
|
|
8
|
+
// this trickery to find the path separator for the OS is for this to work both on the client
|
|
9
|
+
// and on the server properly
|
|
10
|
+
export const pathSeparator = process.env.NEXT_PUBLIC_OS_PATH_SEPARATOR! as
|
|
11
|
+
| '/'
|
|
12
|
+
| '\\';
|
|
13
|
+
|
|
14
|
+
export const normalizePath = (path: string) => {
|
|
15
|
+
let newPath = path;
|
|
16
|
+
|
|
17
|
+
while (newPath.startsWith(`.${pathSeparator}`)) {
|
|
18
|
+
newPath = newPath.slice(2);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
while (newPath.startsWith(pathSeparator)) {
|
|
22
|
+
newPath = newPath.slice(1);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
while (newPath.endsWith(pathSeparator)) {
|
|
26
|
+
newPath = newPath.slice(0, -1);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
return newPath;
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
export const emailsDirectoryAbsolutePath = `${
|
|
33
|
+
process.env.NEXT_PUBLIC_USER_PROJECT_LOCATION
|
|
34
|
+
}${pathSeparator}${normalizePath(emailsDirRelativePath)}`;
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
/* eslint-disable @typescript-eslint/no-non-null-assertion */
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import vm from 'node:vm';
|
|
4
|
+
import { type RawSourceMap } from 'source-map-js';
|
|
5
|
+
import { type OutputFile, build, type BuildFailure } from 'esbuild';
|
|
6
|
+
import type { EmailTemplate as EmailComponent } from './types/email-template';
|
|
7
|
+
import type { ErrorObject } from './types/error-object';
|
|
8
|
+
import { improveErrorWithSourceMap } from './improve-error-with-sourcemap';
|
|
9
|
+
import { staticNodeModulesForVM } from './static-node-modules-for-vm';
|
|
10
|
+
|
|
11
|
+
export const getEmailComponent = async (
|
|
12
|
+
emailPath: string,
|
|
13
|
+
): Promise<
|
|
14
|
+
| {
|
|
15
|
+
emailComponent: EmailComponent;
|
|
16
|
+
|
|
17
|
+
sourceMapToOriginalFile: RawSourceMap;
|
|
18
|
+
}
|
|
19
|
+
| { error: ErrorObject }
|
|
20
|
+
> => {
|
|
21
|
+
let outputFiles: OutputFile[];
|
|
22
|
+
try {
|
|
23
|
+
const buildData = await build({
|
|
24
|
+
bundle: true,
|
|
25
|
+
entryPoints: [emailPath],
|
|
26
|
+
platform: 'node',
|
|
27
|
+
write: false,
|
|
28
|
+
format: 'cjs',
|
|
29
|
+
jsx: 'automatic',
|
|
30
|
+
logLevel: 'silent',
|
|
31
|
+
// allows for using jsx on a .js file
|
|
32
|
+
loader: {
|
|
33
|
+
'.js': 'jsx',
|
|
34
|
+
},
|
|
35
|
+
outdir: 'stdout', // just a stub for esbuild, it won't actually write to this folder
|
|
36
|
+
sourcemap: 'external',
|
|
37
|
+
});
|
|
38
|
+
outputFiles = buildData.outputFiles;
|
|
39
|
+
} catch (exception) {
|
|
40
|
+
const buildFailure = exception as BuildFailure;
|
|
41
|
+
return {
|
|
42
|
+
error: {
|
|
43
|
+
message: buildFailure.message,
|
|
44
|
+
stack: buildFailure.stack,
|
|
45
|
+
name: buildFailure.name,
|
|
46
|
+
cause: buildFailure.cause,
|
|
47
|
+
},
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const sourceMapFile = outputFiles[0]!;
|
|
52
|
+
const bundledEmailFile = outputFiles[1]!;
|
|
53
|
+
const builtEmailCode = bundledEmailFile.text;
|
|
54
|
+
|
|
55
|
+
const fakeContext = {
|
|
56
|
+
...global,
|
|
57
|
+
console,
|
|
58
|
+
Buffer,
|
|
59
|
+
module: { exports: { default: undefined as unknown } },
|
|
60
|
+
__filanem: emailPath,
|
|
61
|
+
__dirname: path.dirname(emailPath),
|
|
62
|
+
require: (module: string) => {
|
|
63
|
+
if (module in staticNodeModulesForVM) {
|
|
64
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
|
|
65
|
+
return staticNodeModulesForVM[module];
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
69
|
+
return require(`${module}`) as unknown;
|
|
70
|
+
// this stupid string templating was necessary to not have
|
|
71
|
+
// webpack warnings like:
|
|
72
|
+
//
|
|
73
|
+
// Import trace for requested module:
|
|
74
|
+
// ./src/utils/get-email-component.tsx
|
|
75
|
+
// ./src/app/page.tsx
|
|
76
|
+
// ⚠ ./src/utils/get-email-component.tsx
|
|
77
|
+
// Critical dependency: the request of a dependency is an expression
|
|
78
|
+
},
|
|
79
|
+
process,
|
|
80
|
+
};
|
|
81
|
+
const sourceMapToEmail = JSON.parse(sourceMapFile.text) as RawSourceMap;
|
|
82
|
+
try {
|
|
83
|
+
vm.runInNewContext(builtEmailCode, fakeContext, { filename: emailPath });
|
|
84
|
+
} catch (exception) {
|
|
85
|
+
const error = exception as Error;
|
|
86
|
+
|
|
87
|
+
return {
|
|
88
|
+
error: improveErrorWithSourceMap(error, emailPath, sourceMapToEmail),
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
if (fakeContext.module.exports.default === undefined) {
|
|
93
|
+
return {
|
|
94
|
+
error: improveErrorWithSourceMap(
|
|
95
|
+
new Error(
|
|
96
|
+
`The email component at ${emailPath} does not contain a default export`,
|
|
97
|
+
),
|
|
98
|
+
emailPath,
|
|
99
|
+
sourceMapToEmail,
|
|
100
|
+
),
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
return {
|
|
105
|
+
emailComponent: fakeContext.module.exports.default as EmailComponent,
|
|
106
|
+
sourceMapToOriginalFile: sourceMapToEmail,
|
|
107
|
+
};
|
|
108
|
+
};
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import * as stackTraceParser from 'stacktrace-parser';
|
|
2
|
+
import { SourceMapConsumer, type RawSourceMap } from 'source-map-js';
|
|
3
|
+
import type { ErrorObject } from './types/error-object';
|
|
4
|
+
|
|
5
|
+
export const improveErrorWithSourceMap = (
|
|
6
|
+
error: Error,
|
|
7
|
+
|
|
8
|
+
originalFilePath: string,
|
|
9
|
+
sourceMapToOriginalFile: RawSourceMap,
|
|
10
|
+
): ErrorObject => {
|
|
11
|
+
let stack: string | undefined;
|
|
12
|
+
|
|
13
|
+
if (typeof error.stack !== 'undefined') {
|
|
14
|
+
const parsedStack = stackTraceParser.parse(error.stack);
|
|
15
|
+
const sourceMapConsumer = new SourceMapConsumer(sourceMapToOriginalFile);
|
|
16
|
+
const newStackLines = [] as string[];
|
|
17
|
+
for (const stackFrame of parsedStack) {
|
|
18
|
+
if (stackFrame.file === originalFilePath) {
|
|
19
|
+
if (stackFrame.column || stackFrame.lineNumber) {
|
|
20
|
+
const positionWithError = sourceMapConsumer.originalPositionFor({
|
|
21
|
+
column: stackFrame.column ?? 0,
|
|
22
|
+
line: stackFrame.lineNumber ?? 0,
|
|
23
|
+
});
|
|
24
|
+
const columnAndLine =
|
|
25
|
+
positionWithError.column && positionWithError.line
|
|
26
|
+
? `${positionWithError.line}:${positionWithError.column}`
|
|
27
|
+
: positionWithError.line;
|
|
28
|
+
newStackLines.push(
|
|
29
|
+
` at ${stackFrame.methodName} (${originalFilePath}:${columnAndLine})`,
|
|
30
|
+
);
|
|
31
|
+
} else {
|
|
32
|
+
newStackLines.push(
|
|
33
|
+
` at ${stackFrame.methodName} (${originalFilePath})`,
|
|
34
|
+
);
|
|
35
|
+
}
|
|
36
|
+
} else {
|
|
37
|
+
const columnAndLine =
|
|
38
|
+
stackFrame.column && stackFrame.lineNumber
|
|
39
|
+
? `${stackFrame.lineNumber}:${stackFrame.column}`
|
|
40
|
+
: stackFrame.lineNumber;
|
|
41
|
+
newStackLines.push(
|
|
42
|
+
` at ${stackFrame.methodName} (${stackFrame.file}:${columnAndLine})`,
|
|
43
|
+
);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
stack = newStackLines.join('\n');
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
return {
|
|
50
|
+
name: error.name,
|
|
51
|
+
message: error.message,
|
|
52
|
+
cause: error.cause,
|
|
53
|
+
stack,
|
|
54
|
+
};
|
|
55
|
+
};
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import zlib from 'node:zlib';
|
|
2
|
+
import vm from 'node:vm';
|
|
3
|
+
import v8 from 'node:v8';
|
|
4
|
+
import util from 'node:util';
|
|
5
|
+
import url from 'node:url';
|
|
6
|
+
import tty from 'node:tty';
|
|
7
|
+
import tls from 'node:tls';
|
|
8
|
+
import timers from 'node:timers';
|
|
9
|
+
import stringDecoder from 'node:string_decoder';
|
|
10
|
+
import stream from 'node:stream';
|
|
11
|
+
import readline from 'node:readline';
|
|
12
|
+
import querystring from 'node:querystring';
|
|
13
|
+
import punycode from 'node:punycode';
|
|
14
|
+
import path from 'node:path';
|
|
15
|
+
import os from 'node:os';
|
|
16
|
+
import net from 'node:net';
|
|
17
|
+
import https from 'node:https';
|
|
18
|
+
import http from 'node:http';
|
|
19
|
+
import fs from 'node:fs';
|
|
20
|
+
import events from 'node:events';
|
|
21
|
+
import domain from 'node:domain';
|
|
22
|
+
import dns from 'node:dns';
|
|
23
|
+
import dgram from 'node:dgram';
|
|
24
|
+
import crypto from 'node:crypto';
|
|
25
|
+
import cluster from 'node:cluster';
|
|
26
|
+
import childProcess from 'node:child_process';
|
|
27
|
+
import buffer from 'node:buffer';
|
|
28
|
+
import assert from 'node:assert';
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* A map of the name of the modules (including `node:` prefixed ones)
|
|
32
|
+
* provided by Node because dynamic requires of them, even on the server
|
|
33
|
+
* will not be resolved properly
|
|
34
|
+
*/
|
|
35
|
+
export const staticNodeModulesForVM = {
|
|
36
|
+
zlib,
|
|
37
|
+
'node:zlib': zlib,
|
|
38
|
+
vm,
|
|
39
|
+
'node:vm': vm,
|
|
40
|
+
v8,
|
|
41
|
+
'node:v8': v8,
|
|
42
|
+
util,
|
|
43
|
+
'node:util': util,
|
|
44
|
+
url,
|
|
45
|
+
'node:url': url,
|
|
46
|
+
tty,
|
|
47
|
+
'node:tty': tty,
|
|
48
|
+
tls,
|
|
49
|
+
'node:tls': tls,
|
|
50
|
+
timers,
|
|
51
|
+
'node:timers': timers,
|
|
52
|
+
'string_decoder': stringDecoder,
|
|
53
|
+
'node:string_decoder': stringDecoder,
|
|
54
|
+
stream,
|
|
55
|
+
'node:stream': stream,
|
|
56
|
+
readline,
|
|
57
|
+
'node:readline': readline,
|
|
58
|
+
querystring,
|
|
59
|
+
'node:querystring': querystring,
|
|
60
|
+
punycode,
|
|
61
|
+
'node:punycode': punycode,
|
|
62
|
+
path,
|
|
63
|
+
'node:path': path,
|
|
64
|
+
os,
|
|
65
|
+
'node:os': os,
|
|
66
|
+
net,
|
|
67
|
+
'node:net': net,
|
|
68
|
+
https,
|
|
69
|
+
'node:https': https,
|
|
70
|
+
http,
|
|
71
|
+
'node:http': http,
|
|
72
|
+
fs,
|
|
73
|
+
'node:fs': fs,
|
|
74
|
+
events,
|
|
75
|
+
'node:events': events,
|
|
76
|
+
domain,
|
|
77
|
+
'node:domain': domain,
|
|
78
|
+
dns,
|
|
79
|
+
'node:dns': dns,
|
|
80
|
+
dgram,
|
|
81
|
+
'node:dgram': dgram,
|
|
82
|
+
crypto,
|
|
83
|
+
'node:crypto': crypto,
|
|
84
|
+
cluster,
|
|
85
|
+
'node:cluster': cluster,
|
|
86
|
+
'child_process': childProcess,
|
|
87
|
+
'node:child_process': childProcess,
|
|
88
|
+
buffer,
|
|
89
|
+
'node:buffer': buffer,
|
|
90
|
+
assert,
|
|
91
|
+
'node:assert': assert,
|
|
92
|
+
};
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
export type As<
|
|
2
|
+
DefaultTag extends React.ElementType,
|
|
3
|
+
T1 extends React.ElementType,
|
|
4
|
+
T2 extends React.ElementType = T1,
|
|
5
|
+
T3 extends React.ElementType = T1,
|
|
6
|
+
T4 extends React.ElementType = T1,
|
|
7
|
+
T5 extends React.ElementType = T1,
|
|
8
|
+
> =
|
|
9
|
+
| (React.ComponentPropsWithRef<DefaultTag> & {
|
|
10
|
+
as?: DefaultTag;
|
|
11
|
+
})
|
|
12
|
+
| (React.ComponentPropsWithRef<T1> & {
|
|
13
|
+
as: T1;
|
|
14
|
+
})
|
|
15
|
+
| (React.ComponentPropsWithRef<T2> & {
|
|
16
|
+
as: T2;
|
|
17
|
+
})
|
|
18
|
+
| (React.ComponentPropsWithRef<T3> & {
|
|
19
|
+
as: T3;
|
|
20
|
+
})
|
|
21
|
+
| (React.ComponentPropsWithRef<T4> & {
|
|
22
|
+
as: T4;
|
|
23
|
+
})
|
|
24
|
+
| (React.ComponentPropsWithRef<T5> & {
|
|
25
|
+
as: T5;
|
|
26
|
+
});
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export interface EmailTemplate {
|
|
2
|
+
(props: Record<string, unknown> | Record<string, never>): React.ReactNode;
|
|
3
|
+
PreviewProps?: Record<string, unknown>;
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
export const isEmailTemplate = (val: unknown): val is EmailTemplate => {
|
|
7
|
+
return typeof val === 'function';
|
|
8
|
+
};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* An object that mimics the structure of the Error class,
|
|
3
|
+
* we just can't use the Error class here because server actions can't
|
|
4
|
+
* return classes
|
|
5
|
+
*/
|
|
6
|
+
export interface ErrorObject {
|
|
7
|
+
name: string;
|
|
8
|
+
stack: string | undefined;
|
|
9
|
+
cause: unknown;
|
|
10
|
+
message: string;
|
|
11
|
+
}
|