JSWatch is a lightweight and efficient JavaScript file monitoring tool that tracks changes in remote JavaScript files. It provides automatic diff generation in markdown format written to stdout.
Supports :
- Static file path
- Dynamic file path
- Multiple Step dynamic file path
But in practice , i personally used this tool not just for javascript file , but also for other remote static file.
- Clone the repository:
git clone https://github.com/0xdead4f/jswatch.git
cd jswatch
- Install required dependencies:
pip install -r requirements.txt
- Create
monitor.json
configuration file.
There is two type of javascript that can be monitored, static and dynamic. The is_static
attribute that indicate how the scanning approach. if Set to True
it will need addition attribute value to proceed.
[
{
// Identifier for the file, will be used as filename
title: "Main Application JS",
// True for direct URL to JS file or False for scan an webpage for dynamic js
is_static: true,
// Static file have 2 option , Multiple Step or not
// Multiple step means, the value of the js file is inside another js file
// so program need to scan 2 times
// [DEV] the current version only support 2 step
is_multiple_step: true,
// URL of the webpage containing the script
url: "https://example.com/static/app.js",
// Pattern to find script tags
regex_js: '<script.*?src="(/static/.*?\\.js)".*?>',
// Base URL for completing relative paths
url_to_append: "https://example.com",
// Pattern to identify correct script content
// this regex is used as getting value from javascript if
// "is_multiple_step" set to True
regex_attribute: "specific_function_name or Variable",
// Custom header for the every request
custom_header: {},
// the Next_step is used when "is_multiple_step" is set to True
next_step: {
// this attribute is used to craft url from given regex value
// user `{regex_attribute}` to format the result of the regex
url_to_append: "https://example.com/_nuxt/{regex_attribute}.js",
// Next regex to determine the current javascript is the right one
regex_attribute: "SPECIFIC_FUNCTION_OR_STRING",
},
// Stats to be collected, the result will be appended in report
// the current stat will be on ./js/{title}.stats.json
stats: [
{
name: "Urls",
regex: "/api/v1/urls/.*",
}
]
},
]
- Run the app
python jswatch.py
Use this when you have a direct URL to the JavaScript file.
[
{
"title": "Main Script",
"is_static": true,
"url": "https://example.com/main.js",
"custom_header": {
"Cookie": "session=admin"
}
}
]
Use this when the JavaScript file needs to be found within a webpage.
[
{
"title": "Dynamic Script",
"is_static": false,
"url": "https://example.com/page.html",
"regex_js": "<script.*?src=\"(/static/.*?\\.js)\".*?>",
"url_to_append": "https://example.com",
"regex_attribute": "specific_content",
"custom_header": {
"Cookie": "session=admin"
}
}
]
Use this when you need to scan multiple pages or javascript file
[
{
"title": "Dynamic Script",
"is_static": false,
"url": "https://example.com/page.html",
"regex_js": "<script.*?src=\"(/static/.*?\\.js)\".*?>",
"url_to_append": "https://example.com",
"regex_attribute": "specific_content",
"custom_header": {
"Cookie": "session=admin"
}
},
{
"title": "Main Script",
"is_static": true,
"url": "https://example.com/main.js",
"custom_header": {
"Cookie": "session=admin"
}
}
]
This configuration is used if target javascript name or url need multiple step to obtain.
[
{
"title": "Test multiple step",
"is_static": false,
"is_multiple_step": true,
"url": "https://example.com/home/",
"regex_js": "<script.*?src=\"(.*?\\.js)\".*?>",
"url_to_append": "https://example.com",
"regex_attribute": "REGEX_TO_OBTAIN_SOME_VALUE",
"next_step": {
"url_to_append": "https://example.com/_nuxt/{regex_attribute}.js",
"regex_attribute": "SPECIFIC_CONTENT_OR_STRING"
}
}
]
-
First Run:
- Creates ./js directory
- Downloads initial versions of files
- Saves them as baselines named base on
title
on the configuration on./js
directory
-
Monitoring:
- Checks files every time you run the program
- Downloads current versions
- Compares with baselines
- Generates dif report for changes
-
Change Detection:
- Formats report in Markdown
- writen into stdout using
print()
- Check a stats based on regex
- Saves report history on
./js/{title}.md
When changes are detected, you'll see reports like this:
## JSwatch : new change for `script.js`
url : https://example.com/script.js
time : 2025-01-05 12:34:56
```diff
- old code
+ new code
```
-
Testing Your Regex:
- Use Python's regex tester to verify patterns
- Test URL construction with url_to_append
-
Common Issues:
- Verify URL accessibility
- Confirm regex patterns match target scripts
- If you are monitoring packed javascript , make sure the indentifier regex is a static String (becuase the function name probably will change)
-
Use
DEBUG
mode- set
DEBUG = True
onjswatch.py
to make more verbose output like regex match
- set
- Add handler if the file already not accesible
- Auto Scrap
- Fork the repository
- Create your feature branch
- Commit your changes
- Push to the branch
- Create a Pull Request
This project is licensed under the MIT License - see the LICENSE file for details.