@nathievzm/lumi 1.1.5 → 1.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.
package/.env.example CHANGED
@@ -1,11 +1,12 @@
1
- # Default target dimensions for images
2
- WIDTH = '800'
3
- HEIGHT = '600'
4
-
5
- # Default folder paths (can be relative or absolute)
6
- INPUT_FOLDER = './input'
7
- OUTPUT_FOLDER = './output'
8
-
9
- # Default processing settings
10
- FORMAT = '.webp'
11
- LIMIT = '10'
1
+ # Default target dimensions for images
2
+ WIDTH = '800'
3
+ HEIGHT = '600'
4
+
5
+ # Default folder paths (can be relative or absolute)
6
+ INPUT_FOLDER = './input'
7
+ OUTPUT_FOLDER = './output'
8
+
9
+ # Default processing settings
10
+ FORMAT = '.webp'
11
+ LIMIT = '10'
12
+ RECURSIVE = 'false'
@@ -0,0 +1,8 @@
1
+ declare module 'bun' {
2
+ interface Env {
3
+ /**
4
+ * The GitHub personal access token used for authentication in GitHub Actions scripts.
5
+ */
6
+ GITHUB_TOKEN?: string
7
+ }
8
+ }
@@ -0,0 +1,44 @@
1
+ import { exit } from 'node:process'
2
+
3
+ import { type PullRequest } from '@octokit/webhooks-types'
4
+
5
+ import { context, octokit } from './octokit'
6
+
7
+ const isPullRequest = (data: unknown): data is PullRequest =>
8
+ typeof data === 'object' && data !== null && 'head' in data
9
+
10
+ const pullRequest = context.payload.pull_request
11
+
12
+ if (!isPullRequest(pullRequest)) {
13
+ throw new Error('this event does not contain a pull request! 😢')
14
+ }
15
+
16
+ const branch = /\w+\/(\d+)-\w+/v.exec(pullRequest.head.ref)
17
+
18
+ if (branch === null || branch.length < 2 || branch[1] === undefined) {
19
+ console.log(`skipping: branch ${pullRequest.head.ref} does not match the issue format. ⏭️`)
20
+ exit(0)
21
+ }
22
+
23
+ const issueNumber = Number(branch[1])
24
+
25
+ const { data: issue, status } = await octokit.rest.issues.get({
26
+ issue_number: issueNumber,
27
+ owner: context.repo.owner,
28
+ repo: context.repo.repo
29
+ })
30
+
31
+ if (status !== 200) {
32
+ throw new Error('failed to fetch the issue! 😟')
33
+ }
34
+
35
+ const labels = issue.labels
36
+ .map(label => (typeof label === 'string' ? label : label.name))
37
+ .filter((name): name is string => typeof name === 'string' && name.length > 0)
38
+
39
+ await octokit.rest.issues.addLabels({
40
+ issue_number: context.issue.number,
41
+ labels,
42
+ owner: context.repo.owner,
43
+ repo: context.repo.repo
44
+ })
@@ -0,0 +1,8 @@
1
+ import { context, octokit } from './octokit'
2
+
3
+ await octokit.rest.issues.addAssignees({
4
+ assignees: [context.actor],
5
+ issue_number: context.issue.number,
6
+ owner: context.repo.owner,
7
+ repo: context.repo.repo
8
+ })
@@ -0,0 +1,10 @@
1
+ import { context, getOctokit } from '@actions/github'
2
+
3
+ const token = Bun.env.GITHUB_TOKEN
4
+
5
+ if (token === undefined) {
6
+ throw new Error('GITHUB_TOKEN is missing! 😭')
7
+ }
8
+
9
+ const octokit = getOctokit(token)
10
+ export { context, octokit }
@@ -0,0 +1,20 @@
1
+ name: add labels from issue to pull request
2
+
3
+ on:
4
+ pull_request:
5
+ types: [opened]
6
+
7
+ jobs:
8
+ add-labels:
9
+ runs-on: ubuntu-latest
10
+ steps:
11
+ - name: check out repository code
12
+ uses: actions/checkout@v6
13
+ - name: set up bun
14
+ uses: oven-sh/setup-bun@v2
15
+ - name: install dependencies
16
+ run: bun install
17
+ - name: run bun script to add labels from issue to pull request
18
+ run: bun .github/scripts/add-labels-pr
19
+ env:
20
+ GITHUB_TOKEN: ${{ secrets.LUMI_ADD_LABELS_PR }}
@@ -1,4 +1,6 @@
1
- name: auto assign author
1
+ name: auto assign author to issue or pr
2
+
3
+ run-name: ${{ github.actor }} is automatically assigned to the issue or pr they just opened ✅
2
4
 
