npm.io
1.2.0 • Published 43m ago

@yaotoshi/n8n-sdk

Licence
MIT
Version
1.2.0
Deps
1
Size
67 kB
Vulns
0
Weekly
0

@yaotoshi/n8n-sdk

SDK TypeScript untuk otomasi n8n yaotoshi — kirim notifikasi WhatsApp, terjemahkan invoice/packing list China dari Google Drive, cek input pembelian importir, dan ambil hasilnya lewat view layer (URL capability tanpa x-api-key). Tipe & klien di-generate dari openapi.json (via openapi-fetch; satu-satunya dependensi runtime, sangat kecil), dual ESM/CJS. Endpoint baru di openapi.json otomatis tersedia sebagai api.POST('/path') — tanpa menulis request helper tangan.

Kontrak v1 (major): POST /webhook/translate-invoice dan /webhook/cek-importir-pembelian selalu membalas 202 (ViewResult dengan status: 'processing') — tidak ada lagi respons HTML sinkron. Hasil diambil via view layer GET /view/<type>/<id> (HTML) / .json (data) — tanpa x-api-key; id capability-nya sendiri adalah secret-nya. wait: true di SDK = polling klien ke view .json (tidak ada parameter wait di wire).

Instalasi

npm install @yaotoshi/n8n-sdk

Penggunaan singkat

import { createN8nClient } from '@yaotoshi/n8n-sdk';

const n8n = createN8nClient({
  apiKey: process.env.N8N_WEBHOOK_SECRET, // nilai header x-api-key (webhook saja)
  // baseUrl opsional; default https://n8n.yaotoshi.xyz
});
Kirim notifikasi WhatsApp
const res = await n8n.sendWa({ to: 'me', message: 'Halo dari SDK' });
// res: { ok: true, messageId: '...', toJid: '6281...@s.whatsapp.net' }

// dengan media (URL publik yang bisa di-download gateway):
await n8n.sendWa({ to: 'me', message: 'Foto 🌄', mediaUrl: 'https://picsum.photos/300' });

to diisi nama penerima (alias/display_name dari direktori penerima), bukan nomor/JID — nomor mentah ditolak.

Terjemahkan invoice dari Google Drive (selalu 202)
const res = await n8n.translateInvoice({
  link: 'https://drive.google.com/file/d/<id>/view',
  // sheetIndex opsional (0-based, default 0) — untuk spreadsheet;
  // di luar jangkauan -> error 400
});
// res: ViewResult
// { ok: true, result_id: '<id capability>', view_type: 'translate',
//   status: 'processing', view: 'https://n8n.yaotoshi.xyz/view/translate/<id>' }

Hasil diambil lewat view layer — segera (polling manual) atau otomatis dengan wait: true (polling klien 3 detik, timeout 5 menit, sampai status: 'done'):

// polling klien: POST 202 -> loop GET view .json sampai done (maks 5 menit)
const done = await n8n.translateInvoice({ link: 'https://drive.google.com/file/d/<id>/view' }, { wait: true });
console.log(done.status, done.verdict, done.markdown); // done, 'TIDAK BERMASALAH', '## ...'
Cek input pembelian importir (selalu 202)
const res = await n8n.checkImportirPembelian({
  id: '5', // nota pembelian importir di cahub
  link: 'https://docs.google.com/spreadsheets/d/<id>/edit', // invoice/packing list
  // sheetIndex opsional (0-based, default 0)
});
// res: ViewResult { ok: true, result_id, view_type: 'cek-importir', status: 'processing', view }

const done = await n8n.checkImportirPembelian({ id: '5', link: '...' }, { wait: true });
Lihat hasil tersimpan (view layer)

URL view dari respons 202 bisa dibuka langsung di browser (HTML, tanpa x-api-key) atau diambil datanya:

// data row hasil (status processing|done + markdown/verdict/issues/model/dst.)
const row = await n8n.getViewData({ type: 'translate', id: res.result_id });
console.log(row.status, row.verdict, row.issues);

// proses ulang in-place (id & URL tetap; 404/409/429 -> N8nApiError)
const queued = await n8n.resetViewData({ type: 'translate', id: res.result_id });
// queued: { ok: true, status: 'processing', view: <URL sama> }

Biaya: reset memicu ulang pemrosesan (LLM) — rate limit 1x/60 detik per row.

getTranslateResult({ rid }) adalah alias deprecated (jawaban ViewResult, bukan HTML lama) yang memanggil getViewData. rid numerik ditolak di sisi klien dengan pesan yang menunjuk method legacy di bawah — bukan lagi 404 samar dari server:

/** @deprecated pakai n8n.getViewData({ type: 'translate', id: rid }) */
const row = await n8n.getTranslateResult({ rid: '18aJlfjIddkjDvRTrsEolirT' });

// rid numerik -> N8nApiError 400: "...pakai getLegacyTranslateResultHtml..."

Id legacy numerik tidak dilayani view layer — semua id baru adalah capability random non-numerik (/gen-key). Item lama yang masih ber-id numerik dibaca lewat endpoint deprecated ber-x-api-key yang membalas HTML halaman hasil, dibungkus SDK sebagai getLegacyTranslateResultHtml:

