syncforge 1.0.2__tar.gz → 1.0.4__tar.gz
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.
- syncforge-1.0.4/PKG-INFO +181 -0
- syncforge-1.0.4/README.md +155 -0
- {syncforge-1.0.2 → syncforge-1.0.4}/pyproject.toml +2 -2
- syncforge-1.0.4/syncforge/middleware.py +86 -0
- syncforge-1.0.4/syncforge.egg-info/PKG-INFO +181 -0
- {syncforge-1.0.2 → syncforge-1.0.4}/syncforge.egg-info/SOURCES.txt +1 -0
- syncforge-1.0.2/PKG-INFO +0 -195
- syncforge-1.0.2/README.md +0 -169
- syncforge-1.0.2/syncforge.egg-info/PKG-INFO +0 -195
- {syncforge-1.0.2 → syncforge-1.0.4}/LICENSE +0 -0
- {syncforge-1.0.2 → syncforge-1.0.4}/setup.cfg +0 -0
- {syncforge-1.0.2 → syncforge-1.0.4}/syncforge/__init__.py +0 -0
- {syncforge-1.0.2 → syncforge-1.0.4}/syncforge/client.py +0 -0
- {syncforge-1.0.2 → syncforge-1.0.4}/syncforge/django.py +0 -0
- {syncforge-1.0.2 → syncforge-1.0.4}/syncforge/exceptions.py +0 -0
- {syncforge-1.0.2 → syncforge-1.0.4}/syncforge/result.py +0 -0
- {syncforge-1.0.2 → syncforge-1.0.4}/syncforge.egg-info/dependency_links.txt +0 -0
- {syncforge-1.0.2 → syncforge-1.0.4}/syncforge.egg-info/top_level.txt +0 -0
syncforge-1.0.4/PKG-INFO
ADDED
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: syncforge
|
|
3
|
+
Version: 1.0.4
|
|
4
|
+
Summary: Official Python SDK for SyncForge — control exactly when data syncs between your database and clients.
|
|
5
|
+
Author-email: suresh dullu polai <sureshpolai63@gmail.com>
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/sureshdulupolai/syncforge
|
|
8
|
+
Project-URL: Documentation, https://syncforge.dev/docs/
|
|
9
|
+
Project-URL: Repository, https://github.com/sureshdulupolai/syncforge
|
|
10
|
+
Project-URL: Bug Tracker, https://github.com/sureshdulupolai/syncforge/issues
|
|
11
|
+
Keywords: syncforge,sync,database,cache,invalidation,django,fastapi
|
|
12
|
+
Classifier: Development Status :: 5 - Production/Stable
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
20
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
21
|
+
Classifier: Topic :: Database
|
|
22
|
+
Requires-Python: >=3.8
|
|
23
|
+
Description-Content-Type: text/markdown
|
|
24
|
+
License-File: LICENSE
|
|
25
|
+
Dynamic: license-file
|
|
26
|
+
|
|
27
|
+
# SyncForge Python SDK
|
|
28
|
+
|
|
29
|
+
[](https://pypi.org/project/syncforge/)
|
|
30
|
+
[](https://pypi.org/project/syncforge/)
|
|
31
|
+
[](LICENSE)
|
|
32
|
+
|
|
33
|
+
**Created by Suresh Dullu Polai**
|
|
34
|
+
|
|
35
|
+
SyncForge is the **FastAPI of data synchronization**. It is a premium, developer-controlled smart data synchronization platform and Web Application Firewall (WAF).
|
|
36
|
+
|
|
37
|
+
Stop relying on dumb polling or expensive real-time sockets for static data. With SyncForge, you take full control over exactly when and how your applications sync data, saving millions of unnecessary database calls and drastically reducing server costs.
|
|
38
|
+
|
|
39
|
+
---
|
|
40
|
+
|
|
41
|
+
## 🌟 Best Features (A to Z)
|
|
42
|
+
|
|
43
|
+
- **Zero-Polling Architecture**: Clients never hit your database to check for updates. They only get notified when *you* tell SyncForge that data has changed.
|
|
44
|
+
- **Built-in Web Application Firewall (WAF)**: Instantly protect your application from SQL Injection, Cross-Site Scripting (XSS), and Path Traversal attacks with a single line of code.
|
|
45
|
+
- **Zero-Code Django Auto-Sync**: Use our `@sync_model` decorator to automatically sync data across all your client devices whenever a Django model is created, updated, or deleted.
|
|
46
|
+
- **Precision Logging**: The middleware tracks request methods, paths, response statuses, and execution times in milliseconds.
|
|
47
|
+
- **Framework Agnostic**: First-class support for Django, FastAPI, Flask, or pure Python scripts.
|
|
48
|
+
- **Zero External Dependencies**: Built entirely on the Python Standard Library (`urllib`, `json`, `threading`).
|
|
49
|
+
|
|
50
|
+
---
|
|
51
|
+
|
|
52
|
+
## 🚀 Installation
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
pip install syncforge
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
---
|
|
59
|
+
|
|
60
|
+
## 🛡️ Built-in WAF Security Middleware (Django)
|
|
61
|
+
|
|
62
|
+
SyncForge SDK includes a professional-grade Web Application Firewall (WAF) and request logger. By adding just one line to your `settings.py`, your entire application is instantly protected from hackers.
|
|
63
|
+
|
|
64
|
+
### Features of the WAF:
|
|
65
|
+
1. **SQL Injection Protection**: Blocks `UNION SELECT`, `OR 1=1`, and other common SQLi payloads.
|
|
66
|
+
2. **XSS Protection**: Blocks `<script>` tags and malicious javascript injections.
|
|
67
|
+
3. **Path Traversal Protection**: Blocks `../` directory traversal attempts.
|
|
68
|
+
4. **Security Headers**: Automatically injects strict `X-Content-Type-Options: nosniff`.
|
|
69
|
+
5. **Performance Logging**: Logs response times beautifully (e.g., `[GET] /api/ - 200 (12.4ms)`).
|
|
70
|
+
|
|
71
|
+
### How to Install:
|
|
72
|
+
Add it to your Django `MIDDLEWARE` list in `settings.py`:
|
|
73
|
+
|
|
74
|
+
```python
|
|
75
|
+
MIDDLEWARE = [
|
|
76
|
+
'django.middleware.security.SecurityMiddleware',
|
|
77
|
+
|
|
78
|
+
# Add SyncForge Security Firewall right after Django's built-in security
|
|
79
|
+
'syncforge.middleware.SyncForgeSecurityMiddleware',
|
|
80
|
+
|
|
81
|
+
'django.contrib.sessions.middleware.SessionMiddleware',
|
|
82
|
+
# ...
|
|
83
|
+
]
|
|
84
|
+
```
|
|
85
|
+
*No further configuration needed! Your app is now secure.*
|
|
86
|
+
|
|
87
|
+
---
|
|
88
|
+
|
|
89
|
+
## 🔄 The `@sync_model` Decorator (Django Auto-Sync)
|
|
90
|
+
|
|
91
|
+
If you use Django, you never have to manually trigger a sync again. Use the `@sync_model` decorator. It hooks into Django's `post_save` and `post_delete` signals to automatically broadcast changes to all connected clients.
|
|
92
|
+
|
|
93
|
+
```python
|
|
94
|
+
# models.py
|
|
95
|
+
from django.db import models
|
|
96
|
+
from syncforge import sf
|
|
97
|
+
from syncforge.django import sync_model
|
|
98
|
+
|
|
99
|
+
# 1. Zero-code Django auto-sync
|
|
100
|
+
@sync_model(sf, sync_mode='event')
|
|
101
|
+
class Product(models.Model):
|
|
102
|
+
name = models.CharField(max_length=100)
|
|
103
|
+
price = models.DecimalField(max_digits=10, decimal_places=2)
|
|
104
|
+
```
|
|
105
|
+
Whenever you call `Product.objects.create(...)` or `product.delete()`, SyncForge automatically invalidates the cache and pushes the new delta to every single user's device.
|
|
106
|
+
|
|
107
|
+
---
|
|
108
|
+
|
|
109
|
+
## ⚡ FastAPI & Flask Integration
|
|
110
|
+
|
|
111
|
+
SyncForge isn't just for Django. You can trigger manual updates from any Python backend.
|
|
112
|
+
|
|
113
|
+
### FastAPI Example:
|
|
114
|
+
```python
|
|
115
|
+
import os
|
|
116
|
+
from fastapi import FastAPI
|
|
117
|
+
from syncforge import SyncForge
|
|
118
|
+
|
|
119
|
+
# Initialize once
|
|
120
|
+
sf = SyncForge(api_key=os.environ.get('SYNCFORGE_API_KEY'))
|
|
121
|
+
app = FastAPI()
|
|
122
|
+
|
|
123
|
+
@app.post("/api/products/")
|
|
124
|
+
async def create_product(name: str):
|
|
125
|
+
# 1. Database operation
|
|
126
|
+
db.execute("INSERT INTO products (name) VALUES (?)", (name,))
|
|
127
|
+
|
|
128
|
+
# 2. Trigger sync — Non-blocking, instant broadcast
|
|
129
|
+
sf.refresh('products')
|
|
130
|
+
|
|
131
|
+
return {"status": "success"}
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
---
|
|
135
|
+
|
|
136
|
+
## 📚 Core API Reference
|
|
137
|
+
|
|
138
|
+
### `SyncForge(api_key, base_url, timeout, silent, async_mode)`
|
|
139
|
+
|
|
140
|
+
| Parameter | Default | Description |
|
|
141
|
+
|--------------|-------------------------------|------------------------------------------------------|
|
|
142
|
+
| `api_key` | required | Your API key from the developer dashboard |
|
|
143
|
+
| `base_url` | `https://syncforge.dev/api` | Override for local dev / self-hosted |
|
|
144
|
+
| `timeout` | `10` | HTTP timeout in seconds |
|
|
145
|
+
| `silent` | `False` | Suppress errors — logs warnings instead of crashing |
|
|
146
|
+
| `async_mode` | `False` | Fire-and-forget — refresh runs in a background thread|
|
|
147
|
+
|
|
148
|
+
### `sf.refresh(*tables)` → `SyncResult | list[SyncResult]`
|
|
149
|
+
|
|
150
|
+
Broadcasts a refresh signal for the specified tables.
|
|
151
|
+
|
|
152
|
+
```python
|
|
153
|
+
sf.refresh('products') # single table
|
|
154
|
+
sf.refresh('products', 'categories', 'orders') # multiple at once
|
|
155
|
+
|
|
156
|
+
result = sf.refresh('products')
|
|
157
|
+
print(result.ok) # True
|
|
158
|
+
print(result.calls_saved) # 1854211 (Analytics data from SyncForge servers)
|
|
159
|
+
print(result.sync_mode) # 'Event — On INSERT / UPDATE / DELETE'
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
### Advanced Usage
|
|
163
|
+
|
|
164
|
+
```python
|
|
165
|
+
# Silent mode — SyncForge errors never crash your app
|
|
166
|
+
sf = SyncForge(api_key='sf_live_...', silent=True)
|
|
167
|
+
|
|
168
|
+
# Async mode — fire-and-forget, returns immediately
|
|
169
|
+
sf = SyncForge(api_key='sf_live_...', async_mode=True)
|
|
170
|
+
sf.refresh('products') # returns None, syncs in background
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
---
|
|
174
|
+
|
|
175
|
+
## 👨💻 About the Author
|
|
176
|
+
|
|
177
|
+
**SyncForge** is passionately built and maintained by **Suresh Dullu Polai**.
|
|
178
|
+
Designed to bring Enterprise-Grade data synchronization and security to developers worldwide, entirely out of the box.
|
|
179
|
+
|
|
180
|
+
## 📄 License
|
|
181
|
+
MIT — see [LICENSE](LICENSE)
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
# SyncForge Python SDK
|
|
2
|
+
|
|
3
|
+
[](https://pypi.org/project/syncforge/)
|
|
4
|
+
[](https://pypi.org/project/syncforge/)
|
|
5
|
+
[](LICENSE)
|
|
6
|
+
|
|
7
|
+
**Created by Suresh Dullu Polai**
|
|
8
|
+
|
|
9
|
+
SyncForge is the **FastAPI of data synchronization**. It is a premium, developer-controlled smart data synchronization platform and Web Application Firewall (WAF).
|
|
10
|
+
|
|
11
|
+
Stop relying on dumb polling or expensive real-time sockets for static data. With SyncForge, you take full control over exactly when and how your applications sync data, saving millions of unnecessary database calls and drastically reducing server costs.
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## 🌟 Best Features (A to Z)
|
|
16
|
+
|
|
17
|
+
- **Zero-Polling Architecture**: Clients never hit your database to check for updates. They only get notified when *you* tell SyncForge that data has changed.
|
|
18
|
+
- **Built-in Web Application Firewall (WAF)**: Instantly protect your application from SQL Injection, Cross-Site Scripting (XSS), and Path Traversal attacks with a single line of code.
|
|
19
|
+
- **Zero-Code Django Auto-Sync**: Use our `@sync_model` decorator to automatically sync data across all your client devices whenever a Django model is created, updated, or deleted.
|
|
20
|
+
- **Precision Logging**: The middleware tracks request methods, paths, response statuses, and execution times in milliseconds.
|
|
21
|
+
- **Framework Agnostic**: First-class support for Django, FastAPI, Flask, or pure Python scripts.
|
|
22
|
+
- **Zero External Dependencies**: Built entirely on the Python Standard Library (`urllib`, `json`, `threading`).
|
|
23
|
+
|
|
24
|
+
---
|
|
25
|
+
|
|
26
|
+
## 🚀 Installation
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
pip install syncforge
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
---
|
|
33
|
+
|
|
34
|
+
## 🛡️ Built-in WAF Security Middleware (Django)
|
|
35
|
+
|
|
36
|
+
SyncForge SDK includes a professional-grade Web Application Firewall (WAF) and request logger. By adding just one line to your `settings.py`, your entire application is instantly protected from hackers.
|
|
37
|
+
|
|
38
|
+
### Features of the WAF:
|
|
39
|
+
1. **SQL Injection Protection**: Blocks `UNION SELECT`, `OR 1=1`, and other common SQLi payloads.
|
|
40
|
+
2. **XSS Protection**: Blocks `<script>` tags and malicious javascript injections.
|
|
41
|
+
3. **Path Traversal Protection**: Blocks `../` directory traversal attempts.
|
|
42
|
+
4. **Security Headers**: Automatically injects strict `X-Content-Type-Options: nosniff`.
|
|
43
|
+
5. **Performance Logging**: Logs response times beautifully (e.g., `[GET] /api/ - 200 (12.4ms)`).
|
|
44
|
+
|
|
45
|
+
### How to Install:
|
|
46
|
+
Add it to your Django `MIDDLEWARE` list in `settings.py`:
|
|
47
|
+
|
|
48
|
+
```python
|
|
49
|
+
MIDDLEWARE = [
|
|
50
|
+
'django.middleware.security.SecurityMiddleware',
|
|
51
|
+
|
|
52
|
+
# Add SyncForge Security Firewall right after Django's built-in security
|
|
53
|
+
'syncforge.middleware.SyncForgeSecurityMiddleware',
|
|
54
|
+
|
|
55
|
+
'django.contrib.sessions.middleware.SessionMiddleware',
|
|
56
|
+
# ...
|
|
57
|
+
]
|
|
58
|
+
```
|
|
59
|
+
*No further configuration needed! Your app is now secure.*
|
|
60
|
+
|
|
61
|
+
---
|
|
62
|
+
|
|
63
|
+
## 🔄 The `@sync_model` Decorator (Django Auto-Sync)
|
|
64
|
+
|
|
65
|
+
If you use Django, you never have to manually trigger a sync again. Use the `@sync_model` decorator. It hooks into Django's `post_save` and `post_delete` signals to automatically broadcast changes to all connected clients.
|
|
66
|
+
|
|
67
|
+
```python
|
|
68
|
+
# models.py
|
|
69
|
+
from django.db import models
|
|
70
|
+
from syncforge import sf
|
|
71
|
+
from syncforge.django import sync_model
|
|
72
|
+
|
|
73
|
+
# 1. Zero-code Django auto-sync
|
|
74
|
+
@sync_model(sf, sync_mode='event')
|
|
75
|
+
class Product(models.Model):
|
|
76
|
+
name = models.CharField(max_length=100)
|
|
77
|
+
price = models.DecimalField(max_digits=10, decimal_places=2)
|
|
78
|
+
```
|
|
79
|
+
Whenever you call `Product.objects.create(...)` or `product.delete()`, SyncForge automatically invalidates the cache and pushes the new delta to every single user's device.
|
|
80
|
+
|
|
81
|
+
---
|
|
82
|
+
|
|
83
|
+
## ⚡ FastAPI & Flask Integration
|
|
84
|
+
|
|
85
|
+
SyncForge isn't just for Django. You can trigger manual updates from any Python backend.
|
|
86
|
+
|
|
87
|
+
### FastAPI Example:
|
|
88
|
+
```python
|
|
89
|
+
import os
|
|
90
|
+
from fastapi import FastAPI
|
|
91
|
+
from syncforge import SyncForge
|
|
92
|
+
|
|
93
|
+
# Initialize once
|
|
94
|
+
sf = SyncForge(api_key=os.environ.get('SYNCFORGE_API_KEY'))
|
|
95
|
+
app = FastAPI()
|
|
96
|
+
|
|
97
|
+
@app.post("/api/products/")
|
|
98
|
+
async def create_product(name: str):
|
|
99
|
+
# 1. Database operation
|
|
100
|
+
db.execute("INSERT INTO products (name) VALUES (?)", (name,))
|
|
101
|
+
|
|
102
|
+
# 2. Trigger sync — Non-blocking, instant broadcast
|
|
103
|
+
sf.refresh('products')
|
|
104
|
+
|
|
105
|
+
return {"status": "success"}
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
---
|
|
109
|
+
|
|
110
|
+
## 📚 Core API Reference
|
|
111
|
+
|
|
112
|
+
### `SyncForge(api_key, base_url, timeout, silent, async_mode)`
|
|
113
|
+
|
|
114
|
+
| Parameter | Default | Description |
|
|
115
|
+
|--------------|-------------------------------|------------------------------------------------------|
|
|
116
|
+
| `api_key` | required | Your API key from the developer dashboard |
|
|
117
|
+
| `base_url` | `https://syncforge.dev/api` | Override for local dev / self-hosted |
|
|
118
|
+
| `timeout` | `10` | HTTP timeout in seconds |
|
|
119
|
+
| `silent` | `False` | Suppress errors — logs warnings instead of crashing |
|
|
120
|
+
| `async_mode` | `False` | Fire-and-forget — refresh runs in a background thread|
|
|
121
|
+
|
|
122
|
+
### `sf.refresh(*tables)` → `SyncResult | list[SyncResult]`
|
|
123
|
+
|
|
124
|
+
Broadcasts a refresh signal for the specified tables.
|
|
125
|
+
|
|
126
|
+
```python
|
|
127
|
+
sf.refresh('products') # single table
|
|
128
|
+
sf.refresh('products', 'categories', 'orders') # multiple at once
|
|
129
|
+
|
|
130
|
+
result = sf.refresh('products')
|
|
131
|
+
print(result.ok) # True
|
|
132
|
+
print(result.calls_saved) # 1854211 (Analytics data from SyncForge servers)
|
|
133
|
+
print(result.sync_mode) # 'Event — On INSERT / UPDATE / DELETE'
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
### Advanced Usage
|
|
137
|
+
|
|
138
|
+
```python
|
|
139
|
+
# Silent mode — SyncForge errors never crash your app
|
|
140
|
+
sf = SyncForge(api_key='sf_live_...', silent=True)
|
|
141
|
+
|
|
142
|
+
# Async mode — fire-and-forget, returns immediately
|
|
143
|
+
sf = SyncForge(api_key='sf_live_...', async_mode=True)
|
|
144
|
+
sf.refresh('products') # returns None, syncs in background
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
---
|
|
148
|
+
|
|
149
|
+
## 👨💻 About the Author
|
|
150
|
+
|
|
151
|
+
**SyncForge** is passionately built and maintained by **Suresh Dullu Polai**.
|
|
152
|
+
Designed to bring Enterprise-Grade data synchronization and security to developers worldwide, entirely out of the box.
|
|
153
|
+
|
|
154
|
+
## 📄 License
|
|
155
|
+
MIT — see [LICENSE](LICENSE)
|
|
@@ -4,13 +4,13 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "syncforge"
|
|
7
|
-
version = "1.0.
|
|
7
|
+
version = "1.0.4"
|
|
8
8
|
description = "Official Python SDK for SyncForge — control exactly when data syncs between your database and clients."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = "MIT"
|
|
11
11
|
license-files = ["LICENSE"]
|
|
12
12
|
authors = [
|
|
13
|
-
{ name = "
|
|
13
|
+
{ name = "suresh dullu polai", email = "sureshpolai63@gmail.com" }
|
|
14
14
|
]
|
|
15
15
|
keywords = ["syncforge", "sync", "database", "cache", "invalidation", "django", "fastapi"]
|
|
16
16
|
classifiers = [
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
"""
|
|
2
|
+
SyncForge Security Middleware
|
|
3
|
+
Professional-grade request/response logging and basic WAF protection for Django apps.
|
|
4
|
+
"""
|
|
5
|
+
import time
|
|
6
|
+
import logging
|
|
7
|
+
|
|
8
|
+
try:
|
|
9
|
+
from django.http import HttpResponseForbidden
|
|
10
|
+
from django.utils.deprecation import MiddlewareMixin
|
|
11
|
+
HAS_DJANGO = True
|
|
12
|
+
except ImportError:
|
|
13
|
+
HAS_DJANGO = False
|
|
14
|
+
class MiddlewareMixin:
|
|
15
|
+
pass
|
|
16
|
+
|
|
17
|
+
logger = logging.getLogger('syncforge.security')
|
|
18
|
+
|
|
19
|
+
class SyncForgeSecurityMiddleware(MiddlewareMixin):
|
|
20
|
+
"""
|
|
21
|
+
Drop-in security and logging middleware.
|
|
22
|
+
Add 'syncforge.middleware.SyncForgeSecurityMiddleware' to your MIDDLEWARE setting.
|
|
23
|
+
"""
|
|
24
|
+
|
|
25
|
+
# Common malicious patterns to block automatically
|
|
26
|
+
MALICIOUS_PATTERNS = [
|
|
27
|
+
'../', # Path Traversal
|
|
28
|
+
'<script', # XSS
|
|
29
|
+
'javascript:', # XSS
|
|
30
|
+
'UNION SELECT', # SQLi
|
|
31
|
+
'OR 1=1', # SQLi
|
|
32
|
+
'-- ', # SQL comment injection
|
|
33
|
+
]
|
|
34
|
+
|
|
35
|
+
def process_request(self, request):
|
|
36
|
+
if not HAS_DJANGO:
|
|
37
|
+
return None
|
|
38
|
+
|
|
39
|
+
request._syncforge_start_time = time.time()
|
|
40
|
+
|
|
41
|
+
# Basic WAF (Web Application Firewall) checks
|
|
42
|
+
if self._is_malicious(request):
|
|
43
|
+
ip = request.META.get('HTTP_X_FORWARDED_FOR') or request.META.get('REMOTE_ADDR')
|
|
44
|
+
logger.warning(f"[SyncForge Security] Blocked malicious request from {ip} on {request.path}")
|
|
45
|
+
return HttpResponseForbidden("Blocked by SyncForge Security Firewall.")
|
|
46
|
+
|
|
47
|
+
return None
|
|
48
|
+
|
|
49
|
+
def process_response(self, request, response):
|
|
50
|
+
if not HAS_DJANGO:
|
|
51
|
+
return response
|
|
52
|
+
|
|
53
|
+
# Logging
|
|
54
|
+
if hasattr(request, '_syncforge_start_time'):
|
|
55
|
+
duration = (time.time() - request._syncforge_start_time) * 1000
|
|
56
|
+
method = request.method
|
|
57
|
+
path = request.path
|
|
58
|
+
status = response.status_code
|
|
59
|
+
|
|
60
|
+
# Format: [POST] /api/users/ - 200 OK (45.2ms)
|
|
61
|
+
if status >= 500:
|
|
62
|
+
level = logger.error
|
|
63
|
+
elif status >= 400:
|
|
64
|
+
level = logger.warning
|
|
65
|
+
else:
|
|
66
|
+
level = logger.info
|
|
67
|
+
|
|
68
|
+
level(f"[SyncForge] [{method}] {path} - {status} ({duration:.1f}ms)")
|
|
69
|
+
|
|
70
|
+
# Inject Security Headers
|
|
71
|
+
response['X-Powered-By'] = 'SyncForge'
|
|
72
|
+
response['X-Content-Type-Options'] = 'nosniff'
|
|
73
|
+
response['X-XSS-Protection'] = '1; mode=block'
|
|
74
|
+
|
|
75
|
+
return response
|
|
76
|
+
|
|
77
|
+
def _is_malicious(self, request):
|
|
78
|
+
path = request.path.upper()
|
|
79
|
+
query = request.META.get('QUERY_STRING', '').upper()
|
|
80
|
+
|
|
81
|
+
for pattern in self.MALICIOUS_PATTERNS:
|
|
82
|
+
p = pattern.upper()
|
|
83
|
+
if p in path or p in query:
|
|
84
|
+
return True
|
|
85
|
+
|
|
86
|
+
return False
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: syncforge
|
|
3
|
+
Version: 1.0.4
|
|
4
|
+
Summary: Official Python SDK for SyncForge — control exactly when data syncs between your database and clients.
|
|
5
|
+
Author-email: suresh dullu polai <sureshpolai63@gmail.com>
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/sureshdulupolai/syncforge
|
|
8
|
+
Project-URL: Documentation, https://syncforge.dev/docs/
|
|
9
|
+
Project-URL: Repository, https://github.com/sureshdulupolai/syncforge
|
|
10
|
+
Project-URL: Bug Tracker, https://github.com/sureshdulupolai/syncforge/issues
|
|
11
|
+
Keywords: syncforge,sync,database,cache,invalidation,django,fastapi
|
|
12
|
+
Classifier: Development Status :: 5 - Production/Stable
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
20
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
21
|
+
Classifier: Topic :: Database
|
|
22
|
+
Requires-Python: >=3.8
|
|
23
|
+
Description-Content-Type: text/markdown
|
|
24
|
+
License-File: LICENSE
|
|
25
|
+
Dynamic: license-file
|
|
26
|
+
|
|
27
|
+
# SyncForge Python SDK
|
|
28
|
+
|
|
29
|
+
[](https://pypi.org/project/syncforge/)
|
|
30
|
+
[](https://pypi.org/project/syncforge/)
|
|
31
|
+
[](LICENSE)
|
|
32
|
+
|
|
33
|
+
**Created by Suresh Dullu Polai**
|
|
34
|
+
|
|
35
|
+
SyncForge is the **FastAPI of data synchronization**. It is a premium, developer-controlled smart data synchronization platform and Web Application Firewall (WAF).
|
|
36
|
+
|
|
37
|
+
Stop relying on dumb polling or expensive real-time sockets for static data. With SyncForge, you take full control over exactly when and how your applications sync data, saving millions of unnecessary database calls and drastically reducing server costs.
|
|
38
|
+
|
|
39
|
+
---
|
|
40
|
+
|
|
41
|
+
## 🌟 Best Features (A to Z)
|
|
42
|
+
|
|
43
|
+
- **Zero-Polling Architecture**: Clients never hit your database to check for updates. They only get notified when *you* tell SyncForge that data has changed.
|
|
44
|
+
- **Built-in Web Application Firewall (WAF)**: Instantly protect your application from SQL Injection, Cross-Site Scripting (XSS), and Path Traversal attacks with a single line of code.
|
|
45
|
+
- **Zero-Code Django Auto-Sync**: Use our `@sync_model` decorator to automatically sync data across all your client devices whenever a Django model is created, updated, or deleted.
|
|
46
|
+
- **Precision Logging**: The middleware tracks request methods, paths, response statuses, and execution times in milliseconds.
|
|
47
|
+
- **Framework Agnostic**: First-class support for Django, FastAPI, Flask, or pure Python scripts.
|
|
48
|
+
- **Zero External Dependencies**: Built entirely on the Python Standard Library (`urllib`, `json`, `threading`).
|
|
49
|
+
|
|
50
|
+
---
|
|
51
|
+
|
|
52
|
+
## 🚀 Installation
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
pip install syncforge
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
---
|
|
59
|
+
|
|
60
|
+
## 🛡️ Built-in WAF Security Middleware (Django)
|
|
61
|
+
|
|
62
|
+
SyncForge SDK includes a professional-grade Web Application Firewall (WAF) and request logger. By adding just one line to your `settings.py`, your entire application is instantly protected from hackers.
|
|
63
|
+
|
|
64
|
+
### Features of the WAF:
|
|
65
|
+
1. **SQL Injection Protection**: Blocks `UNION SELECT`, `OR 1=1`, and other common SQLi payloads.
|
|
66
|
+
2. **XSS Protection**: Blocks `<script>` tags and malicious javascript injections.
|
|
67
|
+
3. **Path Traversal Protection**: Blocks `../` directory traversal attempts.
|
|
68
|
+
4. **Security Headers**: Automatically injects strict `X-Content-Type-Options: nosniff`.
|
|
69
|
+
5. **Performance Logging**: Logs response times beautifully (e.g., `[GET] /api/ - 200 (12.4ms)`).
|
|
70
|
+
|
|
71
|
+
### How to Install:
|
|
72
|
+
Add it to your Django `MIDDLEWARE` list in `settings.py`:
|
|
73
|
+
|
|
74
|
+
```python
|
|
75
|
+
MIDDLEWARE = [
|
|
76
|
+
'django.middleware.security.SecurityMiddleware',
|
|
77
|
+
|
|
78
|
+
# Add SyncForge Security Firewall right after Django's built-in security
|
|
79
|
+
'syncforge.middleware.SyncForgeSecurityMiddleware',
|
|
80
|
+
|
|
81
|
+
'django.contrib.sessions.middleware.SessionMiddleware',
|
|
82
|
+
# ...
|
|
83
|
+
]
|
|
84
|
+
```
|
|
85
|
+
*No further configuration needed! Your app is now secure.*
|
|
86
|
+
|
|
87
|
+
---
|
|
88
|
+
|
|
89
|
+
## 🔄 The `@sync_model` Decorator (Django Auto-Sync)
|
|
90
|
+
|
|
91
|
+
If you use Django, you never have to manually trigger a sync again. Use the `@sync_model` decorator. It hooks into Django's `post_save` and `post_delete` signals to automatically broadcast changes to all connected clients.
|
|
92
|
+
|
|
93
|
+
```python
|
|
94
|
+
# models.py
|
|
95
|
+
from django.db import models
|
|
96
|
+
from syncforge import sf
|
|
97
|
+
from syncforge.django import sync_model
|
|
98
|
+
|
|
99
|
+
# 1. Zero-code Django auto-sync
|
|
100
|
+
@sync_model(sf, sync_mode='event')
|
|
101
|
+
class Product(models.Model):
|
|
102
|
+
name = models.CharField(max_length=100)
|
|
103
|
+
price = models.DecimalField(max_digits=10, decimal_places=2)
|
|
104
|
+
```
|
|
105
|
+
Whenever you call `Product.objects.create(...)` or `product.delete()`, SyncForge automatically invalidates the cache and pushes the new delta to every single user's device.
|
|
106
|
+
|
|
107
|
+
---
|
|
108
|
+
|
|
109
|
+
## ⚡ FastAPI & Flask Integration
|
|
110
|
+
|
|
111
|
+
SyncForge isn't just for Django. You can trigger manual updates from any Python backend.
|
|
112
|
+
|
|
113
|
+
### FastAPI Example:
|
|
114
|
+
```python
|
|
115
|
+
import os
|
|
116
|
+
from fastapi import FastAPI
|
|
117
|
+
from syncforge import SyncForge
|
|
118
|
+
|
|
119
|
+
# Initialize once
|
|
120
|
+
sf = SyncForge(api_key=os.environ.get('SYNCFORGE_API_KEY'))
|
|
121
|
+
app = FastAPI()
|
|
122
|
+
|
|
123
|
+
@app.post("/api/products/")
|
|
124
|
+
async def create_product(name: str):
|
|
125
|
+
# 1. Database operation
|
|
126
|
+
db.execute("INSERT INTO products (name) VALUES (?)", (name,))
|
|
127
|
+
|
|
128
|
+
# 2. Trigger sync — Non-blocking, instant broadcast
|
|
129
|
+
sf.refresh('products')
|
|
130
|
+
|
|
131
|
+
return {"status": "success"}
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
---
|
|
135
|
+
|
|
136
|
+
## 📚 Core API Reference
|
|
137
|
+
|
|
138
|
+
### `SyncForge(api_key, base_url, timeout, silent, async_mode)`
|
|
139
|
+
|
|
140
|
+
| Parameter | Default | Description |
|
|
141
|
+
|--------------|-------------------------------|------------------------------------------------------|
|
|
142
|
+
| `api_key` | required | Your API key from the developer dashboard |
|
|
143
|
+
| `base_url` | `https://syncforge.dev/api` | Override for local dev / self-hosted |
|
|
144
|
+
| `timeout` | `10` | HTTP timeout in seconds |
|
|
145
|
+
| `silent` | `False` | Suppress errors — logs warnings instead of crashing |
|
|
146
|
+
| `async_mode` | `False` | Fire-and-forget — refresh runs in a background thread|
|
|
147
|
+
|
|
148
|
+
### `sf.refresh(*tables)` → `SyncResult | list[SyncResult]`
|
|
149
|
+
|
|
150
|
+
Broadcasts a refresh signal for the specified tables.
|
|
151
|
+
|
|
152
|
+
```python
|
|
153
|
+
sf.refresh('products') # single table
|
|
154
|
+
sf.refresh('products', 'categories', 'orders') # multiple at once
|
|
155
|
+
|
|
156
|
+
result = sf.refresh('products')
|
|
157
|
+
print(result.ok) # True
|
|
158
|
+
print(result.calls_saved) # 1854211 (Analytics data from SyncForge servers)
|
|
159
|
+
print(result.sync_mode) # 'Event — On INSERT / UPDATE / DELETE'
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
### Advanced Usage
|
|
163
|
+
|
|
164
|
+
```python
|
|
165
|
+
# Silent mode — SyncForge errors never crash your app
|
|
166
|
+
sf = SyncForge(api_key='sf_live_...', silent=True)
|
|
167
|
+
|
|
168
|
+
# Async mode — fire-and-forget, returns immediately
|
|
169
|
+
sf = SyncForge(api_key='sf_live_...', async_mode=True)
|
|
170
|
+
sf.refresh('products') # returns None, syncs in background
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
---
|
|
174
|
+
|
|
175
|
+
## 👨💻 About the Author
|
|
176
|
+
|
|
177
|
+
**SyncForge** is passionately built and maintained by **Suresh Dullu Polai**.
|
|
178
|
+
Designed to bring Enterprise-Grade data synchronization and security to developers worldwide, entirely out of the box.
|
|
179
|
+
|
|
180
|
+
## 📄 License
|
|
181
|
+
MIT — see [LICENSE](LICENSE)
|
syncforge-1.0.2/PKG-INFO
DELETED
|
@@ -1,195 +0,0 @@
|
|
|
1
|
-
Metadata-Version: 2.4
|
|
2
|
-
Name: syncforge
|
|
3
|
-
Version: 1.0.2
|
|
4
|
-
Summary: Official Python SDK for SyncForge — control exactly when data syncs between your database and clients.
|
|
5
|
-
Author-email: SyncForge <sureshdulupolai@gmail.com>
|
|
6
|
-
License-Expression: MIT
|
|
7
|
-
Project-URL: Homepage, https://github.com/sureshdulupolai/syncforge
|
|
8
|
-
Project-URL: Documentation, https://syncforge.dev/docs/
|
|
9
|
-
Project-URL: Repository, https://github.com/sureshdulupolai/syncforge
|
|
10
|
-
Project-URL: Bug Tracker, https://github.com/sureshdulupolai/syncforge/issues
|
|
11
|
-
Keywords: syncforge,sync,database,cache,invalidation,django,fastapi
|
|
12
|
-
Classifier: Development Status :: 5 - Production/Stable
|
|
13
|
-
Classifier: Intended Audience :: Developers
|
|
14
|
-
Classifier: Programming Language :: Python :: 3
|
|
15
|
-
Classifier: Programming Language :: Python :: 3.8
|
|
16
|
-
Classifier: Programming Language :: Python :: 3.9
|
|
17
|
-
Classifier: Programming Language :: Python :: 3.10
|
|
18
|
-
Classifier: Programming Language :: Python :: 3.11
|
|
19
|
-
Classifier: Programming Language :: Python :: 3.12
|
|
20
|
-
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
21
|
-
Classifier: Topic :: Database
|
|
22
|
-
Requires-Python: >=3.8
|
|
23
|
-
Description-Content-Type: text/markdown
|
|
24
|
-
License-File: LICENSE
|
|
25
|
-
Dynamic: license-file
|
|
26
|
-
|
|
27
|
-
# SyncForge Python SDK
|
|
28
|
-
|
|
29
|
-
[](https://pypi.org/project/syncforge/)
|
|
30
|
-
[](https://pypi.org/project/syncforge/)
|
|
31
|
-
[](LICENSE)
|
|
32
|
-
|
|
33
|
-
Official Python SDK for the [SyncForge](https://syncforge.dev) data sync platform.
|
|
34
|
-
Control exactly when data syncs between your database and client applications — no polling, no wasted DB calls.
|
|
35
|
-
|
|
36
|
-
---
|
|
37
|
-
|
|
38
|
-
## Installation
|
|
39
|
-
|
|
40
|
-
```bash
|
|
41
|
-
pip install syncforge
|
|
42
|
-
```
|
|
43
|
-
|
|
44
|
-
**Zero external dependencies.** Uses only Python stdlib (`urllib`, `json`, `threading`).
|
|
45
|
-
|
|
46
|
-
---
|
|
47
|
-
|
|
48
|
-
## Quick Start
|
|
49
|
-
|
|
50
|
-
```python
|
|
51
|
-
from syncforge import SyncForge
|
|
52
|
-
|
|
53
|
-
sf = SyncForge(api_key='sf_live_YOUR_KEY')
|
|
54
|
-
|
|
55
|
-
# After any DB write — notify all connected clients
|
|
56
|
-
sf.refresh('products')
|
|
57
|
-
```
|
|
58
|
-
|
|
59
|
-
---
|
|
60
|
-
|
|
61
|
-
## The `syncforge.py` Pattern (Recommended)
|
|
62
|
-
|
|
63
|
-
Place a `syncforge.py` file at your project root — same level as `manage.py` or `main.py`.
|
|
64
|
-
This mirrors the Celery pattern and gives you a single shared instance.
|
|
65
|
-
|
|
66
|
-
```python
|
|
67
|
-
# syncforge.py (project root)
|
|
68
|
-
import os
|
|
69
|
-
from syncforge import SyncForge
|
|
70
|
-
|
|
71
|
-
sf = SyncForge(
|
|
72
|
-
api_key=os.environ.get('SYNCFORGE_API_KEY', 'sf_live_YOUR_KEY')
|
|
73
|
-
)
|
|
74
|
-
```
|
|
75
|
-
|
|
76
|
-
Then import `sf` anywhere:
|
|
77
|
-
|
|
78
|
-
```python
|
|
79
|
-
# views.py / routes.py
|
|
80
|
-
from syncforge import sf
|
|
81
|
-
|
|
82
|
-
def create_product(request):
|
|
83
|
-
Product.objects.create(name='New Item', price=99.99)
|
|
84
|
-
sf.refresh('products') # one line — all clients updated
|
|
85
|
-
return JsonResponse({'status': 'created'})
|
|
86
|
-
```
|
|
87
|
-
|
|
88
|
-
---
|
|
89
|
-
|
|
90
|
-
## API Reference
|
|
91
|
-
|
|
92
|
-
### `SyncForge(api_key, base_url, timeout, silent, async_mode)`
|
|
93
|
-
|
|
94
|
-
| Parameter | Default | Description |
|
|
95
|
-
|--------------|-------------------------------|------------------------------------------------------|
|
|
96
|
-
| `api_key` | required | Your API key (`sf_live_...`) |
|
|
97
|
-
| `base_url` | `https://syncforge.dev/api` | Override for local dev / self-hosted |
|
|
98
|
-
| `timeout` | `10` | HTTP timeout in seconds |
|
|
99
|
-
| `silent` | `False` | Suppress errors — logs warnings instead of raising |
|
|
100
|
-
| `async_mode` | `False` | Fire-and-forget — refresh runs in a background thread|
|
|
101
|
-
|
|
102
|
-
### `sf.refresh(*tables)` → `SyncResult | list[SyncResult]`
|
|
103
|
-
|
|
104
|
-
```python
|
|
105
|
-
sf.refresh('products') # single table
|
|
106
|
-
sf.refresh('products', 'categories', 'orders') # multiple at once
|
|
107
|
-
|
|
108
|
-
result = sf.refresh('products')
|
|
109
|
-
print(result.ok) # True
|
|
110
|
-
print(result.calls_saved) # 1854211
|
|
111
|
-
print(result.sync_mode) # 'Event — On INSERT / UPDATE / DELETE'
|
|
112
|
-
```
|
|
113
|
-
|
|
114
|
-
### `sf.ping()` → `bool`
|
|
115
|
-
Health check — returns `True` if SyncForge is reachable.
|
|
116
|
-
|
|
117
|
-
### `sf.project_info()` → `dict`
|
|
118
|
-
Returns project metadata and all registered tables.
|
|
119
|
-
|
|
120
|
-
### `sf.list_tables()` → `list`
|
|
121
|
-
Lists all tables with their sync mode and stats.
|
|
122
|
-
|
|
123
|
-
---
|
|
124
|
-
|
|
125
|
-
## Django Integration
|
|
126
|
-
|
|
127
|
-
```python
|
|
128
|
-
# syncforge.py (next to manage.py)
|
|
129
|
-
import os
|
|
130
|
-
from syncforge import SyncForge
|
|
131
|
-
sf = SyncForge(api_key=os.environ.get('SYNCFORGE_API_KEY'))
|
|
132
|
-
|
|
133
|
-
# myapp/views.py
|
|
134
|
-
from syncforge import sf
|
|
135
|
-
|
|
136
|
-
def update_products(request):
|
|
137
|
-
Product.objects.filter(on_sale=True).update(price=F('price') * 0.9)
|
|
138
|
-
sf.refresh('products')
|
|
139
|
-
return JsonResponse({'status': 'updated'})
|
|
140
|
-
```
|
|
141
|
-
|
|
142
|
-
## FastAPI Integration
|
|
143
|
-
|
|
144
|
-
```python
|
|
145
|
-
from fastapi import FastAPI
|
|
146
|
-
from syncforge import sf
|
|
147
|
-
|
|
148
|
-
app = FastAPI()
|
|
149
|
-
|
|
150
|
-
@app.post("/products/")
|
|
151
|
-
async def create_product(name: str, price: float):
|
|
152
|
-
db.execute("INSERT INTO products ...")
|
|
153
|
-
sf.refresh('products')
|
|
154
|
-
return {"status": "ok"}
|
|
155
|
-
```
|
|
156
|
-
|
|
157
|
-
---
|
|
158
|
-
|
|
159
|
-
## Production Tips
|
|
160
|
-
|
|
161
|
-
```python
|
|
162
|
-
# Silent mode — SyncForge errors never crash your app
|
|
163
|
-
sf = SyncForge(api_key='sf_live_...', silent=True)
|
|
164
|
-
|
|
165
|
-
# Async mode — fire-and-forget, returns immediately
|
|
166
|
-
sf = SyncForge(api_key='sf_live_...', async_mode=True)
|
|
167
|
-
sf.refresh('products') # returns None, syncs in background
|
|
168
|
-
|
|
169
|
-
# Override base URL for local development
|
|
170
|
-
sf = SyncForge(api_key='sf_live_...', base_url='http://localhost:8000/api')
|
|
171
|
-
```
|
|
172
|
-
|
|
173
|
-
---
|
|
174
|
-
|
|
175
|
-
## Error Handling
|
|
176
|
-
|
|
177
|
-
```python
|
|
178
|
-
from syncforge import SyncForge, AuthError, TableNotFoundError, NetworkError
|
|
179
|
-
|
|
180
|
-
sf = SyncForge(api_key='sf_live_...')
|
|
181
|
-
try:
|
|
182
|
-
sf.refresh('products')
|
|
183
|
-
except AuthError:
|
|
184
|
-
print("Invalid API key")
|
|
185
|
-
except TableNotFoundError:
|
|
186
|
-
print("Register the table in your SyncForge dashboard first")
|
|
187
|
-
except NetworkError:
|
|
188
|
-
print("Could not reach SyncForge — check your internet connection")
|
|
189
|
-
```
|
|
190
|
-
|
|
191
|
-
---
|
|
192
|
-
|
|
193
|
-
## License
|
|
194
|
-
|
|
195
|
-
MIT — see [LICENSE](LICENSE)
|
syncforge-1.0.2/README.md
DELETED
|
@@ -1,169 +0,0 @@
|
|
|
1
|
-
# SyncForge Python SDK
|
|
2
|
-
|
|
3
|
-
[](https://pypi.org/project/syncforge/)
|
|
4
|
-
[](https://pypi.org/project/syncforge/)
|
|
5
|
-
[](LICENSE)
|
|
6
|
-
|
|
7
|
-
Official Python SDK for the [SyncForge](https://syncforge.dev) data sync platform.
|
|
8
|
-
Control exactly when data syncs between your database and client applications — no polling, no wasted DB calls.
|
|
9
|
-
|
|
10
|
-
---
|
|
11
|
-
|
|
12
|
-
## Installation
|
|
13
|
-
|
|
14
|
-
```bash
|
|
15
|
-
pip install syncforge
|
|
16
|
-
```
|
|
17
|
-
|
|
18
|
-
**Zero external dependencies.** Uses only Python stdlib (`urllib`, `json`, `threading`).
|
|
19
|
-
|
|
20
|
-
---
|
|
21
|
-
|
|
22
|
-
## Quick Start
|
|
23
|
-
|
|
24
|
-
```python
|
|
25
|
-
from syncforge import SyncForge
|
|
26
|
-
|
|
27
|
-
sf = SyncForge(api_key='sf_live_YOUR_KEY')
|
|
28
|
-
|
|
29
|
-
# After any DB write — notify all connected clients
|
|
30
|
-
sf.refresh('products')
|
|
31
|
-
```
|
|
32
|
-
|
|
33
|
-
---
|
|
34
|
-
|
|
35
|
-
## The `syncforge.py` Pattern (Recommended)
|
|
36
|
-
|
|
37
|
-
Place a `syncforge.py` file at your project root — same level as `manage.py` or `main.py`.
|
|
38
|
-
This mirrors the Celery pattern and gives you a single shared instance.
|
|
39
|
-
|
|
40
|
-
```python
|
|
41
|
-
# syncforge.py (project root)
|
|
42
|
-
import os
|
|
43
|
-
from syncforge import SyncForge
|
|
44
|
-
|
|
45
|
-
sf = SyncForge(
|
|
46
|
-
api_key=os.environ.get('SYNCFORGE_API_KEY', 'sf_live_YOUR_KEY')
|
|
47
|
-
)
|
|
48
|
-
```
|
|
49
|
-
|
|
50
|
-
Then import `sf` anywhere:
|
|
51
|
-
|
|
52
|
-
```python
|
|
53
|
-
# views.py / routes.py
|
|
54
|
-
from syncforge import sf
|
|
55
|
-
|
|
56
|
-
def create_product(request):
|
|
57
|
-
Product.objects.create(name='New Item', price=99.99)
|
|
58
|
-
sf.refresh('products') # one line — all clients updated
|
|
59
|
-
return JsonResponse({'status': 'created'})
|
|
60
|
-
```
|
|
61
|
-
|
|
62
|
-
---
|
|
63
|
-
|
|
64
|
-
## API Reference
|
|
65
|
-
|
|
66
|
-
### `SyncForge(api_key, base_url, timeout, silent, async_mode)`
|
|
67
|
-
|
|
68
|
-
| Parameter | Default | Description |
|
|
69
|
-
|--------------|-------------------------------|------------------------------------------------------|
|
|
70
|
-
| `api_key` | required | Your API key (`sf_live_...`) |
|
|
71
|
-
| `base_url` | `https://syncforge.dev/api` | Override for local dev / self-hosted |
|
|
72
|
-
| `timeout` | `10` | HTTP timeout in seconds |
|
|
73
|
-
| `silent` | `False` | Suppress errors — logs warnings instead of raising |
|
|
74
|
-
| `async_mode` | `False` | Fire-and-forget — refresh runs in a background thread|
|
|
75
|
-
|
|
76
|
-
### `sf.refresh(*tables)` → `SyncResult | list[SyncResult]`
|
|
77
|
-
|
|
78
|
-
```python
|
|
79
|
-
sf.refresh('products') # single table
|
|
80
|
-
sf.refresh('products', 'categories', 'orders') # multiple at once
|
|
81
|
-
|
|
82
|
-
result = sf.refresh('products')
|
|
83
|
-
print(result.ok) # True
|
|
84
|
-
print(result.calls_saved) # 1854211
|
|
85
|
-
print(result.sync_mode) # 'Event — On INSERT / UPDATE / DELETE'
|
|
86
|
-
```
|
|
87
|
-
|
|
88
|
-
### `sf.ping()` → `bool`
|
|
89
|
-
Health check — returns `True` if SyncForge is reachable.
|
|
90
|
-
|
|
91
|
-
### `sf.project_info()` → `dict`
|
|
92
|
-
Returns project metadata and all registered tables.
|
|
93
|
-
|
|
94
|
-
### `sf.list_tables()` → `list`
|
|
95
|
-
Lists all tables with their sync mode and stats.
|
|
96
|
-
|
|
97
|
-
---
|
|
98
|
-
|
|
99
|
-
## Django Integration
|
|
100
|
-
|
|
101
|
-
```python
|
|
102
|
-
# syncforge.py (next to manage.py)
|
|
103
|
-
import os
|
|
104
|
-
from syncforge import SyncForge
|
|
105
|
-
sf = SyncForge(api_key=os.environ.get('SYNCFORGE_API_KEY'))
|
|
106
|
-
|
|
107
|
-
# myapp/views.py
|
|
108
|
-
from syncforge import sf
|
|
109
|
-
|
|
110
|
-
def update_products(request):
|
|
111
|
-
Product.objects.filter(on_sale=True).update(price=F('price') * 0.9)
|
|
112
|
-
sf.refresh('products')
|
|
113
|
-
return JsonResponse({'status': 'updated'})
|
|
114
|
-
```
|
|
115
|
-
|
|
116
|
-
## FastAPI Integration
|
|
117
|
-
|
|
118
|
-
```python
|
|
119
|
-
from fastapi import FastAPI
|
|
120
|
-
from syncforge import sf
|
|
121
|
-
|
|
122
|
-
app = FastAPI()
|
|
123
|
-
|
|
124
|
-
@app.post("/products/")
|
|
125
|
-
async def create_product(name: str, price: float):
|
|
126
|
-
db.execute("INSERT INTO products ...")
|
|
127
|
-
sf.refresh('products')
|
|
128
|
-
return {"status": "ok"}
|
|
129
|
-
```
|
|
130
|
-
|
|
131
|
-
---
|
|
132
|
-
|
|
133
|
-
## Production Tips
|
|
134
|
-
|
|
135
|
-
```python
|
|
136
|
-
# Silent mode — SyncForge errors never crash your app
|
|
137
|
-
sf = SyncForge(api_key='sf_live_...', silent=True)
|
|
138
|
-
|
|
139
|
-
# Async mode — fire-and-forget, returns immediately
|
|
140
|
-
sf = SyncForge(api_key='sf_live_...', async_mode=True)
|
|
141
|
-
sf.refresh('products') # returns None, syncs in background
|
|
142
|
-
|
|
143
|
-
# Override base URL for local development
|
|
144
|
-
sf = SyncForge(api_key='sf_live_...', base_url='http://localhost:8000/api')
|
|
145
|
-
```
|
|
146
|
-
|
|
147
|
-
---
|
|
148
|
-
|
|
149
|
-
## Error Handling
|
|
150
|
-
|
|
151
|
-
```python
|
|
152
|
-
from syncforge import SyncForge, AuthError, TableNotFoundError, NetworkError
|
|
153
|
-
|
|
154
|
-
sf = SyncForge(api_key='sf_live_...')
|
|
155
|
-
try:
|
|
156
|
-
sf.refresh('products')
|
|
157
|
-
except AuthError:
|
|
158
|
-
print("Invalid API key")
|
|
159
|
-
except TableNotFoundError:
|
|
160
|
-
print("Register the table in your SyncForge dashboard first")
|
|
161
|
-
except NetworkError:
|
|
162
|
-
print("Could not reach SyncForge — check your internet connection")
|
|
163
|
-
```
|
|
164
|
-
|
|
165
|
-
---
|
|
166
|
-
|
|
167
|
-
## License
|
|
168
|
-
|
|
169
|
-
MIT — see [LICENSE](LICENSE)
|
|
@@ -1,195 +0,0 @@
|
|
|
1
|
-
Metadata-Version: 2.4
|
|
2
|
-
Name: syncforge
|
|
3
|
-
Version: 1.0.2
|
|
4
|
-
Summary: Official Python SDK for SyncForge — control exactly when data syncs between your database and clients.
|
|
5
|
-
Author-email: SyncForge <sureshdulupolai@gmail.com>
|
|
6
|
-
License-Expression: MIT
|
|
7
|
-
Project-URL: Homepage, https://github.com/sureshdulupolai/syncforge
|
|
8
|
-
Project-URL: Documentation, https://syncforge.dev/docs/
|
|
9
|
-
Project-URL: Repository, https://github.com/sureshdulupolai/syncforge
|
|
10
|
-
Project-URL: Bug Tracker, https://github.com/sureshdulupolai/syncforge/issues
|
|
11
|
-
Keywords: syncforge,sync,database,cache,invalidation,django,fastapi
|
|
12
|
-
Classifier: Development Status :: 5 - Production/Stable
|
|
13
|
-
Classifier: Intended Audience :: Developers
|
|
14
|
-
Classifier: Programming Language :: Python :: 3
|
|
15
|
-
Classifier: Programming Language :: Python :: 3.8
|
|
16
|
-
Classifier: Programming Language :: Python :: 3.9
|
|
17
|
-
Classifier: Programming Language :: Python :: 3.10
|
|
18
|
-
Classifier: Programming Language :: Python :: 3.11
|
|
19
|
-
Classifier: Programming Language :: Python :: 3.12
|
|
20
|
-
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
21
|
-
Classifier: Topic :: Database
|
|
22
|
-
Requires-Python: >=3.8
|
|
23
|
-
Description-Content-Type: text/markdown
|
|
24
|
-
License-File: LICENSE
|
|
25
|
-
Dynamic: license-file
|
|
26
|
-
|
|
27
|
-
# SyncForge Python SDK
|
|
28
|
-
|
|
29
|
-
[](https://pypi.org/project/syncforge/)
|
|
30
|
-
[](https://pypi.org/project/syncforge/)
|
|
31
|
-
[](LICENSE)
|
|
32
|
-
|
|
33
|
-
Official Python SDK for the [SyncForge](https://syncforge.dev) data sync platform.
|
|
34
|
-
Control exactly when data syncs between your database and client applications — no polling, no wasted DB calls.
|
|
35
|
-
|
|
36
|
-
---
|
|
37
|
-
|
|
38
|
-
## Installation
|
|
39
|
-
|
|
40
|
-
```bash
|
|
41
|
-
pip install syncforge
|
|
42
|
-
```
|
|
43
|
-
|
|
44
|
-
**Zero external dependencies.** Uses only Python stdlib (`urllib`, `json`, `threading`).
|
|
45
|
-
|
|
46
|
-
---
|
|
47
|
-
|
|
48
|
-
## Quick Start
|
|
49
|
-
|
|
50
|
-
```python
|
|
51
|
-
from syncforge import SyncForge
|
|
52
|
-
|
|
53
|
-
sf = SyncForge(api_key='sf_live_YOUR_KEY')
|
|
54
|
-
|
|
55
|
-
# After any DB write — notify all connected clients
|
|
56
|
-
sf.refresh('products')
|
|
57
|
-
```
|
|
58
|
-
|
|
59
|
-
---
|
|
60
|
-
|
|
61
|
-
## The `syncforge.py` Pattern (Recommended)
|
|
62
|
-
|
|
63
|
-
Place a `syncforge.py` file at your project root — same level as `manage.py` or `main.py`.
|
|
64
|
-
This mirrors the Celery pattern and gives you a single shared instance.
|
|
65
|
-
|
|
66
|
-
```python
|
|
67
|
-
# syncforge.py (project root)
|
|
68
|
-
import os
|
|
69
|
-
from syncforge import SyncForge
|
|
70
|
-
|
|
71
|
-
sf = SyncForge(
|
|
72
|
-
api_key=os.environ.get('SYNCFORGE_API_KEY', 'sf_live_YOUR_KEY')
|
|
73
|
-
)
|
|
74
|
-
```
|
|
75
|
-
|
|
76
|
-
Then import `sf` anywhere:
|
|
77
|
-
|
|
78
|
-
```python
|
|
79
|
-
# views.py / routes.py
|
|
80
|
-
from syncforge import sf
|
|
81
|
-
|
|
82
|
-
def create_product(request):
|
|
83
|
-
Product.objects.create(name='New Item', price=99.99)
|
|
84
|
-
sf.refresh('products') # one line — all clients updated
|
|
85
|
-
return JsonResponse({'status': 'created'})
|
|
86
|
-
```
|
|
87
|
-
|
|
88
|
-
---
|
|
89
|
-
|
|
90
|
-
## API Reference
|
|
91
|
-
|
|
92
|
-
### `SyncForge(api_key, base_url, timeout, silent, async_mode)`
|
|
93
|
-
|
|
94
|
-
| Parameter | Default | Description |
|
|
95
|
-
|--------------|-------------------------------|------------------------------------------------------|
|
|
96
|
-
| `api_key` | required | Your API key (`sf_live_...`) |
|
|
97
|
-
| `base_url` | `https://syncforge.dev/api` | Override for local dev / self-hosted |
|
|
98
|
-
| `timeout` | `10` | HTTP timeout in seconds |
|
|
99
|
-
| `silent` | `False` | Suppress errors — logs warnings instead of raising |
|
|
100
|
-
| `async_mode` | `False` | Fire-and-forget — refresh runs in a background thread|
|
|
101
|
-
|
|
102
|
-
### `sf.refresh(*tables)` → `SyncResult | list[SyncResult]`
|
|
103
|
-
|
|
104
|
-
```python
|
|
105
|
-
sf.refresh('products') # single table
|
|
106
|
-
sf.refresh('products', 'categories', 'orders') # multiple at once
|
|
107
|
-
|
|
108
|
-
result = sf.refresh('products')
|
|
109
|
-
print(result.ok) # True
|
|
110
|
-
print(result.calls_saved) # 1854211
|
|
111
|
-
print(result.sync_mode) # 'Event — On INSERT / UPDATE / DELETE'
|
|
112
|
-
```
|
|
113
|
-
|
|
114
|
-
### `sf.ping()` → `bool`
|
|
115
|
-
Health check — returns `True` if SyncForge is reachable.
|
|
116
|
-
|
|
117
|
-
### `sf.project_info()` → `dict`
|
|
118
|
-
Returns project metadata and all registered tables.
|
|
119
|
-
|
|
120
|
-
### `sf.list_tables()` → `list`
|
|
121
|
-
Lists all tables with their sync mode and stats.
|
|
122
|
-
|
|
123
|
-
---
|
|
124
|
-
|
|
125
|
-
## Django Integration
|
|
126
|
-
|
|
127
|
-
```python
|
|
128
|
-
# syncforge.py (next to manage.py)
|
|
129
|
-
import os
|
|
130
|
-
from syncforge import SyncForge
|
|
131
|
-
sf = SyncForge(api_key=os.environ.get('SYNCFORGE_API_KEY'))
|
|
132
|
-
|
|
133
|
-
# myapp/views.py
|
|
134
|
-
from syncforge import sf
|
|
135
|
-
|
|
136
|
-
def update_products(request):
|
|
137
|
-
Product.objects.filter(on_sale=True).update(price=F('price') * 0.9)
|
|
138
|
-
sf.refresh('products')
|
|
139
|
-
return JsonResponse({'status': 'updated'})
|
|
140
|
-
```
|
|
141
|
-
|
|
142
|
-
## FastAPI Integration
|
|
143
|
-
|
|
144
|
-
```python
|
|
145
|
-
from fastapi import FastAPI
|
|
146
|
-
from syncforge import sf
|
|
147
|
-
|
|
148
|
-
app = FastAPI()
|
|
149
|
-
|
|
150
|
-
@app.post("/products/")
|
|
151
|
-
async def create_product(name: str, price: float):
|
|
152
|
-
db.execute("INSERT INTO products ...")
|
|
153
|
-
sf.refresh('products')
|
|
154
|
-
return {"status": "ok"}
|
|
155
|
-
```
|
|
156
|
-
|
|
157
|
-
---
|
|
158
|
-
|
|
159
|
-
## Production Tips
|
|
160
|
-
|
|
161
|
-
```python
|
|
162
|
-
# Silent mode — SyncForge errors never crash your app
|
|
163
|
-
sf = SyncForge(api_key='sf_live_...', silent=True)
|
|
164
|
-
|
|
165
|
-
# Async mode — fire-and-forget, returns immediately
|
|
166
|
-
sf = SyncForge(api_key='sf_live_...', async_mode=True)
|
|
167
|
-
sf.refresh('products') # returns None, syncs in background
|
|
168
|
-
|
|
169
|
-
# Override base URL for local development
|
|
170
|
-
sf = SyncForge(api_key='sf_live_...', base_url='http://localhost:8000/api')
|
|
171
|
-
```
|
|
172
|
-
|
|
173
|
-
---
|
|
174
|
-
|
|
175
|
-
## Error Handling
|
|
176
|
-
|
|
177
|
-
```python
|
|
178
|
-
from syncforge import SyncForge, AuthError, TableNotFoundError, NetworkError
|
|
179
|
-
|
|
180
|
-
sf = SyncForge(api_key='sf_live_...')
|
|
181
|
-
try:
|
|
182
|
-
sf.refresh('products')
|
|
183
|
-
except AuthError:
|
|
184
|
-
print("Invalid API key")
|
|
185
|
-
except TableNotFoundError:
|
|
186
|
-
print("Register the table in your SyncForge dashboard first")
|
|
187
|
-
except NetworkError:
|
|
188
|
-
print("Could not reach SyncForge — check your internet connection")
|
|
189
|
-
```
|
|
190
|
-
|
|
191
|
-
---
|
|
192
|
-
|
|
193
|
-
## License
|
|
194
|
-
|
|
195
|
-
MIT — see [LICENSE](LICENSE)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|