Skip to content

Commit d65fa00

Browse files
committed
initial commit: n8n community node for Documenso
Documenso node with 7 resources and 35 operations using the envelopes API: - Document: find, get, create, create and send, update, delete, duplicate, download, send, resend - Template: find, get, create, update, delete, duplicate, use - Recipient: create, get, update, delete - Field: create (placeholder text + coordinate + JSON modes), get, update, delete - File: upload, download, update, delete - Attachment: find, create, update, delete - Folder: find, create, update, delete DocumensoTrigger webhook node for document signing events. Tooling: tsdown build, biome lint/format, docker compose dev, CI + release workflows.
0 parents  commit d65fa00

64 files changed

Lines changed: 6070 additions & 0 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/ci.yml

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
name: CI
2+
3+
on:
4+
pull_request:
5+
push:
6+
branches: [main]
7+
8+
jobs:
9+
check:
10+
runs-on: ubuntu-latest
11+
steps:
12+
- uses: actions/checkout@v4
13+
14+
- uses: oven-sh/setup-bun@v2
15+
16+
- name: Install dependencies
17+
run: bun install --frozen-lockfile
18+
19+
- name: Typecheck
20+
run: bun run typecheck
21+
22+
- name: Lint
23+
run: bun run lint
24+
25+
- name: Build
26+
run: bun run build

.github/workflows/release.yml

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
name: Release
2+
3+
on:
4+
push:
5+
tags:
6+
- "v*"
7+
8+
permissions:
9+
contents: write
10+
id-token: write
11+
12+
jobs:
13+
release:
14+
name: Release & Publish
15+
runs-on: ubuntu-latest
16+
steps:
17+
- name: Checkout
18+
uses: actions/checkout@v4
19+
20+
- name: Create GitHub Release
21+
uses: softprops/action-gh-release@v2
22+
with:
23+
generate_release_notes: true
24+
prerelease: ${{ contains(github.ref_name, 'alpha') || contains(github.ref_name, 'beta') || contains(github.ref_name, 'rc') }}
25+
26+
- name: Setup Bun
27+
uses: oven-sh/setup-bun@v2
28+
29+
- name: Setup Node.js
30+
uses: actions/setup-node@v4
31+
with:
32+
node-version: "24"
33+
registry-url: "https://registry.npmjs.org"
34+
35+
- name: Install dependencies
36+
run: bun install --frozen-lockfile
37+
38+
- name: Typecheck
39+
run: bun run typecheck
40+
41+
- name: Lint
42+
run: bun run lint
43+
44+
- name: Build
45+
run: bun run build
46+
47+
- name: Determine dist-tag
48+
id: dist-tag
49+
run: |
50+
VERSION="${GITHUB_REF_NAME#v}"
51+
if [[ "$VERSION" == *"alpha"* ]]; then
52+
echo "tag=alpha" >> $GITHUB_OUTPUT
53+
elif [[ "$VERSION" == *"beta"* ]]; then
54+
echo "tag=beta" >> $GITHUB_OUTPUT
55+
elif [[ "$VERSION" == *"rc"* ]]; then
56+
echo "tag=rc" >> $GITHUB_OUTPUT
57+
else
58+
echo "tag=latest" >> $GITHUB_OUTPUT
59+
fi
60+
61+
- name: Publish to npm
62+
run: npm publish --provenance --access public --tag ${{ steps.dist-tag.outputs.tag }}

.gitignore

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
# dependencies (bun install)
2+
node_modules
3+
4+
# output
5+
out
6+
dist
7+
*.tgz
8+
9+
# code coverage
10+
coverage
11+
*.lcov
12+
13+
# logs
14+
logs
15+
_.log
16+
report.[0-9]_.[0-9]_.[0-9]_.[0-9]_.json
17+
18+
# dotenv environment variable files
19+
.env
20+
.env.development.local
21+
.env.test.local
22+
.env.production.local
23+
.env.local
24+
25+
# caches
26+
.eslintcache
27+
.cache
28+
*.tsbuildinfo
29+
30+
# IntelliJ based IDEs
31+
.idea
32+
33+
# Finder (MacOS) folder config
34+
.DS_Store

