@firela/pii-redactor 0.1.0 → 0.1.1
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/index-node.cjs +16 -7
- package/index-worker.js +22 -9
- package/index.d.ts +2 -2
- package/package.json +1 -1
package/index-node.cjs
CHANGED
|
@@ -48,16 +48,20 @@ function processFailure(code, message) {
|
|
|
48
48
|
// to first use (lazy _exports cache below) so the module is cheap to require.
|
|
49
49
|
const wasmBytes = fs.readFileSync(path.join(__dirname, 'pii_redactor.opt.wasm'));
|
|
50
50
|
|
|
51
|
-
|
|
51
|
+
// Cache the in-flight instantiation PROMISE (not the resolved value) so
|
|
52
|
+
// concurrent cold-start callers await the SAME instantiate — no parallel
|
|
53
|
+
// instantiation race.
|
|
54
|
+
let _exportsPromise;
|
|
52
55
|
|
|
53
56
|
/// Lazily instantiate the wasm module ONCE. Cached so the cold-start cost is
|
|
54
57
|
/// paid only on the first parse/detect call. Returns the exports object.
|
|
55
58
|
async function getExports() {
|
|
56
|
-
if (!
|
|
57
|
-
|
|
58
|
-
|
|
59
|
+
if (!_exportsPromise) {
|
|
60
|
+
_exportsPromise = WebAssembly.instantiate(wasmBytes, {}).then(({ instance }) => { // {} = zero imports
|
|
61
|
+
return instance.exports;
|
|
62
|
+
});
|
|
59
63
|
}
|
|
60
|
-
return
|
|
64
|
+
return _exportsPromise;
|
|
61
65
|
}
|
|
62
66
|
|
|
63
67
|
function makeParse(ex) {
|
|
@@ -103,11 +107,16 @@ function makeParse(ex) {
|
|
|
103
107
|
}
|
|
104
108
|
|
|
105
109
|
const resultBytes = Buffer.from(new Uint8Array(ex.memory.buffer, ptr, len));
|
|
106
|
-
const
|
|
107
|
-
|
|
110
|
+
const decoded = resultBytes.toString('utf8'); // decode while buffer is valid
|
|
108
111
|
// Free BOTH buffers every cycle (input + result) per the FFI contract.
|
|
109
112
|
ex.free_result(inputPtr, inputLen);
|
|
110
113
|
ex.free_result(ptr, len);
|
|
114
|
+
let json;
|
|
115
|
+
try {
|
|
116
|
+
json = JSON.parse(decoded);
|
|
117
|
+
} catch (e) {
|
|
118
|
+
return processFailure('INTERNAL', 'parse returned malformed JSON: ' + ((e && e.message) || String(e)));
|
|
119
|
+
}
|
|
111
120
|
return json;
|
|
112
121
|
};
|
|
113
122
|
}
|
package/index-worker.js
CHANGED
|
@@ -35,14 +35,23 @@ const REQUIRED_EXPORTS = ['alloc', 'parse', 'detect', 'free_result', 'memory'];
|
|
|
35
35
|
// instantiation; the result is cached so the cold-start cost is paid once). `mod`
|
|
36
36
|
// is a pre-compiled WebAssembly.Module, so instantiate() returns an Instance
|
|
37
37
|
// (unlike the bytes overload, which returns {module, instance}) — handle both.
|
|
38
|
-
|
|
38
|
+
// Cache the in-flight instantiation PROMISE (not the resolved value) so
|
|
39
|
+
// concurrent cold-start callers await the SAME instantiate — no parallel
|
|
40
|
+
// instantiation race. Validates the FFI exports once on first use.
|
|
41
|
+
let _exportsPromise;
|
|
39
42
|
async function getExports() {
|
|
40
|
-
if (!
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
43
|
+
if (!_exportsPromise) {
|
|
44
|
+
_exportsPromise = WebAssembly.instantiate(mod, {}).then((result) => { // {} = zero imports
|
|
45
|
+
const instance = result.instance || result; // bytes→{instance}, Module→Instance
|
|
46
|
+
const ex = instance.exports;
|
|
47
|
+
const missing = REQUIRED_EXPORTS.filter((name) => !ex[name]);
|
|
48
|
+
if (missing.length) {
|
|
49
|
+
throw new Error('wasm missing required exports: ' + missing.join(', '));
|
|
50
|
+
}
|
|
51
|
+
return ex;
|
|
52
|
+
});
|
|
44
53
|
}
|
|
45
|
-
return
|
|
54
|
+
return _exportsPromise;
|
|
46
55
|
}
|
|
47
56
|
|
|
48
57
|
function processFailure(code, message) {
|
|
@@ -99,11 +108,16 @@ export async function parse(bytes) {
|
|
|
99
108
|
}
|
|
100
109
|
|
|
101
110
|
const resultBytes = new Uint8Array(ex.memory.buffer, ptr, len);
|
|
102
|
-
const
|
|
103
|
-
|
|
111
|
+
const decoded = new TextDecoder().decode(resultBytes); // decode while buffer is valid
|
|
104
112
|
// Free BOTH buffers every cycle (input + result) per the FFI contract.
|
|
105
113
|
ex.free_result(inputPtr, inputLen);
|
|
106
114
|
ex.free_result(ptr, len);
|
|
115
|
+
let json;
|
|
116
|
+
try {
|
|
117
|
+
json = JSON.parse(decoded);
|
|
118
|
+
} catch (e) {
|
|
119
|
+
return processFailure('INTERNAL', 'parse returned malformed JSON: ' + ((e && e.message) || String(e)));
|
|
120
|
+
}
|
|
107
121
|
return json;
|
|
108
122
|
}
|
|
109
123
|
|
|
@@ -130,5 +144,4 @@ export async function detect(bytes) {
|
|
|
130
144
|
return conf;
|
|
131
145
|
}
|
|
132
146
|
|
|
133
|
-
export { parse, detect };
|
|
134
147
|
export default { parse, detect };
|
package/index.d.ts
CHANGED
|
@@ -77,7 +77,7 @@ export type ParseResult = ProcessSuccess | ProcessFailure;
|
|
|
77
77
|
* `errors` lists the categorized error(s). The host never throws on
|
|
78
78
|
* parser-level failures — they arrive as `ProcessFailure`.
|
|
79
79
|
*/
|
|
80
|
-
export declare function parse(bytes: Uint8Array
|
|
80
|
+
export declare function parse(bytes: Uint8Array): Promise<ParseResult>;
|
|
81
81
|
|
|
82
82
|
/**
|
|
83
83
|
* Detection confidence for the given bytes.
|
|
@@ -85,4 +85,4 @@ export declare function parse(bytes: Uint8Array | Buffer): Promise<ParseResult>;
|
|
|
85
85
|
* @param bytes - Statement bytes to identify.
|
|
86
86
|
* @returns Confidence in {0, 50, 100}: 0 = no match, 50 = partial, 100 = definite.
|
|
87
87
|
*/
|
|
88
|
-
export declare function detect(bytes: Uint8Array
|
|
88
|
+
export declare function detect(bytes: Uint8Array): Promise<number>;
|
package/package.json
CHANGED