diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index ae43a57..363cf7f 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -70,3 +70,73 @@ jobs:
cp docs/README_NPM.md app/README.md
cd app
npm publish --provenance --access public
+
+ docker-build-push:
+ name: Build and Push Docker Image
+ if: github.event.release.target_commitish == 'main' && vars.DOCKERHUB_USERNAME != ''
+ needs: [lint-test-app]
+ runs-on: ubuntu-latest
+ env:
+ REGISTRY: docker.io
+ IMAGE_NAME: weaponsforge/cloudinary-cli
+ permissions:
+ contents: read
+ security-events: write
+ packages: write
+ steps:
+ - name: Checkout the repository
+ uses: actions/checkout@v6
+ with:
+ ref: ${{ github.event.release.tag_name }}
+
+ - name: Set up Docker Buildx
+ uses: docker/setup-buildx-action@v3
+
+ - name: Log in to Docker Hub
+ uses: docker/login-action@v3
+ with:
+ registry: ${{ env.REGISTRY }}
+ username: ${{ secrets.DOCKERHUB_USERNAME }}
+ password: ${{ secrets.DOCKERHUB_TOKEN }}
+
+ - name: Generate Docker Image Tags and Labels
+ id: meta
+ uses: docker/metadata-action@v5
+ with:
+ images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
+ tags: |
+ type=ref,event=branch
+ type=ref,event=pr
+ type=semver,pattern={{version}}
+ # type=semver,pattern={{major}}.{{minor}}
+ type=raw,value=latest,enable={{is_default_branch}}
+
+ - name: Build and Push Docker Image
+ id: build
+ uses: docker/build-push-action@v6
+ with:
+ context: ./app
+ file: ./app/Dockerfile
+ target: production
+ platforms: linux/amd64
+ push: true
+ tags: ${{ steps.meta.outputs.tags }}
+ labels: ${{ steps.meta.outputs.labels }}
+ cache-from: type=gha
+ cache-to: type=gha,mode=max
+ build-args: |
+ BUILDKIT_INLINE_CACHE=1
+ CACHEBUST=${{ github.run_id }}
+
+ - name: Scan Image for Vulnerabilities
+ uses: aquasecurity/trivy-action@v0.35.0
+ with:
+ image-ref: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}@${{ steps.build.outputs.digest }}
+ format: 'sarif'
+ output: 'trivy-results.sarif'
+
+ - name: Upload Trivy Scan Results to GitHub Security Tab
+ uses: github/codeql-action/upload-sarif@v4
+ if: always()
+ with:
+ sarif_file: 'trivy-results.sarif'
diff --git a/README.md b/README.md
index b8b7707..46c494b 100644
--- a/README.md
+++ b/README.md
@@ -18,6 +18,8 @@ Create a `.env` file in the `/app` directory, replacing the contents of the `.en
| CLOUDINARY_NAME | Cloudinary account name |
| CLOUDINARY_API_KEY | Cloudinary API key |
| CLOUDINARY_API_SECRET | Cloudinary API secret |
+| CHOKIDAR_USEPOLLING | Enables file watching on `tsx watch` running inside Docker containers on a Windows host. Set it to `true` if running Docker Desktop with WSL2 on a Windows OS host. |
+| CHOKIDAR_INTERVAL | Chokidar polling interval. Set it along with `CHOKIDAR_USEPOLLING=true` if running Docker Desktop with WSL2 on a Windows OS host. The default value is `1000`. |
## Usage
@@ -29,9 +31,13 @@ Create a `.env` file in the `/app` directory, replacing the contents of the `.en
2. Run the container.
`docker compose up`
-3. Run the [Available Scripts](#available-scripts) using Docker.
+3. Edit the `.ts` source files and watch for changes.
+
+4. Run the [Available Scripts](#available-scripts) using Docker.
+
+5. See the examples under the [Code Samples](#-code-samples) section for more information.
+
-4. See the examples under the [Code Samples](#-code-samples) section for more information.
**Example using the development Docker image**
@@ -57,16 +63,24 @@ Build the production image with
#### B. Using Node.js
-1. Install dependencies.
+1. Install dependencies.
```sh
cd app
npm install
```
-2. Run the [Available Scripts](#available-scripts).
+2. Run the app in development mode.
+
+ ```
+ npm run dev
+ ```
-3. See the examples under the [Code Samples](#-code-samples) section for more information.
+3. Edit the `.ts` source files and watch for changes.
+
+4. Run the [Available Scripts](#available-scripts).
+
+5. See the examples under the [Code Samples](#-code-samples) section for more information.
## Available Scripts
@@ -100,7 +114,7 @@ npm start -- \
### `npm run dev`
-Runs the `npm start` script in development mode with `tsx`.
+Runs the `npm start` script in development mode with file watching using `tsx`.
Example usage:
`npm run dev -- -f /assets/sunset.jpg -u`
@@ -127,6 +141,15 @@ Fixes lint errors in TypeScript files.
Watches file changes in `.ts` files using the `tsc --watch` option.
+### `npm run docker:dev`
+
+Docker counterpart of the `npm run dev` script. Exports the `IS_DOCKER=true` variable and runs the `npm run dev` script in development mode with file watching using `tsx` within Docker.
+
+> [!TIP]
+> Set `CHOKIDAR_USEPOLLING=true` and `CHOKIDAR_INTERVAL=1000` in the `.env` file to enable file watching on when running inside Docker containers on a Windows host.
+>
+> Uncomment and use ` _values` in **/src/scripts/optimize/index.ts** to manually set `optimize(_values)` not from CLI input.
+
### `npm run docker:watch:win`
Watches file changes in `.ts` files using the `tsc --watch` option with `dynamicPriorityPolling` in Docker containers running in Windows WSL2.
diff --git a/app/Dockerfile b/app/Dockerfile
index ef04841..8aa3c28 100644
--- a/app/Dockerfile
+++ b/app/Dockerfile
@@ -19,7 +19,7 @@ RUN npm ci
COPY --chown=node:node . ./
USER node
EXPOSE 9229
-CMD ["sh"]
+CMD ["npm", "run", "docker:dev"]
# Proudction target profile
FROM base AS production
diff --git a/app/package-lock.json b/app/package-lock.json
index effeda4..62a633c 100644
--- a/app/package-lock.json
+++ b/app/package-lock.json
@@ -1,34 +1,58 @@
{
"name": "cloudinary-image",
- "version": "1.0.0",
+ "version": "1.0.1",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "cloudinary-image",
- "version": "1.0.0",
+ "version": "1.0.1",
"license": "MIT",
"dependencies": {
- "cloudinary": "^2.10.0",
- "dotenv": "^17.4.2"
+ "cloudinary": "^2.11.0",
+ "dotenv": "^18.0.6"
},
"bin": {
"optimize": "dist/scripts/optimize/index.js"
},
"devDependencies": {
"@eslint/js": "^10.0.1",
- "@types/node": "^26.2.0",
- "eslint": "^10.8.1",
- "globals": "^17.11.0",
- "tsc-alias": "^1.9.1",
- "tsx": "^4.23.12",
+ "@types/node": "^26.6.4",
+ "eslint": "^10.12.0",
+ "globals": "^17.13.0",
+ "tsc-alias": "^1.9.7",
+ "tsx": "^4.23.15",
"typescript": "^6.0.3",
- "typescript-eslint": "^8.67.0"
+ "typescript-eslint": "^8.71.1"
},
"engines": {
"node": ">=24"
}
},
+ "node_modules/@cacheable/memory": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/@cacheable/memory/-/memory-2.2.0.tgz",
+ "integrity": "sha512-CTLKqLItRCEixEAewD3/j9DB3/o96gpTPD4eJ1v+DGOlxZRZncRQkGYqqnAGCscYd6RNeXfGeiuCphsPtqyIfQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@cacheable/utils": "^2.5.0",
+ "@keyv/bigmap": "^1.3.1",
+ "hookified": "^1.15.1",
+ "keyv": "^5.6.0"
+ }
+ },
+ "node_modules/@cacheable/utils": {
+ "version": "2.5.0",
+ "resolved": "https://registry.npmjs.org/@cacheable/utils/-/utils-2.5.0.tgz",
+ "integrity": "sha512-buipgOVDkkPXNR5+xBpDw7Zk2n1EvU7qBJCNUcL7rhQ//kfpOXPAvQ511Os0vpLYJ1pZnvudNytkQt2hst3wqA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "hashery": "^1.5.1",
+ "keyv": "^5.6.0"
+ }
+ },
"node_modules/@esbuild/aix-ppc64": {
"version": "0.28.2",
"resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.28.2.tgz",
@@ -586,9 +610,9 @@
}
},
"node_modules/@eslint/plugin-kit": {
- "version": "0.7.2",
- "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.7.2.tgz",
- "integrity": "sha512-+CNAzxglkrpNf/kKywqQfk74QjtceuOE7Qm+AF8miRvPF/wmmK5+OJOgVh3AVTT3RP2mH3+FOaxlE5v72owk0A==",
+ "version": "0.7.3",
+ "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.7.3.tgz",
+ "integrity": "sha512-IkO+/KEUvwbVpiURZg+P7zF74z5Jxe0UgJxVni+RtoHQ6IZieXaO02kmadomap/q+l6bc/jdPGGqTjhuZnuz1Q==",
"dev": true,
"license": "Apache-2.0",
"dependencies": {
@@ -665,6 +689,30 @@
"url": "https://github.com/sponsors/nzakas"
}
},
+ "node_modules/@keyv/bigmap": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/@keyv/bigmap/-/bigmap-1.3.1.tgz",
+ "integrity": "sha512-WbzE9sdmQtKy8vrNPa9BRnwZh5UF4s1KTmSK0KUVLo3eff5BlQNNWDnFOouNpKfPKDnms9xynJjsMYjMaT/aFQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "hashery": "^1.4.0",
+ "hookified": "^1.15.0"
+ },
+ "engines": {
+ "node": ">= 18"
+ },
+ "peerDependencies": {
+ "keyv": "^5.6.0"
+ }
+ },
+ "node_modules/@keyv/serialize": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/@keyv/serialize/-/serialize-1.1.1.tgz",
+ "integrity": "sha512-dXn3FZhPv0US+7dtJsIi2R+c7qWYiReoEh5zUntWCf4oSpMNib8FDhSoed6m3QyZdx5hK7iLFkYk3rNxwt8vTA==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/@nodelib/fs.scandir": {
"version": "2.1.5",
"resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
@@ -725,27 +773,27 @@
"license": "MIT"
},
"node_modules/@types/node": {
- "version": "26.2.0",
- "resolved": "https://registry.npmjs.org/@types/node/-/node-26.2.0.tgz",
- "integrity": "sha512-5IviulTZeRNp2vAJ514cc/HUlY5nZ9fCbq9DMyC52BrhFZACo3nI0R7qBxhQmo/d27NFe96ur/b7Wwxklda+kg==",
+ "version": "26.6.4",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-26.6.4.tgz",
+ "integrity": "sha512-ldVPDCzj7fsaGZrLB0NuHuTvJcsNasysBAqMolr/cgxrLd1xbqxIr3XJiPnHHJUCxj5sNF1vnRj9aWnrVh5Jcg==",
"dev": true,
"license": "MIT",
"dependencies": {
- "undici-types": "~8.3.0"
+ "undici-types": "~8.9.0"
}
},
"node_modules/@typescript-eslint/eslint-plugin": {
- "version": "8.67.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.67.0.tgz",
- "integrity": "sha512-Un7Heoyj65NREbKAyIrFxeM143NZpExWmy1Nep4DLeQOeLlTeumPjoNKnBrU5D5moWXbPJgRa5Uwcdu0faVNGQ==",
+ "version": "8.71.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.71.1.tgz",
+ "integrity": "sha512-nNlBf6HuotqMgZvSkWD5hNdemiBIxQ2NmrlgfcUIeZRs+BbakjscCQRq/Hb74EFVnFiSWWdL12JruqwBy3ERDw==",
"dev": true,
"license": "MIT",
"dependencies": {
"@eslint-community/regexpp": "^4.12.2",
- "@typescript-eslint/scope-manager": "8.67.0",
- "@typescript-eslint/type-utils": "8.67.0",
- "@typescript-eslint/utils": "8.67.0",
- "@typescript-eslint/visitor-keys": "8.67.0",
+ "@typescript-eslint/scope-manager": "8.71.1",
+ "@typescript-eslint/type-utils": "8.71.1",
+ "@typescript-eslint/utils": "8.71.1",
+ "@typescript-eslint/visitor-keys": "8.71.1",
"ignore": "^7.0.5",
"natural-compare": "^1.4.0",
"ts-api-utils": "^2.5.0"
@@ -758,15 +806,15 @@
"url": "https://opencollective.com/typescript-eslint"
},
"peerDependencies": {
- "@typescript-eslint/parser": "^8.67.0",
+ "@typescript-eslint/parser": "^8.71.1",
"eslint": "^8.57.0 || ^9.0.0 || ^10.0.0",
"typescript": ">=4.8.4 <6.1.0"
}
},
"node_modules/@typescript-eslint/eslint-plugin/node_modules/ignore": {
- "version": "7.0.6",
- "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.6.tgz",
- "integrity": "sha512-BAg6QkE8W+TuQLrrw0Ugr7HegXduRuuj8/ti2kSOc+jz1dmx8/WNcjr6XGnq5YpDWxFwwaavqD0+jIUOKelTsw==",
+ "version": "7.0.12",
+ "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.12.tgz",
+ "integrity": "sha512-/8UvqAPU9DGTI9k4mxtf49U37Isfwr8Uts96+SBHIkFxPJnHS0Ew4f00sM4Scd8V8EjM0jUNtVDdv1kPdt35lg==",
"dev": true,
"license": "MIT",
"engines": {
@@ -774,17 +822,17 @@
}
},
"node_modules/@typescript-eslint/parser": {
- "version": "8.67.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.67.0.tgz",
- "integrity": "sha512-fUBfTuuEulWqX6V8+O3PtScV01tzYYRUDTAirHFKoRAt7nOzoGiPt0M/bB47wWNy0coOOcgEwAMUtBpykMxl6w==",
+ "version": "8.71.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.71.1.tgz",
+ "integrity": "sha512-oM/5sAqz/l1v/zYK1qTOPrn2+JIrBGC1V6uNYucRO5gh6eT9vWJ/RhPbGE59byvZEUQ4VP6XkLBaS5Jti5jpvw==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
- "@typescript-eslint/scope-manager": "8.67.0",
- "@typescript-eslint/types": "8.67.0",
- "@typescript-eslint/typescript-estree": "8.67.0",
- "@typescript-eslint/visitor-keys": "8.67.0",
+ "@typescript-eslint/scope-manager": "8.71.1",
+ "@typescript-eslint/types": "8.71.1",
+ "@typescript-eslint/typescript-estree": "8.71.1",
+ "@typescript-eslint/visitor-keys": "8.71.1",
"debug": "^4.4.3"
},
"engines": {
@@ -800,14 +848,14 @@
}
},
"node_modules/@typescript-eslint/project-service": {
- "version": "8.67.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.67.0.tgz",
- "integrity": "sha512-cvE8c7ulYeXN9fYuszhCeCsbzyVEXuhrRCybnBre7TUmqb5nRmBfQAwCj0O3WJFDeyAZt4VYv51vMCC9LHSdYw==",
+ "version": "8.71.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.71.1.tgz",
+ "integrity": "sha512-Oijc9RUsohHjncg6iGi7gCtjnEjYt9FWv9u6ygK8uKcHK5eLjLAkqERQ9BaytbpceOFdk6kifPCS/zAZE+A99g==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@typescript-eslint/tsconfig-utils": "^8.67.0",
- "@typescript-eslint/types": "^8.67.0",
+ "@typescript-eslint/tsconfig-utils": "^8.71.1",
+ "@typescript-eslint/types": "^8.71.1",
"debug": "^4.4.3"
},
"engines": {
@@ -822,14 +870,14 @@
}
},
"node_modules/@typescript-eslint/scope-manager": {
- "version": "8.67.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.67.0.tgz",
- "integrity": "sha512-EgvsleTwS4E+WzzSvem8fAUubLwatMNF1B5hHSLQxcvs7q2dtRhGyujHwLJSYlG41niJ7GP24Aha2+0mb1b2kg==",
+ "version": "8.71.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.71.1.tgz",
+ "integrity": "sha512-1YUDZXdTnXLlob03SFHBipdyMBsDVm7zoSz0ytTJ39dk5J1TgsTK03VlR/dLXG/RLLUrPcYbD4rp23BmHxHP0w==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@typescript-eslint/types": "8.67.0",
- "@typescript-eslint/visitor-keys": "8.67.0"
+ "@typescript-eslint/types": "8.71.1",
+ "@typescript-eslint/visitor-keys": "8.71.1"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -840,9 +888,9 @@
}
},
"node_modules/@typescript-eslint/tsconfig-utils": {
- "version": "8.67.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.67.0.tgz",
- "integrity": "sha512-vV+LUSv5njUWsknE71fqKTlXUva+R76SaeORd6Zojcunk/6DvKFXONU3BrAs2H49mbygUXt6gbYunzwqNwlhdg==",
+ "version": "8.71.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.71.1.tgz",
+ "integrity": "sha512-oTvkml5SxXhgg+WWKhod5qWQICDXtOB+/Hi9VdPKFAANJ2b7YOgMffgvzXuqog7R6A/JtrzRf128dsxummyWhg==",
"dev": true,
"license": "MIT",
"engines": {
@@ -857,15 +905,15 @@
}
},
"node_modules/@typescript-eslint/type-utils": {
- "version": "8.67.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.67.0.tgz",
- "integrity": "sha512-aVWDXbRmdXO9siTfX4ditQI1T9+zVcNazT48EJCD0v40/9RIFoUgZ05CmGEq9H2gixRpjUn/iplwvlcvutJW/Q==",
+ "version": "8.71.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.71.1.tgz",
+ "integrity": "sha512-kH3t3jZCYv2PZSBEWPKTariLrCaoF1CLoPitYFBJOhAGEwWnSRAtGEifrfrpBa4K9JlwWNZotgA5w3/wLSk/FQ==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@typescript-eslint/types": "8.67.0",
- "@typescript-eslint/typescript-estree": "8.67.0",
- "@typescript-eslint/utils": "8.67.0",
+ "@typescript-eslint/types": "8.71.1",
+ "@typescript-eslint/typescript-estree": "8.71.1",
+ "@typescript-eslint/utils": "8.71.1",
"debug": "^4.4.3",
"ts-api-utils": "^2.5.0"
},
@@ -882,9 +930,9 @@
}
},
"node_modules/@typescript-eslint/types": {
- "version": "8.67.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.67.0.tgz",
- "integrity": "sha512-sBtgslww8nsMYUjhdPBiSyUqSzT8uR6g93A2QXnQC8+cGdjz0CyaOdqHDRJb1AtORbZCNUJBBeFA/tNR2uQmww==",
+ "version": "8.71.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.71.1.tgz",
+ "integrity": "sha512-ybYnPTUwg3VQQOFEiBPLs8Jxl1ry2vXdn1kVKguomBbvxpetdu3MKTNDqFNUrlG8ylP9MpZosmXMFYlGQHk1oQ==",
"dev": true,
"license": "MIT",
"engines": {
@@ -896,16 +944,16 @@
}
},
"node_modules/@typescript-eslint/typescript-estree": {
- "version": "8.67.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.67.0.tgz",
- "integrity": "sha512-EKQBCE9yNlRJYm7jdTW5AhDacDUmSwQb0FAJAmK2EKYrNXIsa2vxcSZx6PvJ/dEdI6lS+Y9W+EXckLj0iPFGcw==",
+ "version": "8.71.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.71.1.tgz",
+ "integrity": "sha512-pSKSEK1JJpHs6KiKVtABCE4iJK5d7FLFzDXQNBQ2oRY7LEd3UwOt3TZemTgu9syTIf56dJWlTn/pdmrO9oKUXQ==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@typescript-eslint/project-service": "8.67.0",
- "@typescript-eslint/tsconfig-utils": "8.67.0",
- "@typescript-eslint/types": "8.67.0",
- "@typescript-eslint/visitor-keys": "8.67.0",
+ "@typescript-eslint/project-service": "8.71.1",
+ "@typescript-eslint/tsconfig-utils": "8.71.1",
+ "@typescript-eslint/types": "8.71.1",
+ "@typescript-eslint/visitor-keys": "8.71.1",
"debug": "^4.4.3",
"minimatch": "^10.2.2",
"semver": "^7.7.3",
@@ -924,16 +972,16 @@
}
},
"node_modules/@typescript-eslint/utils": {
- "version": "8.67.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.67.0.tgz",
- "integrity": "sha512-U9D1FdwEWBwok3hxxSdhclMb0twvt9QnjIQ0VfQ1AiX2epnpSgv2ubVDsayOFyY8K6FX+AQ7E0FKWVG3iKsj1A==",
+ "version": "8.71.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.71.1.tgz",
+ "integrity": "sha512-CBjT6gfAz3DW2j9Q4moFnqt208Aq+506sVGXfpRcyAeqn0EpayL0mjdWoCO2t3RC7GewNrFxdeehuEaPg6DMzQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"@eslint-community/eslint-utils": "^4.9.1",
- "@typescript-eslint/scope-manager": "8.67.0",
- "@typescript-eslint/types": "8.67.0",
- "@typescript-eslint/typescript-estree": "8.67.0"
+ "@typescript-eslint/scope-manager": "8.71.1",
+ "@typescript-eslint/types": "8.71.1",
+ "@typescript-eslint/typescript-estree": "8.71.1"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -948,13 +996,13 @@
}
},
"node_modules/@typescript-eslint/visitor-keys": {
- "version": "8.67.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.67.0.tgz",
- "integrity": "sha512-fkv8dHRDqfGtTHuJeebdrQ7cX6Ad4WAS00rgHh9UGvMycF1mjBfsxry1XsLIFhWZ6Judlh6UdzK+TYlbpCXgnA==",
+ "version": "8.71.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.71.1.tgz",
+ "integrity": "sha512-0GxiUGqMU0qXJt58cBsiG3DP8lUmBaFo2vChtUX+CT7PnR3v/VGLLrzVP4K9r1lNiZXjHYefMBbPunplr09v6w==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@typescript-eslint/types": "8.67.0",
+ "@typescript-eslint/types": "8.71.1",
"eslint-visitor-keys": "^5.0.0"
},
"engines": {
@@ -1054,9 +1102,9 @@
}
},
"node_modules/brace-expansion": {
- "version": "5.0.9",
- "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.9.tgz",
- "integrity": "sha512-ScQ4IuvIEF1TMlP7Zt+vjJ//9zlPb2SDcxWxM3bk8s6t6GGdJ7KO1dCcTidOPJKePW30LE/2cT7wCyPho9/Wxg==",
+ "version": "5.0.12",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.12.tgz",
+ "integrity": "sha512-YovQ3rzhaLMIrDjNDMkNS01tea93qhEhG5xy8f6+R0l+dw3Ki+5sCoIoI942iuLZTHWogWktgwVDhU09iNEimQ==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -1079,6 +1127,20 @@
"node": ">=8"
}
},
+ "node_modules/cacheable": {
+ "version": "2.5.0",
+ "resolved": "https://registry.npmjs.org/cacheable/-/cacheable-2.5.0.tgz",
+ "integrity": "sha512-60cyAOytib/OzBw1JNSoSV/boK1AtHryDIjvVBk7XbN4ugfkM3+Sry7fEjNgPMGgOjuaZPAp8ruZ0Cxafwyq9g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@cacheable/memory": "^2.2.0",
+ "@cacheable/utils": "^2.5.0",
+ "hookified": "^1.15.0",
+ "keyv": "^5.6.0",
+ "qified": "^0.10.1"
+ }
+ },
"node_modules/chokidar": {
"version": "3.6.0",
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz",
@@ -1105,9 +1167,9 @@
}
},
"node_modules/cloudinary": {
- "version": "2.10.0",
- "resolved": "https://registry.npmjs.org/cloudinary/-/cloudinary-2.10.0.tgz",
- "integrity": "sha512-sY09kYg7wprkndAOjZBAYqFZqwL+SxnEGcAvksOvFA+5upnFn949UjkEkHKNSwkBtW/xRDd0p6NgbSXZcxkI3w==",
+ "version": "2.11.0",
+ "resolved": "https://registry.npmjs.org/cloudinary/-/cloudinary-2.11.0.tgz",
+ "integrity": "sha512-o2pAkDDqrzPFE/mn9GCfFjBIGQmPs++Ts6rtkFl4vY528DNHiMovKWjH16HBjeGa9iwI7eAad24aWN2emT0aww==",
"license": "MIT",
"dependencies": {
"lodash": "^4.17.23"
@@ -1180,10 +1242,13 @@
}
},
"node_modules/dotenv": {
- "version": "17.4.2",
- "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-17.4.2.tgz",
- "integrity": "sha512-nI4U3TottKAcAD9LLud4Cb7b2QztQMUEfHbvhTH09bqXTxnSie8WnjPALV/WMCrJZ6UV/qHJ6L03OqO3LcdYZw==",
+ "version": "18.0.6",
+ "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-18.0.6.tgz",
+ "integrity": "sha512-ZMVmohV6CvAJtj++pZNyggluUt6hbRdQAxc2+Z635RL6/AG/ruXv5lHnybUFoxMPL/yrTL/tsF4paZu2l7RA6Q==",
"license": "BSD-2-Clause",
+ "bin": {
+ "dotenv": "dist/index.cjs"
+ },
"engines": {
"node": ">=12"
},
@@ -1247,9 +1312,9 @@
}
},
"node_modules/eslint": {
- "version": "10.8.1",
- "resolved": "https://registry.npmjs.org/eslint/-/eslint-10.8.1.tgz",
- "integrity": "sha512-wqA7W2jbsC/BnV9Iv1UZpKVFkO1AdNoSmYW8NWG4HNOBbkAMvIqDZ27pI2f07dqn583NcIC44ckjAcOXDL1QbQ==",
+ "version": "10.12.0",
+ "resolved": "https://registry.npmjs.org/eslint/-/eslint-10.12.0.tgz",
+ "integrity": "sha512-npHjrHb2o4ehH3mE+YuxABR+0gyb0aVWCIolgJDArwCiHEIsonBm3ZKjel5b0U5+a+MbEvIyRCGCzD3eKKK2NA==",
"dev": true,
"license": "MIT",
"peer": true,
@@ -1262,7 +1327,7 @@
"@eslint/config-array": "^0.23.5",
"@eslint/config-helpers": "^0.7.0",
"@eslint/core": "^1.2.1",
- "@eslint/plugin-kit": "^0.7.2",
+ "@eslint/plugin-kit": "^0.7.3",
"@humanfs/node": "^0.16.6",
"@humanwhocodes/module-importer": "^1.0.1",
"@humanwhocodes/retry": "^0.4.2",
@@ -1277,7 +1342,7 @@
"esquery": "^1.7.0",
"esutils": "^2.0.2",
"fast-deep-equal": "^3.1.3",
- "file-entry-cache": "^8.0.0",
+ "file-entry-cache": "11.1.5 || >11.1.6 <12",
"find-up": "^5.0.0",
"glob-parent": "^6.0.2",
"ignore": "^5.2.0",
@@ -1464,16 +1529,13 @@
}
},
"node_modules/file-entry-cache": {
- "version": "8.0.0",
- "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz",
- "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==",
+ "version": "11.1.5",
+ "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-11.1.5.tgz",
+ "integrity": "sha512-+PFTHITI08JIGhnNpGNI8T8inUpgZfk3GNEqfT9R2zZV2iFXg3CvqzSl/uEhs7TSGujYRELEANyDvS8Fj7+S7Q==",
"dev": true,
"license": "MIT",
"dependencies": {
- "flat-cache": "^4.0.0"
- },
- "engines": {
- "node": ">=16.0.0"
+ "flat-cache": "^6.1.23"
}
},
"node_modules/fill-range": {
@@ -1507,17 +1569,15 @@
}
},
"node_modules/flat-cache": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz",
- "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==",
+ "version": "6.1.23",
+ "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-6.1.23.tgz",
+ "integrity": "sha512-f++BY9pTk+983xK1FLzlLpmM0i0z+jHmx3QESGkURMXujQZz1k5wzwX6hjnQ8goaD0B+sYnDK1yZ6MTyZfUaqA==",
"dev": true,
"license": "MIT",
"dependencies": {
- "flatted": "^3.2.9",
- "keyv": "^4.5.4"
- },
- "engines": {
- "node": ">=16"
+ "cacheable": "^2.5.0",
+ "flatted": "^3.4.2",
+ "hookified": "^1.15.0"
}
},
"node_modules/flatted": {
@@ -1569,9 +1629,9 @@
}
},
"node_modules/globals": {
- "version": "17.11.0",
- "resolved": "https://registry.npmjs.org/globals/-/globals-17.11.0.tgz",
- "integrity": "sha512-Z2I8hM+PbJDXQDq3Icgpzv+mPdwr68iZUU9d5WW4FuXfDUQfkZaZuvjMv42/5crNyw154+9+VWXbYrUgDXbxNw==",
+ "version": "17.13.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-17.13.0.tgz",
+ "integrity": "sha512-RwMTC61u7hrG3ZJMkZQOK4JLJrKS8QtoTii63EmWvFXHqycY9FObBJQCbsLxSO8kjKhWE5kV1GC+Vb1g3RI0Zg==",
"dev": true,
"license": "MIT",
"engines": {
@@ -1602,6 +1662,26 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
+ "node_modules/hashery": {
+ "version": "1.5.1",
+ "resolved": "https://registry.npmjs.org/hashery/-/hashery-1.5.1.tgz",
+ "integrity": "sha512-iZyKG96/JwPz1N55vj2Ie2vXbhu440zfUfJvSwEqEbeLluk7NnapfGqa7LH0mOsnDxTF85Mx8/dyR6HfqcbmbQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "hookified": "^1.15.0"
+ },
+ "engines": {
+ "node": ">=20"
+ }
+ },
+ "node_modules/hookified": {
+ "version": "1.15.1",
+ "resolved": "https://registry.npmjs.org/hookified/-/hookified-1.15.1.tgz",
+ "integrity": "sha512-MvG/clsADq1GPM2KGo2nyfaWVyn9naPiXrqIe4jYjXNZQt238kWyOGrsyc/DmRAQ+Re6yeo6yX/yoNCG5KAEVg==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/ignore": {
"version": "5.3.2",
"resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz",
@@ -1675,13 +1755,6 @@
"dev": true,
"license": "ISC"
},
- "node_modules/json-buffer": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz",
- "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==",
- "dev": true,
- "license": "MIT"
- },
"node_modules/json-schema-traverse": {
"version": "0.4.1",
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
@@ -1697,13 +1770,14 @@
"license": "MIT"
},
"node_modules/keyv": {
- "version": "4.5.4",
- "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz",
- "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==",
+ "version": "5.6.0",
+ "resolved": "https://registry.npmjs.org/keyv/-/keyv-5.6.0.tgz",
+ "integrity": "sha512-CYDD3SOtsHtyXeEORYRx2qBtpDJFjRTGXUtmNEMGyzYOKj1TE3tycdlho7kA1Ufx9OYWZzg52QFBGALTirzDSw==",
"dev": true,
"license": "MIT",
+ "peer": true,
"dependencies": {
- "json-buffer": "3.0.1"
+ "@keyv/serialize": "^1.1.1"
}
},
"node_modules/levn": {
@@ -1946,6 +2020,26 @@
"node": ">=6"
}
},
+ "node_modules/qified": {
+ "version": "0.10.1",
+ "resolved": "https://registry.npmjs.org/qified/-/qified-0.10.1.tgz",
+ "integrity": "sha512-+Owyggi9IxT1ePKGafcI87ubSmxol6smwJ+RAHDQlx9+9cPwFWDiKFFCPuWhr9ignlGpZ9vDQLw67N4dcTVFEA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "hookified": "^2.1.1"
+ },
+ "engines": {
+ "node": ">=20"
+ }
+ },
+ "node_modules/qified/node_modules/hookified": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/hookified/-/hookified-2.2.0.tgz",
+ "integrity": "sha512-p/LgFzRN5FeoD3DLS6bkUapeye6E4SI6yJs6KetENd18S+FBthqYq2amJUWpt5z0EQwwHemidjY5OqJGEKm5uA==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/queue-lit": {
"version": "1.5.2",
"resolved": "https://registry.npmjs.org/queue-lit/-/queue-lit-1.5.2.tgz",
@@ -2117,9 +2211,9 @@
}
},
"node_modules/tinyglobby/node_modules/picomatch": {
- "version": "4.0.5",
- "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.5.tgz",
- "integrity": "sha512-RvwwcruNjI1ncT5xRakeyS9Lf8lcItv34KD+aif+VH9kduAyfYBipGh12274xtenIPZ119/R9BdTBa8gAwSh0A==",
+ "version": "4.0.7",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.7.tgz",
+ "integrity": "sha512-qcJu88Q2IWqJsDD529JKMdwGm/dvInW4HvQnRwiH9JtihJvzGOscDtHE3x1pBKeUOTysQ8kVmLnJ2kJu7yhcGA==",
"dev": true,
"license": "MIT",
"peer": true,
@@ -2157,9 +2251,9 @@
}
},
"node_modules/tsc-alias": {
- "version": "1.9.1",
- "resolved": "https://registry.npmjs.org/tsc-alias/-/tsc-alias-1.9.1.tgz",
- "integrity": "sha512-sFZdVFthH8uvdplPJrOYGOHcxu6UPtcAcY678JPwEQiMzgLZYFO7Qc/rzELp7ingTc+OxtzH6n+8Pn2eVQep6w==",
+ "version": "1.9.7",
+ "resolved": "https://registry.npmjs.org/tsc-alias/-/tsc-alias-1.9.7.tgz",
+ "integrity": "sha512-nGOOLMkaociegx2Y9J1lnbqrledf1EfSq3Ds4H4CLySG5RyD58KrR4ahFIAgpeMVJz4BIhJND3ETt02o9zKQAw==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -2176,12 +2270,16 @@
},
"engines": {
"node": ">=16.20.2"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/justkey007"
}
},
"node_modules/tsx": {
- "version": "4.23.12",
- "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.23.12.tgz",
- "integrity": "sha512-FDf4L4sYzKtzWYhU/Xm0AQFdTjdIxNo9ElTf2mxXM6k8YMHXzYUe4yODVaXP4V9uMFbVg8c0qyBccK2OOxb45Q==",
+ "version": "4.23.15",
+ "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.23.15.tgz",
+ "integrity": "sha512-Yiex1Ovn8z2xPpOWckIiysV1SSyRMY9BkLF++q0yKiDxCqRhosKfMg3janKkiLBwZ5c/YryloKwGZcrEmtwxKw==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -2226,16 +2324,16 @@
}
},
"node_modules/typescript-eslint": {
- "version": "8.67.0",
- "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.67.0.tgz",
- "integrity": "sha512-S2udFs8tCKEKffuJ4TB1idGUZiXdCPGi3IPBGWXarbLQ5UPXORV8QEVzJ4gCRduURMb5EkpNCdjbk0eDIuI8Yg==",
+ "version": "8.71.1",
+ "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.71.1.tgz",
+ "integrity": "sha512-oiNVPC3/NbV1FpaHU07l8O6ynqG9v4PAiW2WvTrAmZdR0f2HI/gE668ElMLCK7Xbsu5k2fK5C4fXNiq05j7/nQ==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@typescript-eslint/eslint-plugin": "8.67.0",
- "@typescript-eslint/parser": "8.67.0",
- "@typescript-eslint/typescript-estree": "8.67.0",
- "@typescript-eslint/utils": "8.67.0"
+ "@typescript-eslint/eslint-plugin": "8.71.1",
+ "@typescript-eslint/parser": "8.71.1",
+ "@typescript-eslint/typescript-estree": "8.71.1",
+ "@typescript-eslint/utils": "8.71.1"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -2250,9 +2348,9 @@
}
},
"node_modules/undici-types": {
- "version": "8.3.0",
- "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-8.3.0.tgz",
- "integrity": "sha512-j375ScV60dom+YkPFIfTLcOiPxkN/buHz5GobjLhixFuANaNs3C9l4GmrWqejgXWJ7BbJcFYpTEUkS1Ge8bpZQ==",
+ "version": "8.9.0",
+ "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-8.9.0.tgz",
+ "integrity": "sha512-KTDyRTYX8sWmKXAikPHHSyc63CRPETMctyjKFupcC6OBLXT3xsN0e9aF7m+mIXutFWpUXuedtowG7iLOzp0kQg==",
"dev": true,
"license": "MIT"
},
diff --git a/app/package.json b/app/package.json
index fec9372..1c1d241 100644
--- a/app/package.json
+++ b/app/package.json
@@ -1,6 +1,6 @@
{
"name": "cloudinary-image",
- "version": "1.0.0",
+ "version": "1.0.1",
"description": "Cloudinary image library wrapper and CLI for optimization and transformations",
"type": "module",
"main": "dist/index.js",
@@ -24,12 +24,13 @@
],
"scripts": {
"start": "node ./dist/scripts/optimize/index.js",
- "dev": "tsx ./src/scripts/optimize",
+ "dev": "tsx watch ./src/scripts/optimize",
"build": "tsc -p tsconfig.json && tsc-alias",
"types:check": "tsc -p tsconfig.json --noEmit",
"watch": "tsc -p tsconfig.json --watch",
"lint": "eslint \"src/**/*.ts\" *.mjs",
"lint:fix": "eslint \"src/**/*.ts\" *.mjs --fix",
+ "docker:dev": "export IS_DOCKER=true && tsx watch ./src/scripts/optimize",
"docker:debug": "export IS_DOCKER=true && node --inspect=0.0.0.0:9229 --import tsx src/scripts/optimize/index.ts",
"docker:watch:win": "tsc -p tsconfig.json --watch --watchFile dynamicPriorityPolling --watchDirectory dynamicPriorityPolling",
"info": "tsx ./src/scripts/envinfo"
@@ -52,16 +53,16 @@
"homepage": "https://github.com/weaponsforge/cloudinary-image#readme",
"devDependencies": {
"@eslint/js": "^10.0.1",
- "@types/node": "^26.2.0",
- "eslint": "^10.8.1",
- "globals": "^17.11.0",
- "tsc-alias": "^1.9.1",
- "tsx": "^4.23.12",
+ "@types/node": "^26.6.4",
+ "eslint": "^10.12.0",
+ "globals": "^17.13.0",
+ "tsc-alias": "^1.9.7",
+ "tsx": "^4.23.15",
"typescript": "^6.0.3",
- "typescript-eslint": "^8.67.0"
+ "typescript-eslint": "^8.71.1"
},
"dependencies": {
- "cloudinary": "^2.10.0",
- "dotenv": "^17.4.2"
+ "cloudinary": "^2.11.0",
+ "dotenv": "^18.0.6"
}
}
diff --git a/app/src/scripts/optimize/index.ts b/app/src/scripts/optimize/index.ts
index 9bb4e7a..1d3d512 100644
--- a/app/src/scripts/optimize/index.ts
+++ b/app/src/scripts/optimize/index.ts
@@ -38,6 +38,18 @@ const { values } = parseArgs({
},
})
+// Uncomment and use _values in optimize(_values) when
+// 1. running `npm run dev` in Docker and
+// 2. when not capturing CLI input parameters (eg., -f 'assets/bridge.jpg' -w 400 -u, etc)
+/*
+const _values: Record = {
+ file: 'assets/bridge.jpg',
+ width: 400,
+ upload: true,
+ deleteAfter: true
+}
+*/
+
if (process.env.IS_DOCKER) {
setTimeout(() => {
optimize(values)
diff --git a/docker-compose.yml b/docker-compose.yml
index 63ae2e8..bc928cb 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -18,4 +18,3 @@ services:
- NODE_ENV=development
stdin_open: true
tty: true
- restart: unless-stopped
diff --git a/docs/README_NPM.md b/docs/README_NPM.md
index 6c31bb4..bea8d6f 100644
--- a/docs/README_NPM.md
+++ b/docs/README_NPM.md
@@ -16,7 +16,7 @@ covering image transformation, optimization, and asset management.
npm i cloudinary-image
```
-2. Create a `.env` file in the `/app` directory, replacing the contents of the `.env.example` file with actual values.
+2. Create a `.env` file in your project directory, replacing the contents of the `.env.example` file with actual values.
| Variable Name | Description |
| --- | --- |