Skip to content

Commit fdbfc74

Browse files
fix(api): add email package build process and extension integration (#2122)
Co-authored-by: Mariano Fuentes <marfuen98@gmail.com>
1 parent aeb0972 commit fdbfc74

4 files changed

Lines changed: 130 additions & 0 deletions

File tree

.github/workflows/trigger-api-tasks-deploy-main.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,9 @@ jobs:
3131
- name: Build Integration Platform package
3232
working-directory: ./packages/integration-platform
3333
run: bun run build
34+
- name: Build Email package
35+
working-directory: ./packages/email
36+
run: bun run build
3437
- name: Build DB package
3538
working-directory: ./packages/db
3639
run: bun run build

.github/workflows/trigger-api-tasks-deploy-release.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,10 @@ jobs:
3535
working-directory: ./packages/integration-platform
3636
run: bun run build
3737

38+
- name: Build Email package
39+
working-directory: ./packages/email
40+
run: bun run build
41+
3842
- name: Build DB package
3943
working-directory: ./packages/db
4044
run: bun run build

apps/api/emailExtension.ts

Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
import type {
2+
BuildContext,
3+
BuildExtension,
4+
BuildManifest,
5+
} from '@trigger.dev/build';
6+
import type { Plugin } from 'esbuild';
7+
import { existsSync } from 'node:fs';
8+
import { cp, mkdir } from 'node:fs/promises';
9+
import { resolve } from 'node:path';
10+
11+
const PACKAGE_NAME = '@trycompai/email';
12+
13+
/**
14+
* Custom Trigger.dev build extension for @trycompai/email workspace package.
15+
*
16+
* Since @trycompai/email is a workspace package (not published to npm),
17+
* we need to:
18+
* 1. Add an esbuild plugin to resolve the import path during build
19+
* 2. Copy the built dist files into the trigger.dev deployment
20+
*/
21+
export function emailExtension(): EmailExtension {
22+
return new EmailExtension();
23+
}
24+
25+
class EmailExtension implements BuildExtension {
26+
public readonly name = 'EmailExtension';
27+
private _packagePath: string | undefined;
28+
29+
async onBuildStart(context: BuildContext) {
30+
if (context.target === 'dev') {
31+
return;
32+
}
33+
34+
this._packagePath = this.findPackageRoot(context.workingDir);
35+
36+
if (!this._packagePath) {
37+
throw new Error(
38+
[
39+
`EmailExtension could not find ${PACKAGE_NAME}.`,
40+
'Make sure the package is built (run `bun run build` in packages/email).',
41+
].join('\n'),
42+
);
43+
}
44+
45+
context.logger.debug(`Found email package at ${this._packagePath}`);
46+
47+
const packagePath = this._packagePath;
48+
const resolvePlugin: Plugin = {
49+
name: 'resolve-email',
50+
setup(build) {
51+
build.onResolve({ filter: /^@trycompai\/email$/ }, () => {
52+
return {
53+
path: resolve(packagePath, 'dist/index.js'),
54+
};
55+
});
56+
57+
build.onResolve(
58+
{ filter: /^@trycompai\/email\// },
59+
(args) => {
60+
const subpath = args.path.replace(`${PACKAGE_NAME}/`, '');
61+
return {
62+
path: resolve(packagePath, 'dist', `${subpath}/index.js`),
63+
};
64+
},
65+
);
66+
},
67+
};
68+
69+
context.registerPlugin(resolvePlugin);
70+
}
71+
72+
async onBuildComplete(context: BuildContext, manifest: BuildManifest) {
73+
if (context.target === 'dev') {
74+
return;
75+
}
76+
77+
const packagePath = this._packagePath;
78+
if (!packagePath) {
79+
return;
80+
}
81+
82+
const packageDistPath = resolve(packagePath, 'dist');
83+
84+
const destPath = resolve(
85+
manifest.outputPath,
86+
'node_modules/@trycompai/email',
87+
);
88+
const destDistPath = resolve(destPath, 'dist');
89+
90+
await mkdir(destDistPath, { recursive: true });
91+
92+
await cp(packageDistPath, destDistPath, { recursive: true });
93+
94+
const packageJsonPath = resolve(packagePath, 'package.json');
95+
if (existsSync(packageJsonPath)) {
96+
await cp(packageJsonPath, resolve(destPath, 'package.json'));
97+
}
98+
99+
context.logger.log(
100+
'Copied @trycompai/email to deployment bundle',
101+
);
102+
}
103+
104+
private findPackageRoot(workingDir: string): string | undefined {
105+
const candidates = [
106+
resolve(workingDir, '../../packages/email'),
107+
resolve(workingDir, '../packages/email'),
108+
];
109+
110+
for (const candidate of candidates) {
111+
if (
112+
existsSync(candidate) &&
113+
existsSync(resolve(candidate, 'dist/index.js'))
114+
) {
115+
return candidate;
116+
}
117+
}
118+
119+
return undefined;
120+
}
121+
}

apps/api/trigger.config.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { PrismaInstrumentation } from '@prisma/instrumentation';
22
import { syncVercelEnvVars } from '@trigger.dev/build/extensions/core';
33
import { defineConfig } from '@trigger.dev/sdk';
44
import { prismaExtension } from './customPrismaExtension';
5+
import { emailExtension } from './emailExtension';
56
import { integrationPlatformExtension } from './integrationPlatformExtension';
67

78
export default defineConfig({
@@ -16,6 +17,7 @@ export default defineConfig({
1617
dbPackageVersion: '^1.3.15', // Version of @trycompai/db package with compiled JS
1718
}),
1819
integrationPlatformExtension(),
20+
emailExtension(),
1921
syncVercelEnvVars(),
2022
],
2123
},

0 commit comments

Comments
 (0)