Files
jlinc-sdk-node/dist/index.js
2026-04-21 19:19:56 +00:00

263 lines
6.4 KiB
JavaScript

const axios = require("axios");
/**
* @typedef {Object} JLINCConfig
* @property {boolean} [debug]
* @property {string} [systemPrefix]
* @property {string} [defaultAgreementId]
* @property {string|null} [domain]
* @property {string|null} [dataStoreApiUrl]
* @property {string|null} [dataStoreApiKey]
* @property {string|null} [archiveApiUrl]
* @property {string|null} [archiveApiKey]
*/
/**
* @typedef {Object} JLINCProduceEventData
* @property {string} [to]
* @property {string} [from]
* @property {string|null} [agreementId]
* @property {any} [payload]
* @property {any} [auth]
*/
/**
* @typedef {Object} JLINCProcessEventData
* @property {string} [to]
* @property {string} [eventId]
* @property {any} [auth]
*/
/**
* @typedef {Object} JLINCProduceAgreementData
* @property {Array<string>} [requiredSigners]
* @property {string} [signer]
* @property {string} [uri]
* @property {Array<string>} [purposes]
* @property {Array<string>} [caveats]
* @property {Array<string>} [validRoles]
* @property {string} [role]
* @property {any} [auth]
*/
/**
* @typedef {Object} JLINCProcessAgreementData
* @property {string} [agreementId]
* @property {string} [signer]
* @property {string} [role]
* @property {any} [auth]
*/
/**
* @param {JLINCConfig} config - The configuration object for the library
*/
let config = {
debug: false,
systemPrefix: 'my-system',
defaultAgreementId: '00000000-0000-0000-0000-000000000000',
domain: null,
dataStoreApiUrl: null,
dataStoreApiKey: null,
archiveApiUrl: null,
archiveApiKey: null,
}
const entities = new Set();
/**
* @param {string} input
* @returns {string}
*/
function sanitize(input) {
return input.replace(/[^a-zA-Z0-9._-]/g, '_');
}
/**
* @param {string} dir
* @param {any} payload
* @returns {Promise<any>}
*/
async function postToApi(dir, payload) {
const response = await axios.post(
`${config.dataStoreApiUrl}/api/v1/data/${dir}`,
payload,
{
headers: {
'Authorization': `Bearer ${config.dataStoreApiKey}`,
}
}
);
return response.data;
}
/**
* @param {string} entityShortName
* @returns {Promise<string>}
*/
async function setEntity(name) {
const entityShortName = `${config.systemPrefix}-${sanitize(name)}@${config.domain}`;
if (!entities.has(entityShortName)) {
try {
await postToApi(`entity/get`, { shortName: entityShortName });
} catch (e) {
await postToApi(`entity/create`, { shortName: entityShortName });
}
entities.add(entityShortName);
}
return entityShortName
}
/**
* @param {JLINCConfig} data - The configuration object for the application.
*/
function jlincInit(data) {
config = {
...config,
...data,
}
}
async function getDomain() {
if (!config.domain) {
const domains = await postToApi(`entity/domains/get`, {});
config.domain = domains[0];
}
}
/**
* @param {JLINCProduceEventData} data - The data required for producing an event.
*/
async function jlincProduceEvent(data) {
let res = null;
try {
await getDomain();
const senderShortName = await setEntity(data.from)
const recipientShortName = await setEntity(data.to)
const agreementId = data.agreementId ?? config.defaultAgreementId;
const postData = {
type: 'data',
senderShortName,
recipientShortName,
agreementId,
data: data.payload,
archive: {
url: config.archiveApiUrl,
key: config.archiveApiKey,
}
};
if (data.auth) postData.auth = data.auth;
res = await postToApi(`event/produce`, postData);
if (config.debug) {
console.log(JSON.stringify({ res }, null, 2));
}
} catch (error) {
console.error("[JLINC] Failed to produce event:", error.message);
if (config.debug) console.error(error)
}
return res;
}
/**
* @param {JLINCProcessEventData} data - The data required for processing an event.
*/
async function jlincProcessEvent(data) {
let res = null;
try {
await getDomain();
const shortName = await setEntity(data.to)
const postData = {
type: 'data',
shortName,
eventId: data.eventId,
archive: {
url: config.archiveApiUrl,
key: config.archiveApiKey,
}
};
if (data.auth) postData.auth = data.auth;
res = await postToApi(`event/process`, postData);
if (config.debug) {
console.log(JSON.stringify({ res }, null, 2));
}
} catch (error) {
console.error("[JLINC] Failed to process event:", error.message);
if (config.debug) console.error(error)
}
return res;
}
/**
* @param {JLINCProduceAgreementData} data - The data required for producing an agreement.
*/
async function jlincProduceAgreement(data) {
let res = null;
try {
await getDomain();
const shortNames = [];
for (const id of data.requiredSigners) {
shortNames.push(await setEntity(id))
}
const shortName = await setEntity(data.signer)
const postData = {
data: {
uri: data.uri,
purposes: data.purposes,
caveats: data.caveats,
shortNames,
validRoles: data.validRoles,
},
shortName,
role: data.role,
archive: {
url: config.archiveApiUrl,
key: config.archiveApiKey,
}
};
if (data.auth) postData.auth = data.auth;
res = await postToApi(`agreement/produce`, postData);
if (config.debug) {
console.log(JSON.stringify({ res }, null, 2));
}
} catch (error) {
console.error("[JLINC] Failed to produce agreement:", error.message);
if (config.debug) console.error(error)
}
return res;
}
/**
* @param {JLINCProcessAgreementData} data - The data required for processing an agreement.
*/
async function jlincProcessAgreement(data) {
let res = null;
try {
await getDomain();
const shortName = await setEntity(data.signer)
const postData = {
agreementId: data.agreementId,
shortName,
role: data.role,
archive: {
url: config.archiveApiUrl,
key: config.archiveApiKey,
}
};
if (data.auth) postData.auth = data.auth;
res = await postToApi(`agreement/process`, postData);
if (config.debug) {
console.log(JSON.stringify({ res }, null, 2));
}
} catch (error) {
console.error("[JLINC] Failed to process agreement:", error.message);
if (config.debug) console.error(error)
}
return res;
}
module.exports = {
jlincInit,
jlincProduceEvent,
jlincProcessEvent,
jlincProduceAgreement,
jlincProcessAgreement,
}