@festapp/banksync 0.2.3 → 0.2.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -610,7 +610,7 @@ function retryAfterSeconds(headers) {
|
|
|
610
610
|
return Number.isFinite(n) && n >= 0 ? n : null;
|
|
611
611
|
}
|
|
612
612
|
async function ensureFioResponse(res, proxy) {
|
|
613
|
-
if (res.status === 500 &&
|
|
613
|
+
if (res.status === 500 && !proxy || proxy && [422, 500].includes(res.status) && res.headers.get("x-fio-upstream-status") === "500") {
|
|
614
614
|
throw new FioTokenInvalidOrInactive();
|
|
615
615
|
}
|
|
616
616
|
if (res.status === 429 || res.status === 409) {
|
|
@@ -610,7 +610,7 @@ function retryAfterSeconds(headers) {
|
|
|
610
610
|
return Number.isFinite(n) && n >= 0 ? n : null;
|
|
611
611
|
}
|
|
612
612
|
async function ensureFioResponse(res, proxy) {
|
|
613
|
-
if (res.status === 500 &&
|
|
613
|
+
if (res.status === 500 && !proxy || proxy && [422, 500].includes(res.status) && res.headers.get("x-fio-upstream-status") === "500") {
|
|
614
614
|
throw new FioTokenInvalidOrInactive();
|
|
615
615
|
}
|
|
616
616
|
if (res.status === 429 || res.status === 409) {
|
package/dist/cloudflare.cjs
CHANGED
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
|
|
12
12
|
|
|
13
13
|
|
|
14
|
-
var
|
|
14
|
+
var _chunk5SYCSFXKcjs = require('./chunk-5SYCSFXK.cjs');
|
|
15
15
|
|
|
16
16
|
// src/mime.ts
|
|
17
17
|
var _postalmime = require('postal-mime'); var _postalmime2 = _interopRequireDefault(_postalmime);
|
|
@@ -68,13 +68,13 @@ function classifyEmail(extracted, identity, account, allowlist) {
|
|
|
68
68
|
if (account.ingest_mode === "api") {
|
|
69
69
|
return { kind: "reject", reason: "email_ingest_disabled", bankAccountId: account.id, received: false };
|
|
70
70
|
}
|
|
71
|
-
const provider =
|
|
71
|
+
const provider = _chunk5SYCSFXKcjs.detectProvider.call(void 0, extracted.text, account.account_number);
|
|
72
72
|
if (provider === "unknown") {
|
|
73
73
|
return { kind: "reject", reason: `unknown_provider: ${account.account_number}`, bankAccountId: account.id, received: true };
|
|
74
74
|
}
|
|
75
75
|
let parsed;
|
|
76
76
|
try {
|
|
77
|
-
parsed =
|
|
77
|
+
parsed = _chunk5SYCSFXKcjs.parseEmail.call(void 0, extracted.text, provider);
|
|
78
78
|
} catch (err) {
|
|
79
79
|
return { kind: "reject", reason: `${err}`.replace(/^Error:\s*/, ""), bankAccountId: account.id, received: true };
|
|
80
80
|
}
|
|
@@ -611,7 +611,7 @@ async function insertTransaction(db, args) {
|
|
|
611
611
|
const v2 = _optionalChain([schema, 'optionalAccess', _16 => _16.value]) === "11";
|
|
612
612
|
const p = {
|
|
613
613
|
...args.payload,
|
|
614
|
-
vs: v2 ? _nullishCoalesce(_nullishCoalesce(args.payload.raw_vs, () => ( args.payload.vs)), () => ( null)) :
|
|
614
|
+
vs: v2 ? _nullishCoalesce(_nullishCoalesce(args.payload.raw_vs, () => ( args.payload.vs)), () => ( null)) : _chunk5SYCSFXKcjs.resolveVariableSymbol.call(void 0, args.payload)
|
|
615
615
|
};
|
|
616
616
|
if (p.transaction_id != null && p.source === "fio_api") {
|
|
617
617
|
const hit = await db.prepare(SQL_FIND_DUPLICATE_FIO).bind(args.bank_account_id, p.transaction_id).first();
|
|
@@ -1228,7 +1228,7 @@ async function ensureDeliveryJobs(db, transactionId, cutover) {
|
|
|
1228
1228
|
for (const row of candidates.results) {
|
|
1229
1229
|
const { pairing_code, consumer_app_id, event_version, created_at: _createdAt, ...transaction } = row;
|
|
1230
1230
|
const deliveryId = _ulid.ulid.call(void 0, );
|
|
1231
|
-
const envelope =
|
|
1231
|
+
const envelope = _chunk5SYCSFXKcjs.buildWebhookEnvelope.call(void 0, {
|
|
1232
1232
|
delivery_id: deliveryId,
|
|
1233
1233
|
pairing_code: row.pairing_code,
|
|
1234
1234
|
transaction,
|
|
@@ -1550,7 +1550,7 @@ async function httpResult(response, deliveryId, usedPrevSecret, primaryStatus) {
|
|
|
1550
1550
|
return "receipt" in parsed ? { kind: "http", httpStatus: response.status, usedPrevSecret, primaryStatus, receipt: parsed.receipt } : { kind: "http", httpStatus: response.status, usedPrevSecret, primaryStatus, receiptError: parsed.error };
|
|
1551
1551
|
}
|
|
1552
1552
|
async function postSigned(url2, envelope, secret) {
|
|
1553
|
-
const signed = await
|
|
1553
|
+
const signed = await _chunk5SYCSFXKcjs.signWebhook.call(void 0, { envelope, secret });
|
|
1554
1554
|
const controller = new AbortController();
|
|
1555
1555
|
const timeoutId = setTimeout(() => controller.abort(), FETCH_TIMEOUT_MS);
|
|
1556
1556
|
try {
|
|
@@ -2708,7 +2708,7 @@ async function recoverBankAccount(db, account, env, proxy) {
|
|
|
2708
2708
|
let statement;
|
|
2709
2709
|
if (batch.cipher !== null && batch.key_version !== null) statement = JSON.parse(await decryptSecret(batch.cipher, batch.key_version, env));
|
|
2710
2710
|
else {
|
|
2711
|
-
statement = await
|
|
2711
|
+
statement = await _chunk5SYCSFXKcjs.fetchFioStatement.call(void 0, credential, batch.from_date, batch.to_date, proxy);
|
|
2712
2712
|
await renew();
|
|
2713
2713
|
const encrypted = await encryptSecret(JSON.stringify(statement), env);
|
|
2714
2714
|
await db.prepare(`UPDATE bank_recovery_batches SET cipher=?,key_version=?,state='spooled' WHERE id=?`).bind(encrypted.cipher, encrypted.keyVersion, batch.id).run();
|
|
@@ -2720,7 +2720,7 @@ async function recoverBankAccount(db, account, env, proxy) {
|
|
|
2720
2720
|
let inserted = 0, skipped = 0;
|
|
2721
2721
|
for (const raw of statement.transactions) {
|
|
2722
2722
|
await renew();
|
|
2723
|
-
const mapped =
|
|
2723
|
+
const mapped = _chunk5SYCSFXKcjs.mapFioTransaction.call(void 0, raw);
|
|
2724
2724
|
if (!mapped || mapped.identity_kind !== "movement") throw new Error("fio_unverified_movement");
|
|
2725
2725
|
if (mapped.currency !== String(_nullishCoalesce(_optionalChain([statement, 'access', _63 => _63.info, 'optionalAccess', _64 => _64.currency]), () => ( ""))).toUpperCase()) throw new Error("fio_statement_currency_mismatch");
|
|
2726
2726
|
const result = await insertTransaction(db, { bank_account_id: account.id, payload: mapped });
|
|
@@ -2969,7 +2969,7 @@ async function runBankApiSync(env, account) {
|
|
|
2969
2969
|
const token = await decryptSecret(account.api_token_cipher, account.api_token_key_ver, env);
|
|
2970
2970
|
if (isBackfill && account.api_last_success_at === null) {
|
|
2971
2971
|
await markBankAccountApiFetchStarted(env.DB, account.id);
|
|
2972
|
-
await
|
|
2972
|
+
await _chunk5SYCSFXKcjs.setFioPointer.call(void 0, token, yyyyMmDdDaysAgo(90), fioProxyConfig(env));
|
|
2973
2973
|
await markBankAccountApiPointerSet(env.DB, account.id);
|
|
2974
2974
|
await writeEvent(env.DB, {
|
|
2975
2975
|
event_type: "api_pointer_set",
|
|
@@ -2989,7 +2989,7 @@ async function runBankApiSync(env, account) {
|
|
|
2989
2989
|
};
|
|
2990
2990
|
}
|
|
2991
2991
|
await markBankAccountApiFetchStarted(env.DB, account.id);
|
|
2992
|
-
const raw = await
|
|
2992
|
+
const raw = await _chunk5SYCSFXKcjs.fetchNewTransactions.call(void 0, token, fioProxyConfig(env));
|
|
2993
2993
|
let inserted = 0;
|
|
2994
2994
|
let skippedDuplicate = 0;
|
|
2995
2995
|
let skippedOutgoing = 0;
|
|
@@ -2998,7 +2998,7 @@ async function runBankApiSync(env, account) {
|
|
|
2998
2998
|
for (const item of raw) {
|
|
2999
2999
|
let mapped;
|
|
3000
3000
|
try {
|
|
3001
|
-
mapped =
|
|
3001
|
+
mapped = _chunk5SYCSFXKcjs.mapFioTransaction.call(void 0, item);
|
|
3002
3002
|
} catch (err) {
|
|
3003
3003
|
parseErrors++;
|
|
3004
3004
|
await insertParseLog(env.DB, {
|
|
@@ -3053,8 +3053,8 @@ async function runBankApiSync(env, account) {
|
|
|
3053
3053
|
deferred: false
|
|
3054
3054
|
};
|
|
3055
3055
|
} catch (err) {
|
|
3056
|
-
await markBankAccountApiFetchFailure(env.DB, account.id, err instanceof
|
|
3057
|
-
if (err instanceof
|
|
3056
|
+
await markBankAccountApiFetchFailure(env.DB, account.id, err instanceof _chunk5SYCSFXKcjs.FioTokenInvalidOrInactive ? err.code : String(err));
|
|
3057
|
+
if (err instanceof _chunk5SYCSFXKcjs.FioRateLimited) {
|
|
3058
3058
|
await writeEvent(env.DB, {
|
|
3059
3059
|
event_type: "api_rate_limited",
|
|
3060
3060
|
bank_account_id: account.id,
|
|
@@ -3079,11 +3079,11 @@ async function runDueBankApiSyncs(env) {
|
|
|
3079
3079
|
deferred: result.deferred
|
|
3080
3080
|
});
|
|
3081
3081
|
} catch (err) {
|
|
3082
|
-
if (err instanceof
|
|
3082
|
+
if (err instanceof _chunk5SYCSFXKcjs.FioRateLimited) {
|
|
3083
3083
|
log("api_rate_limited", { bank_account_id: account.id, account_type: account.account_type, retry_after_s: err.retryAfterS });
|
|
3084
3084
|
continue;
|
|
3085
3085
|
}
|
|
3086
|
-
if (err instanceof
|
|
3086
|
+
if (err instanceof _chunk5SYCSFXKcjs.FioTransientFailure) {
|
|
3087
3087
|
logError("api_transient_failure", err, { bank_account_id: account.id, account_type: account.account_type });
|
|
3088
3088
|
continue;
|
|
3089
3089
|
}
|
|
@@ -3551,10 +3551,10 @@ async function dispatch(url2, req, env, authCtx, bodyText) {
|
|
|
3551
3551
|
api_backfill_done: _nullishCoalesce(_optionalChain([updated, 'optionalAccess', _99 => _99.api_backfill_done]), () => ( false))
|
|
3552
3552
|
});
|
|
3553
3553
|
} catch (err) {
|
|
3554
|
-
if (err instanceof
|
|
3554
|
+
if (err instanceof _chunk5SYCSFXKcjs.FioTokenInvalidOrInactive) {
|
|
3555
3555
|
return jsonResponse({ error: err.code, bank_http_status: err.status }, 422);
|
|
3556
3556
|
}
|
|
3557
|
-
if (err instanceof
|
|
3557
|
+
if (err instanceof _chunk5SYCSFXKcjs.FioRateLimited || err instanceof _chunk5SYCSFXKcjs.FioTransientFailure) {
|
|
3558
3558
|
logError("fio_api_manual_sync_failed", err, { bank_account_id: id });
|
|
3559
3559
|
return jsonResponse({ error: "fio_api_transient_failure" }, 503);
|
|
3560
3560
|
}
|
package/dist/cloudflare.js
CHANGED
package/dist/index.cjs
CHANGED
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
|
|
21
21
|
|
|
22
22
|
|
|
23
|
-
var
|
|
23
|
+
var _chunk5SYCSFXKcjs = require('./chunk-5SYCSFXK.cjs');
|
|
24
24
|
|
|
25
25
|
|
|
26
26
|
|
|
@@ -43,4 +43,4 @@ var _chunk6TJITWUFcjs = require('./chunk-6TJITWUF.cjs');
|
|
|
43
43
|
|
|
44
44
|
|
|
45
45
|
|
|
46
|
-
exports.BANK_CODES =
|
|
46
|
+
exports.BANK_CODES = _chunk5SYCSFXKcjs.BANK_CODES; exports.FioApiError = _chunk5SYCSFXKcjs.FioApiError; exports.FioRateLimited = _chunk5SYCSFXKcjs.FioRateLimited; exports.FioTokenInvalidOrInactive = _chunk5SYCSFXKcjs.FioTokenInvalidOrInactive; exports.FioTransientFailure = _chunk5SYCSFXKcjs.FioTransientFailure; exports.WebhookVerificationError = _chunk5SYCSFXKcjs.WebhookVerificationError; exports.buildWebhookEnvelope = _chunk5SYCSFXKcjs.buildWebhookEnvelope; exports.decimalToCents = _chunk5SYCSFXKcjs.decimalToCents; exports.decodeRf = _chunk5SYCSFXKcjs.decodeRf; exports.detectProvider = _chunk5SYCSFXKcjs.detectProvider; exports.encodeRf = _chunk5SYCSFXKcjs.encodeRf; exports.extractReferenceCandidates = _chunk5SYCSFXKcjs.extractReferenceCandidates; exports.fetchNewTransactions = _chunk5SYCSFXKcjs.fetchNewTransactions; exports.mapFioTransaction = _chunk5SYCSFXKcjs.mapFioTransaction; exports.normalizeCurrency = _chunk5SYCSFXKcjs.normalizeCurrency; exports.parseEmail = _chunk5SYCSFXKcjs.parseEmail; exports.resolveVariableSymbol = _chunk5SYCSFXKcjs.resolveVariableSymbol; exports.setFioPointer = _chunk5SYCSFXKcjs.setFioPointer; exports.signWebhook = _chunk5SYCSFXKcjs.signWebhook; exports.toCents = _chunk5SYCSFXKcjs.toCents; exports.verifyWebhook = _chunk5SYCSFXKcjs.verifyWebhook;
|
package/dist/index.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@festapp/banksync",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.4",
|
|
4
4
|
"description": "Bank transaction ingestion for Cloudflare Workers: Czech bank email and Fio API parsing, durable deduplication, and signed webhook delivery.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"packageManager": "pnpm@11.24.0",
|