Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ v1.0.0 includes breaking changes. If you're upgrading from v0.x, see the **[Migr
- **TypeScript Native**: Full type safety with comprehensive type definitions
- **Automatic Retries**: Built-in retry logic with exponential backoff
- **Streaming Support**: Real-time progress updates via Server-Sent Events
- **Raster Mode**: Return PNG output directly on generate and edit, skipping vectorization
- **Input Validation**: Zod-based schema validation for all requests
- **Dual Package**: ESM and CommonJS support

Expand Down Expand Up @@ -76,6 +77,28 @@ for await (const event of stream) {
}
```

### Raster Mode

Pass `raster: true` to `generate` or `edit` to receive a PNG instead of an SVG. This skips vectorization, so it's faster and simpler. In raster mode the response has no `svgUrl`; instead you get `imageUrl` (a temporary URL to the PNG) and `imageUrlExpiresIn`.

```typescript
// Generate a raster PNG instead of an SVG
const result = await client.generate
.configure({
prompt: 'A minimalist mountain landscape',
quality: 'high',
raster: true,
})
.execute();

console.log('Image URL:', result.imageUrl);
console.log('Expires in:', result.imageUrlExpiresIn);

// raster: true also works on client.edit
```

> **Note:** `raster: true` cannot be combined with `storage: true` — raster mode returns temporary URLs only, and the SDK throws if both are set. Set `base64Png: true` if you need the PNG as a Buffer via `result.pngImageData`.

## Available Clients

| Client | Access | Description |
Expand Down
12 changes: 8 additions & 4 deletions docs/sdk-documentation.md
Original file line number Diff line number Diff line change
Expand Up @@ -182,19 +182,22 @@ if (result.svgText) {
| `styleParams` | `StyleParams` | `{}` | Style parameters object |
| `base64Png` | `boolean` | `false` | Include PNG preview in response |
| `svgText` | `boolean` | `false` | Include SVG source code in response |
| `raster` | `boolean` | `false` | Return a raster PNG instead of an SVG, skipping vectorization. The response then contains `imageUrl`/`imageUrlExpiresIn` instead of `svgUrl`, and `svgText` is not produced. Cannot be combined with `storage: true` (the SDK throws a validation error if both are set) |

#### Generation Response Fields

| Field | Type | Description |
|-------|------|-------------|
| `svgUrl` | `string` | URL of the generated SVG |
| `svgUrl` | `string` | URL of the generated SVG. Absent when `raster: true` |
| `imageUrl` | `string \| undefined` | URL of the generated raster PNG (only when `raster: true`; temporary) |
| `imageUrlExpiresIn` | `string \| undefined` | Expiration for the raster PNG URL (only when `raster: true`) |
| `creditCost` | `number` | Credits consumed by the request |
| `quality` | `string` | Quality level used |
| `message` | `string` | API response message |
| `svgUrlExpiresIn` | `number` | Seconds until the SVG URL expires |
| `generationId` | `string` | Unique ID for the generation |
| `pngImageData` | `Buffer \| undefined` | Decoded PNG preview (when `base64Png` is true) |
| `svgText` | `string \| undefined` | SVG source code (when `svgText` is true) |
| `pngImageData` | `Buffer \| undefined` | Decoded PNG preview (when `base64Png` is true; also available in raster mode) |
| `svgText` | `string \| undefined` | SVG source code (when `svgText` is true; not produced when `raster: true`) |
| `revisedPrompt` | `string \| undefined` | Prompt as revised by the model |
| `metadata` | `object` | Additional API metadata |

Expand Down Expand Up @@ -253,8 +256,9 @@ const result2 = await client.edit
| `background` | `'auto' \| 'transparent' \| 'opaque'` | `'auto'` | Background handling |
| `base64Png` | `boolean` | `false` | Include PNG preview in response |
| `svgText` | `boolean` | `false` | Include SVG source code in response |
| `raster` | `boolean` | `false` | Return a raster PNG instead of an SVG, skipping vectorization. The response then contains `imageUrl`/`imageUrlExpiresIn` instead of `svgUrl`, and `svgText` is not produced. Cannot be combined with `storage: true` (the SDK throws a validation error if both are set) |

The response shape is identical to the [Generation Response Fields](#generation-response-fields) table above.
The response shape is identical to the [Generation Response Fields](#generation-response-fields) table above. When `raster: true`, the `svgUrl` field is absent and the response instead exposes `imageUrl` and `imageUrlExpiresIn` (the temporary raster PNG URL and its expiration); `pngImageData` remains available if `base64Png: true` is set.

### Convert Namespace

Expand Down
54 changes: 52 additions & 2 deletions docs/v1-api-documentation.md
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,7 @@ x-api-key: svgmaker-io{your-api-key}
| `aspectRatio` | string | No | `auto` | Aspect ratio: `auto`, `portrait`, `landscape`, or `square` |
| `background` | string | No | `auto` | Background type: `auto`, `transparent`, or `opaque` |
| `storage` | boolean | No | `false` | Whether to save files to cloud storage. When `false`, returns proxy URLs immediately (files not persisted). When `true`, saves files to Firebase Storage. `generationId` is always returned. |
| `raster` | boolean | No | `false` | When `true`, returns a raster PNG instead of an SVG (vectorization is skipped). The response includes `imageUrl` and `imageUrlExpiresIn` instead of `svgUrl`. Cannot be combined with `storage: true` — raster mode returns temporary URLs only. |
| `stream` | boolean | No | `false` | Enable streaming response (Server-Sent Events) |
| `base64Png` | boolean | No | `false` | Include base64-encoded PNG preview in response |
| `svgText` | boolean | No | `false` | Include raw SVG source code as text in response |
Expand Down Expand Up @@ -255,15 +256,40 @@ curl -X POST https://api.svgmaker.io/v1/generate \
}
```

