@3leaps/docprims 0.1.3

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/LICENSE ADDED
@@ -0,0 +1,6 @@
1
+ MIT OR Apache-2.0
2
+
3
+ This package is part of the docprims repository.
4
+ See the repository root for full license texts:
5
+ - LICENSE-MIT
6
+ - LICENSE-APACHE
package/README.md ADDED
@@ -0,0 +1,29 @@
1
+ # docprims (TypeScript bindings)
2
+
3
+ TypeScript/Node.js bindings for docprims using a Node-API (N-API) native addon (napi-rs).
4
+
5
+ ## Platform support (v0.1.x)
6
+
7
+ Supported:
8
+
9
+ - macOS: arm64
10
+ - Linux: glibc and musl (Alpine)
11
+ - Windows: x64 (msvc)
12
+
13
+ ## Local development
14
+
15
+ The native addon is built from Rust:
16
+
17
+ ```bash
18
+ npm install
19
+ npm run build
20
+ npm run build:native
21
+ npm run test:ci
22
+ ```
23
+
24
+ ## API (minimal)
25
+
26
+ - `extractFile(path, options?)` -> parsed v0 extract object
27
+ - `extractBytes(sourceUri, data, options?)` -> parsed v0 extract object
28
+
29
+ The `*Json` variants return the raw JSON string.
@@ -0,0 +1,15 @@
1
+ export declare const DocprimsErrorCode: {
2
+ readonly Ok: 0;
3
+ readonly Usage: 64;
4
+ readonly DataInvalid: 60;
5
+ readonly ResourceLimit: 70;
6
+ readonly Io: 74;
7
+ readonly Internal: 1;
8
+ };
9
+ export type DocprimsErrorCode = (typeof DocprimsErrorCode)[keyof typeof DocprimsErrorCode];
10
+ export declare class DocprimsError extends Error {
11
+ readonly code: DocprimsErrorCode;
12
+ readonly codeName: string;
13
+ constructor(code: DocprimsErrorCode, message: string);
14
+ }
15
+ //# sourceMappingURL=errors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,iBAAiB;;;;;;;CAOpB,CAAC;AAEX,MAAM,MAAM,iBAAiB,GAC5B,CAAC,OAAO,iBAAiB,CAAC,CAAC,MAAM,OAAO,iBAAiB,CAAC,CAAC;AAM5D,qBAAa,aAAc,SAAQ,KAAK;IACvC,SAAgB,IAAI,EAAE,iBAAiB,CAAC;IACxC,SAAgB,QAAQ,EAAE,MAAM,CAAC;gBAErB,IAAI,EAAE,iBAAiB,EAAE,OAAO,EAAE,MAAM;CAMpD"}
package/dist/errors.js ADDED
@@ -0,0 +1,24 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DocprimsError = exports.DocprimsErrorCode = void 0;
4
+ exports.DocprimsErrorCode = {
5
+ Ok: 0,
6
+ Usage: 64,
7
+ DataInvalid: 60,
8
+ ResourceLimit: 70,
9
+ Io: 74,
10
+ Internal: 1,
11
+ };
12
+ const errorCodeNames = Object.fromEntries(Object.entries(exports.DocprimsErrorCode).map(([k, v]) => [v, k]));
13
+ class DocprimsError extends Error {
14
+ code;
15
+ codeName;
16
+ constructor(code, message) {
17
+ super(message);
18
+ this.name = "DocprimsError";
19
+ this.code = code;
20
+ this.codeName = errorCodeNames[code] ?? `Unknown(${code})`;
21
+ }
22
+ }
23
+ exports.DocprimsError = DocprimsError;
24
+ //# sourceMappingURL=errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":";;;AAAa,QAAA,iBAAiB,GAAG;IAChC,EAAE,EAAE,CAAC;IACL,KAAK,EAAE,EAAE;IACT,WAAW,EAAE,EAAE;IACf,aAAa,EAAE,EAAE;IACjB,EAAE,EAAE,EAAE;IACN,QAAQ,EAAE,CAAC;CACF,CAAC;AAKX,MAAM,cAAc,GAA2B,MAAM,CAAC,WAAW,CAChE,MAAM,CAAC,OAAO,CAAC,yBAAiB,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CACzD,CAAC;AAEF,MAAa,aAAc,SAAQ,KAAK;IACvB,IAAI,CAAoB;IACxB,QAAQ,CAAS;IAEjC,YAAY,IAAuB,EAAE,OAAe;QACnD,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,eAAe,CAAC;QAC5B,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,QAAQ,GAAG,cAAc,CAAC,IAAI,CAAC,IAAI,WAAW,IAAI,GAAG,CAAC;IAC5D,CAAC;CACD;AAVD,sCAUC"}
package/dist/ffi.d.ts ADDED
@@ -0,0 +1,15 @@
1
+ export declare function loadDocprims(): DocprimsLib;
2
+ export type DocprimsCallJsonResult = {
3
+ code: number;
4
+ json?: string;
5
+ message?: string;
6
+ };
7
+ export type DocprimsLib = {
8
+ docprimsVersion: () => string;
9
+ docprimsAbiVersion: () => number;
10
+ docprimsExtractFileJson: (path: string, optionsJson: string) => DocprimsCallJsonResult;
11
+ docprimsExtractBytesJson: (sourceUri: string, data: Uint8Array, optionsJson: string) => DocprimsCallJsonResult;
12
+ };
13
+ export declare function callJsonReturn(fn: () => DocprimsCallJsonResult): unknown;
14
+ export declare function callJsonString(fn: () => DocprimsCallJsonResult): string;
15
+ //# sourceMappingURL=ffi.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ffi.d.ts","sourceRoot":"","sources":["../src/ffi.ts"],"names":[],"mappings":"AAQA,wBAAgB,YAAY,IAAI,WAAW,CAO1C;AAcD,MAAM,MAAM,sBAAsB,GAAG;IACpC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,MAAM,MAAM,WAAW,GAAG;IACzB,eAAe,EAAE,MAAM,MAAM,CAAC;IAC9B,kBAAkB,EAAE,MAAM,MAAM,CAAC;IACjC,uBAAuB,EAAE,CACxB,IAAI,EAAE,MAAM,EACZ,WAAW,EAAE,MAAM,KACf,sBAAsB,CAAC;IAC5B,wBAAwB,EAAE,CACzB,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,UAAU,EAChB,WAAW,EAAE,MAAM,KACf,sBAAsB,CAAC;CAC5B,CAAC;AAUF,wBAAgB,cAAc,CAAC,EAAE,EAAE,MAAM,sBAAsB,GAAG,OAAO,CAMxE;AAED,wBAAgB,cAAc,CAAC,EAAE,EAAE,MAAM,sBAAsB,GAAG,MAAM,CAMvE"}
package/dist/ffi.js ADDED
@@ -0,0 +1,53 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.loadDocprims = loadDocprims;
7
+ exports.callJsonReturn = callJsonReturn;
8
+ exports.callJsonString = callJsonString;
9
+ const node_fs_1 = __importDefault(require("node:fs"));
10
+ const node_path_1 = __importDefault(require("node:path"));
11
+ const errors_1 = require("./errors");
12
+ const native_1 = require("./native");
13
+ let cached = null;
14
+ function loadDocprims() {
15
+ if (cached)
16
+ return cached;
17
+ const packageRoot = findPackageRoot(__dirname);
18
+ const api = (0, native_1.loadNativeBinding)(packageRoot);
19
+ cached = api;
20
+ return cached;
21
+ }
22
+ function findPackageRoot(startDir) {
23
+ let current = startDir;
24
+ for (let i = 0; i < 8; i++) {
25
+ const candidate = node_path_1.default.join(current, "package.json");
26
+ if (node_fs_1.default.existsSync(candidate))
27
+ return current;
28
+ const parent = node_path_1.default.dirname(current);
29
+ if (parent === current)
30
+ break;
31
+ current = parent;
32
+ }
33
+ throw new Error("Could not locate package root (package.json not found)");
34
+ }
35
+ function raiseDocprimsError(code, message) {
36
+ const codeNameSuffix = ` (code=${code})`;
37
+ throw new errors_1.DocprimsError(code, message && message.length > 0 ? message : `docprims error${codeNameSuffix}`);
38
+ }
39
+ function callJsonReturn(fn) {
40
+ const r = fn();
41
+ if (r.code !== errors_1.DocprimsErrorCode.Ok) {
42
+ raiseDocprimsError(r.code, r.message);
43
+ }
44
+ return JSON.parse(r.json);
45
+ }
46
+ function callJsonString(fn) {
47
+ const r = fn();
48
+ if (r.code !== errors_1.DocprimsErrorCode.Ok) {
49
+ raiseDocprimsError(r.code, r.message);
50
+ }
51
+ return r.json;
52
+ }
53
+ //# sourceMappingURL=ffi.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ffi.js","sourceRoot":"","sources":["../src/ffi.ts"],"names":[],"mappings":";;;;;AAQA,oCAOC;AA0CD,wCAMC;AAED,wCAMC;AAvED,sDAAyB;AACzB,0DAA6B;AAE7B,qCAA4D;AAC5D,qCAA6C;AAE7C,IAAI,MAAM,GAAuB,IAAI,CAAC;AAEtC,SAAgB,YAAY;IAC3B,IAAI,MAAM;QAAE,OAAO,MAAM,CAAC;IAE1B,MAAM,WAAW,GAAG,eAAe,CAAC,SAAS,CAAC,CAAC;IAC/C,MAAM,GAAG,GAAgB,IAAA,0BAAiB,EAAC,WAAW,CAAC,CAAC;IACxD,MAAM,GAAG,GAAG,CAAC;IACb,OAAO,MAAM,CAAC;AACf,CAAC;AAED,SAAS,eAAe,CAAC,QAAgB;IACxC,IAAI,OAAO,GAAG,QAAQ,CAAC;IACvB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;QAC5B,MAAM,SAAS,GAAG,mBAAI,CAAC,IAAI,CAAC,OAAO,EAAE,cAAc,CAAC,CAAC;QACrD,IAAI,iBAAE,CAAC,UAAU,CAAC,SAAS,CAAC;YAAE,OAAO,OAAO,CAAC;QAC7C,MAAM,MAAM,GAAG,mBAAI,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;QACrC,IAAI,MAAM,KAAK,OAAO;YAAE,MAAM;QAC9B,OAAO,GAAG,MAAM,CAAC;IAClB,CAAC;IACD,MAAM,IAAI,KAAK,CAAC,wDAAwD,CAAC,CAAC;AAC3E,CAAC;AAsBD,SAAS,kBAAkB,CAAC,IAAY,EAAE,OAAgB;IACzD,MAAM,cAAc,GAAG,UAAU,IAAI,GAAG,CAAC;IACzC,MAAM,IAAI,sBAAa,CACtB,IAAyB,EACzB,OAAO,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,iBAAiB,cAAc,EAAE,CAC3E,CAAC;AACH,CAAC;AAED,SAAgB,cAAc,CAAC,EAAgC;IAC9D,MAAM,CAAC,GAAG,EAAE,EAAE,CAAC;IACf,IAAI,CAAC,CAAC,IAAI,KAAK,0BAAiB,CAAC,EAAE,EAAE,CAAC;QACrC,kBAAkB,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC;IACvC,CAAC;IACD,OAAO,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,IAAc,CAAC,CAAC;AACrC,CAAC;AAED,SAAgB,cAAc,CAAC,EAAgC;IAC9D,MAAM,CAAC,GAAG,EAAE,EAAE,CAAC;IACf,IAAI,CAAC,CAAC,IAAI,KAAK,0BAAiB,CAAC,EAAE,EAAE,CAAC;QACrC,kBAAkB,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC;IACvC,CAAC;IACD,OAAO,CAAC,CAAC,IAAc,CAAC;AACzB,CAAC"}
@@ -0,0 +1,10 @@
1
+ import type { DocprimsExtractV0, ExtractOptions } from "./types";
2
+ export declare function version(): string;
3
+ export declare function abiVersion(): number;
4
+ export declare function extractFileJson(filePath: string, options?: ExtractOptions): string;
5
+ export declare function extractBytesJson(sourceUri: string, data: Uint8Array, options?: ExtractOptions): string;
6
+ export declare function extractFile(filePath: string, options?: ExtractOptions): DocprimsExtractV0;
7
+ export declare function extractBytes(sourceUri: string, data: Uint8Array, options?: ExtractOptions): DocprimsExtractV0;
8
+ export { DocprimsError, DocprimsErrorCode } from "./errors";
9
+ export type { DocprimsExtractV0, ExtractOptions, ExtractLimits } from "./types";
10
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AASjE,wBAAgB,OAAO,IAAI,MAAM,CAEhC;AAED,wBAAgB,UAAU,IAAI,MAAM,CAEnC;AAED,wBAAgB,eAAe,CAC9B,QAAQ,EAAE,MAAM,EAChB,OAAO,CAAC,EAAE,cAAc,GACtB,MAAM,CAIR;AAED,wBAAgB,gBAAgB,CAC/B,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,UAAU,EAChB,OAAO,CAAC,EAAE,cAAc,GACtB,MAAM,CAQR;AAED,wBAAgB,WAAW,CAC1B,QAAQ,EAAE,MAAM,EAChB,OAAO,CAAC,EAAE,cAAc,GACtB,iBAAiB,CAInB;AAED,wBAAgB,YAAY,CAC3B,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,UAAU,EAChB,OAAO,CAAC,EAAE,cAAc,GACtB,iBAAiB,CAQnB;AAED,OAAO,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC;AAC5D,YAAY,EAAE,iBAAiB,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,37 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DocprimsErrorCode = exports.DocprimsError = void 0;
4
+ exports.version = version;
5
+ exports.abiVersion = abiVersion;
6
+ exports.extractFileJson = extractFileJson;
7
+ exports.extractBytesJson = extractBytesJson;
8
+ exports.extractFile = extractFile;
9
+ exports.extractBytes = extractBytes;
10
+ const ffi_1 = require("./ffi");
11
+ function optsToJson(opts) {
12
+ if (!opts)
13
+ return "";
14
+ return JSON.stringify(opts);
15
+ }
16
+ function version() {
17
+ return (0, ffi_1.loadDocprims)().docprimsVersion();
18
+ }
19
+ function abiVersion() {
20
+ return (0, ffi_1.loadDocprims)().docprimsAbiVersion();
21
+ }
22
+ function extractFileJson(filePath, options) {
23
+ return (0, ffi_1.callJsonString)(() => (0, ffi_1.loadDocprims)().docprimsExtractFileJson(filePath, optsToJson(options)));
24
+ }
25
+ function extractBytesJson(sourceUri, data, options) {
26
+ return (0, ffi_1.callJsonString)(() => (0, ffi_1.loadDocprims)().docprimsExtractBytesJson(sourceUri, data, optsToJson(options)));
27
+ }
28
+ function extractFile(filePath, options) {
29
+ return (0, ffi_1.callJsonReturn)(() => (0, ffi_1.loadDocprims)().docprimsExtractFileJson(filePath, optsToJson(options)));
30
+ }
31
+ function extractBytes(sourceUri, data, options) {
32
+ return (0, ffi_1.callJsonReturn)(() => (0, ffi_1.loadDocprims)().docprimsExtractBytesJson(sourceUri, data, optsToJson(options)));
33
+ }
34
+ var errors_1 = require("./errors");
35
+ Object.defineProperty(exports, "DocprimsError", { enumerable: true, get: function () { return errors_1.DocprimsError; } });
36
+ Object.defineProperty(exports, "DocprimsErrorCode", { enumerable: true, get: function () { return errors_1.DocprimsErrorCode; } });
37
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AASA,0BAEC;AAED,gCAEC;AAED,0CAOC;AAED,4CAYC;AAED,kCAOC;AAED,oCAYC;AA3DD,+BAAqE;AAErE,SAAS,UAAU,CAAC,IAAqB;IACxC,IAAI,CAAC,IAAI;QAAE,OAAO,EAAE,CAAC;IACrB,OAAO,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;AAC7B,CAAC;AAED,SAAgB,OAAO;IACtB,OAAO,IAAA,kBAAY,GAAE,CAAC,eAAe,EAAE,CAAC;AACzC,CAAC;AAED,SAAgB,UAAU;IACzB,OAAO,IAAA,kBAAY,GAAE,CAAC,kBAAkB,EAAE,CAAC;AAC5C,CAAC;AAED,SAAgB,eAAe,CAC9B,QAAgB,EAChB,OAAwB;IAExB,OAAO,IAAA,oBAAc,EAAC,GAAG,EAAE,CAC1B,IAAA,kBAAY,GAAE,CAAC,uBAAuB,CAAC,QAAQ,EAAE,UAAU,CAAC,OAAO,CAAC,CAAC,CACrE,CAAC;AACH,CAAC;AAED,SAAgB,gBAAgB,CAC/B,SAAiB,EACjB,IAAgB,EAChB,OAAwB;IAExB,OAAO,IAAA,oBAAc,EAAC,GAAG,EAAE,CAC1B,IAAA,kBAAY,GAAE,CAAC,wBAAwB,CACtC,SAAS,EACT,IAAI,EACJ,UAAU,CAAC,OAAO,CAAC,CACnB,CACD,CAAC;AACH,CAAC;AAED,SAAgB,WAAW,CAC1B,QAAgB,EAChB,OAAwB;IAExB,OAAO,IAAA,oBAAc,EAAC,GAAG,EAAE,CAC1B,IAAA,kBAAY,GAAE,CAAC,uBAAuB,CAAC,QAAQ,EAAE,UAAU,CAAC,OAAO,CAAC,CAAC,CAChD,CAAC;AACxB,CAAC;AAED,SAAgB,YAAY,CAC3B,SAAiB,EACjB,IAAgB,EAChB,OAAwB;IAExB,OAAO,IAAA,oBAAc,EAAC,GAAG,EAAE,CAC1B,IAAA,kBAAY,GAAE,CAAC,wBAAwB,CACtC,SAAS,EACT,IAAI,EACJ,UAAU,CAAC,OAAO,CAAC,CACnB,CACoB,CAAC;AACxB,CAAC;AAED,mCAA4D;AAAnD,uGAAA,aAAa,OAAA;AAAE,2GAAA,iBAAiB,OAAA"}
@@ -0,0 +1,14 @@
1
+ /* tslint:disable */
2
+ /* eslint-disable */
3
+
4
+ /* auto-generated by NAPI-RS */
5
+
6
+ export interface DocprimsCallJsonResult {
7
+ code: number
8
+ json?: string
9
+ message?: string
10
+ }
11
+ export declare function docprimsVersion(): string
12
+ export declare function docprimsAbiVersion(): number
13
+ export declare function docprimsExtractFileJson(path: string, optionsJson: string): DocprimsCallJsonResult
14
+ export declare function docprimsExtractBytesJson(sourceUri: string, data: Buffer, optionsJson: string): DocprimsCallJsonResult
@@ -0,0 +1,318 @@
1
+ /* tslint:disable */
2
+ /* eslint-disable */
3
+ /* prettier-ignore */
4
+
5
+ /* auto-generated by NAPI-RS */
6
+
7
+ const { existsSync, readFileSync } = require('fs')
8
+ const { join } = require('path')
9
+
10
+ const { platform, arch } = process
11
+
12
+ let nativeBinding = null
13
+ let localFileExisted = false
14
+ let loadError = null
15
+
16
+ function isMusl() {
17
+ // For Node 10
18
+ if (!process.report || typeof process.report.getReport !== 'function') {
19
+ try {
20
+ const lddPath = require('child_process').execSync('which ldd').toString().trim()
21
+ return readFileSync(lddPath, 'utf8').includes('musl')
22
+ } catch (e) {
23
+ return true
24
+ }
25
+ } else {
26
+ const { glibcVersionRuntime } = process.report.getReport().header
27
+ return !glibcVersionRuntime
28
+ }
29
+ }
30
+
31
+ switch (platform) {
32
+ case 'android':
33
+ switch (arch) {
34
+ case 'arm64':
35
+ localFileExisted = existsSync(join(__dirname, 'docprims.android-arm64.node'))
36
+ try {
37
+ if (localFileExisted) {
38
+ nativeBinding = require('./docprims.android-arm64.node')
39
+ } else {
40
+ nativeBinding = require('@3leaps/docprims-android-arm64')
41
+ }
42
+ } catch (e) {
43
+ loadError = e
44
+ }
45
+ break
46
+ case 'arm':
47
+ localFileExisted = existsSync(join(__dirname, 'docprims.android-arm-eabi.node'))
48
+ try {
49
+ if (localFileExisted) {
50
+ nativeBinding = require('./docprims.android-arm-eabi.node')
51
+ } else {
52
+ nativeBinding = require('@3leaps/docprims-android-arm-eabi')
53
+ }
54
+ } catch (e) {
55
+ loadError = e
56
+ }
57
+ break
58
+ default:
59
+ throw new Error(`Unsupported architecture on Android ${arch}`)
60
+ }
61
+ break
62
+ case 'win32':
63
+ switch (arch) {
64
+ case 'x64':
65
+ localFileExisted = existsSync(
66
+ join(__dirname, 'docprims.win32-x64-msvc.node')
67
+ )
68
+ try {
69
+ if (localFileExisted) {
70
+ nativeBinding = require('./docprims.win32-x64-msvc.node')
71
+ } else {
72
+ nativeBinding = require('@3leaps/docprims-win32-x64-msvc')
73
+ }
74
+ } catch (e) {
75
+ loadError = e
76
+ }
77
+ break
78
+ case 'ia32':
79
+ localFileExisted = existsSync(
80
+ join(__dirname, 'docprims.win32-ia32-msvc.node')
81
+ )
82
+ try {
83
+ if (localFileExisted) {
84
+ nativeBinding = require('./docprims.win32-ia32-msvc.node')
85
+ } else {
86
+ nativeBinding = require('@3leaps/docprims-win32-ia32-msvc')
87
+ }
88
+ } catch (e) {
89
+ loadError = e
90
+ }
91
+ break
92
+ case 'arm64':
93
+ localFileExisted = existsSync(
94
+ join(__dirname, 'docprims.win32-arm64-msvc.node')
95
+ )
96
+ try {
97
+ if (localFileExisted) {
98
+ nativeBinding = require('./docprims.win32-arm64-msvc.node')
99
+ } else {
100
+ nativeBinding = require('@3leaps/docprims-win32-arm64-msvc')
101
+ }
102
+ } catch (e) {
103
+ loadError = e
104
+ }
105
+ break
106
+ default:
107
+ throw new Error(`Unsupported architecture on Windows: ${arch}`)
108
+ }
109
+ break
110
+ case 'darwin':
111
+ localFileExisted = existsSync(join(__dirname, 'docprims.darwin-universal.node'))
112
+ try {
113
+ if (localFileExisted) {
114
+ nativeBinding = require('./docprims.darwin-universal.node')
115
+ } else {
116
+ nativeBinding = require('@3leaps/docprims-darwin-universal')
117
+ }
118
+ break
119
+ } catch {}
120
+ switch (arch) {
121
+ case 'x64':
122
+ localFileExisted = existsSync(join(__dirname, 'docprims.darwin-x64.node'))
123
+ try {
124
+ if (localFileExisted) {
125
+ nativeBinding = require('./docprims.darwin-x64.node')
126
+ } else {
127
+ nativeBinding = require('@3leaps/docprims-darwin-x64')
128
+ }
129
+ } catch (e) {
130
+ loadError = e
131
+ }
132
+ break
133
+ case 'arm64':
134
+ localFileExisted = existsSync(
135
+ join(__dirname, 'docprims.darwin-arm64.node')
136
+ )
137
+ try {
138
+ if (localFileExisted) {
139
+ nativeBinding = require('./docprims.darwin-arm64.node')
140
+ } else {
141
+ nativeBinding = require('@3leaps/docprims-darwin-arm64')
142
+ }
143
+ } catch (e) {
144
+ loadError = e
145
+ }
146
+ break
147
+ default:
148
+ throw new Error(`Unsupported architecture on macOS: ${arch}`)
149
+ }
150
+ break
151
+ case 'freebsd':
152
+ if (arch !== 'x64') {
153
+ throw new Error(`Unsupported architecture on FreeBSD: ${arch}`)
154
+ }
155
+ localFileExisted = existsSync(join(__dirname, 'docprims.freebsd-x64.node'))
156
+ try {
157
+ if (localFileExisted) {
158
+ nativeBinding = require('./docprims.freebsd-x64.node')
159
+ } else {
160
+ nativeBinding = require('@3leaps/docprims-freebsd-x64')
161
+ }
162
+ } catch (e) {
163
+ loadError = e
164
+ }
165
+ break
166
+ case 'linux':
167
+ switch (arch) {
168
+ case 'x64':
169
+ if (isMusl()) {
170
+ localFileExisted = existsSync(
171
+ join(__dirname, 'docprims.linux-x64-musl.node')
172
+ )
173
+ try {
174
+ if (localFileExisted) {
175
+ nativeBinding = require('./docprims.linux-x64-musl.node')
176
+ } else {
177
+ nativeBinding = require('@3leaps/docprims-linux-x64-musl')
178
+ }
179
+ } catch (e) {
180
+ loadError = e
181
+ }
182
+ } else {
183
+ localFileExisted = existsSync(
184
+ join(__dirname, 'docprims.linux-x64-gnu.node')
185
+ )
186
+ try {
187
+ if (localFileExisted) {
188
+ nativeBinding = require('./docprims.linux-x64-gnu.node')
189
+ } else {
190
+ nativeBinding = require('@3leaps/docprims-linux-x64-gnu')
191
+ }
192
+ } catch (e) {
193
+ loadError = e
194
+ }
195
+ }
196
+ break
197
+ case 'arm64':
198
+ if (isMusl()) {
199
+ localFileExisted = existsSync(
200
+ join(__dirname, 'docprims.linux-arm64-musl.node')
201
+ )
202
+ try {
203
+ if (localFileExisted) {
204
+ nativeBinding = require('./docprims.linux-arm64-musl.node')
205
+ } else {
206
+ nativeBinding = require('@3leaps/docprims-linux-arm64-musl')
207
+ }
208
+ } catch (e) {
209
+ loadError = e
210
+ }
211
+ } else {
212
+ localFileExisted = existsSync(
213
+ join(__dirname, 'docprims.linux-arm64-gnu.node')
214
+ )
215
+ try {
216
+ if (localFileExisted) {
217
+ nativeBinding = require('./docprims.linux-arm64-gnu.node')
218
+ } else {
219
+ nativeBinding = require('@3leaps/docprims-linux-arm64-gnu')
220
+ }
221
+ } catch (e) {
222
+ loadError = e
223
+ }
224
+ }
225
+ break
226
+ case 'arm':
227
+ if (isMusl()) {
228
+ localFileExisted = existsSync(
229
+ join(__dirname, 'docprims.linux-arm-musleabihf.node')
230
+ )
231
+ try {
232
+ if (localFileExisted) {
233
+ nativeBinding = require('./docprims.linux-arm-musleabihf.node')
234
+ } else {
235
+ nativeBinding = require('@3leaps/docprims-linux-arm-musleabihf')
236
+ }
237
+ } catch (e) {
238
+ loadError = e
239
+ }
240
+ } else {
241
+ localFileExisted = existsSync(
242
+ join(__dirname, 'docprims.linux-arm-gnueabihf.node')
243
+ )
244
+ try {
245
+ if (localFileExisted) {
246
+ nativeBinding = require('./docprims.linux-arm-gnueabihf.node')
247
+ } else {
248
+ nativeBinding = require('@3leaps/docprims-linux-arm-gnueabihf')
249
+ }
250
+ } catch (e) {
251
+ loadError = e
252
+ }
253
+ }
254
+ break
255
+ case 'riscv64':
256
+ if (isMusl()) {
257
+ localFileExisted = existsSync(
258
+ join(__dirname, 'docprims.linux-riscv64-musl.node')
259
+ )
260
+ try {
261
+ if (localFileExisted) {
262
+ nativeBinding = require('./docprims.linux-riscv64-musl.node')
263
+ } else {
264
+ nativeBinding = require('@3leaps/docprims-linux-riscv64-musl')
265
+ }
266
+ } catch (e) {
267
+ loadError = e
268
+ }
269
+ } else {
270
+ localFileExisted = existsSync(
271
+ join(__dirname, 'docprims.linux-riscv64-gnu.node')
272
+ )
273
+ try {
274
+ if (localFileExisted) {
275
+ nativeBinding = require('./docprims.linux-riscv64-gnu.node')
276
+ } else {
277
+ nativeBinding = require('@3leaps/docprims-linux-riscv64-gnu')
278
+ }
279
+ } catch (e) {
280
+ loadError = e
281
+ }
282
+ }
283
+ break
284
+ case 's390x':
285
+ localFileExisted = existsSync(
286
+ join(__dirname, 'docprims.linux-s390x-gnu.node')
287
+ )
288
+ try {
289
+ if (localFileExisted) {
290
+ nativeBinding = require('./docprims.linux-s390x-gnu.node')
291
+ } else {
292
+ nativeBinding = require('@3leaps/docprims-linux-s390x-gnu')
293
+ }
294
+ } catch (e) {
295
+ loadError = e
296
+ }
297
+ break
298
+ default:
299
+ throw new Error(`Unsupported architecture on Linux: ${arch}`)
300
+ }
301
+ break
302
+ default:
303
+ throw new Error(`Unsupported OS: ${platform}, architecture: ${arch}`)
304
+ }
305
+
306
+ if (!nativeBinding) {
307
+ if (loadError) {
308
+ throw loadError
309
+ }
310
+ throw new Error(`Failed to load native binding`)
311
+ }
312
+
313
+ const { docprimsVersion, docprimsAbiVersion, docprimsExtractFileJson, docprimsExtractBytesJson } = nativeBinding
314
+
315
+ module.exports.docprimsVersion = docprimsVersion
316
+ module.exports.docprimsAbiVersion = docprimsAbiVersion
317
+ module.exports.docprimsExtractFileJson = docprimsExtractFileJson
318
+ module.exports.docprimsExtractBytesJson = docprimsExtractBytesJson
@@ -0,0 +1,3 @@
1
+ import type { DocprimsLib } from "./ffi";
2
+ export declare function loadNativeBinding(packageRoot: string): DocprimsLib;
3
+ //# sourceMappingURL=native.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"native.d.ts","sourceRoot":"","sources":["../src/native.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,OAAO,CAAC;AAyDzC,wBAAgB,iBAAiB,CAAC,WAAW,EAAE,MAAM,GAAG,WAAW,CAiClE"}
package/dist/native.js ADDED
@@ -0,0 +1,80 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.loadNativeBinding = loadNativeBinding;
7
+ const node_fs_1 = __importDefault(require("node:fs"));
8
+ const node_path_1 = __importDefault(require("node:path"));
9
+ function isMusl() {
10
+ // Best-effort detection for Node on Linux.
11
+ // If `process.report` isn't available, default to musl (safer for container environments).
12
+ const report = process.report;
13
+ if (!report || typeof report.getReport !== "function")
14
+ return true;
15
+ try {
16
+ const r = report.getReport();
17
+ return !r?.header?.glibcVersionRuntime;
18
+ }
19
+ catch {
20
+ return true;
21
+ }
22
+ }
23
+ function bindingIdForRuntime() {
24
+ const platform = process.platform;
25
+ const arch = process.arch;
26
+ if (platform === "darwin") {
27
+ if (arch !== "arm64") {
28
+ throw new Error(`Unsupported platform for docprims: ${platform}/${arch}. ` +
29
+ "macOS x64 is not supported by docprims.");
30
+ }
31
+ return "darwin-arm64";
32
+ }
33
+ if (platform === "win32") {
34
+ if (arch === "x64")
35
+ return "win32-x64-msvc";
36
+ throw new Error(`Unsupported platform for docprims: ${platform}/${arch}`);
37
+ }
38
+ if (platform === "linux") {
39
+ const abi = isMusl() ? "musl" : "gnu";
40
+ if (arch === "x64")
41
+ return `linux-x64-${abi}`;
42
+ if (arch === "arm64")
43
+ return `linux-arm64-${abi}`;
44
+ throw new Error(`Unsupported platform for docprims: ${platform}/${arch}`);
45
+ }
46
+ throw new Error(`Unsupported platform for docprims: ${platform}/${arch}`);
47
+ }
48
+ function packageNameForBindingId(bindingId) {
49
+ return `@3leaps/docprims-${bindingId}`;
50
+ }
51
+ function localNodeFilename(bindingId) {
52
+ return `docprims.${bindingId}.node`;
53
+ }
54
+ function loadNativeBinding(packageRoot) {
55
+ const bindingId = bindingIdForRuntime();
56
+ const localNode = node_path_1.default.join(packageRoot, "dist", "native", localNodeFilename(bindingId));
57
+ const pkg = packageNameForBindingId(bindingId);
58
+ // Prefer local build (git checkout / local path installs).
59
+ if (node_fs_1.default.existsSync(localNode)) {
60
+ // biome-ignore lint/suspicious/noExplicitAny: napi binding is runtime-loaded
61
+ return require(localNode);
62
+ }
63
+ // Otherwise require the platform package (npm optional dependency).
64
+ try {
65
+ // biome-ignore lint/suspicious/noExplicitAny: napi binding is runtime-loaded
66
+ return require(pkg);
67
+ }
68
+ catch (e) {
69
+ const msg = e instanceof Error ? e.message : String(e);
70
+ throw new Error("Failed to load docprims native addon for this platform.\n" +
71
+ `Expected: ${pkg}\n` +
72
+ "\n" +
73
+ "If you are installing from a git checkout or local path, build the native addon first:\n" +
74
+ " npm run build:native\n" +
75
+ "\n" +
76
+ "If you are installing from npm, the platform prebuild package may be missing or failed to install.\n" +
77
+ `Original error: ${msg}`);
78
+ }
79
+ }
80
+ //# sourceMappingURL=native.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"native.js","sourceRoot":"","sources":["../src/native.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,54 @@
1
+ export type ExtractLimits = {
2
+ max_input_bytes?: number;
3
+ max_output_bytes?: number;
4
+ max_blocks?: number;
5
+ };
6
+ export type ExtractOptions = {
7
+ limits?: ExtractLimits;
8
+ };
9
+ export type DocprimsExtractV0 = {
10
+ schema_id: string;
11
+ schema_version: string;
12
+ generator: {
13
+ name: string;
14
+ version: string;
15
+ };
16
+ source: {
17
+ uri: string;
18
+ format: {
19
+ family: string;
20
+ kind: string;
21
+ };
22
+ sha256?: string | null;
23
+ };
24
+ document: {
25
+ quality: {
26
+ status: "complete" | "partial";
27
+ reason?: string | null;
28
+ };
29
+ text: string;
30
+ blocks: Array<{
31
+ id: string;
32
+ kind: string;
33
+ text: string;
34
+ doc_text_range: {
35
+ start_byte: number;
36
+ end_byte: number;
37
+ };
38
+ loc: {
39
+ kind: string;
40
+ container: {
41
+ kind: "file" | "archive";
42
+ path: string;
43
+ part?: string | null;
44
+ };
45
+ hints: Record<string, unknown>;
46
+ };
47
+ children: string[];
48
+ role?: string | null;
49
+ }>;
50
+ warnings: string[];
51
+ metadata?: unknown;
52
+ };
53
+ };
54
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,aAAa,GAAG;IAC3B,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,UAAU,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG;IAC5B,MAAM,CAAC,EAAE,aAAa,CAAC;CACvB,CAAC;AAEF,MAAM,MAAM,iBAAiB,GAAG;IAC/B,SAAS,EAAE,MAAM,CAAC;IAClB,cAAc,EAAE,MAAM,CAAC;IACvB,SAAS,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;IAC7C,MAAM,EAAE;QACP,GAAG,EAAE,MAAM,CAAC;QACZ,MAAM,EAAE;YAAE,MAAM,EAAE,MAAM,CAAC;YAAC,IAAI,EAAE,MAAM,CAAA;SAAE,CAAC;QACzC,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;KACvB,CAAC;IACF,QAAQ,EAAE;QACT,OAAO,EAAE;YAAE,MAAM,EAAE,UAAU,GAAG,SAAS,CAAC;YAAC,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;SAAE,CAAC;QACpE,IAAI,EAAE,MAAM,CAAC;QACb,MAAM,EAAE,KAAK,CAAC;YACb,EAAE,EAAE,MAAM,CAAC;YACX,IAAI,EAAE,MAAM,CAAC;YACb,IAAI,EAAE,MAAM,CAAC;YACb,cAAc,EAAE;gBAAE,UAAU,EAAE,MAAM,CAAC;gBAAC,QAAQ,EAAE,MAAM,CAAA;aAAE,CAAC;YACzD,GAAG,EAAE;gBACJ,IAAI,EAAE,MAAM,CAAC;gBACb,SAAS,EAAE;oBACV,IAAI,EAAE,MAAM,GAAG,SAAS,CAAC;oBACzB,IAAI,EAAE,MAAM,CAAC;oBACb,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;iBACrB,CAAC;gBACF,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;aAC/B,CAAC;YACF,QAAQ,EAAE,MAAM,EAAE,CAAC;YACnB,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;SACrB,CAAC,CAAC;QACH,QAAQ,EAAE,MAAM,EAAE,CAAC;QACnB,QAAQ,CAAC,EAAE,OAAO,CAAC;KACnB,CAAC;CACF,CAAC"}
package/dist/types.js ADDED
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,25 @@
1
+ [package]
2
+ name = "docprims-ts-napi"
3
+ version.workspace = true
4
+ edition.workspace = true
5
+ license.workspace = true
6
+ repository.workspace = true
7
+ authors.workspace = true
8
+ rust-version.workspace = true
9
+ description = "Node-API addon for @3leaps/docprims (TypeScript bindings)"
10
+
11
+ [lib]
12
+ crate-type = ["cdylib"]
13
+
14
+ [dependencies]
15
+ napi = { version = "2.16.16", default-features = false, features = ["napi8"] }
16
+ napi-derive = "2.16.13"
17
+ serde = { workspace = true, features = ["derive"] }
18
+ serde_json.workspace = true
19
+
20
+ docprims-core.workspace = true
21
+ docprims-text.workspace = true
22
+ docprims-ooxml.workspace = true
23
+
24
+ [build-dependencies]
25
+ napi-build = "2.0.1"
@@ -0,0 +1,3 @@
1
+ fn main() {
2
+ napi_build::setup();
3
+ }
@@ -0,0 +1,214 @@
1
+ use std::path::Path;
2
+
3
+ use napi::bindgen_prelude::Buffer;
4
+ use napi_derive::napi;
5
+
6
+ use docprims_core::{DocprimsError, ExtractLimits};
7
+
8
+ #[repr(i32)]
9
+ #[derive(Debug, Clone, Copy, PartialEq, Eq)]
10
+ pub enum DocprimsErrorCode {
11
+ Ok = 0,
12
+ Usage = 64,
13
+ DataInvalid = 60,
14
+ ResourceLimit = 70,
15
+ Io = 74,
16
+ Internal = 1,
17
+ }
18
+
19
+ fn map_err(e: &DocprimsError) -> DocprimsErrorCode {
20
+ match e {
21
+ DocprimsError::UnknownFormat(_) => DocprimsErrorCode::DataInvalid,
22
+ DocprimsError::Malformed(_) => DocprimsErrorCode::DataInvalid,
23
+ DocprimsError::Parse(_) => DocprimsErrorCode::DataInvalid,
24
+ DocprimsError::ResourceLimit(_) => DocprimsErrorCode::ResourceLimit,
25
+ DocprimsError::Io(_) => DocprimsErrorCode::Io,
26
+ _ => DocprimsErrorCode::Internal,
27
+ }
28
+ }
29
+
30
+ #[napi(object)]
31
+ pub struct DocprimsCallJsonResult {
32
+ pub code: i32,
33
+ pub json: Option<String>,
34
+ pub message: Option<String>,
35
+ }
36
+
37
+ fn ok_json(json: String) -> DocprimsCallJsonResult {
38
+ DocprimsCallJsonResult {
39
+ code: DocprimsErrorCode::Ok as i32,
40
+ json: Some(json),
41
+ message: None,
42
+ }
43
+ }
44
+
45
+ fn err_json(code: DocprimsErrorCode, msg: impl Into<String>) -> DocprimsCallJsonResult {
46
+ DocprimsCallJsonResult {
47
+ code: code as i32,
48
+ json: None,
49
+ message: Some(msg.into()),
50
+ }
51
+ }
52
+
53
+ #[derive(Debug, serde::Deserialize)]
54
+ struct DocprimsExtractOptions {
55
+ #[serde(default)]
56
+ limits: Option<ExtractLimitsOverrides>,
57
+ }
58
+
59
+ #[derive(Debug, Default, serde::Deserialize)]
60
+ struct ExtractLimitsOverrides {
61
+ #[serde(default)]
62
+ max_input_bytes: Option<usize>,
63
+ #[serde(default)]
64
+ max_output_bytes: Option<usize>,
65
+ #[serde(default)]
66
+ max_blocks: Option<usize>,
67
+ }
68
+
69
+ fn parse_limits(options_json: &str) -> Result<ExtractLimits, DocprimsErrorCode> {
70
+ if options_json.trim().is_empty() {
71
+ return Ok(ExtractLimits::default());
72
+ }
73
+
74
+ let opts: DocprimsExtractOptions =
75
+ serde_json::from_str(options_json).map_err(|_| DocprimsErrorCode::Usage)?;
76
+
77
+ let mut limits = ExtractLimits::default();
78
+ if let Some(overrides) = opts.limits {
79
+ if let Some(v) = overrides.max_input_bytes {
80
+ limits.max_input_bytes = v;
81
+ }
82
+ if let Some(v) = overrides.max_output_bytes {
83
+ limits.max_output_bytes = v;
84
+ }
85
+ if let Some(v) = overrides.max_blocks {
86
+ limits.max_blocks = v;
87
+ }
88
+ }
89
+ Ok(limits)
90
+ }
91
+
92
+ fn ext_lowercase(s: &str) -> String {
93
+ Path::new(s)
94
+ .extension()
95
+ .and_then(|e| e.to_str())
96
+ .map(|e| e.to_lowercase())
97
+ .unwrap_or_default()
98
+ }
99
+
100
+ #[napi]
101
+ pub fn docprims_version() -> String {
102
+ env!("CARGO_PKG_VERSION").to_string()
103
+ }
104
+
105
+ #[napi]
106
+ pub fn docprims_abi_version() -> u32 {
107
+ 1
108
+ }
109
+
110
+ #[napi]
111
+ pub fn docprims_extract_file_json(path: String, options_json: String) -> DocprimsCallJsonResult {
112
+ let limits = match parse_limits(&options_json) {
113
+ Ok(l) => l,
114
+ Err(code) => return err_json(code, "invalid options_json"),
115
+ };
116
+
117
+ let ext = ext_lowercase(&path);
118
+ let extracted = match ext.as_str() {
119
+ "docx" => docprims_ooxml::extract_docx_v0(&path, limits),
120
+ "xlsx" => docprims_ooxml::extract_xlsx_v0(&path, limits),
121
+ "pptx" => docprims_ooxml::extract_pptx_v0(&path, limits),
122
+ "md" | "markdown" => docprims_text::extract_markdown_v0(&path, limits),
123
+ "html" | "htm" => docprims_text::extract_html_v0(&path, limits),
124
+ "xml" => docprims_text::extract_xml_v0(&path, limits),
125
+ _ => Err(DocprimsError::UnknownFormat(ext)),
126
+ };
127
+
128
+ match extracted {
129
+ Ok(extract) => match serde_json::to_string(&extract) {
130
+ Ok(s) => ok_json(s),
131
+ Err(e) => err_json(
132
+ DocprimsErrorCode::Internal,
133
+ format!("error serializing result: {e}"),
134
+ ),
135
+ },
136
+ Err(e) => {
137
+ let code = map_err(&e);
138
+ err_json(code, e.to_string())
139
+ }
140
+ }
141
+ }
142
+
143
+ #[napi]
144
+ pub fn docprims_extract_bytes_json(
145
+ source_uri: String,
146
+ data: Buffer,
147
+ options_json: String,
148
+ ) -> DocprimsCallJsonResult {
149
+ let limits = match parse_limits(&options_json) {
150
+ Ok(l) => l,
151
+ Err(code) => return err_json(code, "invalid options_json"),
152
+ };
153
+
154
+ if data.len() > limits.max_input_bytes {
155
+ return err_json(
156
+ DocprimsErrorCode::ResourceLimit,
157
+ format!(
158
+ "input exceeds max_input_bytes ({} > {})",
159
+ data.len(),
160
+ limits.max_input_bytes
161
+ ),
162
+ );
163
+ }
164
+
165
+ let ext = ext_lowercase(&source_uri);
166
+ if ext.is_empty() {
167
+ return err_json(
168
+ DocprimsErrorCode::DataInvalid,
169
+ "unsupported format: missing extension in source_uri",
170
+ );
171
+ }
172
+
173
+ let bytes = data.as_ref();
174
+ let extracted = match ext.as_str() {
175
+ "docx" => {
176
+ docprims_ooxml::extract_docx_v0_reader(std::io::Cursor::new(bytes), &source_uri, limits)
177
+ }
178
+ "xlsx" => {
179
+ docprims_ooxml::extract_xlsx_v0_reader(std::io::Cursor::new(bytes), &source_uri, limits)
180
+ }
181
+ "pptx" => {
182
+ docprims_ooxml::extract_pptx_v0_reader(std::io::Cursor::new(bytes), &source_uri, limits)
183
+ }
184
+ "md" | "markdown" => match std::str::from_utf8(bytes) {
185
+ Ok(s) => docprims_text::markdown::extract_v0_str(s, &source_uri, limits),
186
+ Err(_) => Err(DocprimsError::Malformed(
187
+ "non-utf8 markdown input".to_string(),
188
+ )),
189
+ },
190
+ "html" | "htm" => match std::str::from_utf8(bytes) {
191
+ Ok(s) => docprims_text::html::extract_v0_str(s, &source_uri, limits),
192
+ Err(_) => Err(DocprimsError::Malformed("non-utf8 html input".to_string())),
193
+ },
194
+ "xml" => match std::str::from_utf8(bytes) {
195
+ Ok(s) => docprims_text::xml::extract_v0_str(s, &source_uri, limits),
196
+ Err(_) => Err(DocprimsError::Malformed("non-utf8 xml input".to_string())),
197
+ },
198
+ _ => Err(DocprimsError::UnknownFormat(ext)),
199
+ };
200
+
201
+ match extracted {
202
+ Ok(extract) => match serde_json::to_string(&extract) {
203
+ Ok(s) => ok_json(s),
204
+ Err(e) => err_json(
205
+ DocprimsErrorCode::Internal,
206
+ format!("error serializing result: {e}"),
207
+ ),
208
+ },
209
+ Err(e) => {
210
+ let code = map_err(&e);
211
+ err_json(code, e.to_string())
212
+ }
213
+ }
214
+ }
package/package.json ADDED
@@ -0,0 +1,59 @@
1
+ {
2
+ "name": "@3leaps/docprims",
3
+ "version": "0.1.3",
4
+ "description": "GPL-free document text extraction (TypeScript bindings via Node-API native addon)",
5
+ "license": "MIT OR Apache-2.0",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "git+https://github.com/3leaps/docprims.git",
9
+ "directory": "bindings/typescript/docprims"
10
+ },
11
+ "main": "dist/index.js",
12
+ "types": "dist/index.d.ts",
13
+ "files": [
14
+ "dist/",
15
+ "native/",
16
+ "README.md",
17
+ "LICENSE"
18
+ ],
19
+ "engines": {
20
+ "node": ">=18"
21
+ },
22
+ "napi": {
23
+ "name": "docprims",
24
+ "triples": {
25
+ "defaults": false,
26
+ "additional": [
27
+ "x86_64-unknown-linux-gnu",
28
+ "x86_64-unknown-linux-musl",
29
+ "aarch64-unknown-linux-gnu",
30
+ "aarch64-unknown-linux-musl",
31
+ "aarch64-apple-darwin",
32
+ "x86_64-pc-windows-msvc"
33
+ ]
34
+ }
35
+ },
36
+ "scripts": {
37
+ "clean": "node scripts/clean.js",
38
+ "build:native": "napi build --cargo-cwd native --release --platform --strip dist/native",
39
+ "build": "tsc -p tsconfig.build.json",
40
+ "build:test": "tsc -p tsconfig.test.json",
41
+ "test": "npm run clean && npm run build && npm run build:native && npm run build:test && node scripts/run-tests.js",
42
+ "test:ci": "npm run clean && npm run build && npm run build:native && npm run build:test && node scripts/run-tests.js",
43
+ "typecheck": "tsc -p tsconfig.build.json --noEmit"
44
+ },
45
+ "dependencies": {},
46
+ "optionalDependencies": {
47
+ "@3leaps/docprims-linux-x64-gnu": "0.1.3",
48
+ "@3leaps/docprims-linux-x64-musl": "0.1.3",
49
+ "@3leaps/docprims-linux-arm64-gnu": "0.1.3",
50
+ "@3leaps/docprims-linux-arm64-musl": "0.1.3",
51
+ "@3leaps/docprims-darwin-arm64": "0.1.3",
52
+ "@3leaps/docprims-win32-x64-msvc": "0.1.3"
53
+ },
54
+ "devDependencies": {
55
+ "@napi-rs/cli": "^2.18.4",
56
+ "@types/node": "^22.10.0",
57
+ "typescript": "^5.6.3"
58
+ }
59
+ }