@firela/hk-hsbc-credit 0.1.0
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.
- package/hk_hsbc_credit.opt.wasm +0 -0
- package/index-node.cjs +159 -0
- package/index-worker.js +134 -0
- package/index.d.ts +88 -0
- package/package.json +37 -0
|
Binary file
|
package/index-node.cjs
ADDED
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
// _loader-template-node.cjs
|
|
3
|
+
//
|
|
4
|
+
// Phase 74 npm-package Node loader TEMPLATE. At package-assembly time,
|
|
5
|
+
// scripts/assemble-npm-packages.sh sed-substitutes hk_hsbc_credit.opt.wasm with the
|
|
6
|
+
// crate's underscored .opt.wasm name (e.g. eu_deutsche_bank.opt.wasm) and
|
|
7
|
+
// writes the result as `index-node.cjs` into dist/@firela/<name>/. One
|
|
8
|
+
// template serves all 7 publishable packages.
|
|
9
|
+
//
|
|
10
|
+
// This is a rename + templating of the PROVEN loaders/node.js FFI cycle
|
|
11
|
+
// (26 MB/s flat on Node V8 — the run that isolated the wasmi 0.31 superlinear
|
|
12
|
+
// root cause). DO NOT add new behavior here; if the cycle needs to change,
|
|
13
|
+
// change loaders/node.js first and re-template.
|
|
14
|
+
//
|
|
15
|
+
// Contract (docs/WASM_BOUNDARY.md §4): every parser .wasm exports
|
|
16
|
+
// alloc(size)->ptr, parse(inputPtr,inputLen)->u64, detect(inputPtr,inputLen)->u8,
|
|
17
|
+
// free_result(ptr,len), + linear `memory`, with ZERO imports.
|
|
18
|
+
// `WebAssembly.instantiate(bytes, {})` — the empty import object encodes that.
|
|
19
|
+
//
|
|
20
|
+
// FFI cycle (identical to the Worker branch — only the module-load differs):
|
|
21
|
+
// alloc(inputLen) → inputPtr; on 0 return ProcessFailure INTERNAL OOM
|
|
22
|
+
// RE-FETCH view: new Uint8Array(ex.memory.buffer).set(input, inputPtr)
|
|
23
|
+
// (a grow inside parse/alloc invalidates any cached ArrayBuffer —
|
|
24
|
+
// RESEARCH Pitfall 3; must re-fetch every cycle)
|
|
25
|
+
// ex.parse(inputPtr, inputLen) → BigInt packed; trap caught → ProcessFailure
|
|
26
|
+
// INTERNAL, free input best-effort, do NOT rethrow
|
|
27
|
+
// ptr = Number(packed & 0xffffffffn); len = Number((packed >> 32n) & 0xffffffffn)
|
|
28
|
+
// decode JSON from memory.buffer slice [ptr, ptr+len]
|
|
29
|
+
// ex.free_result(inputPtr, inputLen); ex.free_result(ptr, len) — BOTH buffers
|
|
30
|
+
//
|
|
31
|
+
// CF Worker BRANCHES ONLY at module-load (workerd blocks instantiate(bytes));
|
|
32
|
+
// see _loader-template-worker.js. After instantiation the FFI cycle is identical.
|
|
33
|
+
|
|
34
|
+
const fs = require('fs');
|
|
35
|
+
const path = require('path');
|
|
36
|
+
|
|
37
|
+
const REQUIRED_EXPORTS = ['alloc', 'parse', 'detect', 'free_result', 'memory'];
|
|
38
|
+
|
|
39
|
+
/// Build a ProcessFailure-shaped object matching the sdk-core wire envelope
|
|
40
|
+
/// `{success:false, errors:[{code, message}]}`. Used when the HOST catches a
|
|
41
|
+
/// trap / OOM (the parser's own failures arrive as normal ProcessFailure JSON).
|
|
42
|
+
function processFailure(code, message) {
|
|
43
|
+
return { success: false, errors: [{ code, message }] };
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// The wasm bytes are read ONCE at module load (not per-call) — Node caches the
|
|
47
|
+
// file read, and the bytes are immutable. WebAssembly instantiation is deferred
|
|
48
|
+
// to first use (lazy _exports cache below) so the module is cheap to require.
|
|
49
|
+
const wasmBytes = fs.readFileSync(path.join(__dirname, 'hk_hsbc_credit.opt.wasm'));
|
|
50
|
+
|
|
51
|
+
let _exports;
|
|
52
|
+
|
|
53
|
+
/// Lazily instantiate the wasm module ONCE. Cached so the cold-start cost is
|
|
54
|
+
/// paid only on the first parse/detect call. Returns the exports object.
|
|
55
|
+
async function getExports() {
|
|
56
|
+
if (!_exports) {
|
|
57
|
+
const { instance } = await WebAssembly.instantiate(wasmBytes, {}); // {} = zero imports
|
|
58
|
+
_exports = instance.exports;
|
|
59
|
+
}
|
|
60
|
+
return _exports;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function makeParse(ex) {
|
|
64
|
+
return async function parse(bytes) {
|
|
65
|
+
const input = Buffer.isBuffer(bytes) ? bytes : Buffer.from(bytes);
|
|
66
|
+
const inputLen = input.length;
|
|
67
|
+
|
|
68
|
+
const inputPtr = ex.alloc(inputLen);
|
|
69
|
+
if (inputPtr === 0) {
|
|
70
|
+
// OOM: nothing was allocated, nothing to free.
|
|
71
|
+
return processFailure('INTERNAL', 'alloc returned 0 (OOM) for ' + inputLen + ' bytes');
|
|
72
|
+
}
|
|
73
|
+
// Re-fetch the view EVERY cycle: a grow inside parse/alloc invalidates
|
|
74
|
+
// any cached ArrayBuffer over ex.memory.buffer (RESEARCH Pitfall 3).
|
|
75
|
+
new Uint8Array(ex.memory.buffer).set(input, inputPtr);
|
|
76
|
+
|
|
77
|
+
let packed;
|
|
78
|
+
try {
|
|
79
|
+
packed = ex.parse(inputPtr, inputLen); // arrives as BigInt (i64)
|
|
80
|
+
} catch (e) {
|
|
81
|
+
// WASM trap (RuntimeError): free the input buffer, surface as
|
|
82
|
+
// ProcessFailure — do NOT rethrow. Instance stays reusable.
|
|
83
|
+
try {
|
|
84
|
+
ex.free_result(inputPtr, inputLen);
|
|
85
|
+
} catch {
|
|
86
|
+
/* allocator already torn down — best-effort free */
|
|
87
|
+
}
|
|
88
|
+
return processFailure(
|
|
89
|
+
'INTERNAL',
|
|
90
|
+
'wasm trap: ' + ((e && e.message) || String(e))
|
|
91
|
+
);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
const ptr = Number(packed & 0xffffffffn); // low 32 = result ptr
|
|
95
|
+
const len = Number((packed >> 32n) & 0xffffffffn); // high 32 = result len
|
|
96
|
+
if (ptr === 0 || len === 0) {
|
|
97
|
+
try {
|
|
98
|
+
ex.free_result(inputPtr, inputLen);
|
|
99
|
+
} catch {
|
|
100
|
+
/* best-effort */
|
|
101
|
+
}
|
|
102
|
+
return processFailure('INTERNAL', 'parse returned empty result');
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
const resultBytes = Buffer.from(new Uint8Array(ex.memory.buffer, ptr, len));
|
|
106
|
+
const json = JSON.parse(resultBytes.toString('utf8'));
|
|
107
|
+
|
|
108
|
+
// Free BOTH buffers every cycle (input + result) per the FFI contract.
|
|
109
|
+
ex.free_result(inputPtr, inputLen);
|
|
110
|
+
ex.free_result(ptr, len);
|
|
111
|
+
return json;
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
function makeDetect(ex) {
|
|
116
|
+
return async function detect(bytes) {
|
|
117
|
+
const input = Buffer.isBuffer(bytes) ? bytes : Buffer.from(bytes);
|
|
118
|
+
const inputLen = input.length;
|
|
119
|
+
const inputPtr = ex.alloc(inputLen);
|
|
120
|
+
if (inputPtr === 0) return 0;
|
|
121
|
+
new Uint8Array(ex.memory.buffer).set(input, inputPtr);
|
|
122
|
+
let conf;
|
|
123
|
+
try {
|
|
124
|
+
conf = ex.detect(inputPtr, inputLen); // u8 confidence (0/50/100)
|
|
125
|
+
} catch (e) {
|
|
126
|
+
try {
|
|
127
|
+
ex.free_result(inputPtr, inputLen);
|
|
128
|
+
} catch {
|
|
129
|
+
/* best-effort */
|
|
130
|
+
}
|
|
131
|
+
return 0; // a trap in detect → treat as "no match"
|
|
132
|
+
}
|
|
133
|
+
ex.free_result(inputPtr, inputLen);
|
|
134
|
+
return conf;
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/// Parse CSV/JSON bytes into structured JSON. Returns the parser's own envelope
|
|
139
|
+
/// (ProcessSuccess `{success:true, data, warnings?}` or ProcessFailure). A WASM
|
|
140
|
+
/// trap during parse() is caught and surfaced as ProcessFailure — the host
|
|
141
|
+
/// never crashes and the instance stays reusable (RUNT-02).
|
|
142
|
+
async function parse(bytes) {
|
|
143
|
+
const ex = await getExports();
|
|
144
|
+
const missing = REQUIRED_EXPORTS.filter((name) => !ex[name]);
|
|
145
|
+
if (missing.length) {
|
|
146
|
+
throw new Error(
|
|
147
|
+
'createParser: missing required WASM exports: ' + missing.join(', ')
|
|
148
|
+
);
|
|
149
|
+
}
|
|
150
|
+
return makeParse(ex)(bytes);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/// Detection confidence (0/50/100) for bytes.
|
|
154
|
+
async function detect(bytes) {
|
|
155
|
+
const ex = await getExports();
|
|
156
|
+
return makeDetect(ex)(bytes);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
module.exports = { parse, detect };
|
package/index-worker.js
ADDED
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
// _loader-template-worker.js
|
|
2
|
+
//
|
|
3
|
+
// Phase 74 npm-package CF Worker loader TEMPLATE. At package-assembly time,
|
|
4
|
+
// scripts/assemble-npm-packages.sh sed-substitutes hk_hsbc_credit.opt.wasm with the
|
|
5
|
+
// crate's underscored .opt.wasm name (e.g. eu_deutsche_bank.opt.wasm) and
|
|
6
|
+
// writes the result as `index-worker.js` into dist/@firela/<name>/. One
|
|
7
|
+
// template serves all 7 publishable packages.
|
|
8
|
+
//
|
|
9
|
+
// HARD CONSTRAINT (Cloudflare Workers runtime): dynamic WASM *compilation* is
|
|
10
|
+
// BLOCKED (like eval). A parser .wasm MUST be loaded as a Wrangler-bundled,
|
|
11
|
+
// pre-compiled ES-module Module:
|
|
12
|
+
//
|
|
13
|
+
// import mod from "./eu_deutsche_bank.wasm"; // mod is a WebAssembly.Module
|
|
14
|
+
//
|
|
15
|
+
// ...NOT `fs.readFileSync(...)` + `WebAssembly.instantiate(bytes)`. There is no
|
|
16
|
+
// Node `fs` here and `WebAssembly.instantiate(bytes)` is disallowed at runtime.
|
|
17
|
+
// (https://developers.cloudflare.com/workers/runtime-apis/webassembly/)
|
|
18
|
+
//
|
|
19
|
+
// FFI contract (docs/WASM_BOUNDARY.md §4): every parser .wasm exports
|
|
20
|
+
// alloc(size)->ptr, parse(inputPtr,inputLen)->u64, detect(inputPtr,inputLen)->u8,
|
|
21
|
+
// free_result(ptr,len), + linear `memory`, with ZERO imports. The empty import
|
|
22
|
+
// object `{}` below encodes that.
|
|
23
|
+
//
|
|
24
|
+
// This is the ES-import-constrained variant of the Node loader's FFI cycle
|
|
25
|
+
// (loaders/node.js). The alloc → re-fetch view → set → parse (trap-safe)
|
|
26
|
+
// → unpack packed ptr/len → decode → JSON → free BOTH buffers cycle is IDENTICAL
|
|
27
|
+
// to the Node branch; only the WASM entry differs (pre-compiled Module vs raw
|
|
28
|
+
// bytes). The branch is ONLY at module-load.
|
|
29
|
+
|
|
30
|
+
import mod from "./hk_hsbc_credit.opt.wasm";
|
|
31
|
+
|
|
32
|
+
const REQUIRED_EXPORTS = ['alloc', 'parse', 'detect', 'free_result', 'memory'];
|
|
33
|
+
|
|
34
|
+
// Instantiate ONCE, lazily on first request (per CF official guidance — top-level
|
|
35
|
+
// instantiation; the result is cached so the cold-start cost is paid once). `mod`
|
|
36
|
+
// is a pre-compiled WebAssembly.Module, so instantiate() returns an Instance
|
|
37
|
+
// (unlike the bytes overload, which returns {module, instance}) — handle both.
|
|
38
|
+
let _exports;
|
|
39
|
+
async function getExports() {
|
|
40
|
+
if (!_exports) {
|
|
41
|
+
const result = await WebAssembly.instantiate(mod, {}); // {} = zero imports
|
|
42
|
+
const instance = result.instance || result; // bytes→{instance}, Module→Instance
|
|
43
|
+
_exports = instance.exports;
|
|
44
|
+
}
|
|
45
|
+
return _exports;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function processFailure(code, message) {
|
|
49
|
+
return { success: false, errors: [{ code, message }] };
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/// Parse CSV/JSON bytes into structured JSON. Returns the parser's own envelope
|
|
53
|
+
/// (ProcessSuccess `{success:true, data, warnings?}` or ProcessFailure). A WASM
|
|
54
|
+
/// trap during parse() is caught and surfaced as ProcessFailure — the Worker
|
|
55
|
+
/// never crashes and the instance stays reusable (RUNT-02 CF half).
|
|
56
|
+
export async function parse(bytes) {
|
|
57
|
+
const ex = await getExports();
|
|
58
|
+
const input = bytes instanceof Uint8Array ? bytes : new Uint8Array(bytes);
|
|
59
|
+
const inputLen = input.length;
|
|
60
|
+
|
|
61
|
+
const inputPtr = ex.alloc(inputLen);
|
|
62
|
+
if (inputPtr === 0) {
|
|
63
|
+
// OOM: nothing allocated, nothing to free.
|
|
64
|
+
return processFailure(
|
|
65
|
+
'INTERNAL',
|
|
66
|
+
'alloc returned 0 (OOM) for ' + inputLen + ' bytes'
|
|
67
|
+
);
|
|
68
|
+
}
|
|
69
|
+
// Re-fetch the view EVERY cycle: a grow inside parse/alloc invalidates any
|
|
70
|
+
// cached ArrayBuffer over ex.memory.buffer (stale-view hazard).
|
|
71
|
+
new Uint8Array(ex.memory.buffer).set(input, inputPtr);
|
|
72
|
+
|
|
73
|
+
let packed;
|
|
74
|
+
try {
|
|
75
|
+
packed = ex.parse(inputPtr, inputLen); // arrives as BigInt (i64)
|
|
76
|
+
} catch (e) {
|
|
77
|
+
// WASM trap (RuntimeError): free the input buffer, surface as
|
|
78
|
+
// ProcessFailure — do NOT rethrow. Instance stays reusable.
|
|
79
|
+
try {
|
|
80
|
+
ex.free_result(inputPtr, inputLen);
|
|
81
|
+
} catch {
|
|
82
|
+
/* allocator already torn down — best-effort free */
|
|
83
|
+
}
|
|
84
|
+
return processFailure(
|
|
85
|
+
'INTERNAL',
|
|
86
|
+
'wasm trap: ' + ((e && e.message) || String(e))
|
|
87
|
+
);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
const ptr = Number(packed & 0xffffffffn); // low 32 = result ptr
|
|
91
|
+
const len = Number((packed >> 32n) & 0xffffffffn); // high 32 = result len
|
|
92
|
+
if (ptr === 0 || len === 0) {
|
|
93
|
+
try {
|
|
94
|
+
ex.free_result(inputPtr, inputLen);
|
|
95
|
+
} catch {
|
|
96
|
+
/* best-effort */
|
|
97
|
+
}
|
|
98
|
+
return processFailure('INTERNAL', 'parse returned empty result');
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
const resultBytes = new Uint8Array(ex.memory.buffer, ptr, len);
|
|
102
|
+
const json = JSON.parse(new TextDecoder().decode(resultBytes));
|
|
103
|
+
|
|
104
|
+
// Free BOTH buffers every cycle (input + result) per the FFI contract.
|
|
105
|
+
ex.free_result(inputPtr, inputLen);
|
|
106
|
+
ex.free_result(ptr, len);
|
|
107
|
+
return json;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/// Detection confidence (0/50/100) for bytes.
|
|
111
|
+
export async function detect(bytes) {
|
|
112
|
+
const ex = await getExports();
|
|
113
|
+
const input = bytes instanceof Uint8Array ? bytes : new Uint8Array(bytes);
|
|
114
|
+
const inputLen = input.length;
|
|
115
|
+
const inputPtr = ex.alloc(inputLen);
|
|
116
|
+
if (inputPtr === 0) return 0;
|
|
117
|
+
new Uint8Array(ex.memory.buffer).set(input, inputPtr);
|
|
118
|
+
let conf;
|
|
119
|
+
try {
|
|
120
|
+
conf = ex.detect(inputPtr, inputLen);
|
|
121
|
+
} catch (e) {
|
|
122
|
+
try {
|
|
123
|
+
ex.free_result(inputPtr, inputLen);
|
|
124
|
+
} catch {
|
|
125
|
+
/* best-effort */
|
|
126
|
+
}
|
|
127
|
+
return 0; // a trap in detect → treat as "no match"
|
|
128
|
+
}
|
|
129
|
+
ex.free_result(inputPtr, inputLen);
|
|
130
|
+
return conf;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
export { parse, detect };
|
|
134
|
+
export default { parse, detect };
|
package/index.d.ts
ADDED
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
// _index-dts.template.ts
|
|
2
|
+
//
|
|
3
|
+
// Phase 74 npm-package TypeScript declarations TEMPLATE. Hand-written from
|
|
4
|
+
// sdk-core/src/types.rs (the wire-format contract). NOT generated by wasm-bindgen
|
|
5
|
+
// — this SDK uses raw extern "C" + serde_json at the FFI boundary (ERRATUM:
|
|
6
|
+
// ADR-0101; wasm-bindgen/serde-wasm-bindgen are NOT used). The surface is small
|
|
7
|
+
// and stable (parse/detect + wire types), so hand-writing is simpler and keeps
|
|
8
|
+
// the declarations free of wasm-bindgen runtime coupling.
|
|
9
|
+
//
|
|
10
|
+
// Wire-format invariants (types.rs §wire-format contract):
|
|
11
|
+
// - `success` is a JSON boolean (true/false), never a string. Hence
|
|
12
|
+
// ProcessSuccess / ProcessFailure use literal `true` / `false` here.
|
|
13
|
+
// - `amount` is an exact decimal STRING ("128.50"), never a float/number
|
|
14
|
+
// (WASM-02: preserve precision across the boundary).
|
|
15
|
+
// - `metadata` is optional; institution-specific fields live there.
|
|
16
|
+
|
|
17
|
+
/// Parsed transaction in stable JSON wire form.
|
|
18
|
+
///
|
|
19
|
+
/// `date` is an ISO 8601 string, `amount` is an exact decimal string (never
|
|
20
|
+
/// f64 — preserves precision per WASM-02), `currency` is ISO 4217.
|
|
21
|
+
export interface RawTransaction {
|
|
22
|
+
/** ISO 8601 date, e.g. "2024-01-15". */
|
|
23
|
+
date: string;
|
|
24
|
+
/** Exact decimal string ("128.50", "-35.00") — NEVER a number. */
|
|
25
|
+
amount: string;
|
|
26
|
+
/** ISO 4217 currency code, e.g. "CNY", "USD", "EUR". */
|
|
27
|
+
currency: string;
|
|
28
|
+
/** Transaction description / narration. */
|
|
29
|
+
description: string;
|
|
30
|
+
/** Payee / counterparty (optional — omitted from JSON when absent). */
|
|
31
|
+
payee?: string;
|
|
32
|
+
/** Institution-specific structured metadata (optional). */
|
|
33
|
+
metadata?: Record<string, unknown>;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/// Non-fatal warning surfaced alongside a successful result.
|
|
37
|
+
export interface ProcessWarning {
|
|
38
|
+
message: string;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/// Categorized processing error. Serializes as `{code, message}` matching the
|
|
42
|
+
/// sdk-core ProcessError enum variants.
|
|
43
|
+
export type ProcessError =
|
|
44
|
+
| { code: 'FORMAT'; message: string }
|
|
45
|
+
| { code: 'DETECT'; message: string }
|
|
46
|
+
| { code: 'ENCODING'; message: string }
|
|
47
|
+
| { code: 'INTERNAL'; message: string };
|
|
48
|
+
|
|
49
|
+
/// Successful parse/sanitize result.
|
|
50
|
+
///
|
|
51
|
+
/// JSON: `{"success": true, "data": [...], "warnings": [...]}` — the `success`
|
|
52
|
+
/// field is always the boolean literal `true`.
|
|
53
|
+
export interface ProcessSuccess {
|
|
54
|
+
success: true;
|
|
55
|
+
data: RawTransaction[];
|
|
56
|
+
warnings?: ProcessWarning[];
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/// Failed parse/sanitize result.
|
|
60
|
+
///
|
|
61
|
+
/// JSON: `{"success": false, "errors": [...]}` — `success` is always `false`.
|
|
62
|
+
export interface ProcessFailure {
|
|
63
|
+
success: false;
|
|
64
|
+
errors: ProcessError[];
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/// Result envelope returned by `parse()`. Discriminated union on the boolean
|
|
68
|
+
/// `success` field — narrow with `result.success === true`.
|
|
69
|
+
export type ParseResult = ProcessSuccess | ProcessFailure;
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Parse CSV/JSON bytes into structured transactions.
|
|
73
|
+
*
|
|
74
|
+
* @param bytes - Statement bytes (Uint8Array or Node Buffer).
|
|
75
|
+
* @returns The parser's wire envelope. On success, `data` is the transaction
|
|
76
|
+
* array; on failure (malformed input, encoding error, internal trap),
|
|
77
|
+
* `errors` lists the categorized error(s). The host never throws on
|
|
78
|
+
* parser-level failures — they arrive as `ProcessFailure`.
|
|
79
|
+
*/
|
|
80
|
+
export declare function parse(bytes: Uint8Array | Buffer): Promise<ParseResult>;
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Detection confidence for the given bytes.
|
|
84
|
+
*
|
|
85
|
+
* @param bytes - Statement bytes to identify.
|
|
86
|
+
* @returns Confidence in {0, 50, 100}: 0 = no match, 50 = partial, 100 = definite.
|
|
87
|
+
*/
|
|
88
|
+
export declare function detect(bytes: Uint8Array | Buffer): Promise<number>;
|
package/package.json
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@firela/hk-hsbc-credit",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "firela parser/sanitizer WASM module — isomorphic Node.js + Cloudflare Worker loader (ADR-0101 compiled-only).",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./index-node.cjs",
|
|
7
|
+
"module": "./index-worker.js",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"node": {
|
|
11
|
+
"require": "./index-node.cjs"
|
|
12
|
+
},
|
|
13
|
+
"worker": "./index-worker.js",
|
|
14
|
+
"default": "./index-worker.js"
|
|
15
|
+
},
|
|
16
|
+
"./package.json": "./package.json"
|
|
17
|
+
},
|
|
18
|
+
"files": [
|
|
19
|
+
"index-node.cjs",
|
|
20
|
+
"index-worker.js",
|
|
21
|
+
"index.d.ts",
|
|
22
|
+
"hk_hsbc_credit.opt.wasm"
|
|
23
|
+
],
|
|
24
|
+
"engines": {
|
|
25
|
+
"node": ">=20"
|
|
26
|
+
},
|
|
27
|
+
"keywords": [
|
|
28
|
+
"firela",
|
|
29
|
+
"wasm",
|
|
30
|
+
"parser",
|
|
31
|
+
"bank-statement",
|
|
32
|
+
"isomorphic"
|
|
33
|
+
],
|
|
34
|
+
"publishConfig": {
|
|
35
|
+
"access": "public"
|
|
36
|
+
}
|
|
37
|
+
}
|