@canveletedotcom/sdk 2.0.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 ADDED
@@ -0,0 +1,143 @@
1
+ # Canvelete TypeScript SDK
2
+
3
+ Official TypeScript client library for the [Canvelete](https://www.canvelete.com) API.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install @canvelete/sdk
9
+ ```
10
+
11
+ ## Quick Start
12
+
13
+ ```typescript
14
+ import { CanveleteClient } from '@canvelete/sdk';
15
+
16
+ // Initialize client with API key
17
+ const client = new CanveleteClient({
18
+ apiKey: 'cvt_your_api_key_here'
19
+ });
20
+
21
+ // List designs
22
+ const designs = await client.designs.list();
23
+ console.log(`Found ${designs.data.length} designs`);
24
+
25
+ // Create a design
26
+ const design = await client.designs.create({
27
+ name: 'My Design',
28
+ canvasData: {
29
+ elements: [
30
+ {
31
+ type: 'text',
32
+ text: 'Hello Canvelete!',
33
+ x: 100,
34
+ y: 100,
35
+ fontSize: 48
36
+ }
37
+ ]
38
+ },
39
+ width: 1920,
40
+ height: 1080
41
+ });
42
+
43
+ // Render the design
44
+ const imageData = await client.render.create({
45
+ designId: design.data.id,
46
+ format: 'png',
47
+ outputFile: 'output.png'
48
+ });
49
+ ```
50
+
51
+ ## API Reference
52
+
53
+ ### Designs
54
+
55
+ ```typescript
56
+ // List with pagination
57
+ const designs = await client.designs.list({ page: 1, limit: 20 });
58
+
59
+ // Iterate all (auto-pagination)
60
+ for await (const design of client.designs.iterateAll()) {
61
+ console.log(design.name);
62
+ }
63
+
64
+ // Create
65
+ const design = await client.designs.create({ name: 'New Design', canvasData: {...} });
66
+
67
+ // Get
68
+ const design = await client.designs.get('design_id');
69
+
70
+ // Update
71
+ const updated = await client.designs.update('design_id', { name: 'Updated' });
72
+
73
+ // Delete
74
+ await client.designs.delete('design_id');
75
+ ```
76
+
77
+ ### Templates
78
+
79
+ ```typescript
80
+ // List templates
81
+ const templates = await client.templates.list({ search: 'certificate' });
82
+
83
+ // Iterate all
84
+ for await (const template of client.templates.iterateAll()) {
85
+ console.log(template.name);
86
+ }
87
+ ```
88
+
89
+ ### Render
90
+
91
+ ```typescript
92
+ // Render to file
93
+ await client.render.create({
94
+ templateId: 'template_id',
95
+ dynamicData: { name: 'John Doe', date: '2024-01-01' },
96
+ format: 'pdf',
97
+ outputFile: 'certificate.pdf'
98
+ });
99
+
100
+ // Get binary data
101
+ const imageBuffer = await client.render.create({
102
+ designId: 'design_id',
103
+ format: 'png'
104
+ });
105
+ ```
106
+
107
+ ### API Keys
108
+
109
+ ```typescript
110
+ // List keys
111
+ const keys = await client.apiKeys.list();
112
+
113
+ // Create new key
114
+ const newKey = await client.apiKeys.create({ name: 'Production Key' });
115
+ console.log(`Save this: ${newKey.data.key}`); // Shown only once!
116
+ ```
117
+
118
+ ## Error Handling
119
+
120
+ ```typescript
121
+ import {
122
+ AuthenticationError,
123
+ NotFoundError,
124
+ RateLimitError,
125
+ ValidationError
126
+ } from '@canvelete/sdk';
127
+
128
+ try {
129
+ const design = await client.designs.get('invalid_id');
130
+ } catch (error) {
131
+ if (error instanceof NotFoundError) {
132
+ console.error('Design not found');
133
+ } else if (error instanceof AuthenticationError) {
134
+ console.error('Invalid API key');
135
+ } else if (error instanceof RateLimitError) {
136
+ console.error(`Rate limited. Retry after ${error.retryAfter}s`);
137
+ }
138
+ }
139
+ ```
140
+
141
+ ## License
142
+
143
+ MIT
@@ -0,0 +1,46 @@
1
+ /**
2
+ * Main Canvelete API Client
3
+ */
4
+ import { DesignsResource } from './resources/designs';
5
+ import { TemplatesResource } from './resources/templates';
6
+ import { RenderResource } from './resources/render';
7
+ import { APIKeysResource } from './resources/apiKeys';
8
+ import { CanvasResource } from './resources/canvas';
9
+ import { AssetsResource } from './resources/assets';
10
+ import { UsageResource } from './resources/usage';
11
+ import { BillingResource } from './resources/billing';
12
+ import type { ClientOptions } from './types';
13
+ export interface RequestOptions {
14
+ params?: Record<string, string>;
15
+ json?: Record<string, any>;
16
+ binary?: boolean;
17
+ }
18
+ export declare class CanveleteClient {
19
+ private apiKey;
20
+ private baseUrl;
21
+ private timeout;
22
+ designs: DesignsResource;
23
+ templates: TemplatesResource;
24
+ render: RenderResource;
25
+ apiKeys: APIKeysResource;
26
+ canvas: CanvasResource;
27
+ assets: AssetsResource;
28
+ usage: UsageResource;
29
+ billing: BillingResource;
30
+ /**
31
+ * Initialize the Canvelete client
32
+ */
33
+ constructor(options?: ClientOptions);
34
+ /**
35
+ * Get authentication headers
36
+ */
37
+ private getAuthHeaders;
38
+ /**
39
+ * Make an authenticated API request
40
+ */
41
+ request<T>(method: string, endpoint: string, options?: RequestOptions): Promise<T>;
42
+ /**
43
+ * Handle HTTP error responses
44
+ */
45
+ private handleResponseErrors;
46
+ }
package/dist/client.js ADDED
@@ -0,0 +1,132 @@
1
+ /**
2
+ * Main Canvelete API Client
3
+ */
4
+ import { DesignsResource } from './resources/designs';
5
+ import { TemplatesResource } from './resources/templates';
6
+ import { RenderResource } from './resources/render';
7
+ import { APIKeysResource } from './resources/apiKeys';
8
+ import { CanvasResource } from './resources/canvas';
9
+ import { AssetsResource } from './resources/assets';
10
+ import { UsageResource } from './resources/usage';
11
+ import { BillingResource } from './resources/billing';
12
+ import { CanveleteError, AuthenticationError, ValidationError, NotFoundError, RateLimitError, ServerError, InsufficientScopeError, } from './errors';
13
+ export class CanveleteClient {
14
+ /**
15
+ * Initialize the Canvelete client
16
+ */
17
+ constructor(options = {}) {
18
+ this.apiKey = options.apiKey || '';
19
+ this.baseUrl = (options.baseUrl || 'https://www.canvelete.com').replace(/\/$/, '');
20
+ this.timeout = options.timeout || 30000;
21
+ // Initialize resource handlers
22
+ this.designs = new DesignsResource(this);
23
+ this.templates = new TemplatesResource(this);
24
+ this.render = new RenderResource(this);
25
+ this.apiKeys = new APIKeysResource(this);
26
+ // Initialize new resources
27
+ this.canvas = new CanvasResource(this);
28
+ this.assets = new AssetsResource(this);
29
+ this.usage = new UsageResource(this);
30
+ this.billing = new BillingResource(this);
31
+ }
32
+ /**
33
+ * Get authentication headers
34
+ */
35
+ getAuthHeaders() {
36
+ const headers = {
37
+ 'Content-Type': 'application/json',
38
+ 'User-Agent': 'canvelete-ts/2.0.0',
39
+ };
40
+ if (this.apiKey) {
41
+ headers['Authorization'] = `Bearer ${this.apiKey}`;
42
+ }
43
+ else {
44
+ throw new AuthenticationError('No API key provided');
45
+ }
46
+ return headers;
47
+ }
48
+ /**
49
+ * Make an authenticated API request
50
+ */
51
+ async request(method, endpoint, options = {}) {
52
+ let url = `${this.baseUrl}${endpoint}`;
53
+ const headers = this.getAuthHeaders();
54
+ // Add query parameters
55
+ if (options.params) {
56
+ const searchParams = new URLSearchParams(options.params);
57
+ url = `${url}?${searchParams}`;
58
+ }
59
+ // Build request options
60
+ const requestOptions = {
61
+ method,
62
+ headers,
63
+ };
64
+ // Add JSON body
65
+ if (options.json) {
66
+ requestOptions.body = JSON.stringify(options.json);
67
+ }
68
+ // Add timeout via AbortController
69
+ const controller = new AbortController();
70
+ const timeoutId = setTimeout(() => controller.abort(), this.timeout);
71
+ requestOptions.signal = controller.signal;
72
+ try {
73
+ const response = await fetch(url, requestOptions);
74
+ clearTimeout(timeoutId);
75
+ await this.handleResponseErrors(response);
76
+ // Return binary data for render endpoints
77
+ if (options.binary) {
78
+ return await response.arrayBuffer();
79
+ }
80
+ // Parse JSON response
81
+ return await response.json();
82
+ }
83
+ catch (error) {
84
+ clearTimeout(timeoutId);
85
+ if (error instanceof Error && error.name === 'AbortError') {
86
+ throw new CanveleteError(`Request timeout after ${this.timeout}ms`);
87
+ }
88
+ if (error instanceof CanveleteError) {
89
+ throw error;
90
+ }
91
+ throw new CanveleteError(`Request failed: ${error.message}`);
92
+ }
93
+ }
94
+ /**
95
+ * Handle HTTP error responses
96
+ */
97
+ async handleResponseErrors(response) {
98
+ if (response.status < 400) {
99
+ return;
100
+ }
101
+ let message = `HTTP ${response.status}`;
102
+ try {
103
+ const errorData = await response.json();
104
+ message = errorData.error || errorData.message || message;
105
+ }
106
+ catch {
107
+ // Ignore JSON parse errors
108
+ }
109
+ // Map status codes to exceptions
110
+ switch (response.status) {
111
+ case 401:
112
+ throw new AuthenticationError(message, 401, response);
113
+ case 403:
114
+ if (message.toLowerCase().includes('scope')) {
115
+ throw new InsufficientScopeError(message, 403, response);
116
+ }
117
+ throw new AuthenticationError(message, 403, response);
118
+ case 404:
119
+ throw new NotFoundError(message, 404, response);
120
+ case 422:
121
+ throw new ValidationError(message, 422, response);
122
+ case 429:
123
+ const retryAfter = response.headers.get('Retry-After');
124
+ throw new RateLimitError(message, retryAfter ? parseInt(retryAfter) : null, 429, response);
125
+ default:
126
+ if (response.status >= 500) {
127
+ throw new ServerError(message, response.status, response);
128
+ }
129
+ throw new CanveleteError(message, response.status, response);
130
+ }
131
+ }
132
+ }
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Custom error classes for Canvelete SDK
3
+ */
4
+ export declare class CanveleteError extends Error {
5
+ statusCode: number | null;
6
+ response: Response | null;
7
+ constructor(message: string, statusCode?: number | null, response?: Response | null);
8
+ }
9
+ export declare class AuthenticationError extends CanveleteError {
10
+ constructor(message: string, statusCode?: number | null, response?: Response | null);
11
+ }
12
+ export declare class ValidationError extends CanveleteError {
13
+ constructor(message: string, statusCode?: number | null, response?: Response | null);
14
+ }
15
+ export declare class NotFoundError extends CanveleteError {
16
+ constructor(message: string, statusCode?: number | null, response?: Response | null);
17
+ }
18
+ export declare class RateLimitError extends CanveleteError {
19
+ retryAfter: number | null;
20
+ constructor(message: string, retryAfter?: number | null, statusCode?: number | null, response?: Response | null);
21
+ }
22
+ export declare class ServerError extends CanveleteError {
23
+ constructor(message: string, statusCode?: number | null, response?: Response | null);
24
+ }
25
+ export declare class InsufficientScopeError extends CanveleteError {
26
+ constructor(message: string, statusCode?: number | null, response?: Response | null);
27
+ }
package/dist/errors.js ADDED
@@ -0,0 +1,48 @@
1
+ /**
2
+ * Custom error classes for Canvelete SDK
3
+ */
4
+ export class CanveleteError extends Error {
5
+ constructor(message, statusCode = null, response = null) {
6
+ super(message);
7
+ this.name = 'CanveleteError';
8
+ this.statusCode = statusCode;
9
+ this.response = response;
10
+ }
11
+ }
12
+ export class AuthenticationError extends CanveleteError {
13
+ constructor(message, statusCode = null, response = null) {
14
+ super(message, statusCode, response);
15
+ this.name = 'AuthenticationError';
16
+ }
17
+ }
18
+ export class ValidationError extends CanveleteError {
19
+ constructor(message, statusCode = null, response = null) {
20
+ super(message, statusCode, response);
21
+ this.name = 'ValidationError';
22
+ }
23
+ }
24
+ export class NotFoundError extends CanveleteError {
25
+ constructor(message, statusCode = null, response = null) {
26
+ super(message, statusCode, response);
27
+ this.name = 'NotFoundError';
28
+ }
29
+ }
30
+ export class RateLimitError extends CanveleteError {
31
+ constructor(message, retryAfter = null, statusCode = null, response = null) {
32
+ super(message, statusCode, response);
33
+ this.name = 'RateLimitError';
34
+ this.retryAfter = retryAfter;
35
+ }
36
+ }
37
+ export class ServerError extends CanveleteError {
38
+ constructor(message, statusCode = null, response = null) {
39
+ super(message, statusCode, response);
40
+ this.name = 'ServerError';
41
+ }
42
+ }
43
+ export class InsufficientScopeError extends CanveleteError {
44
+ constructor(message, statusCode = null, response = null) {
45
+ super(message, statusCode, response);
46
+ this.name = 'InsufficientScopeError';
47
+ }
48
+ }
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Canvelete TypeScript SDK
3
+ * Official TypeScript client library for the Canvelete API
4
+ */
5
+ export { CanveleteClient } from './client';
6
+ export type { RequestOptions } from './client';
7
+ export * from './errors';
8
+ export * from './types';
9
+ export * from './resources';
package/dist/index.js ADDED
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Canvelete TypeScript SDK
3
+ * Official TypeScript client library for the Canvelete API
4
+ */
5
+ export { CanveleteClient } from './client';
6
+ export * from './errors';
7
+ export * from './types';
8
+ export * from './resources';
@@ -0,0 +1,22 @@
1
+ import type { CanveleteClient } from '../client';
2
+ import type { APIKey, PaginatedResponse } from '../types';
3
+ export interface ListAPIKeysOptions {
4
+ page?: number;
5
+ limit?: number;
6
+ }
7
+ export interface CreateAPIKeyData {
8
+ name: string;
9
+ scopes?: string[];
10
+ expiresAt?: string;
11
+ }
12
+ export interface CreateAPIKeyResponse {
13
+ data: APIKey & {
14
+ key: string;
15
+ };
16
+ }
17
+ export declare class APIKeysResource {
18
+ private client;
19
+ constructor(client: CanveleteClient);
20
+ list(options?: ListAPIKeysOptions): Promise<PaginatedResponse<APIKey>>;
21
+ create(data: CreateAPIKeyData): Promise<CreateAPIKeyResponse>;
22
+ }
@@ -0,0 +1,15 @@
1
+ export class APIKeysResource {
2
+ constructor(client) {
3
+ this.client = client;
4
+ }
5
+ async list(options = {}) {
6
+ const params = {
7
+ page: String(options.page || 1),
8
+ limit: String(options.limit || 20),
9
+ };
10
+ return await this.client.request('GET', '/api/automation/api-keys', { params });
11
+ }
12
+ async create(data) {
13
+ return await this.client.request('POST', '/api/automation/api-keys', { json: data });
14
+ }
15
+ }
@@ -0,0 +1,101 @@
1
+ /**
2
+ * Assets resource for managing user assets and searching stock content
3
+ */
4
+ import type { CanveleteClient } from '../client';
5
+ import type { PaginatedResponse } from '../types';
6
+ export interface Asset {
7
+ id: string;
8
+ name: string;
9
+ type: 'IMAGE' | 'FONT' | 'VIDEO' | 'AUDIO';
10
+ url: string;
11
+ format?: string;
12
+ size?: number;
13
+ width?: number;
14
+ height?: number;
15
+ createdAt: string;
16
+ updatedAt: string;
17
+ }
18
+ export interface StockImage {
19
+ id: string;
20
+ tags: string;
21
+ previewURL: string;
22
+ webformatURL: string;
23
+ largeImageURL: string;
24
+ imageWidth: number;
25
+ imageHeight: number;
26
+ }
27
+ export interface Icon {
28
+ id: string;
29
+ name: string;
30
+ url: string;
31
+ tags?: string[];
32
+ }
33
+ export interface Font {
34
+ family: string;
35
+ variants: string[];
36
+ category?: string;
37
+ }
38
+ export interface ListAssetsOptions {
39
+ page?: number;
40
+ limit?: number;
41
+ type?: 'IMAGE' | 'FONT' | 'VIDEO' | 'AUDIO';
42
+ }
43
+ export interface SearchOptions {
44
+ query: string;
45
+ page?: number;
46
+ perPage?: number;
47
+ }
48
+ export declare class AssetsResource {
49
+ private client;
50
+ constructor(client: CanveleteClient);
51
+ /**
52
+ * List user's uploaded assets
53
+ */
54
+ list(options?: ListAssetsOptions): Promise<PaginatedResponse<Asset>>;
55
+ /**
56
+ * Get a specific asset by ID
57
+ */
58
+ get(assetId: string): Promise<{
59
+ data: Asset;
60
+ }>;
61
+ /**
62
+ * Delete an asset
63
+ */
64
+ delete(assetId: string): Promise<{
65
+ success: boolean;
66
+ }>;
67
+ /**
68
+ * Search for stock images from Pixabay
69
+ */
70
+ searchStockImages(options: SearchOptions): Promise<{
71
+ data: StockImage[];
72
+ }>;
73
+ /**
74
+ * Search for icons
75
+ */
76
+ searchIcons(options: SearchOptions): Promise<{
77
+ data: Icon[];
78
+ }>;
79
+ /**
80
+ * Search for clipart
81
+ */
82
+ searchClipart(options: SearchOptions & {
83
+ tag?: string;
84
+ }): Promise<{
85
+ data: any[];
86
+ }>;
87
+ /**
88
+ * Search for illustrations
89
+ */
90
+ searchIllustrations(options: SearchOptions & {
91
+ category?: string;
92
+ }): Promise<{
93
+ data: any[];
94
+ }>;
95
+ /**
96
+ * List available fonts
97
+ */
98
+ listFonts(category?: string): Promise<{
99
+ data: Font[];
100
+ }>;
101
+ }
@@ -0,0 +1,93 @@
1
+ /**
2
+ * Assets resource for managing user assets and searching stock content
3
+ */
4
+ export class AssetsResource {
5
+ constructor(client) {
6
+ this.client = client;
7
+ }
8
+ /**
9
+ * List user's uploaded assets
10
+ */
11
+ async list(options = {}) {
12
+ const params = {
13
+ page: String(options.page || 1),
14
+ limit: String(options.limit || 20),
15
+ };
16
+ if (options.type) {
17
+ params.type = options.type;
18
+ }
19
+ return await this.client.request('GET', '/api/assets/library', { params });
20
+ }
21
+ /**
22
+ * Get a specific asset by ID
23
+ */
24
+ async get(assetId) {
25
+ return await this.client.request('GET', `/api/assets/${assetId}`);
26
+ }
27
+ /**
28
+ * Delete an asset
29
+ */
30
+ async delete(assetId) {
31
+ return await this.client.request('DELETE', `/api/assets/${assetId}`);
32
+ }
33
+ /**
34
+ * Search for stock images from Pixabay
35
+ */
36
+ async searchStockImages(options) {
37
+ const params = {
38
+ query: options.query,
39
+ page: String(options.page || 1),
40
+ perPage: String(options.perPage || 20),
41
+ };
42
+ return await this.client.request('GET', '/api/assets/stock-images', { params });
43
+ }
44
+ /**
45
+ * Search for icons
46
+ */
47
+ async searchIcons(options) {
48
+ const params = {
49
+ query: options.query,
50
+ page: String(options.page || 1),
51
+ perPage: String(options.perPage || 20),
52
+ };
53
+ return await this.client.request('GET', '/api/assets/icons', { params });
54
+ }
55
+ /**
56
+ * Search for clipart
57
+ */
58
+ async searchClipart(options) {
59
+ const params = {
60
+ query: options.query,
61
+ page: String(options.page || 1),
62
+ perPage: String(options.perPage || 20),
63
+ };
64
+ if (options.tag) {
65
+ params.tag = options.tag;
66
+ }
67
+ return await this.client.request('GET', '/api/assets/clipart', { params });
68
+ }
69
+ /**
70
+ * Search for illustrations
71
+ */
72
+ async searchIllustrations(options) {
73
+ const params = {
74
+ query: options.query,
75
+ page: String(options.page || 1),
76
+ perPage: String(options.perPage || 20),
77
+ };
78
+ if (options.category) {
79
+ params.category = options.category;
80
+ }
81
+ return await this.client.request('GET', '/api/assets/illustrations', { params });
82
+ }
83
+ /**
84
+ * List available fonts
85
+ */
86
+ async listFonts(category) {
87
+ const params = {};
88
+ if (category) {
89
+ params.category = category;
90
+ }
91
+ return await this.client.request('GET', '/api/assets/fonts', { params });
92
+ }
93
+ }