{"id":23398908,"url":"https://github.com/firsttimeez/base-acme","last_synced_at":"2026-02-11T14:03:13.688Z","repository":{"id":267402874,"uuid":"901137205","full_name":"FirstTimeEZ/base-acme","owner":"FirstTimeEZ","description":"An asynchronous module for interacting with ACME servers for automated SSL/TLS certificate issuance and management.","archived":false,"fork":false,"pushed_at":"2024-12-19T14:24:49.000Z","size":79,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-10-02T10:58:29.715Z","etag":null,"topics":["acme","acme-ari","acme-v2","ari","async","automated","automation","certificate","challenge","commonjs","es6","information","management","module","renewal","rfc8555","ssl","tls"],"latest_commit_sha":null,"homepage":"https://www.npmjs.com/package/base-acme-client","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/FirstTimeEZ.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2024-12-10T05:30:31.000Z","updated_at":"2024-12-18T12:25:43.000Z","dependencies_parsed_at":"2024-12-10T06:28:18.597Z","dependency_job_id":"6447b23d-89cd-4259-821e-da31d2468149","html_url":"https://github.com/FirstTimeEZ/base-acme","commit_stats":null,"previous_names":["firsttimeez/base-acme"],"tags_count":17,"template":false,"template_full_name":null,"purl":"pkg:github/FirstTimeEZ/base-acme","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/FirstTimeEZ%2Fbase-acme","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/FirstTimeEZ%2Fbase-acme/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/FirstTimeEZ%2Fbase-acme/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/FirstTimeEZ%2Fbase-acme/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/FirstTimeEZ","download_url":"https://codeload.github.com/FirstTimeEZ/base-acme/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/FirstTimeEZ%2Fbase-acme/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29333919,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-11T12:42:24.625Z","status":"ssl_error","status_checked_at":"2026-02-11T12:41:23.344Z","response_time":97,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["acme","acme-ari","acme-v2","ari","async","automated","automation","certificate","challenge","commonjs","es6","information","management","module","renewal","rfc8555","ssl","tls"],"created_at":"2024-12-22T09:49:52.980Z","updated_at":"2026-02-11T14:03:13.673Z","avatar_url":"https://github.com/FirstTimeEZ.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Automatic Certificate Management Environment (ACME)\n\nA module for interacting with [`ACME`](https://datatracker.ietf.org/doc/html/rfc8555) servers for automated SSL/TLS certificate issuance and management.\n\n# Exports\n\n```javascript\nimport * as bac from 'base-acme-client'; // ES6\n```\n\n### newDirectory\n\nFetches the directory information from an `ACME` server.\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cb\u003eShow jsdoc\u003c/b\u003e\u003c/summary\u003e\n\n```javascript\n/**\n * Fetches the directory information from an ACME server.\n * @async\n * \n * @param {string} mainDirectoryUrl - The URL of the ACME server's directory endpoint\n * \n * @returns {Promise\u003cObject\u003e} An object containing the directory information or an error\n * @property {Object|null} get - The parsed directory JSON or null\n * \n * @property {null|Object} error - The error response if the request was unsuccessful\n */\nexport async function newDirectory(mainDirectoryUrl) { /*...*/ }\n```\n\n\u003c/details\u003e\n\n------------\n\n### newNonce\n\nRetrieves a new nonce from the `ACME` server.\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cb\u003eShow jsdoc\u003c/b\u003e\u003c/summary\u003e\n\n```javascript\n/**\n * Retrieves a new nonce from the ACME server.\n * @async\n * \n * @param {string} [newNonceUrl] - ACME Directory URL to fetch a new nonce.\n * \n * @returns {Promise\u003cObject\u003e} An object containing the nonce or error details\n * @property {string|null} nonce - A new replay nonce for subsequent requests\n * \n * @property {null|Object} error - The error response if the request was unsuccessful\n */\nexport async function newNonce(newNonceUrl) { /*...*/ }\n```\n\n\u003c/details\u003e\n\n------------\n\n### createJsonWebKey\n\nCreates a JSON Web Key (JWK) from a public key.\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cb\u003eShow jsdoc\u003c/b\u003e\u003c/summary\u003e\n\n```javascript\n/**\n * Creates a JSON Web Key (JWK) from a public key.\n * @async\n * \n * @param {Object} publicKey - The public key to convert to JWK format\n * \n * @returns {Promise\u003cObject\u003e} An object containing the JWK and its thumbprint\n * @property {Object} key - The JSON Web Key representation\n * @property {string} print - Base64URL encoded thumbprint of the key\n */\nexport async function createJsonWebKey(publicKey) { /*...*/ }\n```\n\n\u003c/details\u003e\n\n------------\n\n### createAccount\n\nCreates a new account on the `ACME` server.\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cb\u003eShow jsdoc\u003c/b\u003e\u003c/summary\u003e\n\n```javascript\n/**\n * Creates a new account on the ACME server.\n * @async\n * \n * @param {string} nonce - The replay nonce from the server\n * @param {string} newAccountUrl - The URL for creating a new account\n * @param {Object} privateKey - The private key for signing the request\n * @param {Object} jsonWebKey - The JSON Web Key representing the account's public key\n * @param {Object} acmeDirectory - The ACME directory containing URLs for ACME operations\n * \n * @returns {Promise\u003cObject\u003e} An object containing the account creation result\n * @property {Object|null} get - The created account details\n * @property {string|null} location - The location URL of the created account\n * @property {string|null} nonce - A new replay nonce for subsequent requests\n * \n * @property {null|Object} error - Error details if account creation fails\n */\nexport async function createAccount(nonce, newAccountUrl, privateKey, jsonWebKey) { /*...*/ }\n```\n\n\u003c/details\u003e\n\n------------\n\n### createOrder\n\nCreates a new order for certificate issuance on the `ACME` server.\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cb\u003eShow jsdoc\u003c/b\u003e\u003c/summary\u003e\n\n```javascript\n/**\n * Creates a new order for certificate issuance on the ACME server.\n * @async\n * \n * @param {string} kid - Key Identifier for the account\n * @param {string} nonce - The replay nonce from the server\n * @param {Object} privateKey - The private key for signing the request\n * @param {string[]} identifiers - Domain names to be included in the certificate\n * @param {Object} acmeDirectory - The ACME directory containing URLs for ACME operations\n * \n * @returns {Promise\u003cObject\u003e} An object containing the order creation result\n * @property {Object|null} get - The created order details\n * @property {string|null} location - The location URL of the created order\n * @property {string|null} nonce - A new replay nonce for subsequent requests\n * \n * @property {null|Object} error - Error details if order creation fails\n */\nexport async function createOrder(kid, nonce, privateKey, newOrderUrl, identifiers) { /*...*/ }\n```\n\n\u003c/details\u003e\n\n------------\n\n### finalizeOrder\n\nFinalizes a certificate order by submitting a Certificate Signing Request (CSR).\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cb\u003eShow jsdoc\u003c/b\u003e\u003c/summary\u003e\n\n```javascript\n/**\n * Finalizes a certificate order by submitting a Certificate Signing Request (CSR).\n * @async\n * \n * @param {string} commonName - The primary domain name for the certificate\n * @param {string} kid - Key Identifier for the account\n * @param {string} nonce - The replay nonce from the server\n * @param {Object} privateKey - The private key for signing the request\n * @param {Object} publicKeySign - Public key used for signing the CSR\n * @param {Object} privateKeySign - Private key used for signing the CSR\n * @param {string} finalizeUrl - The URL for finalizing the order\n * @param {Object} acmeDirectory - The ACME directory containing URLs for ACME operations\n * @param {string[]} dnsNames - Additional DNS names to be included in the certificate\n * \n * @returns {Promise\u003cObject\u003e} An object containing the order finalization result\n * @property {Object|null} get - The finalized order details\n * @property {string|null} location - The location URL of the finalized order\n * @property {string|null} nonce - A new replay nonce for subsequent requests\n * \n * @property {null|Object} error - Error details if finalization fails\n */\nexport async function finalizeOrder(commonName, kid, nonce, privateKey, publicKeySign, privateKeySign, finalizeUrl, dnsNames) { /*...*/ }\n```\n\n\u003c/details\u003e\n\n------------\n\n### postAsGet\n\nPerforms a POST-as-GET request to retrieve order or authorization status.\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cb\u003eShow jsdoc\u003c/b\u003e\u003c/summary\u003e\n\n```javascript\n/**\n * Performs a POST-as-GET request to retrieve order or authorization status.\n * @async\n * \n * @param {string} kid - Key Identifier for the account\n * @param {string} nonce - The replay nonce from the server\n * @param {Object} privateKey - The private key for signing the request\n * @param {string} url - The URL to retrieve status from\n * @param {Object} acmeDirectory - The ACME directory containing URLs for ACME operations\n * \n * @returns {Promise\u003cObject\u003e} An object containing the retrieved information\n * @property {Object|null} get - The retrieved resource details\n * @property {string|null} location - The location URL of the resource\n * @property {string|null} nonce - A new replay nonce for subsequent requests\n * \n * @property {null|Object} error - Error details if retrieval fails\n*/\nexport async function postAsGet(kid, nonce, privateKey, url) { /*...*/ }\n```\n\n\u003c/details\u003e\n\n------------\n\n### postAsGetChal\n\nPerforms a POST-as-GET request for challenges\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cb\u003eShow jsdoc\u003c/b\u003e\u003c/summary\u003e\n\n```javascript\n/**\n * Performs a POST-as-GET request for challenges\n * @async\n * \n * @param {string} kid - Key Identifier for the account\n * @param {string} nonce - The replay nonce from the server\n * @param {Object} privateKey - The private key for signing the request\n * @param {string} url - The URL to retrieve challenge details from\n * @param {Object} acmeDirectory - The ACME directory containing URLs for ACME operations\n * \n * @returns {Promise\u003cObject\u003e} An object containing the challenge details\n * @property {Object|null} get - The retrieved challenge details\n * @property {string|null} location - The location URL of the challenge\n * @property {string|null} nonce - A new replay nonce for subsequent requests\n * \n * @property {null|Object} error - Error details if retrieval fails\n */\nexport async function postAsGetChal(kid, nonce, privateKey, url) { /*...*/ }\n```\n\n\u003c/details\u003e\n\n------------\n\n### signPayloadJson\n\nSigns a JSON payload for `ACME` server requests.\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cb\u003eShow jsdoc\u003c/b\u003e\u003c/summary\u003e\n\n```javascript\n/**\n * Signs a JSON payload for ACME server requests.\n * @async\n * \n * @param {Object} payload - The payload to be signed\n * @param {Object} protectedHeader - The protected header containing metadata\n * @param {Object} privateKey - The private key used for signing\n * \n * @returns {Promise\u003cstring\u003e} A JSON Web Signature (JWS) string\n */\nexport async function signPayloadJson(payload, protectedHeader, privateKey) { /*...*/ }\n```\n\n\u003c/details\u003e\n\n------------\n\n### signPayload\n\nSigns a payload for `ACME` server requests.\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cb\u003eShow jsdoc\u003c/b\u003e\u003c/summary\u003e\n\n```javascript\n/**\n * Signs a payload for ACME server requests.\n * @async\n * \n * @param {string|Object} payload - The payload to be signed\n * @param {Object} protectedHeader - The protected header containing metadata\n * @param {Object} privateKey - The private key used for signing\n * \n * @returns {Promise\u003cstring\u003e} A JSON Web Signature (JWS) string\n */\nexport async function signPayload(payload, protectedHeader, privateKey) { /*...*/ }\n```\n\n\u003c/details\u003e\n\n------------\n\n### formatPublicKey\n\nFormats a PEM-encoded public key to a key object.\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cb\u003eShow jsdoc\u003c/b\u003e\u003c/summary\u003e\n\n```javascript\n/**\n * Formats a PEM-encoded public key to a key object.\n * \n * @param {string} pem - The PEM-encoded public key\n * \n * @returns {Object} A formatted public key object\n */\nexport function formatPublicKey(pem) { /*...*/ }\n```\n\n\u003c/details\u003e\n\n------------\n\n### formatPrivateKey\n\nFormats a PEM-encoded private key to a key object.\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cb\u003eShow jsdoc\u003c/b\u003e\u003c/summary\u003e\n\n```javascript\n/**\n * Formats a PEM-encoded private key to a key object.\n * \n * @param {string} pem - The PEM-encoded private key\n * \n * @returns {Object} A formatted private key object\n */\nexport function formatPrivateKey(pem) { /*...*/ }\n```\n\n\u003c/details\u003e\n\n------------\n\n### base64urlEncode\n\nEncodes input to a base64url-encoded string.\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cb\u003eShow jsdoc\u003c/b\u003e\u003c/summary\u003e\n\n```javascript\n/**\n * Encodes input to a base64url-encoded string.\n *\n * @param {string|Uint8Array} input - The input to encode\n * \n * @returns {string} A base64url-encoded string\n */\nexport function base64urlEncode(input) { /*...*/ }\n```\n\n\u003c/details\u003e\n\n------------\n\n### hexToBytes\n\nConverts a hexadecimal string to a Uint8Array of bytes.\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cb\u003eShow jsdoc\u003c/b\u003e\u003c/summary\u003e\n\n```javascript\n/**\n * Converts a hexadecimal string to a Uint8Array of bytes.\n * \n * @param {string} hex - The hexadecimal string to convert. It should contain an even number of characters.\n * \n * @returns {Uint8Array} A Uint8Array containing the byte values represented by the hexadecimal string.\n * @throws {Error} Throws an error if the input string has an odd length or contains invalid hexadecimal characters.\n */\nexport function hexToBytes(hex) { /*...*/ }\n```\n\n\u003c/details\u003e\n\n------------\n\n### getNextNonce\n\nRetrieves the next nonce for ACME protocol requests.\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cb\u003eShow jsdoc\u003c/b\u003e\u003c/summary\u003e\n\n```javascript\n/**\n * Retrieves the next nonce for ACME protocol requests.\n *\n * If a replay nonce is provided in the headers, it will return that nonce.\n * Otherwise, it will request a new nonce from the ACME directory.\n *\n * @async\n * \n * @param {Headers} headers - The headers object containing the replay nonce.\n * @param {Object} acmeDirectory - The ACME directory containing URLs for ACME operations\n * \n * @returns {Promise\u003cstring|null\u003e} A promise that resolves to the next nonce as a string,\n *                                  or null if no nonce is available.\n */\nexport async function getNextNonce(headers, acmeDirectory) { /*...*/ }\n```\n\n\u003c/details\u003e\n\n------------\n\n### fetchRequest\n\nSends a signed request to the `ACME` server.\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cb\u003eShow jsdoc\u003c/b\u003e\u003c/summary\u003e\n\n```javascript\n/**\n * Sends a signed request to the ACME server.\n * @async\n * \n * @param {string} method - The HTTP method to use (e.g., 'GET', 'POST')\n * @param {string} url - The URL to send the request to\n * @param {string} signedData - The signed payload to send\n * \n * @returns {Promise\u003cResponse\u003e} The response from the server\n */\nexport async function fetchRequest(method, url, signedData) { /*...*/ }\n```\n\n\u003c/details\u003e\n\n------------\n\n### fetchSuggestedWindow\n\nFetches the suggested renewal window information for a certificate from the specified URL.\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cb\u003eShow jsdoc\u003c/b\u003e\u003c/summary\u003e\n\n```javascript\n/**\n * Fetches the suggested renewal window information for a certificate from the specified URL.\n * @async\n * \n * @param {string} renewalInfoUrl - The base URL for fetching renewal information.\n * @param {string} aki- The Authority Key Identifier in hexadecimal format.\n * @param {string} serial - The serial number in hexadecimal format.\n * \n * @returns {Promise\u003cObject\u003e} A promise that resolves to the parsed JSON of the suggested window\n * @property {Object|null} get - The retrieved suggested window\n * \n * @property {null|Object} error - Error details if retrieval fails\n * \n * @throws {Error} Throws an error if the fetch operation fails.\n */\nexport async function fetchSuggestedWindow(renewalInfoUrl, aki, serial) { /*...*/ }\n```\n\n\u003c/details\u003e\n\n------------\n\n### fetchAndRetryUntilOk\n\nFetch a resource with multiple retry attempts and progressive backoff.\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cb\u003eShow jsdoc\u003c/b\u003e\u003c/summary\u003e\n\n```javascript\n/**\n * Fetch a resource with multiple retry attempts and progressive backoff.\n * @async\n * \n * @param {string|Request} fetchInput - The URL or Request object to fetch\n * @param {Object} init - optional fetch init object\n * @param {number} [attempts=6] - Maximum number of fetch attempts\n * @param {boolean} silent - true to suppress console output on failure attempt\n * \n * @returns {Promise\u003cResponse|undefined\u003e} The response or undefined if all attempts fail\n * \n * @description\n * This function attempts to fetch a resource with the following characteristics:\n * - Starts with one fetch attempt\n * - Increments attempts progressively\n * - Implements an increasing delay between failed attempts (650ms * attempt number)\n * - Logs any caught exceptions\n * - Returns immediately on a successful (ok) response\n * - Returns the last response or undefined if all attempts are exhausted\n * \n * @example\n * const response = await fetchAndRetyUntilOk('https://api.example.com/data');\n * if (response \u0026\u0026 response.ok) {\n *   const data = await response.json();\n *   // Process successful response\n * }\n */\nexport async function fetchAndRetryUntilOk(fetchInput, init, attempts = 6, silent = false) { /*...*/ }\n```\n\n\u003c/details\u003e\n\n------------\n\n### fetchAndRetryProtectedUntilOk\n\nFetch a protected resource with multiple retry attempts and progressive backoff.\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cb\u003eShow jsdoc\u003c/b\u003e\u003c/summary\u003e\n\n```javascript\n/**\n * Fetch a protected resource with multiple retry attempts and progressive backoff.\n * @async\n *\n * @param {Object} payload - The payload to be sent with the request\n * @param {Object} protectedHeader - The protected header containing metadata for the request\n * @param {Object} privateKey - The private key for signing the request\n * @param {Object} acmeDirectory - The ACME directory containing URLs for ACME operations\n * @param {number} [attempts=6] - Maximum number of fetch attempts (default: 6)\n * @param {boolean} silent - true to suppress console output on failure attempt\n * \n * @returns {Promise\u003cResponse|undefined\u003e} The response or undefined if all attempts fail\n *\n * @description\n * This function attempts to fetch a protected resource with the following characteristics:\n * - Starts with one fetch attempt\n * - Increments attempts progressively\n * - Implements an increasing delay between failed attempts (650ms * attempt number)\n * - Logs any caught exceptions\n * - Returns immediately on a successful (ok) response\n * - Returns the last response or undefined if all attempts are exhausted\n *\n * @example\n * const response = await fetchAndRetryProtectedUntilOk(\n *   payload, \n *   protectedHeader, \n *   privateKey, \n *   acmeDirectory\n * );\n * if (response \u0026\u0026 response.ok) {\n *   const data = await response.json();\n *   // Process successful response\n * }\n */\nexport async function fetchAndRetryProtectedUntilOk(payload, protectedHeader, privateKey, acmeDirectory, attempts = 3, silent = false) { /*...*/ }\n```\n\n\u003c/details\u003e\n\n------------\n\n# Errors/Exceptions\n\nErrors and Exceptions will be returned in an object\n\n```\n// Exceptions\n{\n  error: {\n    type: 'bac:exception:methodName',\n    detail: Error: SyntaxError: Unexpected end of input\n        at file:///base-acme-client.js:666:11\n        at ModuleJob.run (node:internal/modules/esm/module_job:271:25)\n        at async onImport.tracePromise.__proto__ (node:internal/modules/esm/loader:547:26)\n        at async asyncRunEntryPointWithESMLoader (node:internal/modules/run_main:116:5),\n    status: 777777\n  }\n}\n\n// Error from the Base ACME Client\n{\n  error: {\n    type: 'bac:failed:methodName',\n    detail: 'Could not complete methodName after multiple attempts',\n    status: 777777\n  }\n}\n\n// Error from the ACME Server\n{\n  error: {\n    type: 'urn:ietf:params:acme:error:orderNotReady',\n    detail: `Order's status (\"valid\") is not acceptable for finalization`,\n    status: 403\n  }\n}\n```\n\n------------\n\n# Full Working Examples\n\nThis module is used by [`Lets Encrypt ACME Client`](https://github.com/FirstTimeEZ/acme) and [`Server SSL`](https://github.com/FirstTimeEZ/server-ssl)","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffirsttimeez%2Fbase-acme","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffirsttimeez%2Fbase-acme","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffirsttimeez%2Fbase-acme/lists"}