docstron 1.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.
@@ -0,0 +1,173 @@
1
+ class Documents {
2
+ constructor(httpClient) {
3
+ this.http = httpClient;
4
+ }
5
+
6
+ /**
7
+ * Generate a PDF document from a template
8
+ * @param {string} templateId - The template ID
9
+ * @param {Object} options - Generation options
10
+ * @param {Object} options.data - Data to populate template placeholders
11
+ * @param {string} [options.response_type='document_id'] - Respose format - 'pdf', 'json_with_base64' or 'document_id'
12
+ * @param {string} [options.password] - Optional password to protect the PDF
13
+ * @returns {Promise<Object|Buffer>} Generated document (format depends om response_type)
14
+ */
15
+
16
+ async generate(templateId, options = {}) {
17
+ if (!templateId) {
18
+ throw new Error('Template ID is required');
19
+ }
20
+
21
+ if (!options.data) {
22
+ throw new Error('Data is required to generate document');
23
+ }
24
+
25
+ const payload = {
26
+ template_id: templateId,
27
+ data: options.data,
28
+ response_type: options.response_type || 'document_id',
29
+ ...(options.password && { password: options.password })
30
+ };
31
+
32
+ // For PDF response_type,
33
+ if (payload.response_type === 'pdf') {
34
+ const response = await this.http.post('/v1/documents/generate', payload, {
35
+ responseType: 'arraybuffer',
36
+ });
37
+ return response;
38
+ }
39
+
40
+ const response = await this.http.post('/v1/documents/generate', payload);
41
+ return response.data;
42
+ }
43
+
44
+ /**
45
+ * Quick generate a PDF without creating a template first
46
+ * @param {Object} options - Quick generation options
47
+ * @param {string} options.html - HTML content with optional placeholders
48
+ * @param {Object} options.data - Data to populate HTML placeholders
49
+ * @param {string} [options.response_type='document_id'] - Response format: 'pdf', 'json_with_base64' or 'document_id'
50
+ * @param {string} [options.extra_css] - Additional CSS styling
51
+ * @param {boolean} [options.save_template=false] - Whether to save as reusable template
52
+ * @param {string} [options.application_id] - Required when save template is true
53
+ * @param {string} [options.password] - Optional password to protect PDF
54
+ * @returns {Promise<Object|Buffer>} Generated Document (format based on response_type)
55
+ */
56
+
57
+ async quickGenerate(options = {}) {
58
+ if (!options.html) {
59
+ throw new Error('HTML content is required');
60
+ }
61
+ if (!options.data) {
62
+ throw new Error('Data is required to generate document');
63
+ }
64
+ if (options.save_template && !options.application_id) {
65
+ throw new Error('application_id is required when save_template is true');
66
+ }
67
+
68
+ // For PDF generation,
69
+ const payload = {
70
+ html: options.html,
71
+ data: options.data,
72
+ response_type: options.response_type || 'document_id',
73
+ ...(options.extra_css && { extra_css: options.extra_css }),
74
+ ...(options.save_template !== undefined && { save_template: options.save_template }),
75
+ ...(options.application_id && { application_id: options.application_id }),
76
+ ...(options.password && { password: options.password })
77
+ }
78
+
79
+ if (payload.response_type === 'pdf') {
80
+ const response = await this.http.post('/v1/documents/quick/generate', payload, {
81
+ responseType: 'arraybuffer'
82
+ });
83
+ return response;
84
+ }
85
+
86
+ const response = await this.http.post('/v1/documents/quick/generate', payload);
87
+ return response.data;
88
+ }
89
+
90
+ /**
91
+ * Get document details by ID
92
+ * @param {string} documentId - the document id
93
+ * @returns {Promise<Object>} Document details
94
+ */
95
+
96
+ async get(documentId) {
97
+ if (!documentId) {
98
+ throw new Error('Document ID is required');
99
+ }
100
+
101
+ const response = await this.http.get(`/v1/documents/${documentId}`);
102
+ return response.data;
103
+ }
104
+
105
+ /**
106
+ * List all documents
107
+ * @returns {Promise<Array>} List of all documents
108
+ */
109
+
110
+ async list() {
111
+ const response = await this.http.get('/v1/documents');
112
+ return response.data;
113
+ }
114
+
115
+ /**
116
+ * Update a document
117
+ * @param {string} documentId - The document ID
118
+ * @param {Object} data - New data to update the document
119
+ * @returns {Promise<Object>} Updated document
120
+ */
121
+
122
+ async update(documentId, data) {
123
+ if (!documentId) {
124
+ throw new Error('Document ID is required');
125
+ }
126
+ if (!data) {
127
+ throw new Error('Data is required to update the document');
128
+ }
129
+
130
+ const response = await this.http.put(`/v1/documents/${documentId}`, { data });
131
+ return response.data;
132
+ }
133
+
134
+ /**
135
+ * Delete a document
136
+ * @param {string} documentId - The document id
137
+ * @returns {Promise<Object>} Deletion confirmation
138
+ */
139
+
140
+ async delete(documentId) {
141
+ if (!documentId) {
142
+ throw new Error('Document ID is required');
143
+ }
144
+ const response = await this.http.delete(`/v1/documents/${documentId}`);
145
+ return response.data;
146
+ }
147
+
148
+ /**
149
+ * Download a document as a PDF
150
+ * @param {string} documentId - The document ID
151
+ * @param {string} [filepath] - Optional file path to save (Node.js only)
152
+ * @returns {Promise<Buffer>} PDF file as buffer
153
+ */
154
+ async download(documentId, filepath) {
155
+ if (!documentId) {
156
+ throw new Error('Document ID is required');
157
+ }
158
+ const response = await this.http.get(`/v1/documents/download/${documentId}`, {
159
+ responseType: 'arraybuffer'
160
+ });
161
+
162
+ // If file path is provided and we're in Node.js, save the file
163
+ if (filepath && typeof require !== undefined) {
164
+ const fs = require('fs');
165
+ fs.writeFileSync(filepath, Buffer.from(response));
166
+ return Buffer.from(response);
167
+ }
168
+
169
+ return Buffer.from(response);
170
+ }
171
+ }
172
+
173
+ module.exports = Documents;
@@ -0,0 +1,97 @@
1
+ class Templates {
2
+ constructor(httpClient) {
3
+ this.http = httpClient;
4
+ }
5
+
6
+
7
+ /**
8
+ * Create a new Template
9
+ * @param {Object} params - Template Parameters
10
+ * @param {string} params.application_id - The application ID
11
+ * @param {string} params.name - Template name
12
+ * @param {string} params.content - HTML content with placeholder
13
+ * @param {boolean} [params.is_active=true] - Whether template is active
14
+ * @param {string} [params.extra_css] - Additiional css styling
15
+ * @returns {Promise<Object>} Cretaed template
16
+ */
17
+
18
+ async create(params) {
19
+ this._validateCreateParams(params);
20
+ const response = await this.http.post('/v1/templates', params);
21
+ return response.data;
22
+ }
23
+
24
+ /**
25
+ * Get a template by ID
26
+ * @param {string} templateId - The template ID
27
+ * @returns {Promise<Object>} Template Details
28
+ */
29
+ async get(templateId) {
30
+ if (!templateId) {
31
+ throw new Error('Template ID is required');
32
+ }
33
+
34
+ const response = await this.http.get(`/v1/templates/${templateId}`);
35
+ return response.data;
36
+ }
37
+
38
+ /**
39
+ * Update an existing template
40
+ * @param {string} templateId - The template ID
41
+ * @param {Object} params - Template parameters to update
42
+ * @returns {Promise<Object>} U*pdated template
43
+ */
44
+ async update(templateId, params) {
45
+ if (!templateId) {
46
+ throw new Error('Template ID is required');
47
+ }
48
+
49
+ const response = await this.http.put(`/v1/templates/${templateId}`, params);
50
+ return response.data;
51
+ }
52
+
53
+ /**
54
+ * Delete a template
55
+ * @param {string} templateId - The template ID
56
+ * @returns {Promise<Object>} Delete Confirmation
57
+ */
58
+
59
+ async delete(templateId) {
60
+ if (!templateId) {
61
+ throw new Error('Template ID is required');
62
+ }
63
+
64
+ const response = await this.http.delete(`/v1/templates/${templateId}`);
65
+ return response.data;
66
+ }
67
+
68
+ /**
69
+ * List all templates for an application
70
+ * @param {string} applicationId - The application ID
71
+ * @returns {Promise<Array>} List of templates
72
+ */
73
+ async list(applicationId) {
74
+ if (!applicationId) {
75
+ throw new Error('Application ID is required');
76
+ }
77
+
78
+ const response = await this.http.get('/v1/templates', {
79
+ params: { application_id: applicationId }
80
+ });
81
+ return response.data;
82
+ }
83
+
84
+ _validateCreateParams(params){
85
+ if(!params.application_id){
86
+ throw new Error('application_id is required');
87
+ }
88
+ if(!params.name){
89
+ throw new Error('name is required');
90
+ }
91
+ if(!params.content){
92
+ throw new Error('content is required');
93
+ }
94
+ }
95
+ }
96
+
97
+ module.exports = Templates;
@@ -0,0 +1,38 @@
1
+ class DocstronError extends Error{
2
+ constructor(message, statusCode, response){
3
+ super(message);
4
+ this.name = 'DocstronError';
5
+ this.statusCode = statusCode;
6
+ this.response = response;
7
+ Error.captureStackTrace(this, this.constructor);
8
+ }
9
+ }
10
+
11
+ class ValidationError extends DocstronError{
12
+ constructor(message, errors){
13
+ super(message, 422, {errors});
14
+ this.name = 'ValidationError';
15
+ this.errors = errors;
16
+ }
17
+ }
18
+
19
+ class AuthenticationError extends DocstronError{
20
+ constructor(message){
21
+ super(message, 401);
22
+ this.name = 'AuthenticationError';
23
+ }
24
+ }
25
+
26
+ class NotFoundError extends DocstronError{
27
+ constructor(message){
28
+ super(message, 404);
29
+ this.name = 'NotFoundError';
30
+ }
31
+ }
32
+
33
+ module.exports = {
34
+ DocstronError,
35
+ ValidationError,
36
+ AuthenticationError,
37
+ NotFoundError,
38
+ }
@@ -0,0 +1,68 @@
1
+ const axios = require('axios');
2
+ const {
3
+ DocstronError,
4
+ ValidationError,
5
+ AuthenticationError,
6
+ NotFoundError
7
+ } = require('./errors');
8
+
9
+ class HttpClient {
10
+ constructor(apiKey, baseURL) {
11
+ this.client = axios.create({
12
+ baseURL: baseURL,
13
+ headers: {
14
+ 'Authorization': `Bearer ${apiKey}`,
15
+ 'Content-Type': 'application/json'
16
+ },
17
+ timeout: 30000
18
+ });
19
+
20
+ this.client.interceptors.response.use(
21
+ (response) => response,
22
+ (error) => {
23
+ if (error.response) {
24
+ const { status, data } = error.response;
25
+ const message = data.message || error.message;
26
+
27
+ switch (status) {
28
+ case 401:
29
+ throw new AuthenticationError(message);
30
+ case 404:
31
+ throw new NotFoundError(message);
32
+ case 422:
33
+ throw new ValidationError(message, data.errors);
34
+ default:
35
+ throw new DocstronError(message, status, data);
36
+ }
37
+ } else if (error.request) {
38
+ throw new DocstronError("No response from server.", 0, null);
39
+ } else {
40
+ throw new DocstronError(error.message, 0, null);
41
+ }
42
+ }
43
+ );
44
+ }
45
+
46
+ async get(url, config = {}) {
47
+ const response = await this.client.get(url, config);
48
+ return response.data;
49
+ }
50
+
51
+ async post(url, data, config = {}) {
52
+ const response = await this.client.post(url, data, config);
53
+ return response.data;
54
+ }
55
+
56
+ async put(url, data, config = {}) {
57
+ const response = await this.client.put(url, data, config);
58
+ return response.data;
59
+ }
60
+
61
+ async delete(url, config = {}) {
62
+ const response = await this.client.delete(url, config);
63
+ return response.data;
64
+ }
65
+ }
66
+
67
+ module.exports = HttpClient;
68
+
package/package.json ADDED
@@ -0,0 +1,42 @@
1
+ {
2
+ "name": "docstron",
3
+ "version": "1.0.0",
4
+ "description": "Node.js SDK for Docstron PDF Generation API - Complete Features",
5
+ "main": "index.js",
6
+ "scripts": {
7
+ "test": "node test/test.js",
8
+ "example": "node examples/basic-usage.js",
9
+ "example:invoice": "node examples/invoice-template.js",
10
+ "example:generate": "node examples/generate-pdf.js",
11
+ "example:quick": "node examples/quick-generate.js",
12
+ "example:existing": "node examples/generate-from-existing-template.js",
13
+ "example:batch": "node examples/batch-generate.js",
14
+ "example:apps": "node examples/manage-applications.js",
15
+ "example:workflow": "node examples/complete-workflow-with-apps.js"
16
+ },
17
+ "keywords": [
18
+ "pdf",
19
+ "pdf-generation",
20
+ "docstron",
21
+ "api-client",
22
+ "document",
23
+ "templates",
24
+ "applications"
25
+ ],
26
+ "author": "CM_Soyza cmsoyza@gmail.com",
27
+ "license": "MIT",
28
+ "repository": {
29
+ "type": "git",
30
+ "url": "https://github.com/ChamithSoyza/doctron-node-sdk"
31
+ },
32
+ "dependencies": {
33
+ "axios": "^1.13.2",
34
+ "dotenv": "^17.2.3"
35
+ },
36
+ "devDependencies": {
37
+ "eslint": "^8.50.0"
38
+ },
39
+ "engines": {
40
+ "node": ">=14.0.0"
41
+ }
42
+ }
package/test/test.js ADDED
@@ -0,0 +1,213 @@
1
+ const Docstron = require('../index');
2
+
3
+ async function runTests() {
4
+ console.log('🧪 Docstron SDK v0.1.0 - Test Suite\n');
5
+
6
+ // Test 1: SDK Version
7
+ console.log('Test 1: Check SDK version');
8
+ try {
9
+ const version = Docstron.getVersion();
10
+ console.log(`✅ Version: ${version}\n`);
11
+ } catch (error) {
12
+ console.log('❌ Failed:', error.message, '\n');
13
+ }
14
+
15
+ // Test 2: Client initialization with API key
16
+ console.log('Test 2: Initialize client with API key');
17
+ try {
18
+ const client = new Docstron('test-api-key');
19
+ console.log('✅ Client initialized successfully');
20
+ console.log(' - Has templates:', typeof client.templates === 'object');
21
+ console.log('');
22
+ } catch (error) {
23
+ console.log('❌ Failed:', error.message, '\n');
24
+ }
25
+
26
+ // Test 3: Client without API key should fail
27
+ console.log('Test 3: Initialize client without API key (should fail)');
28
+ try {
29
+ const client = new Docstron();
30
+ console.log('❌ Should have thrown an error\n');
31
+ } catch (error) {
32
+ console.log('✅ Correctly threw error:', error.message, '\n');
33
+ }
34
+
35
+ // Test 4: Template validation
36
+ console.log('Test 4: Template create validation');
37
+ const client = new Docstron('test-key');
38
+ try {
39
+ await client.templates.create({});
40
+ console.log('❌ Should have thrown validation error\n');
41
+ } catch (error) {
42
+ console.log('✅ Correctly validated required fields:', error.message, '\n');
43
+ }
44
+
45
+ // Test 5: Custom base URL
46
+ console.log('Test 5: Initialize with custom base URL');
47
+ try {
48
+ const customClient = new Docstron('test-key', {
49
+ baseURL: 'https://custom.api.com'
50
+ });
51
+ console.log('✅ Client accepts custom configuration');
52
+ console.log(' - Base URL:', customClient.baseURL, '\n');
53
+ } catch (error) {
54
+ console.log('❌ Failed:', error.message, '\n');
55
+ }
56
+
57
+ // Test 6: Error exports
58
+ console.log('Test 6: Error classes are exported');
59
+ try {
60
+ const {
61
+ DocstronError,
62
+ ValidationError,
63
+ AuthenticationError,
64
+ NotFoundError
65
+ } = require('../index');
66
+
67
+ console.log('✅ All error classes exported:');
68
+ console.log(' - DocstronError:', typeof DocstronError === 'function');
69
+ console.log(' - ValidationError:', typeof ValidationError === 'function');
70
+ console.log(' - AuthenticationError:', typeof AuthenticationError === 'function');
71
+ console.log(' - NotFoundError:', typeof NotFoundError === 'function');
72
+ console.log('');
73
+ } catch (error) {
74
+ console.log('❌ Failed:', error.message, '\n');
75
+ }
76
+
77
+ // Test 7: Documents resource exists
78
+ console.log('Test 7: Documents resource exists');
79
+ try {
80
+ const client = new Docstron('test-key');
81
+ console.log('✅ Documents resource available:', typeof client.documents === 'object');
82
+ console.log(' - Has generate:', typeof client.documents.generate === 'function');
83
+ console.log(' - Has quickGenerate:', typeof client.documents.quickGenerate === 'function');
84
+ console.log(' - Has download:', typeof client.documents.download === 'function');
85
+ console.log('');
86
+ } catch (error) {
87
+ console.log('❌ Failed:', error.message, '\n');
88
+ }
89
+
90
+ // Test 8: Features check
91
+ console.log('Test 8: Check available features');
92
+ try {
93
+ const features = Docstron.getFeatures();
94
+ console.log('✅ Features:', JSON.stringify(features, null, 2));
95
+ console.log('');
96
+ } catch (error) {
97
+ console.log('❌ Failed:', error.message, '\n');
98
+ }
99
+
100
+ // Test 9: Applications resource exists
101
+ console.log('Test 9: Applications resource exists');
102
+ try {
103
+ const client = new Docstron('test-key');
104
+ console.log('✅ Applications resource available:', typeof client.applications === 'object');
105
+ console.log(' - Has create:', typeof client.applications.create === 'function');
106
+ console.log(' - Has get:', typeof client.applications.get === 'function');
107
+ console.log(' - Has list:', typeof client.applications.list === 'function');
108
+ console.log(' - Has update:', typeof client.applications.update === 'function');
109
+ console.log(' - Has delete:', typeof client.applications.delete === 'function');
110
+ console.log('');
111
+ } catch (error) {
112
+ console.log('❌ Failed:', error.message, '\n');
113
+ }
114
+
115
+ console.log('🏁 Test suite completed!\n');
116
+ console.log('⚠️ Note: To test with real API, set DOCSTRON_API_KEY environment variable');
117
+ console.log(' Example: DOCSTRON_API_KEY=your-key node test/test.js\n');
118
+ }
119
+
120
+ // Run the test suite
121
+ runTests().catch(error => {
122
+ console.error('Test suite failed:', error);
123
+ process.exit(1);
124
+ });
125
+
126
+ /*
127
+ const Docstron = require('../index');
128
+
129
+ async function runTests() {
130
+ console.log('🧪 Docstron SDK v0.1.0 - Test Suite\n');
131
+
132
+ // Test 1: SDK Version
133
+ console.log('Test 1: Check SDK version');
134
+ try {
135
+ const version = Docstron.getVersion();
136
+ console.log(`✅ Version: ${version}\n`);
137
+ } catch (error) {
138
+ console.log('❌ Failed:', error.message, '\n');
139
+ }
140
+
141
+ // Test 2: Client initialization with API key
142
+ console.log('Test 2: Initialize client with API key');
143
+ try {
144
+ const client = new Docstron('test-api-key');
145
+ console.log('✅ Client initialized successfully');
146
+ console.log(' - Has templates:', typeof client.templates === 'object');
147
+ console.log('');
148
+ } catch (error) {
149
+ console.log('❌ Failed:', error.message, '\n');
150
+ }
151
+
152
+ // Test 3: Client without API key should fail
153
+ console.log('Test 3: Initialize client without API key (should fail)');
154
+ try {
155
+ const client = new Docstron();
156
+ console.log('❌ Should have thrown an error\n');
157
+ } catch (error) {
158
+ console.log('✅ Correctly threw error:', error.message, '\n');
159
+ }
160
+
161
+ // Test 4: Template validation
162
+ console.log('Test 4: Template create validation');
163
+ const client = new Docstron('test-key');
164
+ try {
165
+ await client.templates.create({});
166
+ console.log('❌ Should have thrown validation error\n');
167
+ } catch (error) {
168
+ console.log('✅ Correctly validated required fields:', error.message, '\n');
169
+ }
170
+
171
+ // Test 5: Custom base URL
172
+ console.log('Test 5: Initialize with custom base URL');
173
+ try {
174
+ const customClient = new Docstron('test-key', {
175
+ baseURL: 'https://custom.api.com'
176
+ });
177
+ console.log('✅ Client accepts custom configuration');
178
+ console.log(' - Base URL:', customClient.baseURL, '\n');
179
+ } catch (error) {
180
+ console.log('❌ Failed:', error.message, '\n');
181
+ }
182
+
183
+ // Test 6: Error exports
184
+ console.log('Test 6: Error classes are exported');
185
+ try {
186
+ const {
187
+ DocstronError,
188
+ ValidationError,
189
+ AuthenticationError,
190
+ NotFoundError
191
+ } = require('../index');
192
+
193
+ console.log('✅ All error classes exported:');
194
+ console.log(' - DocstronError:', typeof DocstronError === 'function');
195
+ console.log(' - ValidationError:', typeof ValidationError === 'function');
196
+ console.log(' - AuthenticationError:', typeof AuthenticationError === 'function');
197
+ console.log(' - NotFoundError:', typeof NotFoundError === 'function');
198
+ console.log('');
199
+ } catch (error) {
200
+ console.log('❌ Failed:', error.message, '\n');
201
+ }
202
+
203
+ console.log('🏁 Test suite completed!\n');
204
+ console.log('⚠️ Note: To test with real API, set DOCSTRON_API_KEY environment variable');
205
+ console.log(' Example: DOCSTRON_API_KEY=your-key node test/test.js\n');
206
+ }
207
+
208
+ // Run the test suite
209
+ runTests().catch(error => {
210
+ console.error('Test suite failed:', error);
211
+ process.exit(1);
212
+ });
213
+ */