CLAUDE.md

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
---
2+
description: n8n community node for Documenso document signing
3+
globs: "*.ts, *.json"
4+
alwaysApply: true
5+
---
6+
7+
# @documenso/n8n-nodes-documenso
8+
9+
n8n community node package for the Documenso open source document signing platform. Uses the `@documenso/sdk-typescript` SDK internally, exposing it through n8n's node UI.
10+
11+
## Commands
12+
13+
- `bun install` — install dependencies
14+
- `bun run build` — build with tsdown (CJS output to dist/)
15+
- `bun run typecheck` — type-check with tsc --noEmit
16+
- `bun run check` — biome check --write (lint + format)
17+
- `bun run lint` — biome lint only
18+
- `bun run format` — biome format --write only
19+
- `bun run dev` — docker compose up (runs n8n with the node loaded at http://localhost:5678)
20+
21+
After changes: `bun run build && docker compose restart` to see them in n8n.
22+
23+
## Code Style
24+
25+
- **Formatter**: Biome — 2-space indent, double quotes
26+
- **Block statements**: Always use braces (`if (x) { ... }`, never `if (x) ...`)
27+
- **`any` types**: Allowed (biome `noExplicitAny: off`) — unavoidable with n8n's `getNodeParameter` and SDK response types
28+
- **Imports**: Auto-organized by biome assist
29+
30+
## Architecture
31+
32+
### Source layout (`src/`)
33+
34+
```
35+
src/
36+
index.ts # Package exports
37+
credentials/
38+
DocumensoApi.credentials.ts # API Key + Base URL credential
39+
nodes/
40+
Documenso/
41+
Documenso.node.ts # Main node — resource/operation selector
42+
Documenso.node.json # Codex metadata
43+
documenso.svg # Node icon
44+
GenericFunctions.ts # SDK client factory + error handling
45+
actions/
46+
router.ts # Dispatches resource+operation → per-item execute
47+
document/ # 10 ops: find, get, create, createAndSend, update, delete, duplicate, download, send, resend
48+
template/ # 7 ops: find, get, create, update, delete, duplicate, use
49+
recipient/ # 4 ops: create, get, update, delete
50+
field/ # 4 ops: create, get, update, delete
51+
file/ # 4 ops: upload, download, update, delete
52+
attachment/ # 4 ops: find, create, update, delete
53+
folder/ # 4 ops: find, create, update, delete
54+
DocumensoTrigger/
55+
DocumensoTrigger.node.ts # Webhook trigger node
56+
```
57+
58+
### Key design decisions
59+
60+
- **Envelopes API only**: Document and Template resources both use `client.envelopes.*` under the hood. Document passes `type: "DOCUMENT"`, Template passes `type: "TEMPLATE"`. We do NOT use the older `client.documents.*` or `client.templates.*` SDK methods.
61+
- **Parameter naming**: Use `documentId`/`templateId` in user-facing params, map to `envelopeId` when calling the SDK.
62+
- **SDK is bundled**: tsdown inlines `@documenso/sdk-typescript` into the output via `noExternal`. Only `n8n-workflow` is external (provided by n8n at runtime). This means the published package has zero runtime dependencies.
63+
- **CJS output**: n8n requires CommonJS. tsdown outputs `.js` (not `.cjs`) via `outExtensions`.
64+
65+
### Adding a new operation
66+
67+
1. Create `src/nodes/Documenso/actions/<resource>/<operation>.operation.ts`
68+
2. Export `description: INodeProperties[]` with `displayOptions: { show: { resource: [...], operation: [...] } }`
69+
3. Export `async function execute(this: IExecuteFunctions, itemIndex: number): Promise<any>`
70+
4. Import and register in the resource's `index.ts` (add to `descriptions` array and `operations` map)
71+
5. If adding a new resource, also register in `Documenso.node.ts`, `router.ts`, and the resource options list
72+
73+
### Operation file pattern
74+
75+
```ts
76+
import type { IExecuteFunctions, INodeProperties } from "n8n-workflow";
77+
import { getDocumensoClient, handleDocumensoError } from "../../GenericFunctions";
78+
79+
export const description: INodeProperties[] = [
80+
{
81+
displayName: "Document ID",
82+
name: "documentId",
83+
type: "string",
84+
required: true,
85+
default: "",
86+
displayOptions: { show: { resource: ["document"], operation: ["myOp"] } },
87+
},
88+
];
89+
90+
export async function execute(this: IExecuteFunctions, itemIndex: number): Promise<any> {
91+
const documentId = this.getNodeParameter("documentId", itemIndex) as string;
92+
try {
93+
const client = await getDocumensoClient(this);
94+
return await client.envelopes.someMethod({ envelopeId: documentId });
95+
} catch (error) {
96+
handleDocumensoError(this, error, itemIndex);
97+
}
98+
}
99+
```
100+
101+
### UX conventions
102+
103+
- Use **fixedCollection** with `multipleValues: true` instead of JSON inputs for structured data (recipients, fields, etc.)
104+
- Use user-friendly operation names: "Send" not "Distribute", "Resend" not "Redistribute"
105+
- Coordinates are **percentages** (0–100) of page width/height, not pixels
106+
- Field positioning supports both **placeholder text matching** (`{{signature}}`) and coordinate modes
107+
- The "Create and Send" operation is the happy path — upload PDF + recipients + fields + send in one step
108+
109+
### Build
110+
111+
tsdown bundles entry points to `dist/`. The `copy` config in `tsdown.config.ts` handles static assets (SVG icon, codex JSON). When adding a new node, add its entry to `tsdown.config.ts` and `package.json`'s `n8n.nodes` array.
112+
113+
### Testing locally
114+
115+
`docker compose up` mounts `dist/` and `package.json` into n8n's custom nodes directory. The node appears in n8n's palette at http://localhost:5678.

0 commit comments

Comments
 (0)