tina4-python 3.3.0__tar.gz → 3.5.0__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.
- {tina4_python-3.3.0 → tina4_python-3.5.0}/PKG-INFO +1 -1
- {tina4_python-3.3.0 → tina4_python-3.5.0}/pyproject.toml +1 -1
- {tina4_python-3.3.0 → tina4_python-3.5.0}/tina4_python/__init__.py +1 -1
- {tina4_python-3.3.0 → tina4_python-3.5.0}/tina4_python/crud/__init__.py +40 -0
- tina4_python-3.5.0/tina4_python/public/js/tina4js.min.js +47 -0
- {tina4_python-3.3.0 → tina4_python-3.5.0}/.gitignore +0 -0
- {tina4_python-3.3.0 → tina4_python-3.5.0}/README.md +0 -0
- {tina4_python-3.3.0 → tina4_python-3.5.0}/tina4_python/CLAUDE.md +0 -0
- {tina4_python-3.3.0 → tina4_python-3.5.0}/tina4_python/HtmlElement.py +0 -0
- {tina4_python-3.3.0 → tina4_python-3.5.0}/tina4_python/Testing.py +0 -0
- {tina4_python-3.3.0 → tina4_python-3.5.0}/tina4_python/ai/__init__.py +0 -0
- {tina4_python-3.3.0 → tina4_python-3.5.0}/tina4_python/api/__init__.py +0 -0
- {tina4_python-3.3.0 → tina4_python-3.5.0}/tina4_python/auth/__init__.py +0 -0
- {tina4_python-3.3.0 → tina4_python-3.5.0}/tina4_python/cache/__init__.py +0 -0
- {tina4_python-3.3.0 → tina4_python-3.5.0}/tina4_python/cli/__init__.py +0 -0
- {tina4_python-3.3.0 → tina4_python-3.5.0}/tina4_python/container/__init__.py +0 -0
- {tina4_python-3.3.0 → tina4_python-3.5.0}/tina4_python/core/__init__.py +0 -0
- {tina4_python-3.3.0 → tina4_python-3.5.0}/tina4_python/core/cache.py +0 -0
- {tina4_python-3.3.0 → tina4_python-3.5.0}/tina4_python/core/constants.py +0 -0
- {tina4_python-3.3.0 → tina4_python-3.5.0}/tina4_python/core/events.py +0 -0
- {tina4_python-3.3.0 → tina4_python-3.5.0}/tina4_python/core/middleware.py +0 -0
- {tina4_python-3.3.0 → tina4_python-3.5.0}/tina4_python/core/request.py +0 -0
- {tina4_python-3.3.0 → tina4_python-3.5.0}/tina4_python/core/response.py +0 -0
- {tina4_python-3.3.0 → tina4_python-3.5.0}/tina4_python/core/router.py +0 -0
- {tina4_python-3.3.0 → tina4_python-3.5.0}/tina4_python/core/server.py +0 -0
- {tina4_python-3.3.0 → tina4_python-3.5.0}/tina4_python/database/__init__.py +0 -0
- {tina4_python-3.3.0 → tina4_python-3.5.0}/tina4_python/database/adapter.py +0 -0
- {tina4_python-3.3.0 → tina4_python-3.5.0}/tina4_python/database/connection.py +0 -0
- {tina4_python-3.3.0 → tina4_python-3.5.0}/tina4_python/database/firebird.py +0 -0
- {tina4_python-3.3.0 → tina4_python-3.5.0}/tina4_python/database/mssql.py +0 -0
- {tina4_python-3.3.0 → tina4_python-3.5.0}/tina4_python/database/mysql.py +0 -0
- {tina4_python-3.3.0 → tina4_python-3.5.0}/tina4_python/database/odbc.py +0 -0
- {tina4_python-3.3.0 → tina4_python-3.5.0}/tina4_python/database/postgres.py +0 -0
- {tina4_python-3.3.0 → tina4_python-3.5.0}/tina4_python/database/sqlite.py +0 -0
- {tina4_python-3.3.0 → tina4_python-3.5.0}/tina4_python/debug/__init__.py +0 -0
- {tina4_python-3.3.0 → tina4_python-3.5.0}/tina4_python/debug/error_overlay.py +0 -0
- {tina4_python-3.3.0 → tina4_python-3.5.0}/tina4_python/dev_admin/__init__.py +0 -0
- {tina4_python-3.3.0 → tina4_python-3.5.0}/tina4_python/dev_reload.py +0 -0
- {tina4_python-3.3.0 → tina4_python-3.5.0}/tina4_python/dotenv/__init__.py +0 -0
- {tina4_python-3.3.0 → tina4_python-3.5.0}/tina4_python/frond/FROND.md +0 -0
- {tina4_python-3.3.0 → tina4_python-3.5.0}/tina4_python/frond/__init__.py +0 -0
- {tina4_python-3.3.0 → tina4_python-3.5.0}/tina4_python/frond/engine.py +0 -0
- {tina4_python-3.3.0 → tina4_python-3.5.0}/tina4_python/gallery/auth/meta.json +0 -0
- {tina4_python-3.3.0 → tina4_python-3.5.0}/tina4_python/gallery/auth/src/routes/api/gallery_auth.py +0 -0
- {tina4_python-3.3.0 → tina4_python-3.5.0}/tina4_python/gallery/database/meta.json +0 -0
- {tina4_python-3.3.0 → tina4_python-3.5.0}/tina4_python/gallery/database/src/routes/api/gallery_db.py +0 -0
- {tina4_python-3.3.0 → tina4_python-3.5.0}/tina4_python/gallery/error-overlay/meta.json +0 -0
- {tina4_python-3.3.0 → tina4_python-3.5.0}/tina4_python/gallery/error-overlay/src/routes/api/gallery_crash.py +0 -0
- {tina4_python-3.3.0 → tina4_python-3.5.0}/tina4_python/gallery/orm/meta.json +0 -0
- {tina4_python-3.3.0 → tina4_python-3.5.0}/tina4_python/gallery/orm/src/orm/Product.py +0 -0
- {tina4_python-3.3.0 → tina4_python-3.5.0}/tina4_python/gallery/orm/src/routes/api/gallery_products.py +0 -0
- {tina4_python-3.3.0 → tina4_python-3.5.0}/tina4_python/gallery/queue/meta.json +0 -0
- {tina4_python-3.3.0 → tina4_python-3.5.0}/tina4_python/gallery/queue/src/routes/api/gallery_queue.py +0 -0
- {tina4_python-3.3.0 → tina4_python-3.5.0}/tina4_python/gallery/rest-api/meta.json +0 -0
- {tina4_python-3.3.0 → tina4_python-3.5.0}/tina4_python/gallery/rest-api/src/routes/api/gallery_hello.py +0 -0
- {tina4_python-3.3.0 → tina4_python-3.5.0}/tina4_python/gallery/templates/meta.json +0 -0
- {tina4_python-3.3.0 → tina4_python-3.5.0}/tina4_python/gallery/templates/src/routes/gallery_page.py +0 -0
- {tina4_python-3.3.0 → tina4_python-3.5.0}/tina4_python/gallery/templates/src/templates/gallery_page.twig +0 -0
- {tina4_python-3.3.0 → tina4_python-3.5.0}/tina4_python/graphql/__init__.py +0 -0
- {tina4_python-3.3.0 → tina4_python-3.5.0}/tina4_python/i18n/__init__.py +0 -0
- {tina4_python-3.3.0 → tina4_python-3.5.0}/tina4_python/messenger/__init__.py +0 -0
- {tina4_python-3.3.0 → tina4_python-3.5.0}/tina4_python/migration/__init__.py +0 -0
- {tina4_python-3.3.0 → tina4_python-3.5.0}/tina4_python/migration/runner.py +0 -0
- {tina4_python-3.3.0 → tina4_python-3.5.0}/tina4_python/orm/__init__.py +0 -0
- {tina4_python-3.3.0 → tina4_python-3.5.0}/tina4_python/orm/fields.py +0 -0
- {tina4_python-3.3.0 → tina4_python-3.5.0}/tina4_python/orm/model.py +0 -0
- {tina4_python-3.3.0 → tina4_python-3.5.0}/tina4_python/public/css/tina4.css +0 -0
- {tina4_python-3.3.0 → tina4_python-3.5.0}/tina4_python/public/css/tina4.min.css +0 -0
- {tina4_python-3.3.0 → tina4_python-3.5.0}/tina4_python/public/favicon.ico +0 -0
- {tina4_python-3.3.0 → tina4_python-3.5.0}/tina4_python/public/images/logo.svg +0 -0
- {tina4_python-3.3.0 → tina4_python-3.5.0}/tina4_python/public/images/tina4-logo-icon.webp +0 -0
- {tina4_python-3.3.0 → tina4_python-3.5.0}/tina4_python/public/js/frond.min.js +0 -0
- {tina4_python-3.3.0 → tina4_python-3.5.0}/tina4_python/public/js/tina4-dev-admin.min.js +0 -0
- {tina4_python-3.3.0 → tina4_python-3.5.0}/tina4_python/public/js/tina4.min.js +0 -0
- {tina4_python-3.3.0 → tina4_python-3.5.0}/tina4_python/public/swagger/index.html +0 -0
- {tina4_python-3.3.0 → tina4_python-3.5.0}/tina4_python/public/swagger/oauth2-redirect.html +0 -0
- {tina4_python-3.3.0 → tina4_python-3.5.0}/tina4_python/queue/__init__.py +0 -0
- {tina4_python-3.3.0 → tina4_python-3.5.0}/tina4_python/queue_backends/__init__.py +0 -0
- {tina4_python-3.3.0 → tina4_python-3.5.0}/tina4_python/queue_backends/kafka_backend.py +0 -0
- {tina4_python-3.3.0 → tina4_python-3.5.0}/tina4_python/queue_backends/mongo_backend.py +0 -0
- {tina4_python-3.3.0 → tina4_python-3.5.0}/tina4_python/queue_backends/rabbitmq_backend.py +0 -0
- {tina4_python-3.3.0 → tina4_python-3.5.0}/tina4_python/scss/__init__.py +0 -0
- {tina4_python-3.3.0 → tina4_python-3.5.0}/tina4_python/scss/tina4css/_alerts.scss +0 -0
- {tina4_python-3.3.0 → tina4_python-3.5.0}/tina4_python/scss/tina4css/_badges.scss +0 -0
- {tina4_python-3.3.0 → tina4_python-3.5.0}/tina4_python/scss/tina4css/_buttons.scss +0 -0
- {tina4_python-3.3.0 → tina4_python-3.5.0}/tina4_python/scss/tina4css/_cards.scss +0 -0
- {tina4_python-3.3.0 → tina4_python-3.5.0}/tina4_python/scss/tina4css/_forms.scss +0 -0
- {tina4_python-3.3.0 → tina4_python-3.5.0}/tina4_python/scss/tina4css/_grid.scss +0 -0
- {tina4_python-3.3.0 → tina4_python-3.5.0}/tina4_python/scss/tina4css/_modals.scss +0 -0
- {tina4_python-3.3.0 → tina4_python-3.5.0}/tina4_python/scss/tina4css/_nav.scss +0 -0
- {tina4_python-3.3.0 → tina4_python-3.5.0}/tina4_python/scss/tina4css/_reset.scss +0 -0
- {tina4_python-3.3.0 → tina4_python-3.5.0}/tina4_python/scss/tina4css/_tables.scss +0 -0
- {tina4_python-3.3.0 → tina4_python-3.5.0}/tina4_python/scss/tina4css/_typography.scss +0 -0
- {tina4_python-3.3.0 → tina4_python-3.5.0}/tina4_python/scss/tina4css/_utilities.scss +0 -0
- {tina4_python-3.3.0 → tina4_python-3.5.0}/tina4_python/scss/tina4css/_variables.scss +0 -0
- {tina4_python-3.3.0 → tina4_python-3.5.0}/tina4_python/scss/tina4css/base.scss +0 -0
- {tina4_python-3.3.0 → tina4_python-3.5.0}/tina4_python/scss/tina4css/colors.scss +0 -0
- {tina4_python-3.3.0 → tina4_python-3.5.0}/tina4_python/scss/tina4css/tina4.scss +0 -0
- {tina4_python-3.3.0 → tina4_python-3.5.0}/tina4_python/seeder/__init__.py +0 -0
- {tina4_python-3.3.0 → tina4_python-3.5.0}/tina4_python/service/__init__.py +0 -0
- {tina4_python-3.3.0 → tina4_python-3.5.0}/tina4_python/session/__init__.py +0 -0
- {tina4_python-3.3.0 → tina4_python-3.5.0}/tina4_python/session_handlers/__init__.py +0 -0
- {tina4_python-3.3.0 → tina4_python-3.5.0}/tina4_python/session_handlers/mongodb_handler.py +0 -0
- {tina4_python-3.3.0 → tina4_python-3.5.0}/tina4_python/session_handlers/redis_handler.py +0 -0
- {tina4_python-3.3.0 → tina4_python-3.5.0}/tina4_python/session_handlers/valkey_handler.py +0 -0
- {tina4_python-3.3.0 → tina4_python-3.5.0}/tina4_python/swagger/__init__.py +0 -0
- {tina4_python-3.3.0 → tina4_python-3.5.0}/tina4_python/templates/components/crud.twig +0 -0
- {tina4_python-3.3.0 → tina4_python-3.5.0}/tina4_python/templates/docker/distroless/Dockerfile +0 -0
- {tina4_python-3.3.0 → tina4_python-3.5.0}/tina4_python/templates/docker/poetry/Dockerfile +0 -0
- {tina4_python-3.3.0 → tina4_python-3.5.0}/tina4_python/templates/docker/python/Dockerfile +0 -0
- {tina4_python-3.3.0 → tina4_python-3.5.0}/tina4_python/templates/docker/uv/Dockerfile +0 -0
- {tina4_python-3.3.0 → tina4_python-3.5.0}/tina4_python/templates/errors/302.twig +0 -0
- {tina4_python-3.3.0 → tina4_python-3.5.0}/tina4_python/templates/errors/401.twig +0 -0
- {tina4_python-3.3.0 → tina4_python-3.5.0}/tina4_python/templates/errors/403.twig +0 -0
- {tina4_python-3.3.0 → tina4_python-3.5.0}/tina4_python/templates/errors/404.twig +0 -0
- {tina4_python-3.3.0 → tina4_python-3.5.0}/tina4_python/templates/errors/500.twig +0 -0
- {tina4_python-3.3.0 → tina4_python-3.5.0}/tina4_python/templates/errors/502.twig +0 -0
- {tina4_python-3.3.0 → tina4_python-3.5.0}/tina4_python/templates/errors/503.twig +0 -0
- {tina4_python-3.3.0 → tina4_python-3.5.0}/tina4_python/templates/errors/base.twig +0 -0
- {tina4_python-3.3.0 → tina4_python-3.5.0}/tina4_python/templates/frontend/README.md +0 -0
- {tina4_python-3.3.0 → tina4_python-3.5.0}/tina4_python/templates/readme.md +0 -0
- {tina4_python-3.3.0 → tina4_python-3.5.0}/tina4_python/translations/af/LC_MESSAGES/messages.mo +0 -0
- {tina4_python-3.3.0 → tina4_python-3.5.0}/tina4_python/translations/af/LC_MESSAGES/messages.po +0 -0
- {tina4_python-3.3.0 → tina4_python-3.5.0}/tina4_python/translations/en/LC_MESSAGES/messages.mo +0 -0
- {tina4_python-3.3.0 → tina4_python-3.5.0}/tina4_python/translations/en/LC_MESSAGES/messages.po +0 -0
- {tina4_python-3.3.0 → tina4_python-3.5.0}/tina4_python/translations/es/LC_MESSAGES/messages.mo +0 -0
- {tina4_python-3.3.0 → tina4_python-3.5.0}/tina4_python/translations/es/LC_MESSAGES/messages.po +0 -0
- {tina4_python-3.3.0 → tina4_python-3.5.0}/tina4_python/translations/fr/LC_MESSAGES/messages.mo +0 -0
- {tina4_python-3.3.0 → tina4_python-3.5.0}/tina4_python/translations/fr/LC_MESSAGES/messages.po +0 -0
- {tina4_python-3.3.0 → tina4_python-3.5.0}/tina4_python/translations/ja/LC_MESSAGES/messages.mo +0 -0
- {tina4_python-3.3.0 → tina4_python-3.5.0}/tina4_python/translations/ja/LC_MESSAGES/messages.po +0 -0
- {tina4_python-3.3.0 → tina4_python-3.5.0}/tina4_python/translations/zh/LC_MESSAGES/messages.mo +0 -0
- {tina4_python-3.3.0 → tina4_python-3.5.0}/tina4_python/translations/zh/LC_MESSAGES/messages.po +0 -0
- {tina4_python-3.3.0 → tina4_python-3.5.0}/tina4_python/websocket/__init__.py +0 -0
- {tina4_python-3.3.0 → tina4_python-3.5.0}/tina4_python/wsdl/__init__.py +0 -0
|
@@ -39,6 +39,32 @@ class AutoCrud:
|
|
|
39
39
|
# Track registered models for introspection
|
|
40
40
|
_registered: dict[str, type] = {}
|
|
41
41
|
|
|
42
|
+
@staticmethod
|
|
43
|
+
def _build_example(model_class) -> dict:
|
|
44
|
+
"""Build a sample request body from ORM field definitions.
|
|
45
|
+
|
|
46
|
+
Generates a dict with field names as keys and example values
|
|
47
|
+
based on field types, suitable for Swagger request body examples.
|
|
48
|
+
"""
|
|
49
|
+
from datetime import datetime
|
|
50
|
+
|
|
51
|
+
example = {}
|
|
52
|
+
for name, field in model_class._fields.items():
|
|
53
|
+
if field.primary_key and field.auto_increment:
|
|
54
|
+
continue # Skip auto-generated PKs
|
|
55
|
+
ft = field.field_type
|
|
56
|
+
if ft == int:
|
|
57
|
+
example[name] = 0
|
|
58
|
+
elif ft == float:
|
|
59
|
+
example[name] = 0.0
|
|
60
|
+
elif ft == bool:
|
|
61
|
+
example[name] = True
|
|
62
|
+
elif ft == datetime:
|
|
63
|
+
example[name] = "2024-01-01T00:00:00"
|
|
64
|
+
else:
|
|
65
|
+
example[name] = "string"
|
|
66
|
+
return example
|
|
67
|
+
|
|
42
68
|
@staticmethod
|
|
43
69
|
def register(model_class, prefix: str = "/api"):
|
|
44
70
|
"""Register REST endpoints for a single ORM model class.
|
|
@@ -62,6 +88,8 @@ class AutoCrud:
|
|
|
62
88
|
base_path = f"{prefix}/{table}"
|
|
63
89
|
pk_field = model_class._get_pk()
|
|
64
90
|
generated = []
|
|
91
|
+
pretty_name = table.replace("_", " ").title()
|
|
92
|
+
example_body = AutoCrud._build_example(model_class)
|
|
65
93
|
|
|
66
94
|
# ── GET /api/{table} — list with pagination ──────────────
|
|
67
95
|
async def list_handler(request, response, _cls=model_class):
|
|
@@ -82,6 +110,8 @@ class AutoCrud:
|
|
|
82
110
|
|
|
83
111
|
list_handler.__name__ = f"autocrud_list_{table}"
|
|
84
112
|
list_handler.__qualname__ = f"autocrud_list_{table}"
|
|
113
|
+
list_handler._swagger_summary = f"List all {pretty_name}"
|
|
114
|
+
list_handler._swagger_tags = [table]
|
|
85
115
|
Router.add("GET", base_path, list_handler)
|
|
86
116
|
generated.append({"method": "GET", "path": base_path, "table": table})
|
|
87
117
|
|
|
@@ -95,6 +125,8 @@ class AutoCrud:
|
|
|
95
125
|
|
|
96
126
|
get_handler.__name__ = f"autocrud_get_{table}"
|
|
97
127
|
get_handler.__qualname__ = f"autocrud_get_{table}"
|
|
128
|
+
get_handler._swagger_summary = f"Get {pretty_name} by ID"
|
|
129
|
+
get_handler._swagger_tags = [table]
|
|
98
130
|
Router.add("GET", f"{base_path}/{{id}}", get_handler)
|
|
99
131
|
generated.append({"method": "GET", "path": f"{base_path}/{{id}}", "table": table})
|
|
100
132
|
|
|
@@ -114,6 +146,9 @@ class AutoCrud:
|
|
|
114
146
|
create_handler.__name__ = f"autocrud_create_{table}"
|
|
115
147
|
create_handler.__qualname__ = f"autocrud_create_{table}"
|
|
116
148
|
create_handler._noauth = True
|
|
149
|
+
create_handler._swagger_summary = f"Create {pretty_name}"
|
|
150
|
+
create_handler._swagger_tags = [table]
|
|
151
|
+
create_handler._swagger_example = example_body
|
|
117
152
|
Router.add("POST", base_path, create_handler)
|
|
118
153
|
generated.append({"method": "POST", "path": base_path, "table": table})
|
|
119
154
|
|
|
@@ -143,6 +178,9 @@ class AutoCrud:
|
|
|
143
178
|
update_handler.__name__ = f"autocrud_update_{table}"
|
|
144
179
|
update_handler.__qualname__ = f"autocrud_update_{table}"
|
|
145
180
|
update_handler._noauth = True
|
|
181
|
+
update_handler._swagger_summary = f"Update {pretty_name}"
|
|
182
|
+
update_handler._swagger_tags = [table]
|
|
183
|
+
update_handler._swagger_example = example_body
|
|
146
184
|
Router.add("PUT", f"{base_path}/{{id}}", update_handler)
|
|
147
185
|
generated.append({"method": "PUT", "path": f"{base_path}/{{id}}", "table": table})
|
|
148
186
|
|
|
@@ -162,6 +200,8 @@ class AutoCrud:
|
|
|
162
200
|
delete_handler.__name__ = f"autocrud_delete_{table}"
|
|
163
201
|
delete_handler.__qualname__ = f"autocrud_delete_{table}"
|
|
164
202
|
delete_handler._noauth = True
|
|
203
|
+
delete_handler._swagger_summary = f"Delete {pretty_name}"
|
|
204
|
+
delete_handler._swagger_tags = [table]
|
|
165
205
|
Router.add("DELETE", f"{base_path}/{{id}}", delete_handler)
|
|
166
206
|
generated.append({"method": "DELETE", "path": f"{base_path}/{{id}}", "table": table})
|
|
167
207
|
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
"use strict";var Tina4=(()=>{var H=Object.defineProperty;var pe=Object.getOwnPropertyDescriptor;var ge=Object.getOwnPropertyNames;var he=Object.prototype.hasOwnProperty;var me=(e,n)=>{for(var t in n)H(e,t,{get:n[t],enumerable:!0})},ye=(e,n,t,o)=>{if(n&&typeof n=="object"||typeof n=="function")for(let r of ge(n))!he.call(e,r)&&r!==t&&H(e,r,{get:()=>n[r],enumerable:!(o=pe(n,r))||o.enumerable});return e};var ve=e=>ye(H({},"__esModule",{value:!0}),e);var Ae={};me(Ae,{Tina4Element:()=>I,api:()=>ie,batch:()=>q,computed:()=>z,effect:()=>m,html:()=>X,isSignal:()=>w,navigate:()=>L,pwa:()=>le,route:()=>oe,router:()=>re,signal:()=>h,ws:()=>ue});var C=null,_=null,M=null;function b(e){M=e}function J(){return M}var B=null,V=null;var N=0,P=new Set;function h(e,n){let t=e,o=new Set,r={_t4:!0,get value(){if(C&&(o.add(C),_)){let a=C;_.push(()=>o.delete(a))}return t},set value(a){if(Object.is(a,t))return;let i=t;if(t=a,r._debugInfo&&r._debugInfo.updateCount++,V&&V(r,i,a),N>0)for(let s of o)P.add(s);else{let s;for(let c of[...o])try{c()}catch(l){s===void 0&&(s=l)}if(s!==void 0)throw s}},_subscribe(a){return o.add(a),()=>{o.delete(a)}},peek(){return t}};return B&&(r._debugInfo={label:n,createdAt:Date.now(),updateCount:0,subs:o},B(r,n)),r}function z(e){let n=h(void 0);return m(()=>{n.value=e()}),{_t4:!0,get value(){return n.value},set value(t){throw new Error("[tina4] computed signals are read-only")},_subscribe(t){return n._subscribe(t)},peek(){return n.peek()}}}function m(e){let n=!1,t=[],o=()=>{if(n)return;for(let s of t)s();t=[];let a=C,i=_;C=o,_=t;try{e()}finally{C=a,_=i}};o();let r=()=>{n=!0;for(let a of t)a();t=[]};return M&&M.push(r),r}function q(e){N++;try{e()}finally{if(N--,N===0){let n=[...P];P.clear();let t;for(let o of n)try{o()}catch(r){t===void 0&&(t=r)}if(t!==void 0)throw t}}}function w(e){return e!==null&&typeof e=="object"&&e._t4===!0}var Q=new WeakMap,D="t4:";function X(e,...n){let t=Q.get(e);if(!t){t=document.createElement("template");let i="";for(let s=0;s<e.length;s++)i+=e[s],s<n.length&&(Te(i)?i+=`__t4_${s}__`:i+=`<!--${D}${s}-->`);t.innerHTML=i,Q.set(e,t)}let o=t.content.cloneNode(!0),r=be(o);for(let{marker:i,index:s}of r)ke(i,n[s]);let a=we(o);for(let i of a)Ce(i,n);return o}function be(e){let n=[];return W(e,t=>{if(t.nodeType===8){let o=t.data;if(o&&o.startsWith(D)){let r=parseInt(o.slice(D.length),10);n.push({marker:t,index:r})}}}),n}function we(e){let n=[];return W(e,t=>{t.nodeType===1&&n.push(t)}),n}function W(e,n){let t=e.childNodes;for(let o=0;o<t.length;o++){let r=t[o];n(r),W(r,n)}}function ke(e,n){let t=e.parentNode;if(t)if(w(n)){let o=document.createTextNode("");t.replaceChild(o,e),m(()=>{o.data=String(n.value??"")})}else if(typeof n=="function"){let o=document.createComment("");t.replaceChild(o,e);let r=[],a=[];m(()=>{for(let d of a)d();a=[];let i=[],s=J();b(i);let c=n();b(s),a=i;for(let d of r)d.parentNode?.removeChild(d);r=[];let l=F(c),f=o.parentNode;if(f)for(let d of l)f.insertBefore(d,o),r.push(d)})}else if(Y(n))t.replaceChild(n,e);else if(n instanceof Node)t.replaceChild(n,e);else if(Array.isArray(n)){let o=document.createDocumentFragment();for(let r of n){let a=F(r);for(let i of a)o.appendChild(i)}t.replaceChild(o,e)}else{let o=document.createTextNode(String(n??""));t.replaceChild(o,e)}}function Ce(e,n){let t=[];for(let o of Array.from(e.attributes)){let r=o.name,a=o.value;if(r.startsWith("@")){let s=r.slice(1),c=a.match(/__t4_(\d+)__/);if(c){let l=n[parseInt(c[1],10)];typeof l=="function"&&e.addEventListener(s,f=>q(()=>l(f)))}t.push(r);continue}if(r.startsWith("?")){let s=r.slice(1),c=a.match(/__t4_(\d+)__/);if(c){let l=n[parseInt(c[1],10)];if(w(l)){let f=l;m(()=>{f.value?e.setAttribute(s,""):e.removeAttribute(s)})}else typeof l=="function"?m(()=>{l()?e.setAttribute(s,""):e.removeAttribute(s)}):l&&e.setAttribute(s,"")}t.push(r);continue}if(r.startsWith(".")){let s=r.slice(1),c=a.match(/__t4_(\d+)__/);if(c){let l=n[parseInt(c[1],10)];w(l)?m(()=>{e[s]=l.value}):e[s]=l}t.push(r);continue}let i=a.match(/__t4_(\d+)__/);if(i){let s=n[parseInt(i[1],10)];if(w(s)){let c=s;m(()=>{e.setAttribute(r,String(c.value??""))})}else typeof s=="function"?m(()=>{e.setAttribute(r,String(s()??""))}):e.setAttribute(r,String(s??""))}}for(let o of t)e.removeAttribute(o)}function F(e){if(e==null||e===!1)return[];if(Y(e))return Array.from(e.childNodes);if(e instanceof Node)return[e];if(Array.isArray(e)){let n=[];for(let t of e)n.push(...F(t));return n}return[document.createTextNode(String(e))]}function Y(e){return e!=null&&typeof e=="object"&&e.nodeType===11}function Te(e){let n=!1,t=!1,o=!1;for(let r=0;r<e.length;r++){let a=e[r];a==="<"&&!n&&!t&&(o=!0),a===">"&&!n&&!t&&(o=!1),o&&(a==='"'&&!n&&(t=!t),a==="'"&&!t&&(n=!n))}return o}var Z=null,ee=null;var I=class extends HTMLElement{constructor(){super();this._props={};this._rendered=!1;let t=this.constructor;this._root=t.shadow?this.attachShadow({mode:"open"}):this;for(let[o,r]of Object.entries(t.props))this._props[o]=h(this._coerce(this.getAttribute(o),r))}static{this.props={}}static{this.styles=""}static{this.shadow=!0}static get observedAttributes(){return Object.keys(this.props)}connectedCallback(){if(this._rendered)return;this._rendered=!0;let t=this.constructor;if(t.styles&&t.shadow&&this._root instanceof ShadowRoot){let r=document.createElement("style");r.textContent=t.styles,this._root.appendChild(r)}let o=this.render();o&&this._root.appendChild(o),this.onMount(),Z&&Z(this)}disconnectedCallback(){this.onUnmount(),ee&&ee(this)}attributeChangedCallback(t,o,r){let i=this.constructor.props[t];i&&this._props[t]&&(this._props[t].value=this._coerce(r,i))}prop(t){if(!this._props[t])throw new Error(`[tina4] Prop '${t}' not declared in static props of <${this.tagName.toLowerCase()}>`);return this._props[t]}emit(t,o){this.dispatchEvent(new CustomEvent(t,{bubbles:!0,composed:!0,...o}))}onMount(){}onUnmount(){}_coerce(t,o){return o===Boolean?t!==null:o===Number?t!==null?Number(t):0:t??""}};var U=[],T=null,S="history",_e=!1,E=[],O=[],te=0;function oe(e,n){let t=[],o;e==="*"?o=".*":o=e.replace(/\{(\w+)\}/g,(a,i)=>(t.push(i),"([^/]+)"));let r=new RegExp(`^${o}$`);typeof n=="function"?U.push({pattern:e,regex:r,paramNames:t,handler:n}):U.push({pattern:e,regex:r,paramNames:t,handler:n.handler,guard:n.guard})}function L(e,n){if(S==="hash")if(n?.replace){let t=new URL(location.href);t.hash="#"+e,history.replaceState(null,"",t.toString()),R()}else location.hash="#"+e;else n?.replace?history.replaceState(null,"",e):history.pushState(null,"",e),R()}function R(){if(!T)return;let e=performance.now(),n=++te,t=S==="hash"?location.hash.slice(1)||"/":location.pathname;for(let o of U){let r=t.match(o.regex);if(!r)continue;let a={};if(o.paramNames.forEach((c,l)=>{a[c]=decodeURIComponent(r[l+1])}),o.guard){let c=o.guard();if(c===!1)return;if(typeof c=="string"){L(c,{replace:!0});return}}for(let c of O)c();O=[],T.innerHTML="";let i=[];b(i);let s=o.handler(a);if(s instanceof Promise)s.then(c=>{if(b(null),n!==te){for(let f of i)f();return}ne(T,c),O=i;let l=performance.now()-e;for(let f of E)f({path:t,params:a,pattern:o.pattern,durationMs:l})});else{b(null),ne(T,s),O=i;let c=performance.now()-e;for(let l of E)l({path:t,params:a,pattern:o.pattern,durationMs:c})}return}}function ne(e,n){n instanceof DocumentFragment||n instanceof Node?e.replaceChildren(n):typeof n=="string"?e.innerHTML=n:n!=null&&e.replaceChildren(document.createTextNode(String(n)))}var re={start(e){if(T=document.querySelector(e.target),!T)throw new Error(`[tina4] Router target '${e.target}' not found in DOM`);S=e.mode??"history",_e=!0,window.addEventListener("popstate",R),S==="hash"&&window.addEventListener("hashchange",R),document.addEventListener("click",n=>{if(n.metaKey||n.ctrlKey||n.shiftKey||n.altKey)return;let t=n.target.closest("a[href]");if(!t||t.origin!==location.origin||t.hasAttribute("target")||t.hasAttribute("download")||t.getAttribute("rel")?.includes("external"))return;n.preventDefault();let o=S==="hash"?t.getAttribute("href"):t.pathname;L(o)}),R()},on(e,n){return E.push(n),()=>{let t=E.indexOf(n);t>=0&&E.splice(t,1)}}};var y={baseUrl:"",auth:!1,tokenKey:"tina4_token",headers:{}},j=[],K=[],Se=0;function se(){try{return localStorage.getItem(y.tokenKey)}catch{return null}}function Ee(e){try{localStorage.setItem(y.tokenKey,e)}catch{}}async function x(e,n,t,o){let r={method:e,headers:{"Content-Type":"application/json",...y.headers}};if(y.auth){let d=se();d&&(r.headers.Authorization=`Bearer ${d}`)}if(t!==void 0&&e!=="GET"){let d=typeof t=="object"&&t!==null?{...t}:t;if(y.auth&&typeof d=="object"&&d!==null){let p=se();p&&(d.formToken=p)}r.body=JSON.stringify(d)}if(o?.headers&&Object.assign(r.headers,o.headers),o?.params){let d=Object.entries(o.params).map(([p,v])=>`${encodeURIComponent(p)}=${encodeURIComponent(String(v))}`).join("&");n+=(n.includes("?")?"&":"?")+d}let a=y.baseUrl+n;r._url=a,r._requestId=++Se;for(let d of j){let p=d(r);p&&(r=p)}let i=await fetch(a,r),s=i.headers.get("FreshToken");s&&Ee(s);let c=i.headers.get("Content-Type")??"",l;c.includes("json")?l=await i.json():l=await i.text();let f={status:i.status,data:l,ok:i.ok,headers:i.headers,_requestId:r._requestId};for(let d of K){let p=d(f);p&&(f=p)}if(!i.ok)throw f;return f.data}var ie={configure(e){Object.assign(y,e)},get(e,n){return x("GET",e,void 0,n)},post(e,n,t){return x("POST",e,n,t)},put(e,n,t){return x("PUT",e,n,t)},patch(e,n,t){return x("PATCH",e,n,t)},delete(e,n){return x("DELETE",e,void 0,n)},intercept(e,n){e==="request"?j.push(n):K.push(n)},_reset(){y.baseUrl="",y.auth=!1,y.tokenKey="tina4_token",y.headers={},j.length=0,K.length=0}};function ae(e){let n=e.cacheStrategy??"network-first",t=JSON.stringify(e.precache??[]),o=e.offlineRoute?`'${e.offlineRoute}'`:"null";return`
|
|
2
|
+
const CACHE = 'tina4-v1';
|
|
3
|
+
const PRECACHE = ${t};
|
|
4
|
+
const OFFLINE = ${o};
|
|
5
|
+
|
|
6
|
+
self.addEventListener('install', (e) => {
|
|
7
|
+
e.waitUntil(
|
|
8
|
+
caches.open(CACHE).then((c) => c.addAll(PRECACHE)).then(() => self.skipWaiting())
|
|
9
|
+
);
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
self.addEventListener('activate', (e) => {
|
|
13
|
+
e.waitUntil(self.clients.claim());
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
self.addEventListener('fetch', (e) => {
|
|
17
|
+
const req = e.request;
|
|
18
|
+
if (req.method !== 'GET') return;
|
|
19
|
+
|
|
20
|
+
${n==="cache-first"?`
|
|
21
|
+
e.respondWith(
|
|
22
|
+
caches.match(req).then((cached) => cached || fetch(req).then((res) => {
|
|
23
|
+
const clone = res.clone();
|
|
24
|
+
caches.open(CACHE).then((c) => c.put(req, clone));
|
|
25
|
+
return res;
|
|
26
|
+
})).catch(() => OFFLINE ? caches.match(OFFLINE) : new Response('Offline', { status: 503 }))
|
|
27
|
+
);`:n==="stale-while-revalidate"?`
|
|
28
|
+
e.respondWith(
|
|
29
|
+
caches.match(req).then((cached) => {
|
|
30
|
+
const fetched = fetch(req).then((res) => {
|
|
31
|
+
caches.open(CACHE).then((c) => c.put(req, res.clone()));
|
|
32
|
+
return res;
|
|
33
|
+
});
|
|
34
|
+
return cached || fetched;
|
|
35
|
+
}).catch(() => OFFLINE ? caches.match(OFFLINE) : new Response('Offline', { status: 503 }))
|
|
36
|
+
);`:`
|
|
37
|
+
e.respondWith(
|
|
38
|
+
fetch(req).then((res) => {
|
|
39
|
+
const clone = res.clone();
|
|
40
|
+
caches.open(CACHE).then((c) => c.put(req, clone));
|
|
41
|
+
return res;
|
|
42
|
+
}).catch(() => caches.match(req).then((cached) =>
|
|
43
|
+
cached || (OFFLINE ? caches.match(OFFLINE) : new Response('Offline', { status: 503 }))
|
|
44
|
+
))
|
|
45
|
+
);`}
|
|
46
|
+
});
|
|
47
|
+
`.trim()}function ce(e){let n={name:e.name,short_name:e.shortName??e.name,start_url:"/",display:e.display??"standalone",background_color:e.backgroundColor??"#ffffff",theme_color:e.themeColor??"#000000"};return e.icon&&(n.icons=[{src:e.icon,sizes:"192x192",type:"image/png"},{src:e.icon,sizes:"512x512",type:"image/png"}]),n}var le={register(e){let n=ce(e),t=new Blob([JSON.stringify(n)],{type:"application/json"}),o=document.createElement("link");o.rel="manifest",o.href=URL.createObjectURL(t),document.head.appendChild(o);let r=document.querySelector('meta[name="theme-color"]');if(r||(r=document.createElement("meta"),r.name="theme-color",document.head.appendChild(r)),r.content=e.themeColor??"#000000","serviceWorker"in navigator){let a=ae(e),i=new Blob([a],{type:"text/javascript"}),s=URL.createObjectURL(i);navigator.serviceWorker.register(s).catch(c=>{console.warn("[tina4] Service worker registration failed:",c)})}},generateServiceWorker(e){return ae(e)},generateManifest(e){return ce(e)}};var Re={reconnect:!0,reconnectDelay:1e3,reconnectMaxDelay:3e4,reconnectAttempts:1/0,protocols:[]};function xe(e,n={}){let t={...Re,...n},o=h("connecting"),r=h(!1),a=h(null),i=h(null),s=h(0),c={message:[],open:[],close:[],error:[]},l=null,f=!1,d=t.reconnectDelay,p=null,v=0;function de(u){if(typeof u!="string")return u;try{return JSON.parse(u)}catch{return u}}function $(){o.value=v>0?"reconnecting":"connecting";try{l=new WebSocket(e,t.protocols)}catch{o.value="closed",r.value=!1;return}l.onopen=()=>{o.value="open",r.value=!0,i.value=null,v=0,d=t.reconnectDelay,s.value=0;for(let u of c.open)u()},l.onmessage=u=>{let g=de(u.data);a.value=g;for(let k of c.message)k(g)},l.onclose=u=>{o.value="closed",r.value=!1;for(let g of c.close)g(u.code,u.reason);!f&&t.reconnect&&v<t.reconnectAttempts&&fe()},l.onerror=u=>{i.value=u;for(let g of c.error)g(u)}}function fe(){v++,s.value=v,o.value="reconnecting",p=setTimeout(()=>{p=null,$()},d),d=Math.min(d*2,t.reconnectMaxDelay)}let G={status:o,connected:r,lastMessage:a,error:i,reconnectCount:s,send(u){if(!l||l.readyState!==WebSocket.OPEN)throw new Error("[tina4] WebSocket is not connected");let g=typeof u=="string"?u:JSON.stringify(u);l.send(g)},on(u,g){return c[u].push(g),()=>{let k=c[u],A=k.indexOf(g);A>=0&&k.splice(A,1)}},pipe(u,g){let k=A=>{u.value=g(A,u.value)};return G.on("message",k)},close(u,g){f=!0,p&&(clearTimeout(p),p=null),l&&l.close(u??1e3,g??""),o.value="closed",r.value=!1}};return $(),G}var ue={connect:xe};return ve(Ae);})();
|
|
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
|
|
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
|
|
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
|
|
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
|
|
File without changes
|
|
File without changes
|
{tina4_python-3.3.0 → tina4_python-3.5.0}/tina4_python/gallery/auth/src/routes/api/gallery_auth.py
RENAMED
|
File without changes
|
|
File without changes
|
{tina4_python-3.3.0 → tina4_python-3.5.0}/tina4_python/gallery/database/src/routes/api/gallery_db.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{tina4_python-3.3.0 → tina4_python-3.5.0}/tina4_python/gallery/queue/src/routes/api/gallery_queue.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{tina4_python-3.3.0 → tina4_python-3.5.0}/tina4_python/gallery/templates/src/routes/gallery_page.py
RENAMED
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{tina4_python-3.3.0 → tina4_python-3.5.0}/tina4_python/templates/docker/distroless/Dockerfile
RENAMED
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{tina4_python-3.3.0 → tina4_python-3.5.0}/tina4_python/translations/af/LC_MESSAGES/messages.mo
RENAMED
|
File without changes
|
{tina4_python-3.3.0 → tina4_python-3.5.0}/tina4_python/translations/af/LC_MESSAGES/messages.po
RENAMED
|
File without changes
|
{tina4_python-3.3.0 → tina4_python-3.5.0}/tina4_python/translations/en/LC_MESSAGES/messages.mo
RENAMED
|
File without changes
|
{tina4_python-3.3.0 → tina4_python-3.5.0}/tina4_python/translations/en/LC_MESSAGES/messages.po
RENAMED
|
File without changes
|
{tina4_python-3.3.0 → tina4_python-3.5.0}/tina4_python/translations/es/LC_MESSAGES/messages.mo
RENAMED
|
File without changes
|
{tina4_python-3.3.0 → tina4_python-3.5.0}/tina4_python/translations/es/LC_MESSAGES/messages.po
RENAMED
|
File without changes
|
{tina4_python-3.3.0 → tina4_python-3.5.0}/tina4_python/translations/fr/LC_MESSAGES/messages.mo
RENAMED
|
File without changes
|
{tina4_python-3.3.0 → tina4_python-3.5.0}/tina4_python/translations/fr/LC_MESSAGES/messages.po
RENAMED
|
File without changes
|
{tina4_python-3.3.0 → tina4_python-3.5.0}/tina4_python/translations/ja/LC_MESSAGES/messages.mo
RENAMED
|
File without changes
|
{tina4_python-3.3.0 → tina4_python-3.5.0}/tina4_python/translations/ja/LC_MESSAGES/messages.po
RENAMED
|
File without changes
|
{tina4_python-3.3.0 → tina4_python-3.5.0}/tina4_python/translations/zh/LC_MESSAGES/messages.mo
RENAMED
|
File without changes
|
{tina4_python-3.3.0 → tina4_python-3.5.0}/tina4_python/translations/zh/LC_MESSAGES/messages.po
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|