From 4c154811442579b0785c3a65d57c50baabdcc567 Mon Sep 17 00:00:00 2001 From: Ruben Hensen Date: Sun, 24 May 2026 14:39:19 +0200 Subject: [PATCH 1/2] feat(pg-node): add Node.js example using @e4a/pg-js MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Mirrors the pg-sveltekit "Informatierijk notificeren" flow (citizen exact-email recipient + organisation email-domain recipient) but as a plain Node CLI script — drop-in starting point for backend integrations that need to encrypt and upload from a server runtime. Two modes: npm run send # encrypt + upload + ask Cryptify to mail recipients npm run upload # encrypt + upload silently, return only the UUID Configuration via .env (loaded with Node's --env-file-if-exists). Defaults to staging; flip PG_CRYPTIFY_URL to production for real mail delivery. The package depends on @e4a/pg-js via "file:../../postguard-js" so local SDK changes are picked up immediately after a rebuild — useful while the non-browser-runtime support work is unreleased. Swap to a "^X.Y.Z" version once the SDK ships to npm. --- README.md | 16 +++++- pg-node/.env.example | 23 ++++++++ pg-node/.gitignore | 2 + pg-node/README.md | 75 ++++++++++++++++++++++++++ pg-node/index.mjs | 107 +++++++++++++++++++++++++++++++++++++ pg-node/package-lock.json | 44 +++++++++++++++ pg-node/package.json | 19 +++++++ pg-node/src/config.mjs | 35 ++++++++++++ pg-node/src/encryption.mjs | 60 +++++++++++++++++++++ 9 files changed, 380 insertions(+), 1 deletion(-) create mode 100644 pg-node/.env.example create mode 100644 pg-node/.gitignore create mode 100644 pg-node/README.md create mode 100644 pg-node/index.mjs create mode 100644 pg-node/package-lock.json create mode 100644 pg-node/package.json create mode 100644 pg-node/src/config.mjs create mode 100644 pg-node/src/encryption.mjs diff --git a/README.md b/README.md index d1e49f9..c2fe0a5 100644 --- a/README.md +++ b/README.md @@ -4,9 +4,10 @@ Example applications demonstrating PostGuard integration. Contains reference implementations for developers building on PostGuard. Code snippets in docs.postguard.eu come from this repo. -There are three sub-projects: +There are four sub-projects: - `pg-sveltekit/`: SvelteKit web app using the `@e4a/pg-js` SDK. +- `pg-node/`: Node.js CLI using the `@e4a/pg-js` SDK from a server runtime. - `pg-dotnet/`: .NET console app using the `postguard-dotnet` SDK. - `pg-manual/`: manual encryption/decryption using the `@e4a/pg-wasm` library directly. @@ -24,6 +25,19 @@ npm run dev See [pg-sveltekit/README.md](pg-sveltekit/README.md) for environment variables and build instructions. +### Node.js example + +Requires Node.js 20.6+ and a PostGuard API key. + +```bash +cd pg-node +npm install +cp .env.example .env # set at minimum PG_API_KEY +npm run send # encrypt + upload + notify recipients +``` + +See [pg-node/README.md](pg-node/README.md) for the full configuration and modes. + ### .NET example Requires the .NET 10.0+ SDK and a PostGuard API key. The example uses the `E4A.PostGuard` NuGet package, so no Rust toolchain or local build of the native library is needed. diff --git a/pg-node/.env.example b/pg-node/.env.example new file mode 100644 index 0000000..5838648 --- /dev/null +++ b/pg-node/.env.example @@ -0,0 +1,23 @@ +# PostGuard for Business API key (PG-…). Get one from +# business.staging.postguard.eu (staging) or business.postguard.eu (production). +PG_API_KEY= + +# Endpoints. Defaults are staging. +PG_PKG_URL=https://pkg.staging.postguard.eu +PG_CRYPTIFY_URL=https://storage.staging.postguard.eu + +# Optional: PostGuard website used in the printed download link. +# Defaults to https://staging.postguard.eu on staging Cryptify, +# else https://postguard.eu. +# PG_DOWNLOAD_URL=https://staging.postguard.eu + +# Recipients. Citizen is an exact email match; Organisation matches by email domain. +PG_CITIZEN_EMAIL=citizen@example.com +PG_ORGANISATION_EMAIL=noreply@example.org + +# Optional unencrypted message body included in Cryptify's notification mail. +PG_MESSAGE= + +# Optional comma-separated list of file paths to encrypt. If empty the +# example uses two in-memory demo files (report.txt + notes.txt). +# PG_INPUT_FILES=./files/report.pdf,./files/notes.txt diff --git a/pg-node/.gitignore b/pg-node/.gitignore new file mode 100644 index 0000000..713d500 --- /dev/null +++ b/pg-node/.gitignore @@ -0,0 +1,2 @@ +node_modules/ +.env diff --git a/pg-node/README.md b/pg-node/README.md new file mode 100644 index 0000000..82266a5 --- /dev/null +++ b/pg-node/README.md @@ -0,0 +1,75 @@ +# pg-node: PostGuard Node.js example + +Node.js example demonstrating how to use the [@e4a/pg-js](https://www.npmjs.com/package/@e4a/pg-js) SDK from a server runtime. Mirrors the [pg-sveltekit](../pg-sveltekit) example's "Informatierijk notificeren" flow (citizen + organisation recipients) but as a CLI script — drop-in starting point for backend integrations. + +## What it does + +Two modes, selected by the script flag: + +1. **Send** (`npm run send`) — encrypts the input files for a citizen (exact email) and an organisation (email domain), uploads to Cryptify, and asks Cryptify to email each recipient a download link. +2. **Upload-only** (`npm run upload`) — same encryption + upload, but silent. Cryptify returns a UUID you can distribute through some other channel. + +Files come from `PG_INPUT_FILES` (comma-separated paths) or two in-memory demo files if that is unset. + +## Prerequisites + +- **Node.js 20.6+** — older versions lack `--env-file-if-exists` (used by `npm start`) and the `File` global (used by the SDK). Node 22 LTS recommended. The SDK itself supports Node 20.3+, Bun, and Deno. +- A PostGuard for Business API key. + +## Setup + +```bash +cd pg-node +npm install +cp .env.example .env +# edit .env: set at minimum PG_API_KEY +``` + +The `package.json` depends on the SDK via `file:../../postguard-js`, so any local changes you make to the SDK take effect after `cd ../../postguard-js && npm run build` followed by `cd ../postguard-examples/pg-node && npm install`. Swap that to `"^X.Y.Z"` once a real release is published. + +## Run + +```bash +npm run send # encrypt + upload + ask Cryptify to send mails +npm run upload # encrypt + upload silently, no mails +``` + +The script prints the resulting `uuid` and the corresponding `…/download?uuid=…` URL. + +## Staging Cryptify does not send email + +The default `PG_CRYPTIFY_URL` is `storage.staging.postguard.eu` — the staging deployment. It **does not actually deliver notification emails**, so you can exercise the full upload + notify flow without spamming real inboxes while you integrate. + +- The upload itself works. You get back a real UUID and the download URL is usable. +- `npm run send` succeeds, but no recipient mail is sent. Open the printed URL yourself to verify the decrypt flow end-to-end. +- Point `PG_CRYPTIFY_URL` at the production Cryptify host to exercise real email delivery. + +## Configuration + +| Variable | Description | Default | +| ----------------------- | ----------------------------------------------------- | ---------------------------------------------------------------------------------- | +| `PG_API_KEY` | PostGuard for Business API key (`PG-…`) | *(required)* | +| `PG_PKG_URL` | PostGuard PKG server URL | `https://pkg.staging.postguard.eu` | +| `PG_CRYPTIFY_URL` | Cryptify file-sharing URL | `https://storage.staging.postguard.eu` | +| `PG_DOWNLOAD_URL` | PostGuard website used in `/download` URLs | `https://staging.postguard.eu` on staging Cryptify, else `https://postguard.eu` | +| `PG_CITIZEN_EMAIL` | Citizen recipient (exact email match) | `citizen@example.com` | +| `PG_ORGANISATION_EMAIL` | Organisation recipient (matches by domain) | `noreply@example.org` | +| `PG_MESSAGE` | Optional unencrypted body for Cryptify's notify mail | *(empty)* | +| `PG_INPUT_FILES` | Comma-separated file paths to encrypt | two in-memory demo files | + +## How it maps to the SDK + +The work happens in [`src/encryption.mjs`](./src/encryption.mjs): + +```js +const sealed = pg.encrypt({ + files, + recipients: [pg.recipient.email(citizen.email), pg.recipient.emailDomain(organisation.email)], + sign: pg.sign.apiKey(apiKey), + onProgress, + signal, +}); +const { uuid } = await sealed.upload({ notify: { recipients: true, message, language: 'EN' } }); +``` + +`notify` must be nested under an object — the SDK validates the shape and throws a clear `TypeError` if you pass `{ notify: true }` or forget to nest. See the [SDK README](https://github.com/encryption4all/postguard-js#server-side-usage-node-bun-deno) for the full server-side surface. diff --git a/pg-node/index.mjs b/pg-node/index.mjs new file mode 100644 index 0000000..e1aa895 --- /dev/null +++ b/pg-node/index.mjs @@ -0,0 +1,107 @@ +// CLI entry point. Run with one of: +// npm run send # encrypts and asks Cryptify to mail recipients +// npm run upload # encrypts and uploads silently +// npm start # same as `npm run send` +// +// Configuration via .env or environment variables — see .env.example. + +import { readFile } from 'node:fs/promises'; +import { basename } from 'node:path'; +import { + API_KEY, + CITIZEN_EMAIL, + ORGANISATION_EMAIL, + MESSAGE, + INPUT_FILES, + DOWNLOAD_URL, + IS_CRYPTIFY_STAGING, + CRYPTIFY_URL, + PKG_URL, +} from './src/config.mjs'; +import { encryptAndSend, encryptAndUpload } from './src/encryption.mjs'; + +if (!API_KEY) { + console.error('Missing PG_API_KEY. Copy .env.example to .env and set it.'); + process.exit(2); +} + +const mode = process.argv.includes('--upload-only') ? 'upload-only' : 'send-email'; + +console.log(`pg-node example — mode: ${mode}`); +console.log(` PKG: ${PKG_URL}`); +console.log(` Cryptify: ${CRYPTIFY_URL}${IS_CRYPTIFY_STAGING ? ' (staging — no mails actually sent)' : ''}`); +console.log(` Citizen: ${CITIZEN_EMAIL}`); +console.log(` Organisation: ${ORGANISATION_EMAIL}`); +console.log(''); + +const files = await loadFiles(); +console.log(`Encrypting ${files.length} file(s):`); +for (const f of files) console.log(` ${f.name} (${f.size} bytes)`); +console.log(''); + +const abortController = new AbortController(); +process.on('SIGINT', () => { + console.log('\nCancelling…'); + abortController.abort(); +}); + +const onProgress = (pct) => { + process.stdout.write(`\r upload progress: ${pct}% `); +}; + +const t0 = performance.now(); +const uuid = + mode === 'send-email' + ? await encryptAndSend({ + files, + citizen: { email: CITIZEN_EMAIL }, + organisation: { email: ORGANISATION_EMAIL }, + apiKey: API_KEY, + message: MESSAGE, + onProgress, + signal: abortController.signal, + }) + : await encryptAndUpload({ + files, + citizen: { email: CITIZEN_EMAIL }, + organisation: { email: ORGANISATION_EMAIL }, + apiKey: API_KEY, + onProgress, + signal: abortController.signal, + }); +const t1 = performance.now(); + +process.stdout.write('\n'); +console.log(''); +console.log(`Done in ${(t1 - t0).toFixed(0)}ms`); +console.log(`UUID: ${uuid}`); +console.log(`Download: ${DOWNLOAD_URL}/download?uuid=${uuid}`); + +if (mode === 'send-email' && IS_CRYPTIFY_STAGING) { + console.log(''); + console.log('Note: staging Cryptify does not actually deliver mails. Open the URL above to test decrypt.'); +} + +/** Read each path in PG_INPUT_FILES as a File. If empty, return two demo files. */ +async function loadFiles() { + if (INPUT_FILES.length === 0) { + return [ + new File( + [new TextEncoder().encode('This is a sample report for PostGuard encryption testing.\n')], + 'report.txt', + { type: 'text/plain' } + ), + new File( + [new TextEncoder().encode('Confidential notes — only the intended recipient can read this.\n')], + 'notes.txt', + { type: 'text/plain' } + ), + ]; + } + return Promise.all( + INPUT_FILES.map(async (path) => { + const bytes = await readFile(path); + return new File([bytes], basename(path)); + }) + ); +} diff --git a/pg-node/package-lock.json b/pg-node/package-lock.json new file mode 100644 index 0000000..4c0bbc9 --- /dev/null +++ b/pg-node/package-lock.json @@ -0,0 +1,44 @@ +{ + "name": "pg-node", + "version": "0.0.1", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "pg-node", + "version": "0.0.1", + "license": "MIT", + "dependencies": { + "@e4a/pg-js": "file:../../postguard-js" + }, + "engines": { + "node": ">=20.6" + } + }, + "../../postguard-js": { + "name": "@e4a/pg-js", + "version": "0.0.0-managed-by-semantic-release", + "license": "MIT", + "dependencies": { + "@e4a/pg-wasm": "^0.5.10", + "@privacybydesign/yivi-client": "1.0.0", + "@privacybydesign/yivi-core": "1.0.0", + "@privacybydesign/yivi-css": "1.0.1", + "@privacybydesign/yivi-web": "1.0.1", + "@transcend-io/conflux": "^6.1.3" + }, + "devDependencies": { + "tsdown": "^0.21.10", + "typescript": "^6.0.3", + "vitest": "^4.1.5" + }, + "engines": { + "node": ">=20.3" + } + }, + "node_modules/@e4a/pg-js": { + "resolved": "../../postguard-js", + "link": true + } + } +} diff --git a/pg-node/package.json b/pg-node/package.json new file mode 100644 index 0000000..50675a1 --- /dev/null +++ b/pg-node/package.json @@ -0,0 +1,19 @@ +{ + "name": "pg-node", + "version": "0.0.1", + "private": true, + "type": "module", + "description": "PostGuard Node.js example — encrypt + upload from a server", + "license": "MIT", + "scripts": { + "start": "node --env-file-if-exists=.env index.mjs", + "send": "node --env-file-if-exists=.env index.mjs --send", + "upload": "node --env-file-if-exists=.env index.mjs --upload-only" + }, + "dependencies": { + "@e4a/pg-js": "file:../../postguard-js" + }, + "engines": { + "node": ">=20.6" + } +} diff --git a/pg-node/src/config.mjs b/pg-node/src/config.mjs new file mode 100644 index 0000000..cbd2b7e --- /dev/null +++ b/pg-node/src/config.mjs @@ -0,0 +1,35 @@ +// Env-driven config. Run with `node --env-file=.env index.mjs` to load +// from .env (Node 20.6+). Mirrors pg-sveltekit's config.ts. + +export const PKG_URL = process.env.PG_PKG_URL || 'https://pkg.staging.postguard.eu'; +export const CRYPTIFY_URL = process.env.PG_CRYPTIFY_URL || 'https://storage.staging.postguard.eu'; +export const API_KEY = process.env.PG_API_KEY; + +// Citizen = exact email recipient; Organisation = email-domain recipient. +// Mirrors the "Informatierijk notificeren" use-case from pg-sveltekit. +export const CITIZEN_EMAIL = process.env.PG_CITIZEN_EMAIL || 'citizen@example.com'; +export const ORGANISATION_EMAIL = process.env.PG_ORGANISATION_EMAIL || 'noreply@example.org'; + +export const MESSAGE = process.env.PG_MESSAGE || ''; + +// Files to encrypt. If unset, the example creates two in-memory demo files. +export const INPUT_FILES = (process.env.PG_INPUT_FILES || '') + .split(',') + .map((s) => s.trim()) + .filter(Boolean); + +// Same staging heuristic as pg-sveltekit: the staging Cryptify accepts +// uploads but does NOT actually deliver notification emails. Useful for +// integration testing without spamming real inboxes. +function detectStagingCryptify(url) { + try { + return new URL(url).hostname.toLowerCase().includes('staging'); + } catch { + return false; + } +} +export const IS_CRYPTIFY_STAGING = detectStagingCryptify(CRYPTIFY_URL); + +export const DOWNLOAD_URL = + process.env.PG_DOWNLOAD_URL || + (IS_CRYPTIFY_STAGING ? 'https://staging.postguard.eu' : 'https://postguard.eu'); diff --git a/pg-node/src/encryption.mjs b/pg-node/src/encryption.mjs new file mode 100644 index 0000000..d993fcb --- /dev/null +++ b/pg-node/src/encryption.mjs @@ -0,0 +1,60 @@ +import { PostGuard } from '@e4a/pg-js'; +import { PKG_URL, CRYPTIFY_URL } from './config.mjs'; + +const pg = new PostGuard({ pkgUrl: PKG_URL, cryptifyUrl: CRYPTIFY_URL }); + +/** Encrypt, upload to Cryptify, and have Cryptify email each recipient + * a download link. + * + * NOTE: the staging Cryptify (storage.staging.postguard.eu) does NOT + * actually deliver these emails — recipients won't receive anything on + * staging. The upload itself still succeeds. */ +export async function encryptAndSend({ + files, + citizen, + organisation, + apiKey, + message, + onProgress, + signal, +}) { + const sealed = pg.encrypt({ + files, + recipients: [pg.recipient.email(citizen.email), pg.recipient.emailDomain(organisation.email)], + sign: pg.sign.apiKey(apiKey), + onProgress, + signal, + }); + + const result = await sealed.upload({ + notify: { + recipients: true, + message: message || undefined, + language: 'EN', + }, + }); + + return result.uuid; +} + +/** Encrypt and upload to Cryptify silently (no Cryptify-sent emails). + * Returns the UUID for distribution through some other channel. */ +export async function encryptAndUpload({ + files, + citizen, + organisation, + apiKey, + onProgress, + signal, +}) { + const sealed = pg.encrypt({ + files, + recipients: [pg.recipient.email(citizen.email), pg.recipient.emailDomain(organisation.email)], + sign: pg.sign.apiKey(apiKey), + onProgress, + signal, + }); + + const result = await sealed.upload(); + return result.uuid; +} From 2bf7463633a990ef10932e132aa3adf5c0cdbc7e Mon Sep 17 00:00:00 2001 From: Ruben Hensen Date: Sun, 24 May 2026 15:36:01 +0200 Subject: [PATCH 2/2] chore(pg-node): depend on published @e4a/pg-js ^1.9.0 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Swaps the temporary file:../../postguard-js link for the published ^1.9.0 release on npm. Bumps the example's engines.node to >=22 to match the SDK. README updated accordingly. Verified end-to-end against staging.postguard.eu — real UUID returned (bb90cb02-b27c-4b0d-a245-4acdb16056e1). --- pg-node/README.md | 4 +- pg-node/package-lock.json | 400 ++++++++++++++++++++++++++++++++++++-- pg-node/package.json | 4 +- 3 files changed, 386 insertions(+), 22 deletions(-) diff --git a/pg-node/README.md b/pg-node/README.md index 82266a5..c348d85 100644 --- a/pg-node/README.md +++ b/pg-node/README.md @@ -13,7 +13,7 @@ Files come from `PG_INPUT_FILES` (comma-separated paths) or two in-memory demo f ## Prerequisites -- **Node.js 20.6+** — older versions lack `--env-file-if-exists` (used by `npm start`) and the `File` global (used by the SDK). Node 22 LTS recommended. The SDK itself supports Node 20.3+, Bun, and Deno. +- **Node.js 22+** — matches `@e4a/pg-js`'s `engines.node`. The SDK also supports Bun and Deno; the same encryption code in `src/encryption.mjs` works there too. - A PostGuard for Business API key. ## Setup @@ -25,7 +25,7 @@ cp .env.example .env # edit .env: set at minimum PG_API_KEY ``` -The `package.json` depends on the SDK via `file:../../postguard-js`, so any local changes you make to the SDK take effect after `cd ../../postguard-js && npm run build` followed by `cd ../postguard-examples/pg-node && npm install`. Swap that to `"^X.Y.Z"` once a real release is published. +The `package.json` depends on the published [`@e4a/pg-js`](https://www.npmjs.com/package/@e4a/pg-js) (currently `^1.9.0`). ## Run diff --git a/pg-node/package-lock.json b/pg-node/package-lock.json index 4c0bbc9..efccb97 100644 --- a/pg-node/package-lock.json +++ b/pg-node/package-lock.json @@ -9,36 +9,400 @@ "version": "0.0.1", "license": "MIT", "dependencies": { - "@e4a/pg-js": "file:../../postguard-js" + "@e4a/pg-js": "^1.9.0" }, "engines": { - "node": ">=20.6" + "node": ">=22" } }, - "../../postguard-js": { - "name": "@e4a/pg-js", - "version": "0.0.0-managed-by-semantic-release", + "node_modules/@e4a/pg-js": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@e4a/pg-js/-/pg-js-1.9.0.tgz", + "integrity": "sha512-ohfN3BBNrAUyl7Jk8Vj7hrAds6lAfDGaghwmMbhL2XWPQL3p+fj3UX2dDdKDGTu7AgDP9ouYxyc+AGUsyqd26A==", "license": "MIT", "dependencies": { - "@e4a/pg-wasm": "^0.5.10", - "@privacybydesign/yivi-client": "1.0.0", - "@privacybydesign/yivi-core": "1.0.0", - "@privacybydesign/yivi-css": "1.0.1", - "@privacybydesign/yivi-web": "1.0.1", + "@e4a/pg-wasm": "^0.6.1", + "@privacybydesign/yivi-client": "^1.0.0", + "@privacybydesign/yivi-core": "^1.0.0", + "@privacybydesign/yivi-css": "^1.0.1", + "@privacybydesign/yivi-web": "^1.0.1", "@transcend-io/conflux": "^6.1.3" }, - "devDependencies": { - "tsdown": "^0.21.10", - "typescript": "^6.0.3", - "vitest": "^4.1.5" + "engines": { + "node": ">=22" + } + }, + "node_modules/@e4a/pg-wasm": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/@e4a/pg-wasm/-/pg-wasm-0.6.1.tgz", + "integrity": "sha512-JghjNQlUNAoD6rNjKxfGqE+Qu6yXNjq2VCZSY0hUl0q76csZnGbGQmutzc3WOFXTOjcKuzzrl89hN/ndxvMLsQ==", + "license": "MIT" + }, + "node_modules/@privacybydesign/yivi-client": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@privacybydesign/yivi-client/-/yivi-client-1.0.0.tgz", + "integrity": "sha512-juWqDD2KCeytycw1AH07HqP6L3GFepHSQa3cyOwP2M8yCzsWml7nVSbAhyfUJnoblq91pcagEA6vVc1xf/5Njg==", + "license": "SEE LICENSE IN REPOSITORY", + "dependencies": { + "deepmerge": "^4.2.2" + }, + "peerDependencies": { + "@privacybydesign/yivi-core": "1.0.0" + } + }, + "node_modules/@privacybydesign/yivi-core": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@privacybydesign/yivi-core/-/yivi-core-1.0.0.tgz", + "integrity": "sha512-jPpx3eiKZTMfY0nCPNRMUupqQIVAP3Z0kOU3XBH8F7dsJIQFi4NJHf4X7+QdmFTgcogR0wSmEjFBoOv+nbq4KA==", + "license": "SEE LICENSE IN REPOSITORY" + }, + "node_modules/@privacybydesign/yivi-css": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@privacybydesign/yivi-css/-/yivi-css-1.0.1.tgz", + "integrity": "sha512-4cN1cSrgmbm5+syhgFOMV0zW0jJMED1WD0vAGlYKrEhf4vMWIZCE0pwFjRwRDlR+Qgy6fNtgW27Qt8EyF0pkfg==", + "license": "SEE LICENSE IN REPOSITORY" + }, + "node_modules/@privacybydesign/yivi-web": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@privacybydesign/yivi-web/-/yivi-web-1.0.1.tgz", + "integrity": "sha512-fyVzdmUG0ZNC5IIsU3+daq95EM06LgrJ5F/uLnqzzJZJNfy0p98dt6Gy/nzVPqd3tUAQK+lO5704kGXLO1qDTg==", + "license": "SEE LICENSE IN REPOSITORY", + "dependencies": { + "deepmerge": "^4.2.2", + "qrcode": "^1.4.2" }, + "peerDependencies": { + "@privacybydesign/yivi-core": "1.0.0" + } + }, + "node_modules/@transcend-io/conflux": { + "version": "6.1.3", + "resolved": "https://registry.npmjs.org/@transcend-io/conflux/-/conflux-6.1.3.tgz", + "integrity": "sha512-MaRZC8qfW1ffkBPNwDqj1UWx3v/cA9qOBOZIuNiej5fHOGsqx6/0kBetq0BeaLoz+G7DfO9YGNapwEZ37BK8vg==", + "license": "MIT", + "dependencies": { + "pako": "^2.1.0" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "license": "MIT", "engines": { - "node": ">=20.3" + "node": ">=8" } }, - "node_modules/@e4a/pg-js": { - "resolved": "../../postguard-js", - "link": true + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/cliui": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", + "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", + "license": "ISC", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^6.2.0" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "license": "MIT" + }, + "node_modules/decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/deepmerge": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", + "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/dijkstrajs": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/dijkstrajs/-/dijkstrajs-1.0.3.tgz", + "integrity": "sha512-qiSlmBq9+BCdCA/L46dw8Uy93mloxsPSbwnm5yrKn2vMPiy8KyAskTF6zuV/j5BMsmOGZDPs7KjU+mjb670kfA==", + "license": "MIT" + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "license": "MIT" + }, + "node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "license": "MIT", + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "license": "ISC", + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "license": "MIT", + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "license": "MIT", + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "license": "MIT", + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/pako": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/pako/-/pako-2.1.0.tgz", + "integrity": "sha512-w+eufiZ1WuJYgPXbV/PO3NCMEc3xqylkKHzp8bxp1uW4qaSNQUkwmLLEc3kKsfz8lpV1F8Ht3U1Cm+9Srog2ug==", + "license": "(MIT AND Zlib)" + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/pngjs": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/pngjs/-/pngjs-5.0.0.tgz", + "integrity": "sha512-40QW5YalBNfQo5yRYmiw7Yz6TKKVr3h6970B2YE+3fQpsWcrbj1PzJgxeJ19DRQjhMbKPIuMY8rFaXc8moolVw==", + "license": "MIT", + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/qrcode": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/qrcode/-/qrcode-1.5.4.tgz", + "integrity": "sha512-1ca71Zgiu6ORjHqFBDpnSMTR2ReToX4l1Au1VFLyVeBTFavzQnv5JxMFr3ukHVKpSrSA2MCk0lNJSykjUfz7Zg==", + "license": "MIT", + "dependencies": { + "dijkstrajs": "^1.0.1", + "pngjs": "^5.0.0", + "yargs": "^15.3.1" + }, + "bin": { + "qrcode": "bin/qrcode" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/require-main-filename": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", + "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", + "license": "ISC" + }, + "node_modules/set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", + "license": "ISC" + }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/which-module": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.1.tgz", + "integrity": "sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==", + "license": "ISC" + }, + "node_modules/wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/y18n": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", + "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", + "license": "ISC" + }, + "node_modules/yargs": { + "version": "15.4.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", + "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==", + "license": "MIT", + "dependencies": { + "cliui": "^6.0.0", + "decamelize": "^1.2.0", + "find-up": "^4.1.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^4.2.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^18.1.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/yargs-parser": { + "version": "18.1.3", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", + "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", + "license": "ISC", + "dependencies": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + }, + "engines": { + "node": ">=6" + } } } } diff --git a/pg-node/package.json b/pg-node/package.json index 50675a1..a258f6e 100644 --- a/pg-node/package.json +++ b/pg-node/package.json @@ -11,9 +11,9 @@ "upload": "node --env-file-if-exists=.env index.mjs --upload-only" }, "dependencies": { - "@e4a/pg-js": "file:../../postguard-js" + "@e4a/pg-js": "^1.9.0" }, "engines": { - "node": ">=20.6" + "node": ">=22" } }