3
5
  on:
4
6
  issues:
@@ -9,22 +11,14 @@ on:
9
11
  jobs:
10
12
  assign:
11
13
  runs-on: ubuntu-latest
12
- permissions:
13
- issues: write
14
- pull-requests: write
15
14
  steps:
16
- - name: assign the user who opened the ticket or pr
17
- uses: actions/github-script@v7
18
- with:
19
- github-token: ${{ secrets.LUMI_AUTOASSIGN_TOKEN }}
20
- script: |
21
- // grab the username of the person who triggered the action
22
- const author = context.actor
23
-
24
- // tell github's api to assign the ticket to that username
25
- await github.rest.issues.addAssignees({
26
- owner: context.repo.owner,
27
- repo: context.repo.repo,
28
- issue_number: context.issue.number,
29
- assignees: [author]
30
- })
15
+ - name: check out repository code
16
+ uses: actions/checkout@v6
17
+ - name: set up bun
18
+ uses: oven-sh/setup-bun@v2
19
+ - name: install dependencies
20
+ run: bun install
21
+ - name: run bun script to auto-assign the author
22
+ run: bun .github/scripts/auto-assign
23
+ env:
24
+ GITHUB_TOKEN: ${{ secrets.LUMI_AUTOASSIGN }}
package/.jules/bolt.md ADDED
@@ -0,0 +1,62 @@
1
+ ## 2026-05-12 - [Optimizing Array & Set Operations]
2
+
3
+ **Learning:** In hot paths handling large numbers of files, using chained array methods like `.flatMap()`, `new Set()`,
4
+ spread operators, and `.filter()` creates unnecessary intermediate arrays and memory allocations. Furthermore,
5
+ repeatedly creating static Sets inside functions adds unnecessary O(N) overhead per call.
6
+
7
+ **Action:** When iterating over potentially large lists (like file paths), favor a single-pass `for...of` loop over
8
+ chained array methods to minimize memory footprint. Always pull static Set creation outside of function scopes to
9
+ initialize them once at the module level.
10
+
11
+ ## 2026-05-15 - [Avoid Caching in Run-Once CLI Apps]
12
+
13
+ **Learning:** Implementing in-memory caching (like storing `sharp.format` values in a module-scoped variable) is
14
+ ineffective and adds unnecessary complexity in a CLI application that has a strictly 'run-once-and-exit' lifecycle. The
15
+ cache is built but never reused because the process terminates immediately after its primary task.
16
+
17
+ **Action:** Always consider the application's lifecycle (e.g., long-running server vs. short-lived CLI script) before
18
+ introducing caching or memoization. Prefer pure functions, readability, and KISS/YAGNI principles over
19
+ micro-optimizations that create global mutable state without a measurable benefit in the specific execution context.
20
+
21
+ ## 2024-05-18 - [Replace Heavy Polyfills with Native APIs]
22
+
23
+ **Learning:** Using heavy polyfills like `@js-temporal/polyfill` solely for simple duration measurement introduces
24
+ significant (~90ms) startup overhead, which is detrimental to CLI performance.
25
+
26
+ **Action:** Always prefer native APIs like `performance.now()` for simple duration tracking to avoid the overhead of
27
+ parsing and instantiating large external libraries.
28
+
29
+ ## 2024-05-19 - [Avoid Awaiting Dynamic Imports in Critical Path]
30
+
31
+ **Learning:** Using \`await import(...)\` for a heavy module during the synchronous CLI startup phase blocks execution,
32
+ failing to deliver the intended performance benefit of a dynamic import (it just shifts the penalty to a different
33
+ point).
34
+
35
+ **Action:** If deferring a heavy module for a non-critical side effect (like update checking), use promise chaining
36
+ (\`.then().catch()\`) without \`await\` to allow the main execution thread to continue immediately.
37
+
38
+ ## 2025-02-14 - [Dynamic Import of Heavy Modules in CLI]
39
+
40
+ **Learning:** `sharp` is a heavyweight module that blocks execution for >130ms on import. This severely impacts the
41
+ startup time of the CLI, making `lumi --help` and error reporting feel slow.
42
+
43
+ **Action:** Used dynamic imports (`await import('sharp')`) to lazily load the library only when image processing methods
44
+ (`resize` and `getSharpFormats`) are called. This avoids importing `sharp` during the synchronous CLI startup path.
45
+
46
+ ## 2024-05-18 - Avoid typeof on imported default types
47
+
48
+ **Learning:** When asserting a type on a dynamically imported module by extracting its default export (e.g.
49
+ `typeof sharp`), the `typeof` keyword must not be applied if the module has been imported specifically into the type
50
+ space via `import { type default as sharp } from 'sharp'`. Applying `typeof` to a type-only import results in a `TS2693`
51
+ compilation error because `typeof` operates on values, not types.
52
+
53
+ **Action:** When strictly importing types to satisfy `import(consistent-type-specifier-style)`, directly apply the
54
+ imported type without `typeof`.
55
+
56
+ ## 2025-05-25 - [Optimize getImages path resolution]
57
+
58
+ **Learning:** `resolve` is significantly slower than `join` in Node's path module, particularly within tight loops.
59
+ Repeatedly resolving a known directory prefix causes measurable overhead when processing large volumes of files.
60
+
61
+ **Action:** Whenever iterating over many files that share a base directory, `resolve` the base directory once outside
62
+ the loop and use `join(resolvedBase, file)` inside the loop to drastically improve performance.
@@ -0,0 +1,58 @@
1
+ ## 2026-05-12 - Added error output for failed images
2
+
3
+ **Learning:** Users need to know exactly which images failed during batch processing. An overall error message is not
4
+ actionable.
5
+
6
+ **Action:** Always output detailed errors for individual batch items when a batch process fails, even if it adds to
7
+ terminal noise, because the user needs to correct specific items.
8
+
9
+ ## 2026-05-13 - Friendly CLI Errors
10
+
11
+ **Learning:** Raw stack traces from unhandled Promise rejections (like `readdir` on a non-existent directory) are
12
+ intimidating for CLI users.
13
+
14
+ **Action:** Always wrap file I/O operations in `try...catch` blocks and use UI logging tools (like `@clack/prompts`) to
15
+ provide actionable, human-readable error messages before gracefully exiting.
16
+
17
+ ## 2026-05-14 - Default CLI Prompt Values
18
+
19
+ **Learning:** When prompting users for repeated or common file conversions, failing to default to the original format
20
+ creates unnecessary friction. Users expect smart defaults that save keystrokes.
21
+
22
+ **Action:** Always set an `initialValue` in CLI selection prompts (`@clack/prompts`) where a logical default exists,
23
+ such as defaulting to a file's original extension during conversion options.
24
+
25
+ ## 2026-05-18 - Rejected Default Value for Dimensions
26
+
27
+ **Learning:** Adding a strict `defaultValue` (e.g., '1080') to the dimensions prompt overrides the helpful `placeholder`
28
+ text visually in the UI, making the interface less descriptive and potentially confusing for users who need custom
29
+ sizes.
30
+
31
+ **Action:** Prioritize descriptive placeholders over hardcoded default values for free-text inputs where the user might
32
+ legitimately need a wide variety of formats (like dimensions).
33
+
34
+ ## 2026-05-20 - Rejected Initial Value for Dimensions
35
+
36
+ **Learning:** Using `initialValue` for dimensions also overrides the `placeholder` text visually in the UI just like
37
+ `defaultValue` does, making the interface less descriptive since users can't see that they can provide two values.
38
+
39
+ **Action:** Avoid using `initialValue` or `defaultValue` in free-text inputs like dimensions, where a helpful
40
+ placeholder explaining multiple formats is more valuable.
41
+
42
+ ## 2025-02-23 - Use placeholder instead of initialValue for CLI text prompts with descriptive help
43
+
44
+ **Learning:** In CLI text prompts (like @clack/prompts), `initialValue` fills the text field, which hides any
45
+ descriptive `placeholder` text that would otherwise provide helpful instructions to the user. Using no `initialValue`
46
+ (or `defaultValue`) ensures the `placeholder` remains visible, guiding the user on the expected input format without
47
+ them needing to clear the field first.
48
+
49
+ **Action:** Avoid setting an `initialValue` in CLI text prompts when a descriptive `placeholder` is present, to ensure
50
+ the helpful placeholder text remains visible to the user.
51
+
52
+ ## 2026-05-25 - Actionable Empty State Errors
53
+
54
+ **Learning:** When users run the tool on a directory that has images in subfolders but not in the root, an error simply
55
+ stating "no valid images found" is confusing and unhelpful.
56
+
57
+ **Action:** Always provide actionable hints in empty states or error messages, such as suggesting the `--recursive`
58
+ flag, to guide the user toward a solution.
@@ -0,0 +1,70 @@
1
+ ## 2026-05-12 - Fix Missing Input Length Limits (DoS Risk)
2
+
3
+ **Vulnerability:** Denial of Service (DoS) vulnerability via resource exhaustion caused by unconstrained width and
4
+ height parameters during image resizing with Sharp.
5
+
6
+ **Learning:** Tools handling image processing can easily be abused to consume excessive memory if user-provided
7
+ dimensions are unchecked, potentially crashing the Node.js/Bun process.
8
+
9
+ **Prevention:** Implement strict length and dimension validation boundaries for all user input governing asset
10
+ generation, catching errors gracefully without leaking system details.
11
+
12
+ ## 2026-05-14 - Fix Path Traversal in Image Output
13
+
14
+ **Vulnerability:** A path traversal vulnerability existed in `src/lib/image.ts`. The output file path was constructed by
15
+ blindly concatenating user input (`cli.format` passed as `extension`) using `join`. An attacker could pass a format
16
+ string like `/../../../tmp/evil.png` to write files to arbitrary locations outside the intended output directory.
17
+
18
+ **Learning:** We must not blindly trust user input that influences file paths, especially file extensions or format
19
+ modifiers. When working with Node.js `path.join`, it resolves relative segments, which can escape the current directory.
20
+
21
+ **Prevention:** Always validate constructed file paths. Before performing any file operation, resolve the final output
22
+ path and check if it strictly starts with the resolved target directory path to prevent path traversals.
23
+
24
+ ## 2026-05-18 - [Path Traversal in Input Resolution]
25
+
26
+ **Vulnerability:** The application was vulnerable to path traversal because it resolved the input image path via
27
+ `join(input, image)` and passed it directly to `sharp` without validation.
28
+
29
+ **Learning:** Even though the `outputPath` was properly guarded against path traversal, the missing guard on `inputPath`
30
+ could allow an attacker to read arbitrary files off the filesystem by specifying a malicious `image` filename with `../`
31
+ sequences.
32
+
33
+ **Prevention:** Always sanitize and guard both input and output paths to ensure they strictly reside within the intended
34
+ boundaries.
35
+
36
+ ## 2026-05-19 - [Null Byte Injection in Path Resolution]
37
+
38
+ **Vulnerability:** The `guard` function used to prevent path traversal was relying on `node:path`'s `resolve` and
39
+ `startsWith` to verify paths. However, strings containing null bytes (`\0`) could cause `resolve` to behave unexpectedly
40
+ or terminate strings prematurely in underlying C++ extensions or certain filesystem API scenarios, effectively bypassing
41
+ the `startsWith` validation check.
42
+
43
+ **Learning:** Node's built-in path module does not inherently protect against null byte injection, and combining strings
44
+ with null bytes can lead to bypassing directory containment checks.
45
+
46
+ **Prevention:** Always explicitly check for and reject null bytes (`\0`) in user-supplied paths before using them in
47
+ file system operations or path resolutions.
48
+
49
+ ## 2026-05-20 - [Null Byte Injection in Folder Parameter]
50
+
51
+ **Vulnerability:** While the `guard` function previously checked for null bytes (`\0`) in the `path` parameter, it
52
+ neglected to perform the same check on the `folder` parameter. This inconsistency left a potential path traversal bypass
53
+ vector open if the base folder path itself originated from untrusted input.
54
+
55
+ **Learning:** Null byte injection protections must be consistently applied to all path components involved in a security
56
+ boundary check, not just the immediately obvious file path.
57
+
58
+ **Prevention:** Ensure comprehensive null byte validation (`\0`) on all path inputs (both base directories and target
59
+ paths) prior to resolving them with `node:path` functions.
60
+
61
+ ## 2025-05-21 - Early Path Component Validation
62
+
63
+ **Vulnerability:** Path traversal and null byte injection vectors existed because inputs to `node:path` functions were
64
+ not sanitised early enough.
65
+
66
+ **Learning:** By passing an unsanitised component into `node:path` functions like `join`, a null byte could prematurely
67
+ terminate strings and bypass directory boundary checks.
68
+
69
+ **Prevention:** Explicitly reject null bytes ('\0') in all user-provided path components before passing them to
70
+ `node:path` functions or combining them.
package/.oxlintrc.json CHANGED
@@ -24,7 +24,8 @@
24
24
  "no-continue": "off",
25
25
  "require-param-type": "off",
26
26
  "require-returns-type": "off",
27
- "max-dependencies": ["warn", { "max": 16 }]
27
+ "max-dependencies": ["warn", { "max": 16 }],
28
+ "max-classes-per-file": ["warn", { "max": 3 }]
28
29
  },
29
30
  "env": {
30
31
  "builtin": true
@@ -5,7 +5,9 @@
5
5
  "oxc.enable.oxlint": true,
6
6
  "oxc.enable.oxfmt": true,
7
7
  "editor.codeActionsOnSave": {
8
- "source.fixAll.oxc": "always"
8
+ "source.fixAll.oxc": "always",
9
+ "source.format.oxc": "always",
10
+ "source.fixAll": "always"
9
11
  },
10
12
  "files.insertFinalNewline": false,
11
13
  "files.trimTrailingWhitespace": true
package/CHANGELOG.md CHANGED
@@ -1,3 +1,84 @@
1
+ # [1.2.0](https://github.com/nathievzm/lumi/compare/v1.1.6...v1.2.0) (2026-05-29)
2
+
3
+ ### Bug Fixes
4
+
5
+ - guard function and recursive flag
6
+ ([41fcb3e](https://github.com/nathievzm/lumi/commit/41fcb3e38c7c271971543b2cc38665f7c545c9c2))
7
+
8
+ ### Features
9
+
10
+ - **image:** cache sharp dynamic import promise to improve performance
11
+ ([08a02fd](https://github.com/nathievzm/lumi/commit/08a02fd0a166dfd3587b76c9635fee323ddff38c))
12
+ - **ui:** add initialValue to dimensions prompt to reduce user friction
13
+ ([b72ccaf](https://github.com/nathievzm/lumi/commit/b72ccafe8dfbd66d35a5b3abbe727500f36e5921))
14
+ - **ux:** add initialValue to askWidthAndHeight prompt
15
+ ([027ec53](https://github.com/nathievzm/lumi/commit/027ec536da421716121f306fefa5d23fa5c49696))
16
+ - **ux:** add initialValue to askWidthAndHeight prompt
17
+ ([a095643](https://github.com/nathievzm/lumi/commit/a09564304ba0b49d3e9d2d45ed64a9460c578a97))
18
+ - **ux:** update journal learning about initialValue vs placeholder
19
+ ([80c873f](https://github.com/nathievzm/lumi/commit/80c873fb16ded0ad9b098670f92f9839cf0c66d7))
20
+ - **ux:** update journal learning about initialValue vs placeholder
21
+ ([3f75765](https://github.com/nathievzm/lumi/commit/3f7576541d7792a0004e8ba2dddb8d8873106303))
22
+ - **ux:** update journal learning about initialValue vs placeholder
23
+ ([b56fd87](https://github.com/nathievzm/lumi/commit/b56fd876ee00478efe24b604c5084e8c27d49509))
24
+
25
+ ### Performance Improvements
26
+
27
+ - **image:** lazily load heavy sharp module to improve startup time
28
+ ([5c3c9a4](https://github.com/nathievzm/lumi/commit/5c3c9a424e21d46c7830feb5e80517a4e274ba91))
29
+ - optimize path resolution in `getImages`
30
+ ([1b91635](https://github.com/nathievzm/lumi/commit/1b91635306851cd1840e1a11b9eacd361741993d))
31
+
32
+ ### Reverts
33
+
34
+ - Remove initialValue from dimension prompt to show placeholder
35
+ ([06b9a0c](https://github.com/nathievzm/lumi/commit/06b9a0c35089d89d056fecc8ff50e7a31b34a789))
36
+
37
+ ## [1.1.6](https://github.com/nathievzm/lumi/compare/v1.1.5...v1.1.6) (2026-05-19)
38
+
39
+ ### Bug Fixes
40
+
41
+ - prevent path traversal on input image resolution
42
+ ([cfe9f2a](https://github.com/nathievzm/lumi/commit/cfe9f2a78d570b63fbfe2051bc21b13710930c0e))
43
+ - **prompt:** remove defaultValue to prefer descriptive placeholder
44
+ ([bf63182](https://github.com/nathievzm/lumi/commit/bf631822bf0ab3c9bbc99600692ca7143d651bb6))
45
+ - remove step that logs the whole github json
46
+ ([1ff461d](https://github.com/nathievzm/lumi/commit/1ff461d9192421c6562d85436e45d30fd0b22085))
47
+ - revert changes from jules
48
+ ([2a4db48](https://github.com/nathievzm/lumi/commit/2a4db4843b381da26fb42b1c11839f469029e78e))
49
+
50
+ ### Features
51
+
52
+ - add code to add the issue labels to the pr
53
+ ([d8b5d87](https://github.com/nathievzm/lumi/commit/d8b5d8789879f76a9969a67223593db89638a3ac))
54
+ - add test workflow to sync pr with issue
55
+ ([a4f8e10](https://github.com/nathievzm/lumi/commit/a4f8e1032d12283a456003d5d274bef98914028f))
56
+ - add ts script to get pull request
57
+ ([c7f0e2d](https://github.com/nathievzm/lumi/commit/c7f0e2d9b20b0040889d6dcae76b62eaf5fb17f9))
58
+ - log found connected found issue
59
+ ([edb6375](https://github.com/nathievzm/lumi/commit/edb6375a3881361afc0819b27f71418d560d62b4))
60
+ - move notify function to update module
61
+ ([d701256](https://github.com/nathievzm/lumi/commit/d701256b69b54eae195090ff23dd4ed64f2b0cc1))
62
+ - **prompt:** add default value to dimension prompt
63
+ ([7271ae5](https://github.com/nathievzm/lumi/commit/7271ae5aaef008a8024b916deaae6d6465b9c7bc))
64
+ - remove error when branch doesn't have correct format
65
+ ([03fc8fb](https://github.com/nathievzm/lumi/commit/03fc8fb50466cedd78b959b51c52cd5c52800144))
66
+ - replace auto-assign workflow with ts script and bun action
67
+ ([aeda5fa](https://github.com/nathievzm/lumi/commit/aeda5fa6d09b030a50c079c0ca628ecbd1cd3d50))
68
+ - replace small try/catch by global try/catch block with new errors
69
+ ([74f3d2c](https://github.com/nathievzm/lumi/commit/74f3d2cff8f95e7d521670d9eefca55510ccd3e9))
70
+ - use gh script action to run js scripts
71
+ ([3afe134](https://github.com/nathievzm/lumi/commit/3afe134d76c5d7d14c7cd1dbdce384e0507d5f48))
72
+
73
+ ### Performance Improvements
74
+
75
+ - cache sharp formats to avoid redundant computation
76
+ ([3eea037](https://github.com/nathievzm/lumi/commit/3eea037679b3b9677a13fa4898c2bb81ff31b0c9))
77
+ - cache sharp formats to avoid redundant computation and fix CI
78
+ ([4eeea88](https://github.com/nathievzm/lumi/commit/4eeea88ce1daebafcf8417e996dde515aa6fbf86))
79
+ - replace @js-temporal/polyfill with performance.now()
80
+ ([e28a380](https://github.com/nathievzm/lumi/commit/e28a38065d9f5bc08ea31d04fa37d7e171f42d29))
81
+
1
82
  ## [1.1.5](https://github.com/nathievzm/lumi/compare/v1.1.4...v1.1.5) (2026-05-14)
2
83
 
3
84
  ### Bug Fixes
package/README.md CHANGED
@@ -14,6 +14,7 @@ A fast, interactive CLI tool for batch image processing. Resize, convert, and op
14
14
  - **Animated Support:** Seamlessly handles animated GIFs and WebP files.
15
15
  - **Concurrency Control:** Fine-tune performance with configurable processing limits.
16
16
  - **Environment Driven:** Fully configurable via `.env` files or CLI flags.
17
+ - **Update Notifications:** Automatically alerts you when a new version is available.
17
18
 
18
19
  ## 📦 Installation
19
20
 
@@ -111,6 +112,7 @@ bun install
111
112
  - `bun fmt:check`: Check for formatting issues.
112
113
  - `bun changelog`: Update the changelog.
113
114
  - `bun release`: Release a new version with `bumpp` and update the changelog.
115
+ - `bun prepare`: Install git hooks with `lefthook`.
114
116
 
115
117
  ## 📄 License
116
118
 
package/lefthook.yml CHANGED
@@ -1,9 +1,6 @@
1
1
  pre-commit:
2
- # running all checks at the same time for maximum speed ⚡
3
- parallel: true
4
2
  jobs:
5
3
  - name: format
6
- glob: '*.{ts,js,json,yml,yaml,md}'
7
4
  run: bun fmt && git add .
8
5
 
9
6
  - name: lint
@@ -15,7 +12,6 @@ pre-commit:
15
12
  commit-msg:
16
13
  jobs:
17
14
  - name: commitlint
18
- # using bun to run commitlint as fast as possible 🌸
19
15
  run: bunx --bun commitlint --edit {1}
20
16
 
21
17
  pre-push:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nathievzm/lumi",
3
- "version": "1.1.5",
3
+ "version": "1.2.0",
4
4
  "description": "a concurrent cli tool to resize and convert images using bun and sharp",
5
5
  "keywords": [
6
6
  "bun",
@@ -50,8 +50,7 @@
50
50
  "start": "bun src/index.ts"
51
51
  },
52
52
  "dependencies": {
53
- "@clack/prompts": "^1.3.0",
54
- "@js-temporal/polyfill": "^0.5.1",
53
+ "@clack/prompts": "^1.4.0",
55
54
  "boxen": "^8.0.1",
56
55
  "image-extensions": "^1.1.0",
57
56
  "p-limit": "^7.3.0",
@@ -60,15 +59,17 @@
60
59
  "update-notifier": "^7.3.1"
61
60
  },
62
61
  "devDependencies": {
62
+ "@actions/github": "^9.1.1",
63
63
  "@commitlint/cli": "^20.5.3",
64
64
  "@commitlint/config-conventional": "^20.5.3",
65
+ "@octokit/webhooks-types": "^7.6.1",
65
66
  "@types/bun": "latest",
66
67
  "@types/update-notifier": "^6.0.8",
67
68
  "bumpp": "^11.1.0",
68
69
  "conventional-changelog-cli": "^5.0.0",
69
70
  "lefthook": "^2.1.6",
70
71
  "oxfmt": "^0.47.0",
71
- "oxlint": "^1.64.0",
72
+ "oxlint": "^1.65.0",
72
73
  "oxlint-tsgolint": "^0.22.1",
73
74
  "typescript": "^6.0.3"
74
75
  }
package/src/env.d.ts CHANGED
@@ -1,27 +1,27 @@
1
1
  declare module 'bun' {
2
2
  interface Env {
3
3
  /**
4
- * Default target width for resized images.
4
+ * The default target width in pixels for resized images.
5
5
  */
6
6
  WIDTH?: string
7
7
  /**
8
- * Default target height for resized images.
8
+ * The default target height in pixels for resized images.
9
9
  */
10
10
  HEIGHT?: string
11
11
  /**
12
- * Default path to the input folder containing images.
12
+ * The default path to the input directory containing source images.
13
13
  */
14
14
  INPUT_FOLDER?: string
15
15
  /**
16
- * Default path where processed images will be saved.
16
+ * The default path to the destination directory where processed images will be saved.
17
17
  */
18
18
  OUTPUT_FOLDER?: string
19
19
  /**
20
- * Default global output format (e.g., '.webp', '.png').
20
+ * The default global output format extension (e.g., `.webp`, `.png`).
21
21
  */
22
22
  FORMAT?: string
23
23
  /**
24
- * Default concurrent processing limit.
24
+ * The default concurrent processing limit.
25
25
  */
26
26
  LIMIT?: string
27
27
  /**