repoimage 0.2.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.
Files changed (71) hide show
  1. package/.claude/settings.local.json +8 -0
  2. package/AGENTS.md +28 -0
  3. package/PROJECT-AGENTS.md +55 -0
  4. package/README.md +153 -0
  5. package/TODO.md +132 -0
  6. package/client/index.html +12 -0
  7. package/client/package.json +23 -0
  8. package/client/src/App.tsx +599 -0
  9. package/client/src/components/FsBrowser.tsx +210 -0
  10. package/client/src/components/Settings.tsx +81 -0
  11. package/client/src/index.css +797 -0
  12. package/client/src/lib/api.ts +69 -0
  13. package/client/src/lib/collect.ts +204 -0
  14. package/client/src/lib/format.ts +96 -0
  15. package/client/src/lib/session.ts +58 -0
  16. package/client/src/main.tsx +10 -0
  17. package/client/src/vite-env.d.ts +1 -0
  18. package/client/tsconfig.json +18 -0
  19. package/client/vite.config.ts +27 -0
  20. package/docs/README.md +28 -0
  21. package/docs/api/overview.md +65 -0
  22. package/docs/api/scan.md +188 -0
  23. package/docs/architecture.md +155 -0
  24. package/docs/design/invariants.md +19 -0
  25. package/docs/design/role-system.md +50 -0
  26. package/docs/development/README.md +94 -0
  27. package/docs/features/README.md +21 -0
  28. package/docs/features/compression-score.md +75 -0
  29. package/docs/features/exclusions.md +63 -0
  30. package/docs/features/session.md +64 -0
  31. package/package.json +37 -0
  32. package/server/dist/cli.d.ts +3 -0
  33. package/server/dist/cli.d.ts.map +1 -0
  34. package/server/dist/cli.js +54 -0
  35. package/server/dist/cli.js.map +1 -0
  36. package/server/dist/fs-list.d.ts +3 -0
  37. package/server/dist/fs-list.d.ts.map +1 -0
  38. package/server/dist/fs-list.js +73 -0
  39. package/server/dist/fs-list.js.map +1 -0
  40. package/server/dist/paths.d.ts +3 -0
  41. package/server/dist/paths.d.ts.map +1 -0
  42. package/server/dist/paths.js +12 -0
  43. package/server/dist/paths.js.map +1 -0
  44. package/server/dist/scan.d.ts +16 -0
  45. package/server/dist/scan.d.ts.map +1 -0
  46. package/server/dist/scan.js +158 -0
  47. package/server/dist/scan.js.map +1 -0
  48. package/server/dist/server.d.ts +6 -0
  49. package/server/dist/server.d.ts.map +1 -0
  50. package/server/dist/server.js +313 -0
  51. package/server/dist/server.js.map +1 -0
  52. package/server/package.json +22 -0
  53. package/server/src/cli.ts +63 -0
  54. package/server/src/fs-list.ts +70 -0
  55. package/server/src/paths.ts +6 -0
  56. package/server/src/scan.ts +203 -0
  57. package/server/src/server.ts +356 -0
  58. package/server/tsconfig.json +9 -0
  59. package/shared/package.json +10 -0
  60. package/shared/src/constants.ts +37 -0
  61. package/shared/src/index.ts +4 -0
  62. package/shared/src/role-guess.ts +103 -0
  63. package/shared/src/schema.ts +18 -0
  64. package/shared/src/types.ts +36 -0
  65. package/shared/tsconfig.json +9 -0
  66. package/test/cli.test.js +56 -0
  67. package/test/fs-list.test.js +39 -0
  68. package/test/role-guess.test.js +50 -0
  69. package/test/scan.test.js +150 -0
  70. package/test/server.test.js +308 -0
  71. package/tsconfig.base.json +14 -0
