commit d8ce78a81617a3a28f0fbcdd35d3a793ab3503c6 Author: George Lambert Date: Fri Sep 11 13:51:00 2026 -0400 Initial import of verae-activate from zapier monorepo diff --git a/NATS.md b/NATS.md new file mode 100644 index 0000000..5d8bec8 --- /dev/null +++ b/NATS.md @@ -0,0 +1,10 @@ +# NATS — verae-activate + +This Zapier Platform app **does not use NATS**. + +| Direction | Address | Peer | Body | +|-----------|---------|------|------| +| IN | Zapier UI / runtime | user Zap | `number1`, `number2`, `text`, `data` / `sha256` | +| OUT HTTPS (optional) | zappier-edge `/v1/add` or `/v1/timestamp` | only if `api_base` + `api_key` set | JSON | + +Blank connection fields → local compute only. diff --git a/README.md b/README.md new file mode 100644 index 0000000..9a5f17b --- /dev/null +++ b/README.md @@ -0,0 +1,18 @@ +# Verae Time — Zapier activate app + +This is the integration you **push tomorrow**. It has one action: + +**Add Numbers** — `number1` + `number2` → `sum`. + +It runs **inside Zapier**. You do not need `api.veraetime.net`, NATS, or a public URL. + +Step-by-step account setup: [../../docs/04-activate/SETUP-ZAPIER-DEVELOPER.md](../../docs/04-activate/SETUP-ZAPIER-DEVELOPER.md) + +```bash +cd packages/verae-activate +npm install +npm test +zapier-platform login +zapier-platform register "Verae Time" +zapier-platform push +``` diff --git a/SUMMARY.md b/SUMMARY.md new file mode 100644 index 0000000..975de3d --- /dev/null +++ b/SUMMARY.md @@ -0,0 +1,11 @@ +# verae-activate (Zapier Platform app) + +**Job:** Private Zapier integration you push first. Actions run in Zapier cloud. + +**Expects:** User connection (API key optional). + +**Sends:** nothing if fields blank (Add Numbers / Echo / SHA256 / Create Timestamp local mock). If `api_base` + `api_key`, HTTPS to zappier-edge. + +**Does not** speak NATS. + +**Test:** `npm test`; `zapier-platform validate`. diff --git a/authentication.js b/authentication.js new file mode 100644 index 0000000..6773138 --- /dev/null +++ b/authentication.js @@ -0,0 +1,57 @@ +/** + * Connection for the activate-now Zapier app. + * + * No live Verae or zappier server is required. The test always succeeds so a + * developer can push and run Add Numbers before billing or timestamping is wired. + * + * Optional later: set ZAPPIER_API_BASE + api_key to send Add Numbers through + * packages/zappier POST /v1/add. + * + * @module authentication + */ + +/** + * @param {object} z + * @param {object} bundle + * @returns {Promise<{ok: boolean, mode: string, label: string}>} + */ +const testAuth = async (z, bundle) => { + const base = (bundle.authData.api_base || process.env.ZAPPIER_API_BASE || '').replace(/\/$/, ''); + const key = bundle.authData.api_key || ''; + if (base && key) { + const response = await z.request({ + url: `${base}/v1/status`, + headers: { 'x-api-key': key }, + }); + return { + ok: true, + mode: 'hosted', + label: response.data?.status === 'ok' ? 'zappier' : 'hosted', + }; + } + return { ok: true, mode: 'local', label: 'Verae Time (Add Numbers)' }; +}; + +module.exports = { + type: 'custom', + fields: [ + { + key: 'api_key', + type: 'string', + required: false, + label: 'API Key (optional)', + helpText: + 'Leave blank for Add Numbers (runs inside Zapier). Later, paste a key from your zappier portal. See https://github.com/zapier/zapier-platform#authentication', + }, + { + key: 'api_base', + type: 'string', + required: false, + label: 'API base URL (optional)', + helpText: + 'Example: https://your-host.example.com — only needed when routing Add Numbers to hosted /v1/add.', + }, + ], + test: testAuth, + connectionLabel: '{{label}}', +}; diff --git a/creates/add_numbers.js b/creates/add_numbers.js new file mode 100644 index 0000000..4fca13e --- /dev/null +++ b/creates/add_numbers.js @@ -0,0 +1,94 @@ +/** + * Add Numbers — Zapier create that needs no backend. + * + * Inputs: number1, number2 (Zapier number fields). + * Output: { number1, number2, sum, mode }. + * + * If both api_base and api_key are set on the connection, POST /v1/add on the + * zappier commercial edge instead of adding locally. + * + * @module creates/add_numbers + */ + +/** + * @param {unknown} value + * @param {string} name + * @returns {number} + */ +function toFiniteNumber(value, name) { + const n = typeof value === 'number' ? value : Number(value); + if (!Number.isFinite(n)) { + throw new Error(`${name} must be a finite number`); + } + return n; +} + +/** + * @param {object} z Zapier z toolkit + * @param {object} bundle + * @param {object} bundle.inputData + * @param {string|number} bundle.inputData.number1 + * @param {string|number} bundle.inputData.number2 + * @param {object} bundle.authData + * @returns {Promise<{number1: number, number2: number, sum: number, mode: string}>} + */ +const perform = async (z, bundle) => { + const number1 = toFiniteNumber(bundle.inputData.number1, 'number1'); + const number2 = toFiniteNumber(bundle.inputData.number2, 'number2'); + const base = (bundle.authData.api_base || process.env.ZAPPIER_API_BASE || '').replace(/\/$/, ''); + const key = bundle.authData.api_key || ''; + + if (base && key) { + const response = await z.request({ + method: 'POST', + url: `${base}/v1/add`, + headers: { 'x-api-key': key, 'content-type': 'application/json' }, + body: { number1, number2 }, + }); + const data = response.data || {}; + return { + number1: data.number1 ?? number1, + number2: data.number2 ?? number2, + sum: data.sum, + mode: 'hosted', + }; + } + + return { number1, number2, sum: number1 + number2, mode: 'local' }; +}; + +module.exports = { + key: 'add_numbers', + noun: 'Sum', + display: { + label: 'Add Numbers', + description: 'Adds number1 and number2. Works with no API — use this to prove the Zapier connection.', + }, + operation: { + cleanInputData: false, + inputFields: [ + { + key: 'number1', + label: 'Number 1', + type: 'number', + required: true, + helpText: 'First addend.', + }, + { + key: 'number2', + label: 'Number 2', + type: 'number', + required: true, + helpText: 'Second addend.', + }, + ], + perform, + sample: { number1: 2, number2: 3, sum: 5, mode: 'local' }, + outputFields: [ + { key: 'number1', label: 'Number 1', type: 'number' }, + { key: 'number2', label: 'Number 2', type: 'number' }, + { key: 'sum', label: 'Sum', type: 'number' }, + { key: 'mode', label: 'Mode', type: 'string' }, + ], + }, +}; diff --git a/creates/echo.js b/creates/echo.js new file mode 100644 index 0000000..0ad7175 --- /dev/null +++ b/creates/echo.js @@ -0,0 +1,29 @@ +/** + * Echo — returns the input string. Second activate-now action (no backend). + * @module creates/echo + */ + +const perform = async (_z, bundle) => { + const text = String(bundle.inputData.text ?? ''); + return { text, length: text.length, mode: 'local' }; +}; + +module.exports = { + key: 'echo', + noun: 'Echo', + display: { + label: 'Echo Text', + description: 'Returns the text you send. No API required.', + }, + operation: { + cleanInputData: false, + inputFields: [{ key: 'text', label: 'Text', type: 'string', required: true }], + perform, + sample: { text: 'hello', length: 5, mode: 'local' }, + outputFields: [ + { key: 'text', type: 'string' }, + { key: 'length', type: 'integer' }, + { key: 'mode', type: 'string' }, + ], + }, +}; diff --git a/creates/sha256.js b/creates/sha256.js new file mode 100644 index 0000000..6c707b2 --- /dev/null +++ b/creates/sha256.js @@ -0,0 +1,36 @@ +/** + * SHA256 of a string — local, no API. Lets you hash a file/text in a Zap. + * @module creates/sha256 + */ + +const { createHash } = require('node:crypto'); + +const perform = async (_z, bundle) => { + const text = String(bundle.inputData.text ?? ''); + const sha256 = createHash('sha256').update(text, 'utf8').digest('hex'); + return { textLength: text.length, sha256, mode: 'local' }; +}; + +module.exports = { + key: 'sha256_hash', + noun: 'Hash', + display: { + label: 'SHA256 Hash Text', + description: 'Computes SHA256 hex of text inside Zapier. No Verae call.', + }, + operation: { + cleanInputData: false, + inputFields: [{ key: 'text', label: 'Text', type: 'text', required: true }], + perform, + sample: { + textLength: 5, + sha256: '2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824', + mode: 'local', + }, + outputFields: [ + { key: 'sha256', type: 'string' }, + { key: 'textLength', type: 'integer' }, + { key: 'mode', type: 'string' }, + ], + }, +}; diff --git a/creates/timestamp.js b/creates/timestamp.js new file mode 100644 index 0000000..edf6cb9 --- /dev/null +++ b/creates/timestamp.js @@ -0,0 +1,54 @@ +/** + * Create Timestamp — hosted if api_base+api_key, else local mock job. + * @module creates/timestamp + */ + +const { randomUUID } = require('node:crypto'); + +const perform = async (z, bundle) => { + const data = String(bundle.inputData.data ?? ''); + const sha256 = bundle.inputData.sha256; + const base = (bundle.authData.api_base || process.env.ZAPPIER_API_BASE || '').replace(/\/$/, ''); + const key = bundle.authData.api_key || ''; + if (base && key) { + const response = await z.request({ + method: 'POST', + url: `${base}/v1/timestamp`, + headers: { 'x-api-key': key, 'content-type': 'application/json' }, + body: { data, sha256, hashAlg: bundle.inputData.hashAlg }, + }); + return { ...(response.data || {}), mode: 'hosted' }; + } + return { + jobId: randomUUID(), + sha256: sha256 || null, + existing: false, + mode: 'local-mock', + note: 'No API configured — mock jobId only. Set API base + key to hit zappier /v1/timestamp.', + }; +}; + +module.exports = { + key: 'create_timestamp', + noun: 'Timestamp', + display: { + label: 'Create Timestamp', + description: 'Registers data/SHA256. Local mock if no API; hosted zappier when connected.', + }, + operation: { + cleanInputData: false, + inputFields: [ + { key: 'data', label: 'Data', type: 'text', required: false }, + { key: 'sha256', label: 'SHA256 hex', type: 'string', required: false }, + { key: 'hashAlg', label: 'Hash algorithm', type: 'string', required: false, default: 'SHA256' }, + ], + perform, + sample: { jobId: '00000000-0000-4000-8000-000000000000', existing: false, mode: 'local-mock' }, + outputFields: [ + { key: 'jobId', type: 'string' }, + { key: 'sha256', type: 'string' }, + { key: 'existing', type: 'boolean' }, + { key: 'mode', type: 'string' }, + ], + }, +}; diff --git a/index.js b/index.js new file mode 100644 index 0000000..0767dc0 --- /dev/null +++ b/index.js @@ -0,0 +1,26 @@ +/** + * Verae Time Zapier app — activate-now definition. + * + * Morning path: connect with empty API fields, run Add Numbers. + * Later: same app grows timestamp creates against middleware/zappier. + * + * @module index + */ + +const authentication = require('./authentication'); +const addNumbers = require('./creates/add_numbers'); +const echo = require('./creates/echo'); +const sha256Hash = require('./creates/sha256'); +const createTimestamp = require('./creates/timestamp'); + +module.exports = { + version: require('./package.json').version, + platformVersion: require('zapier-platform-core').version, + authentication, + creates: { + [addNumbers.key]: addNumbers, + [echo.key]: echo, + [sha256Hash.key]: sha256Hash, + [createTimestamp.key]: createTimestamp, + }, +}; diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..737be3b --- /dev/null +++ b/package-lock.json @@ -0,0 +1,899 @@ +{ + "name": "verae-time", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "verae-time", + "version": "1.0.0", + "dependencies": { + "zapier-platform-core": "19.1.0" + }, + "engines": { + "node": ">=18", + "npm": ">=5.6.0" + } + }, + "node_modules/@babel/runtime": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.29.7.tgz", + "integrity": "sha512-Nq8OhGWiZIZGV6hLHoyAKLLcJihP/xFeBMGJoUrxTX2psI8dCifzLhZISFb+VWS3wFMRDmCGw5R+dOySCqPLhw==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@types/node": { + "version": "20.19.43", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.43.tgz", + "integrity": "sha512-6oYBAi5ikg4Pl+kGsoYtawUMBT2zZMCvPNF7pVLnHZfd1zf38DRiWn/gT01RYCdUqkv7Fhr+C9ot4/tb+2sVvA==", + "license": "MIT", + "optional": true, + "dependencies": { + "undici-types": "~6.21.0" + } + }, + "node_modules/@zapier/secret-scrubber": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/@zapier/secret-scrubber/-/secret-scrubber-1.1.6.tgz", + "integrity": "sha512-ETblIxh6lnkVHjVqQ8XVB2Ymeo7RudR7kIiZylXtYXAfpmGLXIzbk1h9fjF/SuO21k7jdxaMBaBdqUCBHv8+og==", + "license": "ISC", + "dependencies": { + "create-hash": "1.2.0", + "lodash.isplainobject": "4.0.6" + } + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "license": "MIT" + }, + "node_modules/available-typed-arrays": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", + "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", + "license": "MIT", + "dependencies": { + "possible-typed-array-names": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/call-bind": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.9.tgz", + "integrity": "sha512-a/hy+pNsFUTR+Iz8TCJvXudKVLAnz/DyeSUo10I5yvFDQJBFU2s9uqQpoSrJlroHUKoKqzg+epxyP9lqFdzfBQ==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "get-intrinsic": "^1.3.0", + "set-function-length": "^1.2.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/call-bound": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", + "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "get-intrinsic": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/cipher-base": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.7.tgz", + "integrity": "sha512-Mz9QMT5fJe7bKI7MH31UilT5cEK5EHHRCccw/YRFsRY47AuNgaV6HY3rscp0/I4Q+tTW/5zoqpSeRRI54TkDWA==", + "license": "MIT", + "dependencies": { + "inherits": "^2.0.4", + "safe-buffer": "^5.2.1", + "to-buffer": "^1.2.2" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "license": "MIT", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/content-disposition": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", + "license": "MIT", + "dependencies": { + "safe-buffer": "5.2.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", + "license": "MIT" + }, + "node_modules/create-hash": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", + "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", + "license": "MIT", + "dependencies": { + "cipher-base": "^1.0.1", + "inherits": "^2.0.1", + "md5.js": "^1.3.4", + "ripemd160": "^2.0.1", + "sha.js": "^2.4.0" + } + }, + "node_modules/crypto-js": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-4.2.0.tgz", + "integrity": "sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q==", + "deprecated": "Active development of CryptoJS has been discontinued. This library is no longer maintained.", + "license": "MIT" + }, + "node_modules/define-data-property": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/dotenv": { + "version": "17.2.1", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-17.2.1.tgz", + "integrity": "sha512-kQhDYKZecqnM0fCnzI5eIv5L4cAe/iRI+HqMbO/hbRdTAeXDG+M9FjipUxNfbARuEg4iHIbhnhs78BCHNbSxEQ==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://dotenvx.com" + } + }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.2.tgz", + "integrity": "sha512-HWcBoN6NileqtSydK2FqHbS/LoDd2pqrnQHLyJzBj4kOp/ky2MWMN694xOfkK8/SnUsW2DH7EfyVlydKCsm1Zw==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/fernet": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/fernet/-/fernet-0.3.3.tgz", + "integrity": "sha512-DvvqouVhv3VCor83wkQbSycekYUKDRQ1IKqcInaF5n5BSKgWBVfYLbSf7RRxojwQO0DZySiz5MlM2vO4MG3SUg==", + "license": "MIT", + "dependencies": { + "crypto-js": "~4.2.0", + "urlsafe-base64": "1.0.0" + } + }, + "node_modules/for-each": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.5.tgz", + "integrity": "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==", + "license": "MIT", + "dependencies": { + "is-callable": "^1.2.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/form-data": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.5.tgz", + "integrity": "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==", + "license": "MIT", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.2", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/form-data/node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/form-data/node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-property-descriptors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "license": "MIT", + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hash-base": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.1.2.tgz", + "integrity": "sha512-Bb33KbowVTIj5s7Ked1OsqHUeCpz//tPwR+E2zJgJKo9Z5XolZ9b6bdUgjmYlwnWhoOQKoTd1TYToZGn5mAYOg==", + "license": "MIT", + "dependencies": { + "inherits": "^2.0.4", + "readable-stream": "^2.3.8", + "safe-buffer": "^5.2.1", + "to-buffer": "^1.2.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/hasown": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.4.tgz", + "integrity": "sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==", + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "license": "ISC" + }, + "node_modules/is-callable": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", + "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-typed-array": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.15.tgz", + "integrity": "sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==", + "license": "MIT", + "dependencies": { + "which-typed-array": "^1.1.16" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "license": "MIT" + }, + "node_modules/json-metaschema": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/json-metaschema/-/json-metaschema-1.3.0.tgz", + "integrity": "sha512-FMDPEZQzqIVOQZ3OxzWryI28W6IZ9QKLcHObO9bS+SJrwnV3xQD0QtnhtgSpIZd8Xuy0xBqeRA74vfTnpK4eVg==", + "license": "Public Domain" + }, + "node_modules/json-schema-to-ts": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/json-schema-to-ts/-/json-schema-to-ts-3.1.1.tgz", + "integrity": "sha512-+DWg8jCJG2TEnpy7kOm/7/AxaYoaRbjVB4LFZLySZlWn8exGs3A4OLJR966cVvU26N7X9TWxl+Jsw7dzAqKT6g==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.18.3", + "ts-algebra": "^2.0.0" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/jsonschema": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/jsonschema/-/jsonschema-1.5.0.tgz", + "integrity": "sha512-K+A9hhqbn0f3pJX17Q/7H6yQfD/5OXgdrR5UE12gMXCiN9D5Xq2o5mddV2QEcX/bjla99ASsAAQUyMCCRWAEhw==", + "license": "MIT", + "engines": { + "node": "*" + } + }, + "node_modules/lodash": { + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.18.1.tgz", + "integrity": "sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q==", + "license": "MIT" + }, + "node_modules/lodash.isplainobject": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==", + "license": "MIT" + }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/md5.js": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", + "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==", + "license": "MIT", + "dependencies": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "node_modules/mime-db": { + "version": "1.54.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz", + "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.1.tgz", + "integrity": "sha512-xRc4oEhT6eaBpU1XF7AjpOFD+xQmXNB5OVKwp4tqCuBpHLS/ZbBDrc07mYTDqVMg6PfxUjjNp85O6Cd2Z/5HWA==", + "license": "MIT", + "dependencies": { + "mime-db": "^1.54.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/node-abort-controller": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/node-abort-controller/-/node-abort-controller-3.1.1.tgz", + "integrity": "sha512-AGK2yQKIjRuqnc6VkX2Xj5d+QW8xZ87pa1UK6yA6ouUyuxfHuMP6umE5QK7UmTeOAymo+Zx1Fxiuw9rVx8taHQ==", + "license": "MIT" + }, + "node_modules/node-fetch": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "license": "MIT", + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, + "node_modules/oauth-sign": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", + "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", + "license": "Apache-2.0", + "engines": { + "node": "*" + } + }, + "node_modules/possible-typed-array-names": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz", + "integrity": "sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "license": "MIT" + }, + "node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "license": "MIT", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/readable-stream/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "license": "MIT" + }, + "node_modules/ripemd160": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.3.tgz", + "integrity": "sha512-5Di9UC0+8h1L6ZD2d7awM7E/T4uA1fJRlx6zk/NvdCCVEoAnFqvHmCuNeIKoCeIixBX/q8uM+6ycDvF8woqosA==", + "license": "MIT", + "dependencies": { + "hash-base": "^3.1.2", + "inherits": "^2.0.4" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/semver": { + "version": "7.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", + "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/set-function-length": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", + "license": "MIT", + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/sha.js": { + "version": "2.4.12", + "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.12.tgz", + "integrity": "sha512-8LzC5+bvI45BjpfXU8V5fdU2mfeKiQe1D1gIMn7XUlF3OTUrpdJpPPH4EMAnF0DsHHdSZqCdSss5qCmJKuiO3w==", + "license": "(MIT AND BSD-3-Clause)", + "dependencies": { + "inherits": "^2.0.4", + "safe-buffer": "^5.2.1", + "to-buffer": "^1.2.0" + }, + "bin": { + "sha.js": "bin.js" + }, + "engines": { + "node": ">= 0.10" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/string_decoder/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "license": "MIT" + }, + "node_modules/to-buffer": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/to-buffer/-/to-buffer-1.2.2.tgz", + "integrity": "sha512-db0E3UJjcFhpDhAF4tLo03oli3pwl3dbnzXOUIlRKrp+ldk/VUxzpWYZENsw2SZiuBjHAk7DfB0VU7NKdpb6sw==", + "license": "MIT", + "dependencies": { + "isarray": "^2.0.5", + "safe-buffer": "^5.2.1", + "typed-array-buffer": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/to-buffer/node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "license": "MIT" + }, + "node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", + "license": "MIT" + }, + "node_modules/ts-algebra": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ts-algebra/-/ts-algebra-2.0.0.tgz", + "integrity": "sha512-FPAhNPFMrkwz76P7cdjdmiShwMynZYN6SgOujD1urY4oNm80Ou9oMdmbR45LotcKOXoy7wSmHkRFE6Mxbrhefw==", + "license": "MIT" + }, + "node_modules/typed-array-buffer": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz", + "integrity": "sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "is-typed-array": "^1.1.14" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/undici-types": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", + "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", + "license": "MIT", + "optional": true + }, + "node_modules/urlsafe-base64": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/urlsafe-base64/-/urlsafe-base64-1.0.0.tgz", + "integrity": "sha512-RtuPeMy7c1UrHwproMZN9gN6kiZ0SvJwRaEzwZY0j9MypEkFqyBaKv176jvlPtg58Zh36bOkS0NFABXMHvvGCA==" + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "license": "MIT" + }, + "node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", + "license": "BSD-2-Clause" + }, + "node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "license": "MIT", + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, + "node_modules/which-typed-array": { + "version": "1.1.22", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.22.tgz", + "integrity": "sha512-fvO4ExWMFsqyhG3AiPAObMuY1lxaqgYcxbc49CNdWDDECOJNgQyvsOWVwbZc+qf3rzRtxojBK+CMEv0Ld5CYpw==", + "license": "MIT", + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.9", + "call-bound": "^1.0.4", + "for-each": "^0.3.5", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/zapier-platform-core": { + "version": "19.1.0", + "resolved": "https://registry.npmjs.org/zapier-platform-core/-/zapier-platform-core-19.1.0.tgz", + "integrity": "sha512-MWR11n0SNNxixay1zT5SFb4yJHH7zp/4GFbgLw6l70uJ2iJipzpAjro095ygUitM6RHDfIbICPk2yUHWtEtb+w==", + "license": "SEE LICENSE IN LICENSE", + "dependencies": { + "@zapier/secret-scrubber": "^1.1.2", + "content-disposition": "0.5.4", + "dotenv": "17.2.1", + "fernet": "^0.3.3", + "form-data": "4.0.5", + "json-schema-to-ts": "3.1.1", + "lodash": "4.18.1", + "mime-types": "3.0.1", + "node-abort-controller": "3.1.1", + "node-fetch": "2.7.0", + "oauth-sign": "0.9.0", + "semver": "7.7.2", + "zapier-platform-schema": "19.1.0" + }, + "engines": { + "node": ">=16", + "npm": ">=5.6.0" + }, + "optionalDependencies": { + "@types/node": "^20.3.1" + }, + "peerDependencies": { + "zapier-platform-legacy-scripting-runner": ">=3" + }, + "peerDependenciesMeta": { + "zapier-platform-legacy-scripting-runner": { + "optional": true + } + } + }, + "node_modules/zapier-platform-schema": { + "version": "19.1.0", + "resolved": "https://registry.npmjs.org/zapier-platform-schema/-/zapier-platform-schema-19.1.0.tgz", + "integrity": "sha512-aD7/29RRvuMz/UIEe0++fjQY+/VCNUj5DjUUM3FvX2JKXj9zNXVhrTfEsc5nFbsKmm3mnQyPHwk3FGZewmDalA==", + "license": "SEE LICENSE IN LICENSE", + "dependencies": { + "json-metaschema": "1.3.0", + "jsonschema": "1.5.0", + "lodash": "4.18.1" + } + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..8f2939d --- /dev/null +++ b/package.json @@ -0,0 +1,18 @@ +{ + "name": "verae-time", + "version": "1.0.0", + "description": "Verae Time — start with Add Numbers, then timestamping.", + "main": "index.js", + "scripts": { + "test": "node --test test/**/*.test.js", + "validate": "zapier-platform validate" + }, + "engines": { + "node": ">=18", + "npm": ">=5.6.0" + }, + "dependencies": { + "zapier-platform-core": "19.1.0" + }, + "private": true +} diff --git a/test/add_numbers.test.js b/test/add_numbers.test.js new file mode 100644 index 0000000..f9fe70b --- /dev/null +++ b/test/add_numbers.test.js @@ -0,0 +1,111 @@ +/** + * Activate-now tests: Add Numbers local + hosted paths. + */ + +const { describe, it } = require('node:test'); +const assert = require('node:assert/strict'); + +const App = require('../index'); +const addNumbers = require('../creates/add_numbers'); +const authentication = require('../authentication'); + +describe('verae-activate app', () => { + it('exports Add Numbers create and custom auth', () => { + assert.equal(authentication.type, 'custom'); + assert.ok(App.creates.add_numbers); + assert.ok(App.creates.echo); + assert.ok(App.creates.sha256_hash); + assert.ok(App.creates.create_timestamp); + assert.equal(addNumbers.key, 'add_numbers'); + assert.ok(addNumbers.operation.inputFields.some((f) => f.key === 'number1')); + assert.ok(addNumbers.operation.inputFields.some((f) => f.key === 'number2')); + }); + + it('adds two numbers locally with no API', async () => { + const z = { request: async () => { throw new Error('should not HTTP'); } }; + const result = await addNumbers.operation.perform(z, { + inputData: { number1: 2, number2: 3 }, + authData: {}, + }); + assert.deepEqual(result, { number1: 2, number2: 3, sum: 5, mode: 'local' }); + }); + + it('coerces numeric strings', async () => { + const result = await addNumbers.operation.perform({}, { + inputData: { number1: '10.5', number2: '-0.5' }, + authData: {}, + }); + assert.equal(result.sum, 10); + assert.equal(result.mode, 'local'); + }); + + it('rejects non-finite number1', async () => { + await assert.rejects( + () => addNumbers.operation.perform({}, { inputData: { number1: 'x', number2: 1 }, authData: {} }), + /number1 must be a finite number/, + ); + }); + + it('POSTs to hosted /v1/add when api_base and api_key are set', async () => { + const calls = []; + const z = { + request: async (opts) => { + calls.push(opts); + return { data: { number1: 1, number2: 4, sum: 5, quote: { totalCents: 0 } } }; + }, + }; + const result = await addNumbers.operation.perform(z, { + inputData: { number1: 1, number2: 4 }, + authData: { api_base: 'https://edge.example.com/', api_key: 'key-ada' }, + }); + assert.equal(calls[0].method, 'POST'); + assert.equal(calls[0].url, 'https://edge.example.com/v1/add'); + assert.equal(calls[0].headers['x-api-key'], 'key-ada'); + assert.deepEqual(calls[0].body, { number1: 1, number2: 4 }); + assert.equal(result.mode, 'hosted'); + assert.equal(result.sum, 5); + }); + + it('create timestamp local mock without API', async () => { + const ts = require('../creates/timestamp'); + const out = await ts.operation.perform( + { request: async () => { throw new Error('no http'); } }, + { inputData: { data: 'x' }, authData: {} }, + ); + assert.equal(out.mode, 'local-mock'); + assert.ok(out.jobId); + }); + + it('sha256 hashes hello', async () => { + const sha = require('../creates/sha256'); + const out = await sha.operation.perform({}, { inputData: { text: 'hello' }, authData: {} }); + assert.equal(out.sha256, '2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824'); + assert.equal(out.mode, 'local'); + }); + + it('echo returns text length', async () => { + const echo = require('../creates/echo'); + const out = await echo.operation.perform({}, { inputData: { text: 'ab' }, authData: {} }); + assert.equal(out.length, 2); + assert.equal(out.mode, 'local'); + }); + + it('auth test is local when fields empty', async () => { + const out = await authentication.test({ request: async () => ({ data: {} }) }, { authData: {} }); + assert.equal(out.ok, true); + assert.equal(out.mode, 'local'); + }); + + it('auth test hits /v1/status when hosted', async () => { + const z = { + request: async (opts) => { + assert.equal(opts.url, 'https://edge.example.com/v1/status'); + return { data: { status: 'ok' } }; + }, + }; + const out = await authentication.test(z, { + authData: { api_base: 'https://edge.example.com', api_key: 'k' }, + }); + assert.equal(out.mode, 'hosted'); + }); +});