@mappa-ai/mappa-node 2.0.8 → 2.0.10

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.
Files changed (2) hide show
  1. package/README.md +164 -167
  2. package/package.json +3 -9
package/README.md CHANGED
@@ -1,239 +1,236 @@
1
1
  # @mappa-ai/mappa-node
2
2
 
3
- Official TypeScript SDK for the Mappa API.
3
+ [![npm version](https://img.shields.io/npm/v/@mappa-ai/mappa-node.svg)](https://www.npmjs.com/package/@mappa-ai/mappa-node)
4
+ [![TypeScript](https://img.shields.io/badge/TypeScript-5.0+-blue.svg)](https://www.typescriptlang.org/)
4
5
 
5
- Built for server and worker runtimes. Primary targets are Node.js and Bun.
6
+ Behavioral intelligence for your app. Type-safe. Async-first. Production-ready.
6
7
 
7
- ## Agent + Dev Quickstart
8
+ ## Install
9
+
10
+ ```bash
11
+ # npm
12
+ npm install @mappa-ai/mappa-node
13
+
14
+ # yarn
15
+ yarn add @mappa-ai/mappa-node
8
16
 
9
- - Install package: `npm install @mappa-ai/mappa-node`
10
- - Use server-side only with `MAPPA_API_KEY`
11
- - Validate package changes: `bun run check && bun run type-check && bun test`
12
- - Build distribution artifacts: `bun run build`
13
- - Follow package-specific agent rules: `packages/sdk-ts/AGENTS.md`
17
+ # pnpm
18
+ pnpm add @mappa-ai/mappa-node
19
+
20
+ # bun
21
+ bun add @mappa-ai/mappa-node
22
+ ```
14
23
 
15
24
  ## Runtime support
16
25
 
17
- - Primary: Node.js, Bun
18
- - Compatible: Deno, Cloudflare Workers, other fetch-compatible server/edge runtimes
19
- - Browser: blocked by default to protect secret API keys
26
+ Runs anywhere fetch runs. Node, Bun, Deno, Cloudflare Workers. Browser blocked by default — your API key stays secret.
20
27
 
21
- ## Security model
28
+ ## Security
22
29
 
23
- This SDK is designed for secret API keys.
30
+ Your API key is secret. We enforce it.
24
31
 
25
- - Do not call Mappa directly from browser apps with a private API key
26
- - Put your key in a server or edge function and proxy requests
27
- - The client throws in browser-like runtimes unless you set `dangerouslyAllowBrowser: true`
32
+ - Keep `MAPPA_API_KEY` server-side.
33
+ - Proxy requests through your backend.
34
+ - Browser calls throw unless you set `dangerouslyAllowBrowser: true`.
28
35
 
29
- ## Server proxy pattern
36
+ ## Choose a workflow
30
37
 
31
- Use your backend as a trust boundary:
38
+ Three paths. Pick yours.
32
39
 
33
- - Browser uploads/calls your endpoint
34
- - Your endpoint uses this SDK with `MAPPA_API_KEY`
35
- - Your endpoint returns only safe response fields
40
+ | Method | When to use |
41
+ | --- | --- |
42
+ | `generateFromFile` / `generateFromUrl` | One call. Done. |
43
+ | `createJob` + `webhook` | Fire and forget. We call you. |
44
+ | `createJob` + `wait()` / `stream()` | Stay in control. |
36
45
 
37
- ### Next.js App Router example
46
+ ## Webhooks the production path
38
47
 
39
- ```ts
40
- // app/api/mappa/report/route.ts
41
- import { NextResponse } from "next/server";
42
- import { Mappa, isMappaError } from "@mappa-ai/mappa-node";
43
-
44
- const mappa = new Mappa({ apiKey: process.env.MAPPA_API_KEY! });
45
-
46
- export async function POST(req: Request) {
47
- try {
48
- const form = await req.formData();
49
- const file = form.get("file");
50
-
51
- if (!(file instanceof File)) {
52
- return NextResponse.json({ error: "file is required" }, { status: 400 });
53
- }
54
-
55
- const report = await mappa.reports.generateFromFile({
56
- file,
57
- output: { template: "general_report" },
58
- target: { strategy: "dominant" },
59
- });
60
-
61
- return NextResponse.json({
62
- id: report.id,
63
- template: report.output.template,
64
- summary: report.summary ?? null,
65
- });
66
- } catch (err) {
67
- if (isMappaError(err)) {
68
- return NextResponse.json(
69
- { error: err.message, requestId: err.requestId ?? null },
70
- { status: 502 },
71
- );
72
- }
73
- return NextResponse.json({ error: "Unexpected error" }, { status: 500 });
74
- }
75
- }
76
- ```
48
+ Submit jobs. Move on. Mappa calls your endpoint when it's done. Signatures included.
77
49
 
78
- For advanced flow control, prefer `createJob` + `handle.wait()` or `handle.stream()`.
50
+ ### Publish
79
51
 
80
- ### Framework-agnostic pattern
52
+ One field. That's it.
81
53
 
82
54
  ```ts
83
- // POST /api/report
84
- // 1) Validate auth and input
85
- // 2) Call Mappa on the server
86
- // 3) Return sanitized output
55
+ import { Mappa } from "@mappa-ai/mappa-node"
56
+
57
+ const mappa = new Mappa({ apiKey: process.env.MAPPA_API_KEY! })
58
+
59
+ const receipt = await mappa.reports.createJobFromFile({
60
+ file: audioBlob,
61
+ output: { template: "general_report" },
62
+ target: { strategy: "dominant" },
63
+ webhook: {
64
+ url: "https://your-app.com/api/webhooks/mappa",
65
+ headers: { "x-tenant-id": "tenant_123" },
66
+ },
67
+ })
68
+
69
+ console.log(receipt.jobId)
87
70
  ```
88
71
 
72
+ Already have media uploaded? Same idea.
73
+
89
74
  ```ts
90
- const mappa = new Mappa({ apiKey: process.env.MAPPA_API_KEY! });
91
- const report = await mappa.reports.generateFromFile({
92
- file,
93
- output: { template: "general_report" },
94
- target: { strategy: "dominant" },
95
- });
96
- return { id: report.id, summary: report.summary };
75
+ await mappa.reports.createJob({
76
+ media: { mediaId: "media_abc123" },
77
+ output: { template: "general_report" },
78
+ target: { strategy: "dominant" },
79
+ webhook: { url: "https://your-app.com/api/webhooks/mappa" },
80
+ })
97
81
  ```
98
82
 
99
- ### Security checklist
83
+ ### Consume
100
84
 
101
- - Keep `MAPPA_API_KEY` server-only
102
- - Require auth for proxy endpoints
103
- - Validate input size and type before SDK calls
104
- - Add rate limits on proxy endpoints
105
- - Log `requestId` values from SDK errors for traceability
85
+ Verify. Parse. React.
106
86
 
107
- ## Install
87
+ ```ts
88
+ import { Mappa } from "@mappa-ai/mappa-node"
108
89
 
109
- ```bash
110
- npm install @mappa-ai/mappa-node
111
- ```
90
+ const mappa = new Mappa({ apiKey: process.env.MAPPA_API_KEY! })
112
91
 
113
- ## Quickstart
92
+ export async function POST(req: Request): Promise<Response> {
93
+ const payload = await req.text()
114
94
 
115
- ```ts
116
- import { Mappa } from "@mappa-ai/mappa-node";
95
+ await mappa.webhooks.verifySignature({
96
+ payload,
97
+ headers: Object.fromEntries(req.headers),
98
+ secret: process.env.MAPPA_WEBHOOK_SECRET!,
99
+ })
117
100
 
118
- const mappa = new Mappa({
119
- apiKey: process.env.MAPPA_API_KEY!,
120
- });
101
+ const event = mappa.webhooks.parseEvent(payload)
121
102
 
122
- const media = await mappa.files.upload({
123
- file: new Blob(["...binary..."]),
124
- });
103
+ if (event.type === "report.completed") {
104
+ const report = await mappa.reports.get(event.data.reportId)
105
+ console.log("done", report.id)
106
+ return new Response("ok", { status: 200 })
107
+ }
125
108
 
126
- const receipt = await mappa.reports.createJob({
127
- media: { mediaId: media.mediaId },
128
- output: { template: "general_report" },
129
- target: { strategy: "dominant" },
130
- });
109
+ if (event.type === "report.failed") {
110
+ console.error("failed", event.data.jobId, event.data.error.code)
111
+ return new Response("ok", { status: 200 })
112
+ }
131
113
 
132
- const report = await receipt.handle?.wait();
133
- console.log(report?.id);
114
+ return new Response("ignored", { status: 200 })
115
+ }
134
116
  ```
135
117
 
136
- ## Node filesystem helpers
118
+ ## Polling when you want to wait
137
119
 
138
- For Node/Bun file-path ergonomics, use the Node adapter subpath.
120
+ Sometimes you need the answer now.
121
+
122
+ ### `wait()`
139
123
 
140
124
  ```ts
141
- import { Mappa } from "@mappa-ai/mappa-node";
142
- import { uploadFromPath, generateReportFromPath } from "@mappa-ai/mappa-node/node";
125
+ import { Mappa } from "@mappa-ai/mappa-node"
143
126
 
144
- const mappa = new Mappa({ apiKey: process.env.MAPPA_API_KEY! });
127
+ const mappa = new Mappa({ apiKey: process.env.MAPPA_API_KEY! })
145
128
 
146
- const media = await uploadFromPath(mappa, {
147
- path: "./recording.wav",
148
- });
129
+ const media = await mappa.files.upload({ file: audioBlob })
149
130
 
150
- const report = await generateReportFromPath(mappa, {
151
- path: "./recording.wav",
152
- output: { template: "general_report" },
153
- target: { strategy: "dominant" },
154
- });
131
+ const job = await mappa.reports.createJob({
132
+ media: { mediaId: media.mediaId },
133
+ output: { template: "general_report" },
134
+ target: { strategy: "dominant" },
135
+ })
136
+
137
+ const report = await job.handle?.wait()
138
+ console.log(report?.id)
155
139
  ```
156
140
 
157
- ## Matching analysis
141
+ ### `stream()`
158
142
 
159
143
  ```ts
160
- const job = await mappa.matchingAnalysis.createJob({
161
- entityA: { type: "entity_id", entityId: "entity_a" },
162
- entityB: { type: "entity_id", entityId: "entity_b" },
163
- context: "Compare communication style",
164
- output: { template: "matching_analysis" },
165
- });
166
-
167
- const analysis = await job.handle?.wait();
168
- console.log(analysis?.id);
144
+ for await (const event of job.handle?.stream() ?? []) {
145
+ if (event.type === "stage") {
146
+ console.log(event.stage, event.progress)
147
+ }
148
+ }
169
149
  ```
170
150
 
171
- ## Observability and retries
151
+ ## Helpers
152
+
153
+ ### `generateFromFile`
154
+
155
+ Upload, process, return. One call.
172
156
 
173
157
  ```ts
174
- const mappa = new Mappa({
175
- apiKey: process.env.MAPPA_API_KEY!,
176
- timeoutMs: 30000,
177
- maxRetries: 2,
178
- telemetry: {
179
- onRequest: (ctx) => console.log("req", ctx.method, ctx.url, ctx.requestId),
180
- onResponse: (ctx) => console.log("res", ctx.status, ctx.durationMs),
181
- onError: (ctx) => console.error("err", ctx.requestId, ctx.error),
182
- },
183
- });
158
+ const report = await mappa.reports.generateFromFile({
159
+ file: audioBlob,
160
+ output: { template: "general_report" },
161
+ target: { strategy: "dominant" },
162
+ })
163
+
164
+ console.log(report.id)
184
165
  ```
185
166
 
186
- ## Webhooks
167
+ ### `generateFromUrl`
168
+
169
+ Got a URL? We fetch it.
187
170
 
188
171
  ```ts
189
- const payload = rawBodyString;
172
+ const report = await mappa.reports.generateFromUrl({
173
+ url: "https://example.com/recording.wav",
174
+ output: { template: "general_report" },
175
+ target: { strategy: "dominant" },
176
+ })
190
177
 
191
- await mappa.webhooks.verifySignature({
192
- payload,
193
- headers: req.headers,
194
- secret: process.env.MAPPA_WEBHOOK_SECRET!,
195
- });
178
+ console.log(report.id)
179
+ ```
196
180
 
197
- const event = mappa.webhooks.parseEvent(payload);
198
- if (event.type === "report.completed") {
199
- console.log(event.data.reportId);
200
- }
181
+ ## Node/Bun file paths
182
+
183
+ Working with file paths? Use the `/node` subpath.
184
+
185
+ ```ts
186
+ import { Mappa } from "@mappa-ai/mappa-node"
187
+ import { generateReportFromPath, uploadFromPath } from "@mappa-ai/mappa-node/node"
188
+
189
+ const mappa = new Mappa({ apiKey: process.env.MAPPA_API_KEY! })
190
+
191
+ const media = await uploadFromPath(mappa, { path: "./recording.wav" })
192
+
193
+ const report = await generateReportFromPath(mappa, {
194
+ path: "./recording.wav",
195
+ output: { template: "general_report" },
196
+ target: { strategy: "dominant" },
197
+ })
198
+
199
+ console.log(media.mediaId, report.id)
201
200
  ```
202
201
 
203
202
  ## Error handling
204
203
 
204
+ Things break. We tell you why.
205
+
205
206
  ```ts
206
- import {
207
- isInsufficientCreditsError,
208
- isMappaError,
209
- isStreamError,
210
- } from "@mappa-ai/mappa-node";
207
+ import { isInsufficientCreditsError, isMappaError, isStreamError } from "@mappa-ai/mappa-node"
211
208
 
212
209
  try {
213
- // ...
210
+ // ...
214
211
  } catch (err) {
215
- if (isInsufficientCreditsError(err)) {
216
- console.error(err.required, err.available);
217
- } else if (isStreamError(err)) {
218
- console.error(err.jobId, err.retryCount);
219
- } else if (isMappaError(err)) {
220
- console.error(err.requestId, err.code, err.message);
221
- }
212
+ if (isInsufficientCreditsError(err)) {
213
+ console.error(err.required, err.available)
214
+ return
215
+ }
216
+
217
+ if (isStreamError(err)) {
218
+ console.error(err.jobId, err.retryCount)
219
+ return
220
+ }
221
+
222
+ if (isMappaError(err)) {
223
+ console.error(err.requestId, err.code, err.message)
224
+ }
222
225
  }
223
226
  ```
224
227
 
225
228
  ## Scope
226
229
 
227
- - API-key workflows only
228
- - Includes: health, files, jobs, reports, matching-analysis, feedback, entities, webhooks
229
- - Excludes: billing and user-session console endpoints
230
+ API-key workflows. Reports, files, jobs, webhooks, feedback, entities. Billing lives in the dashboard.
230
231
 
231
- ## Development
232
+ ---
232
233
 
233
- ```bash
234
- bun run build
235
- bun run check
236
- bun run type-check
237
- bun test
238
- ```
234
+ Questions? [api-docs.mappa.ai](https://api-docs.mappa.ai)
239
235
 
236
+ For SDK maintenance, see `README_INTERNAL.md`.
package/package.json CHANGED
@@ -1,16 +1,10 @@
1
1
  {
2
2
  "name": "@mappa-ai/mappa-node",
3
- "version": "2.0.8",
3
+ "version": "2.0.10",
4
4
  "description": "Official TypeScript/Node SDK for the Mappa API",
5
- "license": "MIT",
6
- "repository": {
7
- "type": "git",
8
- "url": "git+https://github.com/mappa-ai/behavioral-engine.git",
9
- "directory": "packages/sdk-ts"
10
- },
11
- "homepage": "https://github.com/mappa-ai/behavioral-engine/tree/main/packages/sdk-ts#readme",
5
+ "homepage": "https://api-docs.mappa.ai",
12
6
  "bugs": {
13
- "url": "https://github.com/mappa-ai/behavioral-engine/issues"
7
+ "url": "https://api-docs.mappa.ai"
14
8
  },
15
9
  "keywords": [
16
10
  "mappa",