pompelmi 0.17.0-dev.36 → 0.17.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/README.md CHANGED
@@ -33,6 +33,7 @@
33
33
  <img alt="node" src="https://img.shields.io/badge/node-%3E%3D18-339933?logo=node.js&logoColor=white">
34
34
  <img alt="types" src="https://img.shields.io/badge/types-TypeScript-3178C6?logo=typescript&logoColor=white">
35
35
  <a href="https://github.com/pompelmi/pompelmi/blob/main/LICENSE"><img alt="license" src="https://img.shields.io/npm/l/pompelmi"></a>
36
+ <a href="https://securityscorecards.dev/viewer/?uri=github.com/pompelmi/pompelmi"><img alt="OpenSSF Scorecard" src="https://api.securityscorecards.dev/projects/github.com/pompelmi/pompelmi/badge"/></a>
36
37
  <a href="https://codecov.io/gh/pompelmi/pompelmi"><img alt="codecov" src="https://codecov.io/gh/pompelmi/pompelmi/branch/main/graph/badge.svg?flag=core"/></a>
37
38
  <a href="https://github.com/pompelmi/pompelmi/stargazers"><img alt="GitHub stars" src="https://img.shields.io/github/stars/pompelmi/pompelmi?style=social"></a>
38
39
  <a href="https://github.com/pompelmi/pompelmi/actions/workflows/ci-release-publish.yml"><img alt="CI / Release / Publish" src="https://img.shields.io/github/actions/workflow/status/pompelmi/pompelmi/ci-release-publish.yml?branch=main&label=CI%20%2F%20Release%20%2F%20Publish"></a>
@@ -45,6 +46,7 @@
45
46
  <p align="center"><a href="https://pompelmi.github.io/pompelmi/">Documentation</a> ·
46
47
  <a href="#installation">Install</a> ·
47
48
  <a href="#quick-start">Quick‑start</a> ·
49
+ <a href="#minimal-node-usage">Minimal Node</a> ·
48
50
  <a href="#github-action">GitHub Action</a> ·
49
51
  <a href="#adapters">Adapters</a> ·
50
52
  <a href="#diagrams">Diagrams</a> ·
@@ -65,6 +67,7 @@
65
67
 