@@ -0,0 +1,64 @@
1
+ # Browser Session Persistence
2
+
3
+ RepoImage remembers your session state between browser visits, so you can pick up where you left off.
4
+
5
+ ## What Gets Saved
6
+
7
+ **Automatically saved in localStorage:**
8
+
9
+ 1. **Current working directory** — The folder path you're scanning
10
+ 2. **Exclude preference** — Whether "Exclude common folders" is enabled
11
+ 3. **Scan results cache** — The images from your last scan
12
+
13
+ ## What Happens When You Return
14
+
15
+ When you reload the page or come back later:
16
+
17
+ 1. Your last folder path is restored in the input field
18
+ 2. The exclude preference is restored (checked or unchecked)
19
+ 3. If you had recent scan results, they appear in the table (no need to re-scan immediately)
20
+
21
+ Example:
22
+
23
+ ```
24
+ Session 1: Open RepoImage
25
+ → Enter /home/user/my-project
26
+ → Toggle "Exclude common folders" ON
27
+ → Scan, get 42 images
28
+ → Close browser
29
+
30
+ Session 2: Open RepoImage again
31
+ → Folder input shows: /home/user/my-project
32
+ → "Exclude common folders" is ON
33
+ → Table shows: 42 cached images (from previous scan)
34
+ → Click "Browse" or press Enter to re-scan if needed
35
+ ```
36
+
37
+ ## Cache Invalidation
38
+
39
+ The **scan results cache is optional and not guaranteed**:
40
+
41
+ - If the folder has changed, results may be stale (re-scan to refresh)
42
+ - If you switch projects, old cache is overwritten
43
+ - If you clear browser data/storage, cache is lost
44
+
45
+ The cache is a **convenience only** — always re-scan if you need current data.
46
+
47
+ ## Clearing All Data
48
+
49
+ To clear all saved session state (folder, preferences, cache):
50
+
51
+ 1. Click the ⚙️ (gear) icon in the top-right
52
+ 2. Click "Clear all data"
53
+ 3. Confirm the alert
54
+
55
+ All localStorage is wiped, and the UI resets to defaults.
56
+
57
+ ## Technical Details
58
+
59
+ - **Storage:** Browser localStorage (persists across sessions)
60
+ - **Scope:** Per origin (domain + protocol + port)
61
+ - **Lifetime:** Persists until manually cleared or browser data is deleted
62
+ - **Size:** Minimal (folder path ~200 bytes, preferences ~5 bytes, images vary)
63
+
64
+ If you use private/incognito mode, localStorage is cleared when the window closes.
package/package.json ADDED
@@ -0,0 +1,37 @@
1
+ {
2
+ "name": "repoimage",
3
+ "version": "0.2.0",
4
+ "description": "Scan a repository for image files and estimate compression quality",
5
+ "workspaces": [
6
+ "shared",
7
+ "server",
8
+ "client"
9
+ ],
10
+ "bin": {
11
+ "repoimage": "./server/dist/cli.js"
12
+ },
13
+ "repository": {
14
+ "type": "git",
15
+ "url": "https://github.com/yourappdotie/repoimage/"
16
+ },
17
+ "scripts": {
18
+ "build": "npm run build -w @repoimage/shared && npm run build -w @repoimage/server && npm run build -w @repoimage/client",
19
+ "dev": "concurrently -n server,client -c blue,green \"npm run dev -w @repoimage/server\" \"npm run dev -w @repoimage/client\"",
20
+ "gui": "npm run build && npm run start -w @repoimage/server",
21
+ "start": "node server/dist/cli.js",
22
+ "test": "npm run build -w @repoimage/shared && npm run build -w @repoimage/server && node --test test/*.test.js"
23
+ },
24
+ "devDependencies": {
25
+ "concurrently": "^9.1.2",
26
+ "typescript": "^5.7.2"
27
+ },
28
+ "keywords": [
29
+ "images",
30
+ "file-finder",
31
+ "directory-walker",
32
+ "compression",
33
+ "optimization"
34
+ ],
35
+ "author": "Ger O'Connell <info@levelhead.ie>",
36
+ "license": "MIT"
37
+ }
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":""}
@@ -0,0 +1,54 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ const scan_1 = require("./scan");
5
+ const args = process.argv.slice(2);
6
+ const jsonMode = args.includes('--json');
7
+ const sortByScore = args.includes('--sort-by-score');
8
+ const folders = args.filter(arg => !arg.startsWith('--'));
9
+ if (folders.length === 0) {
10
+ const usage = 'Usage: repoimage [--json] [--sort-by-score] <folder1> [folder2] ...\n' +
11
+ 'Example: repoimage --json /path/to/repo\n' +
12
+ ' repoimage --sort-by-score /path/to/Pictures';
13
+ if (jsonMode) {
14
+ process.stderr.write(`${usage}\n`);
15
+ }
16
+ else {
17
+ console.log(usage);
18
+ }
19
+ process.exit(1);
20
+ }
21
+ let { images, issues } = (0, scan_1.findImagesInFolders)(folders, { verbose: !jsonMode });
22
+ if (sortByScore) {
23
+ images = (0, scan_1.sortByCompressionScore)(images);
24
+ }
25
+ if (jsonMode) {
26
+ process.stdout.write(JSON.stringify({ images, issues }));
27
+ process.stdout.write('\n');
28
+ process.exit(0);
29
+ }
30
+ if (issues.length) {
31
+ for (const issue of issues) {
32
+ console.error(issue.message);
33
+ }
34
+ if (issues.some(i => i.code === 'MISSING_FOLDER')) {
35
+ console.error('');
36
+ }
37
+ }
38
+ function formatFileSize(bytes) {
39
+ if (bytes === 0)
40
+ return '0 B';
41
+ const k = 1024;
42
+ const sizes = ['B', 'KB', 'MB', 'GB'];
43
+ const i = Math.floor(Math.log(bytes) / Math.log(k));
44
+ return `${parseFloat((bytes / k ** i).toFixed(2))} ${sizes[i]}`;
45
+ }
46
+ console.log(`\nFound ${images.length} images:`);
47
+ images.forEach((image, index) => {
48
+ const dimensions = image.width && image.height ? `${image.width}x${image.height}` : 'unknown';
49
+ const compression = image.compressionRatio ? `${image.compressionRatio}/10` : 'N/A';
50
+ console.log(`${index + 1}. ${image.path} (${formatFileSize(image.size)}, ${dimensions}, compression: ${compression})`);
51
+ });
52
+ const totalSize = images.reduce((sum, image) => sum + image.size, 0);
53
+ console.log(`\nTotal: ${images.length} images found (${formatFileSize(totalSize)})`);
54
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";;;AAEA,iCAAqE;AAErE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AACnC,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;AACzC,MAAM,WAAW,GAAG,IAAI,CAAC,QAAQ,CAAC,iBAAiB,CAAC,CAAC;AACrD,MAAM,OAAO,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC;AAE1D,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;IACzB,MAAM,KAAK,GACT,uEAAuE;QACvE,2CAA2C;QAC3C,sDAAsD,CAAC;IACzD,IAAI,QAAQ,EAAE,CAAC;QACb,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,KAAK,IAAI,CAAC,CAAC;IACrC,CAAC;SAAM,CAAC;QACN,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;IACrB,CAAC;IACD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC;AAED,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,IAAA,0BAAmB,EAAC,OAAO,EAAE,EAAE,OAAO,EAAE,CAAC,QAAQ,EAAE,CAAC,CAAC;AAE9E,IAAI,WAAW,EAAE,CAAC;IAChB,MAAM,GAAG,IAAA,6BAAsB,EAAC,MAAM,CAAC,CAAC;AAC1C,CAAC;AAED,IAAI,QAAQ,EAAE,CAAC;IACb,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC;IACzD,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAC3B,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC;AAED,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC;IAClB,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC3B,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IAC/B,CAAC;IACD,IAAI,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,gBAAgB,CAAC,EAAE,CAAC;QAClD,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IACpB,CAAC;AACH,CAAC;AAED,SAAS,cAAc,CAAC,KAAa;IACnC,IAAI,KAAK,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IAC9B,MAAM,CAAC,GAAG,IAAI,CAAC;IACf,MAAM,KAAK,GAAG,CAAC,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;IACtC,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;IACpD,OAAO,GAAG,UAAU,CAAC,CAAC,KAAK,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;AAClE,CAAC;AAED,OAAO,CAAC,GAAG,CAAC,WAAW,MAAM,CAAC,MAAM,UAAU,CAAC,CAAC;AAChD,MAAM,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE;IAC9B,MAAM,UAAU,GACd,KAAK,CAAC,KAAK,IAAI,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,KAAK,IAAI,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC;IAC7E,MAAM,WAAW,GAAG,KAAK,CAAC,gBAAgB,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,gBAAgB,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC;IACpF,OAAO,CAAC,GAAG,CACT,GAAG,KAAK,GAAG,CAAC,KAAK,KAAK,CAAC,IAAI,KAAK,cAAc,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,UAAU,kBAAkB,WAAW,GAAG,CAC1G,CAAC;AACJ,CAAC,CAAC,CAAC;AAEH,MAAM,SAAS,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,KAAK,EAAE,EAAE,CAAC,GAAG,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;AACrE,OAAO,CAAC,GAAG,CAAC,YAAY,MAAM,CAAC,MAAM,kBAAkB,cAAc,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { FsListResult } from '@repoimage/shared';
2
+ export declare function listDirectory(inputPath: string): FsListResult;
3
+ //# sourceMappingURL=fs-list.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fs-list.d.ts","sourceRoot":"","sources":["../src/fs-list.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAe,YAAY,EAAE,MAAM,mBAAmB,CAAC;AASnE,wBAAgB,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,YAAY,CA0D7D"}
@@ -0,0 +1,73 @@
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.listDirectory = listDirectory;
7
+ const fs_1 = __importDefault(require("fs"));
8
+ const path_1 = __importDefault(require("path"));
9
+ function typeFromDirent(d) {
10
+ if (d.isSymbolicLink())
11
+ return 'symlink';
12
+ if (d.isDirectory())
13
+ return 'directory';
14
+ if (d.isFile())
15
+ return 'file';
16
+ return 'other';
17
+ }
18
+ function listDirectory(inputPath) {
19
+ const resolved = path_1.default.resolve(inputPath);
20
+ if (!fs_1.default.existsSync(resolved)) {
21
+ return { error: 'ENOENT', message: `Path not found: ${resolved}` };
22
+ }
23
+ let st;
24
+ try {
25
+ st = fs_1.default.statSync(resolved);
26
+ }
27
+ catch (e) {
28
+ return {
29
+ error: 'ESTAT',
30
+ message: e instanceof Error ? e.message : String(e)
31
+ };
32
+ }
33
+ if (!st.isDirectory()) {
34
+ return { error: 'ENOTDIR', message: `Not a directory: ${resolved}` };
35
+ }
36
+ let dirents;
37
+ try {
38
+ dirents = fs_1.default.readdirSync(resolved, { withFileTypes: true });
39
+ }
40
+ catch (e) {
41
+ return {
42
+ error: 'EACCES',
43
+ message: e instanceof Error ? e.message : String(e)
44
+ };
45
+ }
46
+ const entries = dirents.map(d => {
47
+ const name = d.name;
48
+ const fullPath = path_1.default.join(resolved, name);
49
+ return {
50
+ name,
51
+ path: fullPath.split(path_1.default.sep).join('/'),
52
+ type: typeFromDirent(d)
53
+ };
54
+ });
55
+ entries.sort((a, b) => {
56
+ const order = {
57
+ directory: 0,
58
+ symlink: 1,
59
+ file: 2,
60
+ other: 3
61
+ };
62
+ const oa = order[a.type] ?? 3;
63
+ const ob = order[b.type] ?? 3;
64
+ if (oa !== ob)
65
+ return oa - ob;
66
+ return a.name.localeCompare(b.name, undefined, { sensitivity: 'base' });
67
+ });
68
+ return {
69
+ path: resolved.split(path_1.default.sep).join('/'),
70
+ entries
71
+ };
72
+ }
73
+ //# sourceMappingURL=fs-list.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fs-list.js","sourceRoot":"","sources":["../src/fs-list.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ /** Default production client bundle: `client/dist` from repo root. */
2
+ export declare function defaultClientRoot(): string;
3
+ //# sourceMappingURL=paths.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"paths.d.ts","sourceRoot":"","sources":["../src/paths.ts"],"names":[],"mappings":"AAEA,sEAAsE;AACtE,wBAAgB,iBAAiB,IAAI,MAAM,CAE1C"}
@@ -0,0 +1,12 @@
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.defaultClientRoot = defaultClientRoot;
7
+ const path_1 = __importDefault(require("path"));
8
+ /** Default production client bundle: `client/dist` from repo root. */
9
+ function defaultClientRoot() {
10
+ return path_1.default.resolve(__dirname, '../../client/dist');
11
+ }
12
+ //# sourceMappingURL=paths.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"paths.js","sourceRoot":"","sources":["../src/paths.ts"],"names":[],"mappings":";;;;;AAGA,8CAEC;AALD,gDAAwB;AAExB,sEAAsE;AACtE,SAAgB,iBAAiB;IAC/B,OAAO,cAAI,CAAC,OAAO,CAAC,SAAS,EAAE,mBAAmB,CAAC,CAAC;AACtD,CAAC"}
@@ -0,0 +1,16 @@
1
+ import { IMAGE_EXTENSIONS, type ImageRow, type RawImageEntry, type ScanIssue } from '@repoimage/shared';
2
+ export { IMAGE_EXTENSIONS };
3
+ export declare function computeCompressionFields(ext: string, fileSize: number, width: number | null | undefined, height: number | null | undefined): {
4
+ uncompressedSize: number | null;
5
+ compressionRatio: string | null;
6
+ };
7
+ export declare function enrichImageEntry(entry: RawImageEntry): ImageRow | null;
8
+ export declare function findImagesInFolders(folders: string[], options?: {
9
+ verbose?: boolean;
10
+ excludeCommon?: boolean;
11
+ }): {
12
+ images: ImageRow[];
13
+ issues: ScanIssue[];
14
+ };
15
+ export declare function sortByCompressionScore(images: ImageRow[]): ImageRow[];
16
+ //# sourceMappingURL=scan.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scan.d.ts","sourceRoot":"","sources":["../src/scan.ts"],"names":[],"mappings":"AAGA,OAAO,EACL,gBAAgB,EAGhB,KAAK,QAAQ,EACb,KAAK,aAAa,EAClB,KAAK,SAAS,EACf,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EAAE,gBAAgB,EAAE,CAAC;AAE5B,wBAAgB,wBAAwB,CACtC,GAAG,EAAE,MAAM,EACX,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EAChC,MAAM,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAChC;IAAE,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,CAatE;AAED,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,aAAa,GAAG,QAAQ,GAAG,IAAI,CA8CtE;AAyED,wBAAgB,mBAAmB,CACjC,OAAO,EAAE,MAAM,EAAE,EACjB,OAAO,GAAE;IAAE,OAAO,CAAC,EAAE,OAAO,CAAC;IAAC,aAAa,CAAC,EAAE,OAAO,CAAA;CAAO,GAC3D;IAAE,MAAM,EAAE,QAAQ,EAAE,CAAC;IAAC,MAAM,EAAE,SAAS,EAAE,CAAA;CAAE,CAsC7C;AAED,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,QAAQ,EAAE,GAAG,QAAQ,EAAE,CAMrE"}
@@ -0,0 +1,158 @@
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.IMAGE_EXTENSIONS = void 0;
7
+ exports.computeCompressionFields = computeCompressionFields;
8
+ exports.enrichImageEntry = enrichImageEntry;
9
+ exports.findImagesInFolders = findImagesInFolders;
10
+ exports.sortByCompressionScore = sortByCompressionScore;
11
+ const fs_1 = __importDefault(require("fs"));
12
+ const path_1 = __importDefault(require("path"));
13
+ const image_size_1 = __importDefault(require("image-size"));
14
+ const shared_1 = require("@repoimage/shared");
15
+ Object.defineProperty(exports, "IMAGE_EXTENSIONS", { enumerable: true, get: function () { return shared_1.IMAGE_EXTENSIONS; } });
16
+ function computeCompressionFields(ext, fileSize, width, height) {
17
+ let uncompressedSize = null;
18
+ let compressionRatio = null;
19
+ if (width && height && !['.svg'].includes(ext)) {
20
+ const bytesPerPixel = ['.png', '.gif'].includes(ext) ? 4 : 3;
21
+ uncompressedSize = width * height * bytesPerPixel;
22
+ const linearRatio = fileSize / uncompressedSize;
23
+ const logScore = Math.max(0, Math.min(10, -Math.log2(linearRatio)));
24
+ compressionRatio = logScore.toFixed(1);
25
+ }
26
+ return { uncompressedSize, compressionRatio };
27
+ }
28
+ function enrichImageEntry(entry) {
29
+ const relativePath = String(entry.path || '').replace(/\\/g, '/').trim();
30
+ if (!relativePath || relativePath.split('/').includes('..')) {
31
+ return null;
32
+ }
33
+ const size = Number(entry.size);
34
+ if (!Number.isFinite(size) || size < 0) {
35
+ return null;
36
+ }
37
+ let width = entry.width != null ? Number(entry.width) : null;
38
+ let height = entry.height != null ? Number(entry.height) : null;
39
+ if (!Number.isFinite(width))
40
+ width = null;
41
+ if (!Number.isFinite(height))
42
+ height = null;
43
+ const ext = path_1.default.extname(relativePath).toLowerCase();
44
+ const { uncompressedSize, compressionRatio } = computeCompressionFields(ext, size, width, height);
45
+ const { roleGuess, roleGuessReason } = (0, shared_1.guessRole)({
46
+ path: relativePath,
47
+ size,
48
+ width,
49
+ height
50
+ });
51
+ const row = {
52
+ path: relativePath,
53
+ size: Math.round(size),
54
+ width,
55
+ height,
56
+ uncompressedSize,
57
+ compressionRatio,
58
+ role: null,
59
+ roleGuess
60
+ };
61
+ if (roleGuessReason) {
62
+ row.roleGuessReason = roleGuessReason;
63
+ }
64
+ return row;
65
+ }
66
+ function isImageFile(filename) {
67
+ const ext = path_1.default.extname(filename).toLowerCase();
68
+ return shared_1.IMAGE_EXTENSIONS.includes(ext);
69
+ }
70
+ function shouldExcludePath(dirName, excludeCommon) {
71
+ if (!excludeCommon) {
72
+ return false;
73
+ }
74
+ return shared_1.COMMON_EXCLUDE_PATHS.includes(dirName);
75
+ }
76
+ function walkDirectory(dirPath, imageFiles, ctx) {
77
+ try {
78
+ const items = fs_1.default.readdirSync(dirPath);
79
+ for (const item of items) {
80
+ const fullPath = path_1.default.join(dirPath, item);
81
+ const stat = fs_1.default.statSync(fullPath);
82
+ if (stat.isDirectory()) {
83
+ if (!shouldExcludePath(item, ctx.excludeCommon)) {
84
+ walkDirectory(fullPath, imageFiles, ctx);
85
+ }
86
+ }
87
+ else if (stat.isFile() && isImageFile(item)) {
88
+ try {
89
+ const dimensions = (0, image_size_1.default)(fullPath);
90
+ imageFiles.push({
91
+ path: fullPath,
92
+ size: stat.size,
93
+ width: dimensions.width ?? null,
94
+ height: dimensions.height ?? null
95
+ });
96
+ }
97
+ catch {
98
+ imageFiles.push({
99
+ path: fullPath,
100
+ size: stat.size,
101
+ width: null,
102
+ height: null
103
+ });
104
+ }
105
+ }
106
+ }
107
+ }
108
+ catch (error) {
109
+ const message = error instanceof Error ? error.message : String(error);
110
+ ctx.issues.push({ code: 'DIR_READ_ERROR', path: dirPath, message });
111
+ if (ctx.verbose) {
112
+ console.error(`Error reading directory ${dirPath}:`, message);
113
+ }
114
+ }
115
+ return imageFiles;
116
+ }
117
+ function findImagesInFolders(folders, options = {}) {
118
+ const verbose = Boolean(options.verbose);
119
+ const excludeCommon = Boolean(options.excludeCommon);
120
+ const issues = [];
121
+ const ctx = { issues, verbose, excludeCommon };
122
+ const allImages = [];
123
+ for (const folder of folders) {
124
+ if (!fs_1.default.existsSync(folder)) {
125
+ const message = `Folder does not exist: ${folder}`;
126
+ issues.push({ code: 'MISSING_FOLDER', path: folder, message });
127
+ if (verbose) {
128
+ console.error(message);
129
+ }
130
+ continue;
131
+ }
132
+ if (verbose) {
133
+ console.log(`Scanning folder: ${folder}`);
134
+ }
135
+ const images = walkDirectory(folder, [], ctx);
136
+ const relativeImages = images
137
+ .map(image => {
138
+ const relativePath = path_1.default.relative(folder, image.path).split(path_1.default.sep).join('/');
139
+ return enrichImageEntry({
140
+ path: relativePath,
141
+ size: image.size,
142
+ width: image.width,
143
+ height: image.height
144
+ });
145
+ })
146
+ .filter((row) => row != null);
147
+ allImages.push(...relativeImages);
148
+ }
149
+ return { images: allImages, issues };
150
+ }
151
+ function sortByCompressionScore(images) {
152
+ return [...images].sort((a, b) => {
153
+ const scoreA = parseFloat(a.compressionRatio ?? '') || 0;
154
+ const scoreB = parseFloat(b.compressionRatio ?? '') || 0;
155
+ return scoreB - scoreA;
156
+ });
157
+ }
158
+ //# sourceMappingURL=scan.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scan.js","sourceRoot":"","sources":["../src/scan.ts"],"names":[],"mappings":";;;;;;AAcA,4DAkBC;AAED,4CA8CC;AAyED,kDAyCC;AAED,wDAMC;AA1MD,4CAAoB;AACpB,gDAAwB;AACxB,4DAAgC;AAChC,8CAO2B;AAElB,iGARP,yBAAgB,OAQO;AAEzB,SAAgB,wBAAwB,CACtC,GAAW,EACX,QAAgB,EAChB,KAAgC,EAChC,MAAiC;IAEjC,IAAI,gBAAgB,GAAkB,IAAI,CAAC;IAC3C,IAAI,gBAAgB,GAAkB,IAAI,CAAC;IAE3C,IAAI,KAAK,IAAI,MAAM,IAAI,CAAC,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;QAC/C,MAAM,aAAa,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAC7D,gBAAgB,GAAG,KAAK,GAAG,MAAM,GAAG,aAAa,CAAC;QAClD,MAAM,WAAW,GAAG,QAAQ,GAAG,gBAAgB,CAAC;QAChD,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;QACpE,gBAAgB,GAAG,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;IACzC,CAAC;IAED,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,CAAC;AAChD,CAAC;AAED,SAAgB,gBAAgB,CAAC,KAAoB;IACnD,MAAM,YAAY,GAAG,MAAM,CAAC,KAAK,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;IACzE,IAAI,CAAC,YAAY,IAAI,YAAY,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;QAC5D,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,IAAI,GAAG,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAChC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,IAAI,GAAG,CAAC,EAAE,CAAC;QACvC,OAAO,IAAI,CAAC;IACd,CAAC;IAED,IAAI,KAAK,GAAkB,KAAK,CAAC,KAAK,IAAI,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IAC5E,IAAI,MAAM,GAAkB,KAAK,CAAC,MAAM,IAAI,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IAC/E,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC;QAAE,KAAK,GAAG,IAAI,CAAC;IAC1C,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC;QAAE,MAAM,GAAG,IAAI,CAAC;IAE5C,MAAM,GAAG,GAAG,cAAI,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC,WAAW,EAAE,CAAC;IACrD,MAAM,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,GAAG,wBAAwB,CACrE,GAAG,EACH,IAAI,EACJ,KAAK,EACL,MAAM,CACP,CAAC;IACF,MAAM,EAAE,SAAS,EAAE,eAAe,EAAE,GAAG,IAAA,kBAAS,EAAC;QAC/C,IAAI,EAAE,YAAY;QAClB,IAAI;QACJ,KAAK;QACL,MAAM;KACP,CAAC,CAAC;IAEH,MAAM,GAAG,GAAa;QACpB,IAAI,EAAE,YAAY;QAClB,IAAI,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC;QACtB,KAAK;QACL,MAAM;QACN,gBAAgB;QAChB,gBAAgB;QAChB,IAAI,EAAE,IAAI;QACV,SAAS;KACV,CAAC;IAEF,IAAI,eAAe,EAAE,CAAC;QACpB,GAAG,CAAC,eAAe,GAAG,eAAe,CAAC;IACxC,CAAC;IAED,OAAO,GAAG,CAAC;AACb,CAAC;AAED,SAAS,WAAW,CAAC,QAAgB;IACnC,MAAM,GAAG,GAAG,cAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,WAAW,EAAE,CAAC;IACjD,OAAQ,yBAAsC,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;AAC/D,CAAC;AAED,SAAS,iBAAiB,CAAC,OAAe,EAAE,aAAsB;IAChE,IAAI,CAAC,aAAa,EAAE,CAAC;QACnB,OAAO,KAAK,CAAC;IACf,CAAC;IACD,OAAQ,6BAA0C,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;AACvE,CAAC;AAeD,SAAS,aAAa,CACpB,OAAe,EACf,UAAqB,EACrB,GAAgB;IAEhB,IAAI,CAAC;QACH,MAAM,KAAK,GAAG,YAAE,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC;QAEtC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,MAAM,QAAQ,GAAG,cAAI,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;YAC1C,MAAM,IAAI,GAAG,YAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;YAEnC,IAAI,IAAI,CAAC,WAAW,EAAE,EAAE,CAAC;gBACvB,IAAI,CAAC,iBAAiB,CAAC,IAAI,EAAE,GAAG,CAAC,aAAa,CAAC,EAAE,CAAC;oBAChD,aAAa,CAAC,QAAQ,EAAE,UAAU,EAAE,GAAG,CAAC,CAAC;gBAC3C,CAAC;YACH,CAAC;iBAAM,IAAI,IAAI,CAAC,MAAM,EAAE,IAAI,WAAW,CAAC,IAAI,CAAC,EAAE,CAAC;gBAC9C,IAAI,CAAC;oBACH,MAAM,UAAU,GAAG,IAAA,oBAAM,EAAC,QAAQ,CAAC,CAAC;oBACpC,UAAU,CAAC,IAAI,CAAC;wBACd,IAAI,EAAE,QAAQ;wBACd,IAAI,EAAE,IAAI,CAAC,IAAI;wBACf,KAAK,EAAE,UAAU,CAAC,KAAK,IAAI,IAAI;wBAC/B,MAAM,EAAE,UAAU,CAAC,MAAM,IAAI,IAAI;qBAClC,CAAC,CAAC;gBACL,CAAC;gBAAC,MAAM,CAAC;oBACP,UAAU,CAAC,IAAI,CAAC;wBACd,IAAI,EAAE,QAAQ;wBACd,IAAI,EAAE,IAAI,CAAC,IAAI;wBACf,KAAK,EAAE,IAAI;wBACX,MAAM,EAAE,IAAI;qBACb,CAAC,CAAC;gBACL,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QACvE,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,gBAAgB,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC,CAAC;QACpE,IAAI,GAAG,CAAC,OAAO,EAAE,CAAC;YAChB,OAAO,CAAC,KAAK,CAAC,2BAA2B,OAAO,GAAG,EAAE,OAAO,CAAC,CAAC;QAChE,CAAC;IACH,CAAC;IAED,OAAO,UAAU,CAAC;AACpB,CAAC;AAED,SAAgB,mBAAmB,CACjC,OAAiB,EACjB,UAA0D,EAAE;IAE5D,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;IACzC,MAAM,aAAa,GAAG,OAAO,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC;IACrD,MAAM,MAAM,GAAgB,EAAE,CAAC;IAC/B,MAAM,GAAG,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,aAAa,EAAE,CAAC;IAC/C,MAAM,SAAS,GAAe,EAAE,CAAC;IAEjC,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;QAC7B,IAAI,CAAC,YAAE,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC;YAC3B,MAAM,OAAO,GAAG,0BAA0B,MAAM,EAAE,CAAC;YACnD,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,gBAAgB,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,CAAC;YAC/D,IAAI,OAAO,EAAE,CAAC;gBACZ,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;YACzB,CAAC;YACD,SAAS;QACX,CAAC;QAED,IAAI,OAAO,EAAE,CAAC;YACZ,OAAO,CAAC,GAAG,CAAC,oBAAoB,MAAM,EAAE,CAAC,CAAC;QAC5C,CAAC;QAED,MAAM,MAAM,GAAG,aAAa,CAAC,MAAM,EAAE,EAAE,EAAE,GAAG,CAAC,CAAC;QAC9C,MAAM,cAAc,GAAG,MAAM;aAC1B,GAAG,CAAC,KAAK,CAAC,EAAE;YACX,MAAM,YAAY,GAAG,cAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,cAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YACjF,OAAO,gBAAgB,CAAC;gBACtB,IAAI,EAAE,YAAY;gBAClB,IAAI,EAAE,KAAK,CAAC,IAAI;gBAChB,KAAK,EAAE,KAAK,CAAC,KAAK;gBAClB,MAAM,EAAE,KAAK,CAAC,MAAM;aACrB,CAAC,CAAC;QACL,CAAC,CAAC;aACD,MAAM,CAAC,CAAC,GAAG,EAAmB,EAAE,CAAC,GAAG,IAAI,IAAI,CAAC,CAAC;QAEjD,SAAS,CAAC,IAAI,CAAC,GAAG,cAAc,CAAC,CAAC;IACpC,CAAC;IAED,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,CAAC;AACvC,CAAC;AAED,SAAgB,sBAAsB,CAAC,MAAkB;IACvD,OAAO,CAAC,GAAG,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;QAC/B,MAAM,MAAM,GAAG,UAAU,CAAC,CAAC,CAAC,gBAAgB,IAAI,EAAE,CAAC,IAAI,CAAC,CAAC;QACzD,MAAM,MAAM,GAAG,UAAU,CAAC,CAAC,CAAC,gBAAgB,IAAI,EAAE,CAAC,IAAI,CAAC,CAAC;QACzD,OAAO,MAAM,GAAG,MAAM,CAAC;IACzB,CAAC,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,6 @@
1
+ import http from 'http';
2
+ export interface RepoimageServerOptions {
3
+ clientRoot?: string;
4
+ }
5
+ export declare function createRepoimageServer(options?: RepoimageServerOptions): http.Server;
6
+ //# sourceMappingURL=server.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,MAAM,CAAC;AAiHxB,MAAM,WAAW,sBAAsB;IACrC,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,wBAAgB,qBAAqB,CAAC,OAAO,GAAE,sBAA2B,GAAG,IAAI,CAAC,MAAM,CAiOvF"}