@digital-passports/javascript-sdk
Version:
JavaScript SDK for interacting with the Digital Passport Hub REST API.
144 lines (131 loc) • 4.36 kB
JavaScript
// Digital Passport Hub JavaScript SDK
// For more information, see: https://digitalpassporthub.com/api-documentation
const { version } = require('./package.json');
/**
* Custom error for Digital Passport SDK
*/
class DigitalPassportError extends Error {
/**
* @param {string} message
* @param {number} [status]
* @param {any} [details]
*/
constructor(message, status, details) {
super(message);
this.name = 'DigitalPassportError';
this.status = status;
this.details = details;
}
}
const BASE_URL = 'https://api.digitalpassporthub.com/v1/';
/**
* @typedef {Object} DigitalPassportOptions
* @property {string} [apiKey] - API key for authentication
* @property {string} [environment] - Environment (default: 'production')
* @property {Function} [fetch] - Custom fetch implementation
*/
let fetchDefault = undefined;
/**
* Digital Passport SDK
*/
class DigitalPassport {
/**
* @param {DigitalPassportOptions} options
*/
constructor({ apiKey, environment = 'production', fetch } = {}) {
this.apiKey = apiKey || (typeof process !== 'undefined' ? process.env.DIGITAL_PASSPORT_API_KEY : undefined);
if (!this.apiKey) throw new DigitalPassportError('API key is required');
this.environment = environment;
if (fetch) {
this._fetch = fetch;
} else if (typeof window === 'undefined' && typeof require === 'function') {
// Only require node-fetch in Node.js at runtime
if (!fetchDefault) {
try {
fetchDefault = require('node-fetch');
} catch (e) {
fetchDefault = undefined;
}
}
this._fetch = fetchDefault;
} else if (typeof fetch === 'function') {
this._fetch = fetch.bind(globalThis);
} else {
this._fetch = undefined;
}
if (!this._fetch) {
throw new DigitalPassportError('No fetch implementation found. Please provide a fetch function in the options.');
}
}
async _request(path, options = {}) {
const url = BASE_URL + path;
const headers = {
'Authorization': `Bearer ${this.apiKey}`,
'Content-Type': 'application/json',
...(options.headers || {})
};
try {
const response = await this._fetch(url, {
...options,
headers
});
const contentType = response.headers.get('content-type');
let data;
if (contentType && contentType.includes('application/json')) {
data = await response.json();
} else {
data = await response.text();
}
if (!response.ok) {
throw new DigitalPassportError(
`HTTP ${response.status}: ${data && data.message ? data.message : data}`,
response.status,
data
);
}
return data;
} catch (err) {
if (err instanceof DigitalPassportError) throw err;
throw new DigitalPassportError(`Failed to fetch ${url}: ${err.message}`);
}
}
/**
* List all Digital Product Passports
* @returns {Promise<object>} Paginated list of passports
*/
async listPassports() {
return this._request('passports', { method: 'GET' });
}
/**
* Create a new Digital Product Passport
* @param {object} data - Passport data (sku, name, etc.)
* @returns {Promise<object>} Created passport object
*/
async createPassport(data) {
if (!data || !data.sku || !data.name) {
throw new DigitalPassportError('Passport data with sku and name is required');
}
return this._request('passports', {
method: 'POST',
body: JSON.stringify(data)
});
}
/**
* Generate a QR code for a specific passport
* @param {string} passportId - ID of the passport
* @param {object} options - QR code options (size, format)
* @returns {Promise<object>} QR code data
*/
async generateQRCode(passportId, options = {}) {
if (!passportId) throw new DigitalPassportError('passportId is required');
const params = new URLSearchParams(options).toString();
const path = `passports/${passportId}/qrcode${params ? '?' + params : ''}`;
return this._request(path, { method: 'GET' });
}
}
module.exports = {
DigitalPassport,
DigitalPassportError,
version,
default: DigitalPassport
};