@elqnt/notifications 1.0.0 → 1.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/README.md +56 -0
- package/SKILL.md +328 -0
- package/dist/hooks/index.d.mts +27 -7
- package/dist/hooks/index.d.ts +27 -7
- package/dist/hooks/index.js +34 -5
- package/dist/hooks/index.js.map +1 -1
- package/dist/hooks/index.mjs +33 -4
- package/dist/hooks/index.mjs.map +1 -1
- package/dist/index.d.mts +0 -1
- package/dist/index.d.ts +0 -1
- package/dist/index.js +1 -8
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +0 -7
- package/dist/models/index.js +1 -2
- package/dist/models/index.js.map +1 -1
- package/dist/models/index.mjs +0 -1
- package/package.json +13 -12
- package/dist/chunk-E6ORNZJX.js +0 -36
- package/dist/chunk-E6ORNZJX.js.map +0 -1
- package/dist/chunk-OPXXF4IO.mjs +0 -36
- package/dist/chunk-OPXXF4IO.mjs.map +0 -1
package/README.md
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# @elqnt/notifications
|
|
2
|
+
|
|
3
|
+
Outbound notification primitives for the Eloquent platform. Today: sending a
|
|
4
|
+
pre-rendered notification email through the API Gateway. Fully typed, zero `any`.
|
|
5
|
+
|
|
6
|
+
> **Building a custom app / using an AI coding agent?** Read [`SKILL.md`](./SKILL.md)
|
|
7
|
+
> — the full agent guide: the one-way architecture (intent → app hook → `useEmail`
|
|
8
|
+
> → gateway → integrations service), the gateway-token flow, and the exact spec of
|
|
9
|
+
> the hook (`useEmail` → `send`). It ships in the package, so the contract is this
|
|
10
|
+
> package's own `.d.ts` — your code type-checks against it.
|
|
11
|
+
|
|
12
|
+
## Installation
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
pnpm add @elqnt/notifications
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## Quick Start
|
|
19
|
+
|
|
20
|
+
```typescript
|
|
21
|
+
import { useEmail } from "@elqnt/notifications/hooks";
|
|
22
|
+
|
|
23
|
+
const { loading, error, send } = useEmail({ baseUrl: apiGatewayUrl, orgId });
|
|
24
|
+
|
|
25
|
+
const res = await send({
|
|
26
|
+
to: ["user@example.com"],
|
|
27
|
+
subject: "Your report is ready",
|
|
28
|
+
body: "<p>Hi — your weekly report is attached.</p>", // already rendered
|
|
29
|
+
});
|
|
30
|
+
// res: SendEmailResponse | null (null on error → check `error`)
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Hook
|
|
34
|
+
|
|
35
|
+
### `useEmail(options)`
|
|
36
|
+
|
|
37
|
+
```typescript
|
|
38
|
+
const {
|
|
39
|
+
loading, // boolean
|
|
40
|
+
error, // string | null
|
|
41
|
+
send, // (request: SendEmailRequest) => Promise<SendEmailResponse | null>
|
|
42
|
+
} = useEmail({ baseUrl, orgId });
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
`send` posts to `POST /api/v1/email/send` (gateway → integrations service). It
|
|
46
|
+
**never throws**: on failure it returns `null` and sets `error`.
|
|
47
|
+
|
|
48
|
+
## Types
|
|
49
|
+
|
|
50
|
+
```typescript
|
|
51
|
+
import type { UseEmailOptions, UseEmailReturn } from "@elqnt/notifications/hooks";
|
|
52
|
+
import type { SendEmailRequest, SendEmailResponse } from "@elqnt/notifications/models";
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
The root `@elqnt/notifications` re-exports the model types only (for SSR/type
|
|
56
|
+
imports). The hook is reached **only** via `@elqnt/notifications/hooks`.
|
package/SKILL.md
ADDED
|
@@ -0,0 +1,328 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: notifications
|
|
3
|
+
description: Send notification emails from a custom frontend on the Eloquent platform using the @elqnt/notifications hooks. Covers the one true path (custom app → useEmail hook → API Gateway → integrations Go service), the gateway-token/secret flow, and the EXACT input/output spec of the hook (useEmail — send) plus all types.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Notifications — Sending Email from a Custom Frontend
|
|
7
|
+
|
|
8
|
+
Eloquent's **notifications** package wraps the platform's outbound notification
|
|
9
|
+
surface. Today it exposes **one** thing: sending a **pre-rendered notification
|
|
10
|
+
email** through the API Gateway to the integrations service. This skill is only
|
|
11
|
+
about driving that through the `@elqnt/notifications` package.
|
|
12
|
+
|
|
13
|
+
> Package is `@elqnt/notifications`. It exports exactly one hook: `useEmail`.
|
|
14
|
+
> The body you send is **already rendered** — `{ to, subject, body }`. The
|
|
15
|
+
> package does not template, queue, schedule, or fan-out; for bulk/newsletter
|
|
16
|
+
> flows the gateway has separate routes (`/api/v1/email/bulk-send`,
|
|
17
|
+
> `/api/v1/newsletter/...`) not yet wrapped by this package.
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
## ⛔ The contract — read this before writing any code
|
|
22
|
+
|
|
23
|
+
This skill ships **inside the package**, so the contract is not a separate file
|
|
24
|
+
to keep in sync — it **is** the package's own published type declarations
|
|
25
|
+
(`@elqnt/notifications` → `dist/**/*.d.ts`). Because your app *imports the real
|
|
26
|
+
hook*, the TypeScript compiler enforces the contract for you: a wrong param or a
|
|
27
|
+
misused return value won't compile.
|
|
28
|
+
|
|
29
|
+
The single source of truth, in order:
|
|
30
|
+
|
|
31
|
+
1. `import { useEmail } from "@elqnt/notifications/hooks"` — the only hook.
|
|
32
|
+
2. `import type { UseEmailOptions, UseEmailReturn } from "@elqnt/notifications/hooks"`
|
|
33
|
+
— the **named, exact** surface of the hook (every method, its params, its
|
|
34
|
+
return type). The table below is a human-readable mirror of these.
|
|
35
|
+
3. `import type { SendEmailRequest, SendEmailResponse } from "@elqnt/notifications/models"`
|
|
36
|
+
— the request/response DTOs. (Also re-exported from the root
|
|
37
|
+
`@elqnt/notifications` for type-only/SSR imports.)
|
|
38
|
+
|
|
39
|
+
**Rules (do not drift):**
|
|
40
|
+
|
|
41
|
+
1. **Use only the exported hook** and only the method it exposes (`send`). Do
|
|
42
|
+
**not** invent hooks, methods, params, or return shapes — if it's not on
|
|
43
|
+
`UseEmailReturn`, it doesn't exist.
|
|
44
|
+
2. **Let the compiler check you.** Build with `tsc`; never `as any` /
|
|
45
|
+
`@ts-ignore` your way around the hook's types.
|
|
46
|
+
3. **Never bypass the hook.** No `fetch`/`axios` to `/api/v1/email/...`, no NATS,
|
|
47
|
+
no direct service calls.
|
|
48
|
+
4. **Wrap, don't scatter.** The hook is imported in exactly one app file
|
|
49
|
+
(`hooks/use-<domain>.ts`); see ["The domain layer"](#the-domain-layer).
|
|
50
|
+
5. **`body` is already rendered.** The package sends what you give it; rendering
|
|
51
|
+
HTML/markdown is the app's job.
|
|
52
|
+
|
|
53
|
+
The prose/table below explains the method; the package's shipped `.d.ts` is what
|
|
54
|
+
your code type-checks against.
|
|
55
|
+
|
|
56
|
+
---
|
|
57
|
+
|
|
58
|
+
## Architecture — the one and only path
|
|
59
|
+
|
|
60
|
+
A component **never** calls the package hook directly. It only sees your **domain
|
|
61
|
+
intent** (e.g. "notify these users"), served by your **app hook**, which is the
|
|
62
|
+
*only* place that wraps `useEmail`.
|
|
63
|
+
|
|
64
|
+
```
|
|
65
|
+
┌──────────────────────────────────────────────────────────────────────────────┐
|
|
66
|
+
│ YOUR CUSTOM APP (Next.js / React) │
|
|
67
|
+
│ │
|
|
68
|
+
│ SSR layout: read API_GATEWAY_URL_PUBLIC (request-time) + ORG_ID │
|
|
69
|
+
│ └─► AppConfigProvider { apiGatewayUrl, orgId } │
|
|
70
|
+
│ │
|
|
71
|
+
│ components/* ── trigger "send a notification" intents │
|
|
72
|
+
│ │ │
|
|
73
|
+
│ ▼ │
|
|
74
|
+
│ hooks/use-notify.ts ── app hook: the only file importing @elqnt/notifications│
|
|
75
|
+
│ │ │
|
|
76
|
+
│ ▼ │
|
|
77
|
+
│ useEmail (@elqnt/notifications/hooks) │
|
|
78
|
+
│ │ │
|
|
79
|
+
│ ▼ │
|
|
80
|
+
│ browserApiRequest (@elqnt/api-client/browser) │
|
|
81
|
+
│ │ getGatewayToken() ⇒ GET /api/gateway-token (mint HS256 JWT, JWT_SECRET)│
|
|
82
|
+
│ │ attaches: Authorization: Bearer <jwt>, X-Org-ID, X-User-ID, X-Product│
|
|
83
|
+
└─────────┼──────────────────────────────────────────────────────────────────────┘
|
|
84
|
+
▼
|
|
85
|
+
┌─────────────────┐ verify JWT, stamp X-Org-ID/X-Product, route match
|
|
86
|
+
│ API GATEWAY │ POST /api/v1/email/send → integrations svc
|
|
87
|
+
└───────┬─────────┘
|
|
88
|
+
▼
|
|
89
|
+
┌─────────────────┐ renders nothing — sends the pre-rendered body
|
|
90
|
+
│ integrations(Go)│ via the configured email provider
|
|
91
|
+
└─────────────────┘
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
Rules: the frontend **never** calls the integrations service directly and
|
|
95
|
+
**never** touches NATS. Every call is HTTP through the gateway carrying an org id
|
|
96
|
+
+ gateway token. And **components never import `@elqnt/notifications`** — only the
|
|
97
|
+
app hook does.
|
|
98
|
+
|
|
99
|
+
---
|
|
100
|
+
|
|
101
|
+
## The gateway token (the secret) — how the custom app gets it
|
|
102
|
+
|
|
103
|
+
Every request to the gateway needs `Authorization: Bearer <token>`: a short-lived
|
|
104
|
+
**HS256 JWT** signed with the shared **gateway secret**. You never hardcode it.
|
|
105
|
+
|
|
106
|
+
### Browser flow (what the hook uses)
|
|
107
|
+
|
|
108
|
+
The hook → `browserApiRequest` → `getGatewayToken()` internally. You do **not**
|
|
109
|
+
pass a token to the hook. `getGatewayToken()` (from `@elqnt/api-client/browser`)
|
|
110
|
+
by default does:
|
|
111
|
+
|
|
112
|
+
```
|
|
113
|
+
fetch("/api/gateway-token") ⇒ { token, expiresIn }
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
So your custom app must expose a **`/api/gateway-token` route** that mints the JWT
|
|
117
|
+
server-side (the secret stays on the server, never reaches the browser). The
|
|
118
|
+
client caches the token and refreshes ~5 min before expiry.
|
|
119
|
+
|
|
120
|
+
```ts
|
|
121
|
+
// app/api/gateway-token/route.ts (Next.js route handler — server only)
|
|
122
|
+
import { NextResponse } from "next/server";
|
|
123
|
+
import * as jose from "jose";
|
|
124
|
+
|
|
125
|
+
export async function GET() {
|
|
126
|
+
const secret = new TextEncoder().encode(process.env.JWT_SECRET!); // SAME secret the gateway validates with
|
|
127
|
+
const token = await new jose.SignJWT({
|
|
128
|
+
org_id: process.env.ORG_ID!,
|
|
129
|
+
user_id: "system",
|
|
130
|
+
email: "system@my-app.com",
|
|
131
|
+
role: "system",
|
|
132
|
+
scopes: ["write:notifications"], // OR-matched against the route's required scopes
|
|
133
|
+
product: "my-product", // gateway resolves product from THIS claim first
|
|
134
|
+
})
|
|
135
|
+
.setProtectedHeader({ alg: "HS256" })
|
|
136
|
+
.setIssuedAt()
|
|
137
|
+
.setIssuer("eloquent-gateway") // must match gateway JWT_ISSUER
|
|
138
|
+
.setAudience("eloquent-api") // must match gateway JWT_AUDIENCE
|
|
139
|
+
.setExpirationTime("1h")
|
|
140
|
+
.sign(secret);
|
|
141
|
+
|
|
142
|
+
return NextResponse.json({ token, expiresIn: 3600 });
|
|
143
|
+
}
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
> The gateway re-stamps `X-Org-ID` / `X-User-ID` / `X-Product` from the **signed
|
|
147
|
+
> JWT claims** before proxying, so a forged header can't override the token — the
|
|
148
|
+
> JWT is authoritative.
|
|
149
|
+
|
|
150
|
+
Override the token source (mobile/native, or a non-default URL) once at startup:
|
|
151
|
+
|
|
152
|
+
```ts
|
|
153
|
+
import { configureAuth } from "@elqnt/api-client/browser";
|
|
154
|
+
configureAuth(async () => myTokenProvider()); // URL string or async () => token|null
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
### Server flow (server actions / SSR)
|
|
158
|
+
|
|
159
|
+
The `useEmail` hook is **browser-only** (`"use client"`). For SSR/server actions,
|
|
160
|
+
send via `@elqnt/api-client/server`'s `createServerClient` (mints the JWT itself
|
|
161
|
+
with `JWT_SECRET` — no `/api/gateway-token` hop) and POST `/api/v1/email/send`
|
|
162
|
+
directly.
|
|
163
|
+
|
|
164
|
+
```ts
|
|
165
|
+
import { createServerClient } from "@elqnt/api-client/server";
|
|
166
|
+
|
|
167
|
+
const client = createServerClient({
|
|
168
|
+
gatewayUrl: process.env.API_GATEWAY_URL_INTERNAL!, // in-cluster gateway URL (server-side)
|
|
169
|
+
jwtSecret: process.env.JWT_SECRET!, // the shared gateway secret
|
|
170
|
+
defaultProduct: "my-product", // gateway reads product from the JWT claim first
|
|
171
|
+
defaultScopes: ["read", "write"],
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
await client.post("/api/v1/email/send",
|
|
175
|
+
{ to: ["user@example.com"], subject: "Welcome", body: "<p>Hi</p>" },
|
|
176
|
+
{ orgId });
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
### Env vars
|
|
180
|
+
|
|
181
|
+
| Var | Used by | Purpose |
|
|
182
|
+
|---|---|---|
|
|
183
|
+
| `JWT_SECRET` | `/api/gateway-token` route + `createServerClient` | sign the gateway JWT (same value the gateway validates with) |
|
|
184
|
+
| `API_GATEWAY_URL_INTERNAL` | `createServerClient` `gatewayUrl` | in-cluster gateway URL (server) |
|
|
185
|
+
| `API_GATEWAY_URL_PUBLIC` | SSR layout → `AppConfigProvider` → browser `baseUrl` | public gateway URL, read **at request time** (not `NEXT_PUBLIC_*`) |
|
|
186
|
+
| `ORG_ID` | token route / app config | the org all requests are scoped to |
|
|
187
|
+
|
|
188
|
+
### Headers the API layer sets per request
|
|
189
|
+
|
|
190
|
+
| From hook option | Header |
|
|
191
|
+
|---|---|
|
|
192
|
+
| auto token | `Authorization: Bearer <token>` |
|
|
193
|
+
| `orgId` | `X-Org-ID` |
|
|
194
|
+
| `userId` | `X-User-ID` |
|
|
195
|
+
| `userEmail` | `X-User-Email` |
|
|
196
|
+
| `product` (default `"eloquent"`) | `X-Product` |
|
|
197
|
+
|
|
198
|
+
---
|
|
199
|
+
|
|
200
|
+
## Hook options
|
|
201
|
+
|
|
202
|
+
There is **no provider/context** in this package. You pass options into the hook
|
|
203
|
+
call. `UseEmailOptions` is the shared `ApiClientOptions`:
|
|
204
|
+
|
|
205
|
+
```ts
|
|
206
|
+
interface ApiClientOptions {
|
|
207
|
+
baseUrl: string; // API Gateway base URL — required
|
|
208
|
+
orgId: string; // required → X-Org-ID
|
|
209
|
+
userId?: string; // → X-User-ID
|
|
210
|
+
userEmail?: string; // → X-User-Email
|
|
211
|
+
product?: string; // → X-Product, defaults to "eloquent"
|
|
212
|
+
headers?: Record<string, string>;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
type UseEmailOptions = ApiClientOptions;
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
> **Imperative, not auto-fetching.** The hook does **not** send anything on
|
|
219
|
+
> mount. You call `send(...)` on demand. The hook exposes `loading` / `error`
|
|
220
|
+
> flags. On failure `send` returns `null` and sets `error` — it does **not**
|
|
221
|
+
> throw.
|
|
222
|
+
|
|
223
|
+
---
|
|
224
|
+
|
|
225
|
+
## Hook: `useEmail`
|
|
226
|
+
|
|
227
|
+
```ts
|
|
228
|
+
import { useEmail } from "@elqnt/notifications/hooks";
|
|
229
|
+
|
|
230
|
+
const email = useEmail({ baseUrl, orgId, product: "my-product" });
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
Returns `{ loading, error, send }` (`UseEmailReturn`):
|
|
234
|
+
|
|
235
|
+
| Member | Signature | Resolves to | Endpoint |
|
|
236
|
+
|---|---|---|---|
|
|
237
|
+
| `loading` | `boolean` | — | — |
|
|
238
|
+
| `error` | `string \| null` | — | — |
|
|
239
|
+
| `send` | `(request: SendEmailRequest) => Promise<SendEmailResponse \| null>` | `null` on error (sets `error`) | `POST /api/v1/email/send` |
|
|
240
|
+
|
|
241
|
+
```ts
|
|
242
|
+
const res = await email.send({
|
|
243
|
+
to: ["user@example.com", "ops@example.com"],
|
|
244
|
+
subject: "Your report is ready",
|
|
245
|
+
body: "<p>Hi — your weekly report is attached.</p>", // already rendered
|
|
246
|
+
});
|
|
247
|
+
if (!res || !res.success) {
|
|
248
|
+
// email.error is set; surface it
|
|
249
|
+
}
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
---
|
|
253
|
+
|
|
254
|
+
## Types (`@elqnt/notifications/models`)
|
|
255
|
+
|
|
256
|
+
> Generated from Go via `tygo generate`. Never edit `models/email.ts` manually.
|
|
257
|
+
|
|
258
|
+
```ts
|
|
259
|
+
/** Request for sending a pre-rendered notification email. */
|
|
260
|
+
interface SendEmailRequest {
|
|
261
|
+
to: string[]; // one or more recipient addresses
|
|
262
|
+
subject: string;
|
|
263
|
+
body: string; // already-rendered HTML/text
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
/** Response from sending an email. */
|
|
267
|
+
interface SendEmailResponse {
|
|
268
|
+
success: boolean;
|
|
269
|
+
message?: string; // provider/error detail when present
|
|
270
|
+
}
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
---
|
|
274
|
+
|
|
275
|
+
## The domain layer
|
|
276
|
+
|
|
277
|
+
Wrap the hook in **one** app file; components speak your intent, not
|
|
278
|
+
`SendEmailRequest`.
|
|
279
|
+
|
|
280
|
+
```ts
|
|
281
|
+
// hooks/use-notify.ts
|
|
282
|
+
"use client";
|
|
283
|
+
import { useEmail } from "@elqnt/notifications/hooks";
|
|
284
|
+
import { useAppConfig } from "@/contexts/app-config-context";
|
|
285
|
+
|
|
286
|
+
export function useNotify() {
|
|
287
|
+
const { apiGatewayUrl, orgId } = useAppConfig();
|
|
288
|
+
const email = useEmail({ baseUrl: apiGatewayUrl, orgId, product: "my-product" });
|
|
289
|
+
|
|
290
|
+
return {
|
|
291
|
+
loading: email.loading,
|
|
292
|
+
error: email.error,
|
|
293
|
+
async notifyReportReady(to: string[], reportName: string): Promise<boolean> {
|
|
294
|
+
const res = await email.send({
|
|
295
|
+
to,
|
|
296
|
+
subject: `Your report "${reportName}" is ready`,
|
|
297
|
+
body: renderReportEmail(reportName), // your app renders the body
|
|
298
|
+
});
|
|
299
|
+
return !!res?.success;
|
|
300
|
+
},
|
|
301
|
+
};
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
export type UseNotifyReturn = ReturnType<typeof useNotify>;
|
|
305
|
+
```
|
|
306
|
+
|
|
307
|
+
`{ apiGatewayUrl, orgId }` come from an `AppConfigProvider` fed by SSR
|
|
308
|
+
(`API_GATEWAY_URL_PUBLIC` read at request time — never a `NEXT_PUBLIC_*` var).
|
|
309
|
+
See the `@elqnt/entity` SKILL.md for the full `AppConfigProvider` pattern.
|
|
310
|
+
|
|
311
|
+
---
|
|
312
|
+
|
|
313
|
+
## Gotchas
|
|
314
|
+
|
|
315
|
+
- **One hook, one method.** Only `useEmail().send`. Bulk-send and newsletter
|
|
316
|
+
flows exist on the gateway but are **not** wrapped here yet — don't invent
|
|
317
|
+
`sendBulk`/`useNewsletter`.
|
|
318
|
+
- **`body` is pre-rendered.** The package/service does not template. Render the
|
|
319
|
+
HTML/text in your app before calling `send`.
|
|
320
|
+
- **`send` doesn't throw.** It returns `null` and sets `error` on failure (and a
|
|
321
|
+
non-null result may still have `success: false` — check it).
|
|
322
|
+
- **Hook is browser-only** (`"use client"`). For SSR/server actions, POST
|
|
323
|
+
`/api/v1/email/send` via `createServerClient` — not the hook.
|
|
324
|
+
- **Root import is models-only.** `@elqnt/notifications` re-exports only the
|
|
325
|
+
types; the hook is reached **only** via `@elqnt/notifications/hooks`. Importing
|
|
326
|
+
the hook from the root would drag `"use client"` into server components.
|
|
327
|
+
- **`product` matters.** The gateway resolves product from the **JWT claim**
|
|
328
|
+
(server) and `X-Product` (browser). It scopes which org/provider config is used.
|
package/dist/hooks/index.d.mts
CHANGED
|
@@ -1,11 +1,31 @@
|
|
|
1
|
+
import { ApiClientOptions } from '@elqnt/api-client/browser';
|
|
1
2
|
import { SendEmailRequest, SendEmailResponse } from '../models/index.mjs';
|
|
2
3
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
4
|
+
/**
|
|
5
|
+
* Options for {@link useEmail}. Extends the shared gateway client options
|
|
6
|
+
* (`baseUrl`, `orgId`, `product`, …) from `@elqnt/api-client`.
|
|
7
|
+
*/
|
|
8
|
+
type UseEmailOptions = ApiClientOptions;
|
|
9
|
+
/**
|
|
10
|
+
* The exact, named contract of {@link useEmail}. Consumers type-check against
|
|
11
|
+
* this published interface — it can't drift from the implementation.
|
|
12
|
+
*
|
|
13
|
+
* Per the SDK hook contract: `{ loading, error, ...methods }`; methods are
|
|
14
|
+
* `async (...args) => Promise<Result>`, call on demand (no fetch-on-mount), and
|
|
15
|
+
* never throw — on failure they resolve to a documented default and set `error`.
|
|
16
|
+
*/
|
|
17
|
+
interface UseEmailReturn {
|
|
18
|
+
/** True while a `send` request is in flight. */
|
|
19
|
+
loading: boolean;
|
|
20
|
+
/** Last error message, or `null`. Cleared at the start of each `send`. */
|
|
21
|
+
error: string | null;
|
|
22
|
+
/**
|
|
23
|
+
* Send a pre-rendered notification email.
|
|
24
|
+
* `POST /api/v1/email/send` (gateway → integrations service).
|
|
25
|
+
* Resolves to the response on success, or `null` on failure (sets `error`).
|
|
26
|
+
*/
|
|
8
27
|
send: (request: SendEmailRequest) => Promise<SendEmailResponse | null>;
|
|
9
|
-
}
|
|
28
|
+
}
|
|
29
|
+
declare function useEmail(options: UseEmailOptions): UseEmailReturn;
|
|
10
30
|
|
|
11
|
-
export { useEmail };
|
|
31
|
+
export { type UseEmailOptions, type UseEmailReturn, useEmail };
|
package/dist/hooks/index.d.ts
CHANGED
|
@@ -1,11 +1,31 @@
|
|
|
1
|
+
import { ApiClientOptions } from '@elqnt/api-client/browser';
|
|
1
2
|
import { SendEmailRequest, SendEmailResponse } from '../models/index.js';
|
|
2
3
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
4
|
+
/**
|
|
5
|
+
* Options for {@link useEmail}. Extends the shared gateway client options
|
|
6
|
+
* (`baseUrl`, `orgId`, `product`, …) from `@elqnt/api-client`.
|
|
7
|
+
*/
|
|
8
|
+
type UseEmailOptions = ApiClientOptions;
|
|
9
|
+
/**
|
|
10
|
+
* The exact, named contract of {@link useEmail}. Consumers type-check against
|
|
11
|
+
* this published interface — it can't drift from the implementation.
|
|
12
|
+
*
|
|
13
|
+
* Per the SDK hook contract: `{ loading, error, ...methods }`; methods are
|
|
14
|
+
* `async (...args) => Promise<Result>`, call on demand (no fetch-on-mount), and
|
|
15
|
+
* never throw — on failure they resolve to a documented default and set `error`.
|
|
16
|
+
*/
|
|
17
|
+
interface UseEmailReturn {
|
|
18
|
+
/** True while a `send` request is in flight. */
|
|
19
|
+
loading: boolean;
|
|
20
|
+
/** Last error message, or `null`. Cleared at the start of each `send`. */
|
|
21
|
+
error: string | null;
|
|
22
|
+
/**
|
|
23
|
+
* Send a pre-rendered notification email.
|
|
24
|
+
* `POST /api/v1/email/send` (gateway → integrations service).
|
|
25
|
+
* Resolves to the response on success, or `null` on failure (sets `error`).
|
|
26
|
+
*/
|
|
8
27
|
send: (request: SendEmailRequest) => Promise<SendEmailResponse | null>;
|
|
9
|
-
}
|
|
28
|
+
}
|
|
29
|
+
declare function useEmail(options: UseEmailOptions): UseEmailReturn;
|
|
10
30
|
|
|
11
|
-
export { useEmail };
|
|
31
|
+
export { type UseEmailOptions, type UseEmailReturn, useEmail };
|
package/dist/hooks/index.js
CHANGED
|
@@ -1,9 +1,38 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports, "__esModule", {value: true});"use client";
|
|
2
|
-
"use client";
|
|
1
|
+
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } }"use client";
|
|
3
2
|
|
|
3
|
+
// hooks/use-email.ts
|
|
4
|
+
var _react = require('react');
|
|
5
|
+
var _browser = require('@elqnt/api-client/browser');
|
|
6
|
+
function useEmail(options) {
|
|
7
|
+
const [loading, setLoading] = _react.useState.call(void 0, false);
|
|
8
|
+
const [error, setError] = _react.useState.call(void 0, null);
|
|
9
|
+
const apiOptions = _react.useMemo.call(void 0, () => ({ ...options }), [options]);
|
|
10
|
+
const send = _react.useCallback.call(void 0,
|
|
11
|
+
async (request) => {
|
|
12
|
+
setLoading(true);
|
|
13
|
+
setError(null);
|
|
14
|
+
try {
|
|
15
|
+
const response = await _browser.browserApiRequest.call(void 0,
|
|
16
|
+
"/api/v1/email/send",
|
|
17
|
+
{
|
|
18
|
+
method: "POST",
|
|
19
|
+
body: request,
|
|
20
|
+
...apiOptions
|
|
21
|
+
}
|
|
22
|
+
);
|
|
23
|
+
return _nullishCoalesce(response.data, () => ( null));
|
|
24
|
+
} catch (e) {
|
|
25
|
+
setError(e instanceof Error ? e.message : "Failed to send email");
|
|
26
|
+
return null;
|
|
27
|
+
} finally {
|
|
28
|
+
setLoading(false);
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
[apiOptions]
|
|
32
|
+
);
|
|
33
|
+
return { loading, error, send };
|
|
34
|
+
}
|
|
4
35
|
|
|
5
|
-
var _chunkE6ORNZJXjs = require('../chunk-E6ORNZJX.js');
|
|
6
36
|
|
|
7
|
-
|
|
8
|
-
exports.useEmail = _chunkE6ORNZJXjs.useEmail;
|
|
37
|
+
exports.useEmail = useEmail;
|
|
9
38
|
//# sourceMappingURL=index.js.map
|
package/dist/hooks/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["/home/runner/work/eloquent
|
|
1
|
+
{"version":3,"sources":["/home/runner/work/eloquent/eloquent/packages/@elqnt/notifications/dist/hooks/index.js","../../hooks/use-email.ts"],"names":[],"mappings":"AAAA,yLAAY;AACZ;AACA;ACAA,8BAA+C;AAC/C,oDAAkC;AA+B3B,SAAS,QAAA,CAAS,OAAA,EAA0C;AACjE,EAAA,MAAM,CAAC,OAAA,EAAS,UAAU,EAAA,EAAI,6BAAA,KAAc,CAAA;AAC5C,EAAA,MAAM,CAAC,KAAA,EAAO,QAAQ,EAAA,EAAI,6BAAA,IAA4B,CAAA;AAEtD,EAAA,MAAM,WAAA,EAAa,4BAAA,CAA0B,EAAA,GAAA,CAAO,EAAE,GAAG,QAAQ,CAAA,CAAA,EAAI,CAAC,OAAO,CAAC,CAAA;AAE9E,EAAA,MAAM,KAAA,EAAO,gCAAA;AAAA,IACX,MAAA,CAAO,OAAA,EAAA,GAAiE;AACtE,MAAA,UAAA,CAAW,IAAI,CAAA;AACf,MAAA,QAAA,CAAS,IAAI,CAAA;AACb,MAAA,IAAI;AACF,QAAA,MAAM,SAAA,EAAW,MAAM,wCAAA;AAAA,UACrB,oBAAA;AAAA,UACA;AAAA,YACE,MAAA,EAAQ,MAAA;AAAA,YACR,IAAA,EAAM,OAAA;AAAA,YACN,GAAG;AAAA,UACL;AAAA,QACF,CAAA;AACA,QAAA,wBAAO,QAAA,CAAS,IAAA,UAAQ,MAAA;AAAA,MAC1B,EAAA,MAAA,CAAS,CAAA,EAAG;AACV,QAAA,QAAA,CAAS,EAAA,WAAa,MAAA,EAAQ,CAAA,CAAE,QAAA,EAAU,sBAAsB,CAAA;AAChE,QAAA,OAAO,IAAA;AAAA,MACT,EAAA,QAAE;AACA,QAAA,UAAA,CAAW,KAAK,CAAA;AAAA,MAClB;AAAA,IACF,CAAA;AAAA,IACA,CAAC,UAAU;AAAA,EACb,CAAA;AAEA,EAAA,OAAO,EAAE,OAAA,EAAS,KAAA,EAAO,KAAK,CAAA;AAChC;AD/BA;AACE;AACF,4BAAC","file":"/home/runner/work/eloquent/eloquent/packages/@elqnt/notifications/dist/hooks/index.js","sourcesContent":[null,"\"use client\";\n\nimport { useCallback, useMemo, useState } from \"react\";\nimport { browserApiRequest } from \"@elqnt/api-client/browser\";\nimport type { ApiClientOptions } from \"@elqnt/api-client/browser\";\nimport type { SendEmailRequest, SendEmailResponse } from \"../models\";\n\n/**\n * Options for {@link useEmail}. Extends the shared gateway client options\n * (`baseUrl`, `orgId`, `product`, …) from `@elqnt/api-client`.\n */\nexport type UseEmailOptions = ApiClientOptions;\n\n/**\n * The exact, named contract of {@link useEmail}. Consumers type-check against\n * this published interface — it can't drift from the implementation.\n *\n * Per the SDK hook contract: `{ loading, error, ...methods }`; methods are\n * `async (...args) => Promise<Result>`, call on demand (no fetch-on-mount), and\n * never throw — on failure they resolve to a documented default and set `error`.\n */\nexport interface UseEmailReturn {\n /** True while a `send` request is in flight. */\n loading: boolean;\n /** Last error message, or `null`. Cleared at the start of each `send`. */\n error: string | null;\n /**\n * Send a pre-rendered notification email.\n * `POST /api/v1/email/send` (gateway → integrations service).\n * Resolves to the response on success, or `null` on failure (sets `error`).\n */\n send: (request: SendEmailRequest) => Promise<SendEmailResponse | null>;\n}\n\nexport function useEmail(options: UseEmailOptions): UseEmailReturn {\n const [loading, setLoading] = useState(false);\n const [error, setError] = useState<string | null>(null);\n\n const apiOptions = useMemo<ApiClientOptions>(() => ({ ...options }), [options]);\n\n const send = useCallback(\n async (request: SendEmailRequest): Promise<SendEmailResponse | null> => {\n setLoading(true);\n setError(null);\n try {\n const response = await browserApiRequest<SendEmailResponse>(\n \"/api/v1/email/send\",\n {\n method: \"POST\",\n body: request,\n ...apiOptions,\n }\n );\n return response.data ?? null;\n } catch (e) {\n setError(e instanceof Error ? e.message : \"Failed to send email\");\n return null;\n } finally {\n setLoading(false);\n }\n },\n [apiOptions]\n );\n\n return { loading, error, send };\n}\n"]}
|
package/dist/hooks/index.mjs
CHANGED
|
@@ -1,8 +1,37 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
} from "
|
|
2
|
+
|
|
3
|
+
// hooks/use-email.ts
|
|
4
|
+
import { useCallback, useMemo, useState } from "react";
|
|
5
|
+
import { browserApiRequest } from "@elqnt/api-client/browser";
|
|
6
|
+
function useEmail(options) {
|
|
7
|
+
const [loading, setLoading] = useState(false);
|
|
8
|
+
const [error, setError] = useState(null);
|
|
9
|
+
const apiOptions = useMemo(() => ({ ...options }), [options]);
|
|
10
|
+
const send = useCallback(
|
|
11
|
+
async (request) => {
|
|
12
|
+
setLoading(true);
|
|
13
|
+
setError(null);
|
|
14
|
+
try {
|
|
15
|
+
const response = await browserApiRequest(
|
|
16
|
+
"/api/v1/email/send",
|
|
17
|
+
{
|
|
18
|
+
method: "POST",
|
|
19
|
+
body: request,
|
|
20
|
+
...apiOptions
|
|
21
|
+
}
|
|
22
|
+
);
|
|
23
|
+
return response.data ?? null;
|
|
24
|
+
} catch (e) {
|
|
25
|
+
setError(e instanceof Error ? e.message : "Failed to send email");
|
|
26
|
+
return null;
|
|
27
|
+
} finally {
|
|
28
|
+
setLoading(false);
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
[apiOptions]
|
|
32
|
+
);
|
|
33
|
+
return { loading, error, send };
|
|
34
|
+
}
|
|
6
35
|
export {
|
|
7
36
|
useEmail
|
|
8
37
|
};
|
package/dist/hooks/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../hooks/use-email.ts"],"sourcesContent":["\"use client\";\n\nimport { useCallback, useMemo, useState } from \"react\";\nimport { browserApiRequest } from \"@elqnt/api-client/browser\";\nimport type { ApiClientOptions } from \"@elqnt/api-client/browser\";\nimport type { SendEmailRequest, SendEmailResponse } from \"../models\";\n\n/**\n * Options for {@link useEmail}. Extends the shared gateway client options\n * (`baseUrl`, `orgId`, `product`, …) from `@elqnt/api-client`.\n */\nexport type UseEmailOptions = ApiClientOptions;\n\n/**\n * The exact, named contract of {@link useEmail}. Consumers type-check against\n * this published interface — it can't drift from the implementation.\n *\n * Per the SDK hook contract: `{ loading, error, ...methods }`; methods are\n * `async (...args) => Promise<Result>`, call on demand (no fetch-on-mount), and\n * never throw — on failure they resolve to a documented default and set `error`.\n */\nexport interface UseEmailReturn {\n /** True while a `send` request is in flight. */\n loading: boolean;\n /** Last error message, or `null`. Cleared at the start of each `send`. */\n error: string | null;\n /**\n * Send a pre-rendered notification email.\n * `POST /api/v1/email/send` (gateway → integrations service).\n * Resolves to the response on success, or `null` on failure (sets `error`).\n */\n send: (request: SendEmailRequest) => Promise<SendEmailResponse | null>;\n}\n\nexport function useEmail(options: UseEmailOptions): UseEmailReturn {\n const [loading, setLoading] = useState(false);\n const [error, setError] = useState<string | null>(null);\n\n const apiOptions = useMemo<ApiClientOptions>(() => ({ ...options }), [options]);\n\n const send = useCallback(\n async (request: SendEmailRequest): Promise<SendEmailResponse | null> => {\n setLoading(true);\n setError(null);\n try {\n const response = await browserApiRequest<SendEmailResponse>(\n \"/api/v1/email/send\",\n {\n method: \"POST\",\n body: request,\n ...apiOptions,\n }\n );\n return response.data ?? null;\n } catch (e) {\n setError(e instanceof Error ? e.message : \"Failed to send email\");\n return null;\n } finally {\n setLoading(false);\n }\n },\n [apiOptions]\n );\n\n return { loading, error, send };\n}\n"],"mappings":";;;AAEA,SAAS,aAAa,SAAS,gBAAgB;AAC/C,SAAS,yBAAyB;AA+B3B,SAAS,SAAS,SAA0C;AACjE,QAAM,CAAC,SAAS,UAAU,IAAI,SAAS,KAAK;AAC5C,QAAM,CAAC,OAAO,QAAQ,IAAI,SAAwB,IAAI;AAEtD,QAAM,aAAa,QAA0B,OAAO,EAAE,GAAG,QAAQ,IAAI,CAAC,OAAO,CAAC;AAE9E,QAAM,OAAO;AAAA,IACX,OAAO,YAAiE;AACtE,iBAAW,IAAI;AACf,eAAS,IAAI;AACb,UAAI;AACF,cAAM,WAAW,MAAM;AAAA,UACrB;AAAA,UACA;AAAA,YACE,QAAQ;AAAA,YACR,MAAM;AAAA,YACN,GAAG;AAAA,UACL;AAAA,QACF;AACA,eAAO,SAAS,QAAQ;AAAA,MAC1B,SAAS,GAAG;AACV,iBAAS,aAAa,QAAQ,EAAE,UAAU,sBAAsB;AAChE,eAAO;AAAA,MACT,UAAE;AACA,mBAAW,KAAK;AAAA,MAClB;AAAA,IACF;AAAA,IACA,CAAC,UAAU;AAAA,EACb;AAEA,SAAO,EAAE,SAAS,OAAO,KAAK;AAChC;","names":[]}
|
package/dist/index.d.mts
CHANGED
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -1,8 +1 @@
|
|
|
1
|
-
"use strict"
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
var _chunkE6ORNZJXjs = require('./chunk-E6ORNZJX.js');
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
exports.useEmail = _chunkE6ORNZJXjs.useEmail;
|
|
8
|
-
//# sourceMappingURL=index.js.map
|
|
1
|
+
"use strict";//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["/home/runner/work/eloquent
|
|
1
|
+
{"version":3,"sources":["/home/runner/work/eloquent/eloquent/packages/@elqnt/notifications/dist/index.js"],"names":[],"mappings":"AAAA","file":"/home/runner/work/eloquent/eloquent/packages/@elqnt/notifications/dist/index.js"}
|
package/dist/index.mjs
CHANGED
package/dist/models/index.js
CHANGED
|
@@ -1,2 +1 @@
|
|
|
1
|
-
"use strict"
|
|
2
|
-
//# sourceMappingURL=index.js.map
|
|
1
|
+
"use strict";//# sourceMappingURL=index.js.map
|
package/dist/models/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["/home/runner/work/eloquent
|
|
1
|
+
{"version":3,"sources":["/home/runner/work/eloquent/eloquent/packages/@elqnt/notifications/dist/models/index.js"],"names":[],"mappings":"AAAA","file":"/home/runner/work/eloquent/eloquent/packages/@elqnt/notifications/dist/models/index.js"}
|
package/dist/models/index.mjs
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@elqnt/notifications",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"description": "Notification infrastructure for Eloquent platform (email, push, SMS)",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"module": "./dist/index.mjs",
|
|
@@ -23,30 +23,31 @@
|
|
|
23
23
|
}
|
|
24
24
|
},
|
|
25
25
|
"files": [
|
|
26
|
-
"dist"
|
|
26
|
+
"dist",
|
|
27
|
+
"SKILL.md"
|
|
27
28
|
],
|
|
28
|
-
"scripts": {
|
|
29
|
-
"build": "tsup",
|
|
30
|
-
"dev": "tsup --watch",
|
|
31
|
-
"clean": "rm -rf dist",
|
|
32
|
-
"typecheck": "tsc --noEmit"
|
|
33
|
-
},
|
|
34
29
|
"repository": {
|
|
35
30
|
"type": "git",
|
|
36
31
|
"url": "git+https://github.com/Blazi-Commerce/eloquent-packages.git",
|
|
37
32
|
"directory": "packages/notifications"
|
|
38
33
|
},
|
|
39
34
|
"dependencies": {
|
|
40
|
-
"@elqnt/api-client": "
|
|
35
|
+
"@elqnt/api-client": "2.2.0"
|
|
41
36
|
},
|
|
42
37
|
"peerDependencies": {
|
|
43
38
|
"react": "^18.0.0 || ^19.0.0"
|
|
44
39
|
},
|
|
45
40
|
"devDependencies": {
|
|
46
|
-
"@elqnt/api-client": "^1.0.0",
|
|
47
41
|
"@types/react": "^19.0.0",
|
|
48
42
|
"react": "^19.0.0",
|
|
49
43
|
"tsup": "^8.0.0",
|
|
50
|
-
"typescript": "^5.0.0"
|
|
44
|
+
"typescript": "^5.0.0",
|
|
45
|
+
"@elqnt/api-client": "2.2.0"
|
|
46
|
+
},
|
|
47
|
+
"scripts": {
|
|
48
|
+
"build": "tsup",
|
|
49
|
+
"dev": "tsup --watch",
|
|
50
|
+
"clean": "rm -rf dist",
|
|
51
|
+
"typecheck": "tsc --noEmit"
|
|
51
52
|
}
|
|
52
|
-
}
|
|
53
|
+
}
|
package/dist/chunk-E6ORNZJX.js
DELETED
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } }"use client";
|
|
2
|
-
|
|
3
|
-
// hooks/use-email.ts
|
|
4
|
-
var _react = require('react');
|
|
5
|
-
var _browser = require('@elqnt/api-client/browser');
|
|
6
|
-
function useEmail(options) {
|
|
7
|
-
const apiOptions = _react.useMemo.call(void 0,
|
|
8
|
-
() => ({ baseUrl: options.baseUrl, orgId: options.orgId }),
|
|
9
|
-
[options.baseUrl, options.orgId]
|
|
10
|
-
);
|
|
11
|
-
const send = _react.useCallback.call(void 0,
|
|
12
|
-
async (request) => {
|
|
13
|
-
try {
|
|
14
|
-
const response = await _browser.browserApiRequest.call(void 0,
|
|
15
|
-
"/api/v1/email/send",
|
|
16
|
-
{
|
|
17
|
-
method: "POST",
|
|
18
|
-
body: request,
|
|
19
|
-
...apiOptions
|
|
20
|
-
}
|
|
21
|
-
);
|
|
22
|
-
return _nullishCoalesce(response.data, () => ( null));
|
|
23
|
-
} catch (e) {
|
|
24
|
-
console.warn("Failed to send email notification");
|
|
25
|
-
return null;
|
|
26
|
-
}
|
|
27
|
-
},
|
|
28
|
-
[apiOptions]
|
|
29
|
-
);
|
|
30
|
-
return { send };
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
exports.useEmail = useEmail;
|
|
36
|
-
//# sourceMappingURL=chunk-E6ORNZJX.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["/home/runner/work/eloquent-packages/eloquent-packages/packages/notifications/dist/chunk-E6ORNZJX.js","../hooks/use-email.ts"],"names":[],"mappings":"AAAA,yLAAY;AACZ;AACA;ACAA,8BAAqC;AACrC,oDAAkC;AAS3B,SAAS,QAAA,CAAS,OAAA,EAA0B;AACjD,EAAA,MAAM,WAAA,EAAa,4BAAA;AAAA,IACjB,CAAA,EAAA,GAAA,CAAO,EAAE,OAAA,EAAS,OAAA,CAAQ,OAAA,EAAS,KAAA,EAAO,OAAA,CAAQ,MAAM,CAAA,CAAA;AAAA,IACxD,CAAC,OAAA,CAAQ,OAAA,EAAS,OAAA,CAAQ,KAAK;AAAA,EACjC,CAAA;AAEA,EAAA,MAAM,KAAA,EAAO,gCAAA;AAAA,IACX,MAAA,CAAO,OAAA,EAAA,GAAiE;AACtE,MAAA,IAAI;AACF,QAAA,MAAM,SAAA,EAAW,MAAM,wCAAA;AAAA,UACrB,oBAAA;AAAA,UACA;AAAA,YACE,MAAA,EAAQ,MAAA;AAAA,YACR,IAAA,EAAM,OAAA;AAAA,YACN,GAAG;AAAA,UACL;AAAA,QACF,CAAA;AACA,QAAA,wBAAO,QAAA,CAAS,IAAA,UAAQ,MAAA;AAAA,MAC1B,EAAA,UAAQ;AACN,QAAA,OAAA,CAAQ,IAAA,CAAK,mCAAmC,CAAA;AAChD,QAAA,OAAO,IAAA;AAAA,MACT;AAAA,IACF,CAAA;AAAA,IACA,CAAC,UAAU;AAAA,EACb,CAAA;AAEA,EAAA,OAAO,EAAE,KAAK,CAAA;AAChB;ADRA;AACA;AACE;AACF,4BAAC","file":"/home/runner/work/eloquent-packages/eloquent-packages/packages/notifications/dist/chunk-E6ORNZJX.js","sourcesContent":[null,"\"use client\";\n\nimport { useCallback, useMemo } from \"react\";\nimport { browserApiRequest } from \"@elqnt/api-client/browser\";\nimport type { ApiClientOptions } from \"@elqnt/api-client/browser\";\nimport type { SendEmailRequest, SendEmailResponse } from \"../models\";\n\ninterface UseEmailOptions {\n baseUrl: string;\n orgId: string;\n}\n\nexport function useEmail(options: UseEmailOptions) {\n const apiOptions = useMemo<ApiClientOptions>(\n () => ({ baseUrl: options.baseUrl, orgId: options.orgId }),\n [options.baseUrl, options.orgId]\n );\n\n const send = useCallback(\n async (request: SendEmailRequest): Promise<SendEmailResponse | null> => {\n try {\n const response = await browserApiRequest<SendEmailResponse>(\n \"/api/v1/email/send\",\n {\n method: \"POST\",\n body: request,\n ...apiOptions,\n }\n );\n return response.data ?? null;\n } catch {\n console.warn(\"Failed to send email notification\");\n return null;\n }\n },\n [apiOptions]\n );\n\n return { send };\n}\n"]}
|
package/dist/chunk-OPXXF4IO.mjs
DELETED
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
"use client";
|
|
2
|
-
|
|
3
|
-
// hooks/use-email.ts
|
|
4
|
-
import { useCallback, useMemo } from "react";
|
|
5
|
-
import { browserApiRequest } from "@elqnt/api-client/browser";
|
|
6
|
-
function useEmail(options) {
|
|
7
|
-
const apiOptions = useMemo(
|
|
8
|
-
() => ({ baseUrl: options.baseUrl, orgId: options.orgId }),
|
|
9
|
-
[options.baseUrl, options.orgId]
|
|
10
|
-
);
|
|
11
|
-
const send = useCallback(
|
|
12
|
-
async (request) => {
|
|
13
|
-
try {
|
|
14
|
-
const response = await browserApiRequest(
|
|
15
|
-
"/api/v1/email/send",
|
|
16
|
-
{
|
|
17
|
-
method: "POST",
|
|
18
|
-
body: request,
|
|
19
|
-
...apiOptions
|
|
20
|
-
}
|
|
21
|
-
);
|
|
22
|
-
return response.data ?? null;
|
|
23
|
-
} catch {
|
|
24
|
-
console.warn("Failed to send email notification");
|
|
25
|
-
return null;
|
|
26
|
-
}
|
|
27
|
-
},
|
|
28
|
-
[apiOptions]
|
|
29
|
-
);
|
|
30
|
-
return { send };
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
export {
|
|
34
|
-
useEmail
|
|
35
|
-
};
|
|
36
|
-
//# sourceMappingURL=chunk-OPXXF4IO.mjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../hooks/use-email.ts"],"sourcesContent":["\"use client\";\n\nimport { useCallback, useMemo } from \"react\";\nimport { browserApiRequest } from \"@elqnt/api-client/browser\";\nimport type { ApiClientOptions } from \"@elqnt/api-client/browser\";\nimport type { SendEmailRequest, SendEmailResponse } from \"../models\";\n\ninterface UseEmailOptions {\n baseUrl: string;\n orgId: string;\n}\n\nexport function useEmail(options: UseEmailOptions) {\n const apiOptions = useMemo<ApiClientOptions>(\n () => ({ baseUrl: options.baseUrl, orgId: options.orgId }),\n [options.baseUrl, options.orgId]\n );\n\n const send = useCallback(\n async (request: SendEmailRequest): Promise<SendEmailResponse | null> => {\n try {\n const response = await browserApiRequest<SendEmailResponse>(\n \"/api/v1/email/send\",\n {\n method: \"POST\",\n body: request,\n ...apiOptions,\n }\n );\n return response.data ?? null;\n } catch {\n console.warn(\"Failed to send email notification\");\n return null;\n }\n },\n [apiOptions]\n );\n\n return { send };\n}\n"],"mappings":";;;AAEA,SAAS,aAAa,eAAe;AACrC,SAAS,yBAAyB;AAS3B,SAAS,SAAS,SAA0B;AACjD,QAAM,aAAa;AAAA,IACjB,OAAO,EAAE,SAAS,QAAQ,SAAS,OAAO,QAAQ,MAAM;AAAA,IACxD,CAAC,QAAQ,SAAS,QAAQ,KAAK;AAAA,EACjC;AAEA,QAAM,OAAO;AAAA,IACX,OAAO,YAAiE;AACtE,UAAI;AACF,cAAM,WAAW,MAAM;AAAA,UACrB;AAAA,UACA;AAAA,YACE,QAAQ;AAAA,YACR,MAAM;AAAA,YACN,GAAG;AAAA,UACL;AAAA,QACF;AACA,eAAO,SAAS,QAAQ;AAAA,MAC1B,QAAQ;AACN,gBAAQ,KAAK,mCAAmC;AAChD,eAAO;AAAA,MACT;AAAA,IACF;AAAA,IACA,CAAC,UAAU;AAAA,EACb;AAEA,SAAO,EAAE,KAAK;AAChB;","names":[]}
|