Official Plugin: SendGrid (email)

SendGridPlugin is the second official reference plugin for the StreetJS plugin system. It sends email via the SendGrid v3 API with no third-party SDK — pure node:https. Its request-building is deterministic and verified offline; the network send is a thin wrapper.

Manifest

1
2
3
4
5
import { sendGridPluginManifest } from 'streetjs';
sendGridPluginManifest();
// { name: 'street-plugin-sendgrid', version: '1.0.0',
//   capabilities: ['email','notifications','sendgrid'],
//   permissions: ['net','secrets','middleware'] }

Configuration

1
2
3
4
5
interface SendGridPluginConfig {
  apiKey: string;        // required
  defaultFrom?: string;  // fallback sender
  stateKey?: string;     // ctx.state key for the injected client (default 'mail')
}

Install through the PluginHost (signed)

1
2
3
4
5
6
7
8
import { generateKeyPairSync } from 'node:crypto';
import { PluginHost, signManifest, SendGridPlugin, sendGridPluginManifest } from 'streetjs';

const { publicKey, privateKey } = generateKeyPairSync('ed25519');
const host = new PluginHost({ grantedPermissions: ['net','secrets','middleware'], publicKey });
host.register(new SendGridPlugin({ apiKey: process.env.SENDGRID_API_KEY!, defaultFrom: 'noreply@acme.com' }),
              signManifest(sendGridPluginManifest(), privateKey));
await host.enable('street-plugin-sendgrid');

Using it

The plugin injects a SendGridClient into ctx.state[stateKey] (default mail):

1
2
3
4
5
for (const mw of host.middlewaresOf('street-plugin-sendgrid')) app.use(mw);

// in a handler:
const mail = ctx.state['mail']; // SendGridClient
await mail.send({ to: 'user@acme.com', subject: 'Welcome', html: '<h1>Hi</h1>' });

Offline-verifiable request building

1
2
3
4
5
6
import { SendGridClient } from 'streetjs';
const req = new SendGridClient({ apiKey: 'SG.x', defaultFrom: 'a@b.com' })
  .buildMailSendRequest({ to: 'u@b.com', subject: 'Hi', text: 'hello' });
// req.url === 'https://api.sendgrid.com/v3/mail/send'
// req.headers.authorization === 'Bearer SG.x'
// JSON.parse(req.body) → { personalizations:[{to:[{email}]}], from, subject, content }

Verification

packages/core/src/tests/plugin-sendgrid.test.ts (7 tests): config schema, deterministic request building (bearer auth + v3 JSON body, html + from override, missing from/to/content rejection), signed-manifest install through PluginHost, permission gating, lifecycle + sandbox injection, and invalid-config enable failure.

1
cd packages/core && npx tsc && node --test dist/src/tests/plugin-sendgrid.test.js