/** @deprecated hanya untuk row ber-id numerik pra-migrasi */
const html = await n8n.getLegacyTranslateResultHtml({ rid: '173' });

Contoh lengkap (dengan error handling)

import { createN8nClient, N8nApiError } from '@yaotoshi/n8n-sdk';

const n8n = createN8nClient({
  apiKey: process.env.N8N_WEBHOOK_SECRET, // nilai header x-api-key
});

try {
  const res = await n8n.checkImportirPembelian(
    { id: '268', link: 'https://docs.google.com/spreadsheets/d/<id>/edit' },
    { wait: true }, // polling klien sampai done (atau timeout 5 menit -> status terakhir)
  );
  if (res.status === 'done') {
    console.log(res.verdict); // 'BERMASALAH (1 masalah)' | 'TIDAK BERMASALAH' | 'GAGAL'
    console.log(res.issues, res.model, res.markdown);
  } else {
    console.log('masih diproses', res.view); // timeout 5 menit
  }
} catch (err) {
  if (err instanceof N8nApiError) {
    console.error('status', err.status, '| pesan:', err.message);
    // status 400 | pesan: Nota pembelian 99999999 tidak ditemukan di cahub
    // (pesan sudah dibersihkan dari sufiks internal n8n, siap dipakai mesin)
  } else {
    throw err;
  }
}

Catatan waktu: wait: true memakai polling klien (3 detik, timeout 5 menit — batas lama proses n8n). Cek yang rute reusenya aktif (hasil terjemahan sudah tersimpan) selesai ~10–30 detik; yang belum pernah diterjemahkan menjalankan terjemahan penuh ~1–2 menit (memakai workflow Terjemahkan secara internal). Gunakan fetch dengan timeout longgar (AbortSignal.timeout(180_000)) bila kamu meneruskan fetch kustom.

Wire selalu 202. wait adalah opsi polling di sisi klien — tidak ada parameter wait di body request.

Error

Semua kegagalan dilempar sebagai N8nApiError:

import { N8nApiError } from '@yaotoshi/n8n-sdk';

try {
  await n8n.sendWa({ to: 'tidak-ada', message: 'x' });
} catch (err) {
  if (err instanceof N8nApiError) {
    console.log(err.status, err.message); // status 400, message berisi daftar alias valid
  }
}
Skenario status message (contoh)
x-api-key salah / tidak ada 401 / 403 x-api-key tidak valid atau tidak diizinkan
Alias tak dikenal 400 Alias tidak dikenal… + daftar alias valid
Alias ambigu (cocok >1 penerima) 400 Daftar kandidat
mediaUrl gagal di-fetch gateway 400 Failed to fetch media…
Link bukan Google Drive 400 Host tidak diizinkan…
sheetIndex di luar jangkauan 400 sheetIndex … di luar jangkauan…
Tipe file tidak didukung 400 Tipe file tidak didukung…
Cek: id/link kosong 400 Field id wajib diisi…
Cek: nota tidak ditemukan 400 Nota pembelian <id> tidak ditemukan di cahub
View: id/type tidak dikenal 404 not found
View: reset saat masih diproses 409 processing (body server: {ok:false, error:'processing'})
View: rate limit (reset per-row 60s / 30 req/menit per IP) 429 rate limited (body server: {ok:false, error:'rate limited'})
getTranslateResult dengan rid numerik 400 (klien) rid numerik legacy tidak dilayani view layer - pakai getLegacyTranslateResultHtml…
Legacy translate-result: rid tidak ada / key salah 400 / 403 pesan error dari body JSON
Koneksi/network TypeError: fetch failed (dari fetch)

Catatan: view layer (getViewData/resetViewData) dipanggil tanpa x-api-key — id capability adalah secret-nya. apiKey tetap wajib di createN8nClient untuk jalur webhook.

Kontribusi / sinkron tipe

Tipe di-generate dari openapi.json:

npm run generate:sdk
npm run build
npm test

Aturan menambah endpoint publik: baca .claude/rules/api-sdk-sync.md di repo n8n-selfhosted — update openapi.json, naikkan version, regenerate, commit satu paket. Setelah regenerate, panggilan typed untuk endpoint baru tersedia otomatis (api.POST('/webhook/...')); wrapper ergonomis (sendWa, translateInvoice) tinggal 3 baris di src/index.ts. CI (publish-n8n-sdk.yml) menolak bila tipe tidak sinkron atau README tidak menyebut method, dan menerbitkan npm otomatis bila versi berbeda.

Dokumentasi API (Scalar)

Live: https://n8n.yaotoshi.xyz/docs/ — kontrak dari openapi.json disajikan server statis kecil (scripts/view-server.mjs di root repo, pm2 n8n-web), di-routing tunnel path /docs* di depan rule n8n biasa. Versi tanpa server juga tersedia: buka docs.html di browser (kontrak di-embed). Regenerasi bila openapi.json berubah:

bash scripts/gen-docs.sh

Lisensi

MIT

Keywords