#### Response (raster: true)

When `raster: true`, the endpoint returns a raster PNG instead of an SVG. The `svgUrl` field is absent; the response includes `imageUrl` and `imageUrlExpiresIn` instead. `raster: true` cannot be combined with `storage: true`.

```json
{
"success": true,
"data": {
"creditCost": 3,
"quality": "high",
"message": "Image generated successfully",
"imageUrl": "https://svgmaker.io/api/files/eyJ1cmwiOiJodHRwOi8v...",
"imageUrlExpiresIn": "12h",
"base64Png": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAA..."
},
"metadata": {
"requestId": "req_6-vXlRW6lfD_",
"creditsUsed": 3,
"creditsRemaining": 102.5
}
}
```

#### Response Fields

| Field | Type | Description |
|-------|------|-------------|
| `creditCost` | number | Credits charged for this operation |
| `quality` | string | Quality level used (`low`, `medium`, `high`) |
| `message` | string | Status message (`Image generated successfully` when `storage: false`, `Files stored to cloud successfully` when `storage: true`) |
| `svgUrl` | string | URL to access the generated SVG (proxy URL or persistent URL) |
| `svgUrl` | string | URL to access the generated SVG (proxy URL or persistent URL). Absent when `raster: true`. |
| `svgUrlExpiresIn` | string | Expiration time for proxy URLs (e.g., "12h"). Only present for proxy URLs. |
| `imageUrl` | string | URL to access the generated raster PNG (temporary). Only present when `raster: true`. |
| `imageUrlExpiresIn` | string | Expiration time for the raster PNG URL (e.g., "12h"). Only present when `raster: true`. |
| `generationId` | string | Unique identifier for the generation. Always present. |
| `base64Png` | string | Base64-encoded PNG preview. Only present when `base64Png: true`. |
| `svgText` | string | Raw SVG source code. Only present when `svgText: true`. |
Expand Down Expand Up @@ -297,6 +323,7 @@ x-api-key: svgmaker-io{your-api-key}
| `aspectRatio` | string | No | `auto` | Aspect ratio: `auto`, `portrait`, `landscape`, or `square` |
| `background` | string | No | `auto` | Background type: `auto`, `transparent`, or `opaque` |
| `storage` | string | No | `false` | Whether to save to cloud storage. Pass `"true"` or `"false"` as a string. |
| `raster` | string | No | `false` | When `"true"`, returns a raster PNG instead of an SVG (vectorization is skipped). The response includes `imageUrl` and `imageUrlExpiresIn` instead of `svgUrl`. Cannot be combined with `storage: true` — raster mode returns temporary URLs only. Pass `"true"` or `"false"` as a string. |
| `stream` | string | No | `false` | Enable streaming response. Pass `"true"` or `"false"` as a string. |
| `base64Png` | string | No | `false` | Include base64-encoded PNG preview. Pass `"true"` or `"false"` as a string. |
| `svgText` | string | No | `false` | Include raw SVG source code. Pass `"true"` or `"false"` as a string. |
Expand Down Expand Up @@ -378,9 +405,32 @@ curl -X POST https://api.svgmaker.io/v1/edit \
}
```

#### Response (raster: true)

When `raster: true`, the endpoint returns a raster PNG instead of an SVG. The `svgUrl` field is absent; the response includes `imageUrl` and `imageUrlExpiresIn` instead. `raster: true` cannot be combined with `storage: true`.

```json
{
"success": true,
"data": {
"creditCost": 3,
"quality": "medium",
"message": "Image edited successfully",
"imageUrl": "https://svgmaker.io/api/files/eyJ1cmwiOiJodHRwOi8v...",
"imageUrlExpiresIn": "12h",
"base64Png": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAA..."
},
"metadata": {
"requestId": "req_6-vXlRW6lfD_",
"creditsUsed": 3,
"creditsRemaining": 97.5
}
}
```

#### Response Fields

Same as Generate endpoint (see above).
Same as Generate endpoint (see above). When `raster: true`, the response includes `imageUrl` and `imageUrlExpiresIn` instead of `svgUrl`.

---

Expand Down
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@genwave/svgmaker-sdk",
"version": "1.0.0",
"version": "1.1.0",
"description": "Official Node.js SDK for SVGMaker API",
"main": "./dist/cjs/index.js",
"module": "./dist/esm/index.js",
Expand Down
12 changes: 12 additions & 0 deletions src/clients/EditClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,12 +42,17 @@ const editParamsSchema = z
base64Png: z.boolean().optional(),
svgText: z.boolean().optional(),
model: z.string().optional(),
raster: z.boolean().optional(),
})
.refine(data => data.prompt || data.styleParams, {
message: 'Either prompt or styleParams must be provided',
})
.refine(data => !(data.model && data.quality), {
message: "Cannot specify both 'model' and 'quality'. Use one or the other.",
})
.refine(data => !(data.raster && data.storage), {
message:
"Cannot use 'storage: true' with 'raster: true'. Raster mode returns temporary URLs only.",
});

/**
Expand Down Expand Up @@ -103,6 +108,7 @@ export class EditClient extends BaseClient {
'base64Png',
'svgText',
'model',
'raster',
]);

// Execute request
Expand Down Expand Up @@ -131,6 +137,8 @@ export class EditClient extends BaseClient {
pngImageData,
svgText,
quality: data.quality,
imageUrl: data.imageUrl,
imageUrlExpiresIn: data.imageUrlExpiresIn,
};

this.logger.debug('Image/SVG edit completed', {
Expand Down Expand Up @@ -241,6 +249,10 @@ export class EditClient extends BaseClient {
formData.append('model', client.params.model);
}

if (client.params.raster !== undefined) {
formData.append('raster', String(client.params.raster));
}

// Make request to the streaming endpoint using native fetch
const response = await fetch(`${this.config.baseUrl}/v1/edit`, {
method: 'POST',
Expand Down
7 changes: 7 additions & 0 deletions src/clients/GenerateClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ const generateParamsSchema = z
base64Png: z.boolean().optional(),
svgText: z.boolean().optional(),
model: z.string().optional(),
raster: z.boolean().optional(),
styleParams: z
.object({
style: z
Expand All @@ -44,6 +45,10 @@ const generateParamsSchema = z
})
.refine(data => !(data.model && data.quality), {
message: "Cannot specify both 'model' and 'quality'. Use one or the other.",
})
.refine(data => !(data.raster && data.storage), {
message:
"Cannot use 'storage: true' with 'raster: true'. Raster mode returns temporary URLs only.",
});

/**
Expand Down Expand Up @@ -105,6 +110,8 @@ export class GenerateClient extends BaseClient {
pngImageData: rawResult.pngImageData,
svgText,
quality: rawResult.quality ?? this.params.quality ?? 'medium',
imageUrl: rawResult.imageUrl,
imageUrlExpiresIn: rawResult.imageUrlExpiresIn,
};

this.logger.debug('SVG generation completed', {
Expand Down
24 changes: 20 additions & 4 deletions src/types/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,9 @@ export interface GenerateParams {

/** Optional: Specific AI model ID to use. Cannot be combined with quality. Credits are charged based on the model. */
model?: string;

/** Optional: Return PNG instead of SVG. Skips vectorization. Cannot combine with storage: true. */
raster?: boolean;
}

/**
Expand Down Expand Up @@ -130,6 +133,9 @@ export interface EditParams {

/** Optional: Specific AI model ID to use. Cannot be combined with quality. Credits are charged based on the model. */
model?: string;

/** Optional: Return PNG instead of SVG. Skips vectorization. Cannot combine with storage: true. */
raster?: boolean;
}

/**
Expand Down Expand Up @@ -159,8 +165,8 @@ export type ConvertParams = AiVectorizeParams;
* Base SVGMaker API response
*/
export interface BaseResponse {
/** URL to the generated/edited/converted SVG */
svgUrl: string;
/** URL to the generated/edited/converted SVG (absent in raster mode) */
svgUrl?: string;

/** Number of credits consumed by the operation */
creditCost: number;
Expand All @@ -176,6 +182,12 @@ export interface BaseResponse {

/** Unique identifier for this generation */
generationId?: string;

/** URL to the raster PNG image (only when raster: true) */
imageUrl?: string;

/** Expiration time for the image URL (only when raster: true) */
imageUrlExpiresIn?: string;
}

/**
Expand Down Expand Up @@ -378,8 +390,8 @@ export interface ProcessingStreamEvent extends StreamEventBase {
*/
export interface CompleteStreamEvent extends StreamEventBase {
status: 'complete';
/** URL to the generated/edited/converted SVG */
svgUrl: string;
/** URL to the generated/edited/converted SVG (absent in raster mode) */
svgUrl?: string;
/** SVG source code as text - only when svgText=true */
svgText?: string;
/** Expiration time for the SVG URL */
Expand All @@ -392,6 +404,10 @@ export interface CompleteStreamEvent extends StreamEventBase {
message?: string;
/** Response metadata */
metadata?: ResponseMetadata;
/** URL to the raster PNG image (only when raster: true) */
imageUrl?: string;
/** Expiration time for the image URL (only when raster: true) */
imageUrlExpiresIn?: string;
}

/**
Expand Down
Loading
Loading