66
68
  - [Install](#installation)
67
69
  - [Quick‑start](#quick-start)
70
+ - [Minimal Node usage](#minimal-node-usage)
68
71
  - [GitHub Action](#github-action)
69
72
  - [Adapters](#adapters)
70
73
  - [Diagrams](#diagrams)
@@ -131,7 +134,6 @@
131
134
 
132
135
  ```bash
133
136
  # core library
134
- [![OpenSSF Scorecard](https://api.securityscorecards.dev/projects/github.com/pompelmi/pompelmi/badge)](https://securityscorecards.dev/viewer/?uri=github.com/pompelmi/pompelmi)
135
137
  npm i pompelmi
136
138
  # or
137
139
  pnpm add pompelmi
@@ -175,6 +177,21 @@ export const scanner = composeScanners(
175
177
  );
176
178
  ```
177
179
 
180
+ ### Minimal Node usage
181
+
182
+ ```ts
183
+ import { scanFile } from 'pompelmi';
184
+
185
+ const res = await scanFile('path/to/file.zip'); // or any file
186
+ console.log(res.verdict); // "clean" | "suspicious" | "malicious"
187
+ ```
188
+
189
+ > See `examples/scan-one-file.ts` for a runnable script:
190
+ >
191
+ > ```bash
192
+ > pnpm tsx examples/scan-one-file.ts ./path/to/file
193
+ > ```
194
+
178
195
  ### Express
179
196
 
180
197
  ```ts
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pompelmi",
3
- "version": "0.17.0-dev.36",
3
+ "version": "0.17.0",
4
4
  "description": "RFI-safe file uploads for Node.js — Express/Koa/Next.js middleware with deep ZIP inspection, MIME/size checks, and optional YARA scanning.",
5
5
  "main": "./dist/pompelmi.cjs",
6
6
  "module": "./dist/pompelmi.esm.js",
@@ -56,13 +56,14 @@
56
56
  "repo:audit": "node scripts/audit.mjs",
57
57
  "pack:check": "node scripts/pack-check.mjs",
58
58
  "pack:list": "pnpm -r --filter \"@pompelmi/*\" --if-present pack --json --dry-run",
59
- "pack:strict": "node scripts/pack-check.mjs --strict"
59
+ "pack:strict": "node scripts/pack-check.mjs --strict",
60
+ "clean": "rimraf dist"
60
61
  },
61
62
  "license": "MIT",
62
63
  "devDependencies": {
63
64
  "@biomejs/biome": "^2.2.4",
64
65
  "@pompelmi/core": "workspace:*",
65
- "@pompelmi/engine": "workspace:0.17.0-dev.36-dev.6",
66
+ "@pompelmi/engine": "workspace:0.17.0-dev.6",
66
67
  "@pompelmi/engine-heuristics": "workspace:^0.1.0",
67
68
  "@rollup/plugin-commonjs": "^28.0.6",
68
69
  "@rollup/plugin-node-resolve": "^16.0.1",
@@ -80,7 +81,7 @@
80
81
  "gh-pages": "^6.3.0",
81
82
  "knip": "^5.64.0",
82
83
  "multer": "^2.0.2",
83
- "react": "^18.0.0",
84
+ "react": "^19.2.0",
84
85
  "rollup": "^4.x",
85
86
  "ts-prune": "^0.10.3",
86
87
  "tslib": "^2.8.1",
@@ -100,7 +101,12 @@
100
101
  "@litko/yara-x": "^0.2.1"
101
102
  },
102
103
  "exports": {
103
- ".": {},
104
+ ".": {
105
+ "import": "./dist/pompelmi.esm.js",
106
+ "require": "./dist/pompelmi.cjs",
107
+ "default": "./dist/pompelmi.esm.js",
108
+ "types": "./dist/types/index.d.ts"
109
+ },
104
110
  "./package.json": "./package.json"
105
111
  },
106
112
  "files": [
@@ -109,7 +115,8 @@
109
115
  "README.md",
110
116
  "LICENSE*",
111
117
  "package.json",
112
- "CHANGELOG*"
118
+ "CHANGELOG*",
119
+ "LICENSE"
113
120
  ],
114
121
  "keywords": [
115
122
  "security",
@@ -151,5 +158,6 @@
151
158
  },
152
159
  "publishConfig": {
153
160
  "access": "public"
154
- }
161
+ },
162
+ "types": "./dist/types/index.d.ts"
155
163
  }
package/dist/index.cjs.js DELETED
@@ -1,86 +0,0 @@
1
- 'use strict';
2
-
3
- var react = require('react');
4
-
5
- /**
6
- * Reads an array of File objects via FileReader and returns their text.
7
- */
8
- async function scanFiles(files) {
9
- const readText = file => new Promise((resolve, reject) => {
10
- const reader = new FileReader();
11
- reader.onload = () => resolve(reader.result);
12
- reader.onerror = () => reject(reader.error);
13
- reader.readAsText(file);
14
- });
15
- const results = [];
16
- for (const file of files) {
17
- const content = await readText(file);
18
- results.push({
19
- file,
20
- content
21
- });
22
- }
23
- return results;
24
- }
25
-
26
- /**
27
- * Validates a File by MIME type and size (max 5 MB).
28
- */
29
- function validateFile(file) {
30
- const maxSize = 5 * 1024 * 1024;
31
- const allowedTypes = ['text/plain', 'application/json', 'text/csv'];
32
- if (!allowedTypes.includes(file.type)) {
33
- return {
34
- valid: false,
35
- error: 'Unsupported file type'
36
- };
37
- }
38
- if (file.size > maxSize) {
39
- return {
40
- valid: false,
41
- error: 'File too large (max 5 MB)'
42
- };
43
- }
44
- return {
45
- valid: true
46
- };
47
- }
48
-
49
- /**
50
- * React Hook: handles <input type="file" onChange> with validation + scanning.
51
- */
52
- function useFileScanner() {
53
- const [results, setResults] = react.useState([]);
54
- const [errors, setErrors] = react.useState([]);
55
- const onChange = react.useCallback(async e => {
56
- const fileList = Array.from(e.target.files || []);
57
- const good = [];
58
- const bad = [];
59
- for (const file of fileList) {
60
- const {
61
- valid,
62
- error
63
- } = validateFile(file);
64
- if (valid) good.push(file);else bad.push({
65
- file,
66
- error: error
67
- });
68
- }
69
- setErrors(bad);
70
- if (good.length) {
71
- const scanned = await scanFiles(good);
72
- setResults(scanned);
73
- } else {
74
- setResults([]);
75
- }
76
- }, []);
77
- return {
78
- results,
79
- errors,
80
- onChange
81
- };
82
- }
83
-
84
- exports.scanFiles = scanFiles;
85
- exports.useFileScanner = useFileScanner;
86
- exports.validateFile = validateFile;
package/dist/index.esm.js DELETED
@@ -1,82 +0,0 @@
1
- import { useState, useCallback } from 'react';
2
-
3
- /**
4
- * Reads an array of File objects via FileReader and returns their text.
5
- */
6
- async function scanFiles(files) {
7
- const readText = file => new Promise((resolve, reject) => {
8
- const reader = new FileReader();
9
- reader.onload = () => resolve(reader.result);
10
- reader.onerror = () => reject(reader.error);
11
- reader.readAsText(file);
12
- });
13
- const results = [];
14
- for (const file of files) {
15
- const content = await readText(file);
16
- results.push({
17
- file,
18
- content
19
- });
20
- }
21
- return results;
22
- }
23
-
24
- /**
25
- * Validates a File by MIME type and size (max 5 MB).
26
- */
27
- function validateFile(file) {
28
- const maxSize = 5 * 1024 * 1024;
29
- const allowedTypes = ['text/plain', 'application/json', 'text/csv'];
30
- if (!allowedTypes.includes(file.type)) {
31
- return {
32
- valid: false,
33
- error: 'Unsupported file type'
34
- };
35
- }
36
- if (file.size > maxSize) {
37
- return {
38
- valid: false,
39
- error: 'File too large (max 5 MB)'
40
- };
41
- }
42
- return {
43
- valid: true
44
- };
45
- }
46
-
47
- /**
48
- * React Hook: handles <input type="file" onChange> with validation + scanning.
49
- */
50
- function useFileScanner() {
51
- const [results, setResults] = useState([]);
52
- const [errors, setErrors] = useState([]);
53
- const onChange = useCallback(async e => {
54
- const fileList = Array.from(e.target.files || []);
55
- const good = [];
56
- const bad = [];
57
- for (const file of fileList) {
58
- const {
59
- valid,
60
- error
61
- } = validateFile(file);
62
- if (valid) good.push(file);else bad.push({
63
- file,
64
- error: error
65
- });
66
- }
67
- setErrors(bad);
68
- if (good.length) {
69
- const scanned = await scanFiles(good);
70
- setResults(scanned);
71
- } else {
72
- setResults([]);
73
- }
74
- }, []);
75
- return {
76
- results,
77
- errors,
78
- onChange
79
- };
80
- }
81
-
82
- export { scanFiles, useFileScanner, validateFile };