Skip to content

Commit fa0c02d

Browse files
committed
feat: Include embedUrl in .create return
1 parent 42321d5 commit fa0c02d

4 files changed

Lines changed: 57 additions & 12 deletions

File tree

README.md

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -49,10 +49,10 @@ const png = await szum.render({
4949

5050
## Saved charts
5151

52-
Save a config server-side and embed the returned short URL in an `<img>` tag (Pro plan):
52+
Save a config server-side and embed the returned short URL in an `<img>` tag, or drop the embed URL into an `<iframe>` for an interactive version (Pro plan):
5353

5454
```typescript
55-
const { url, id } = await szum.charts.create({
55+
const { url, embedUrl, id } = await szum.charts.create({
5656
format: "svg",
5757
theme: "editorial",
5858
marks: [
@@ -66,11 +66,12 @@ const { url, id } = await szum.charts.create({
6666
],
6767
});
6868

69-
// Use in HTML: <img src={url} />
69+
// Static image: <img src={url} />
70+
// Interactive embed: <iframe src={embedUrl} />
7071
// Revoke later: await szum.charts.delete(id);
7172
```
7273

73-
The returned URL points at `https://szum.io/c/<id>` and renders the same chart on every fetch.
74+
`url` points at `https://szum.io/c/<id>` and renders the same chart image on every fetch. `embedUrl` points at `https://szum.io/e/<id>` and serves an interactive HTML page with tooltips, legend toggle, and responsive resize.
7475

7576
## Configuration
7677

src/charts.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ export class SzumCharts {
2222
async create(
2323
config: ChartConfig,
2424
options?: RequestOptions,
25-
): Promise<{ url: string; id: string }> {
25+
): Promise<{ url: string; embedUrl: string; id: string }> {
2626
const response = await this.api.request(
2727
"/api/charts",
2828
{
@@ -34,9 +34,10 @@ export class SzumCharts {
3434

3535
const obj = await parseJsonObject(response);
3636
const url = requireString(obj, "url", response);
37+
const embedUrl = requireString(obj, "embedUrl", response);
3738
const id = requireString(obj, "id", response);
3839

39-
return { url, id };
40+
return { url, embedUrl, id };
4041
}
4142

4243
async delete(id: string, options?: RequestOptions): Promise<void> {

src/client.test.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,12 +84,16 @@ describe("Szum (integration)", () => {
8484

8585
describe("charts.create", () => {
8686
it.skipIf(!HAS_API_KEY)(
87-
"returns { url, id } for a valid config",
87+
"returns { url, embedUrl, id } for a valid config",
8888
async () => {
8989
const result = await szum.charts.create(VALID_CONFIG);
9090

9191
expect(typeof result.url).toBe("string");
9292
expect(result.url).toMatch(/^https?:\/\//);
93+
expect(result.url).toContain("/c/");
94+
expect(typeof result.embedUrl).toBe("string");
95+
expect(result.embedUrl).toMatch(/^https?:\/\//);
96+
expect(result.embedUrl).toContain("/e/");
9397
expect(typeof result.id).toBe("string");
9498
expect(result.id.length).toBeGreaterThan(0);
9599
},

src/client.unit.test.ts

Lines changed: 44 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -387,6 +387,7 @@ describe("Szum (unit)", () => {
387387
createMockResponse({
388388
body: JSON.stringify({
389389
url: "https://szum.io/c/abc123",
390+
embedUrl: "https://szum.io/e/abc123",
390391
id: "abc123",
391392
}),
392393
}),
@@ -403,22 +404,31 @@ describe("Szum (unit)", () => {
403404
expect(body.config).toEqual({ ...VALID_CONFIG, version: SCHEMA_VERSION });
404405
});
405406

406-
it("returns { url, id } on success", async () => {
407+
it("returns { url, embedUrl, id } on success", async () => {
407408
const szum = new Szum({
408409
apiKey: "sk_test",
409410
baseUrl: "https://test.szum.io",
410411
});
411412
const expectedUrl = "https://szum.io/c/abc123";
413+
const expectedEmbedUrl = "https://szum.io/e/abc123";
412414
const expectedId = "abc123";
413415
fetchMock.mockResolvedValue(
414416
createMockResponse({
415-
body: JSON.stringify({ url: expectedUrl, id: expectedId }),
417+
body: JSON.stringify({
418+
url: expectedUrl,
419+
embedUrl: expectedEmbedUrl,
420+
id: expectedId,
421+
}),
416422
}),
417423
);
418424

419425
const result = await szum.charts.create(VALID_CONFIG);
420426

421-
expect(result).toEqual({ url: expectedUrl, id: expectedId });
427+
expect(result).toEqual({
428+
url: expectedUrl,
429+
embedUrl: expectedEmbedUrl,
430+
id: expectedId,
431+
});
422432
});
423433

424434
it("throws SzumAPIError when response is missing 'url'", async () => {
@@ -428,7 +438,10 @@ describe("Szum (unit)", () => {
428438
});
429439
fetchMock.mockResolvedValue(
430440
createMockResponse({
431-
body: JSON.stringify({ id: "abc123" }),
441+
body: JSON.stringify({
442+
embedUrl: "https://szum.io/e/abc123",
443+
id: "abc123",
444+
}),
432445
}),
433446
);
434447

@@ -441,14 +454,40 @@ describe("Szum (unit)", () => {
441454
}
442455
});
443456

457+
it("throws SzumAPIError when response is missing 'embedUrl'", async () => {
458+
const szum = new Szum({
459+
apiKey: "sk_test",
460+
baseUrl: "https://test.szum.io",
461+
});
462+
fetchMock.mockResolvedValue(
463+
createMockResponse({
464+
body: JSON.stringify({
465+
url: "https://szum.io/c/abc123",
466+
id: "abc123",
467+
}),
468+
}),
469+
);
470+
471+
try {
472+
await szum.charts.create(VALID_CONFIG);
473+
expect.unreachable("should have thrown");
474+
} catch (err) {
475+
expect(err).toBeInstanceOf(SzumAPIError);
476+
expect((err as SzumError).message).toMatch(/missing 'embedUrl'/);
477+
}
478+
});
479+
444480
it("throws SzumAPIError when response is missing 'id'", async () => {
445481
const szum = new Szum({
446482
apiKey: "sk_test",
447483
baseUrl: "https://test.szum.io",
448484
});
449485
fetchMock.mockResolvedValue(
450486
createMockResponse({
451-
body: JSON.stringify({ url: "https://szum.io/c/abc123" }),
487+
body: JSON.stringify({
488+
url: "https://szum.io/c/abc123",
489+
embedUrl: "https://szum.io/e/abc123",
490+
}),
452491
}),
453492
);
454493

0 commit comments

Comments
 (0)