ApiLogicServer 15.0.47__py3-none-any.whl → 15.0.54__py3-none-any.whl

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.
Files changed (123) hide show
  1. api_logic_server_cli/api_logic_server.py +18 -5
  2. api_logic_server_cli/api_logic_server_info.yaml +3 -3
  3. api_logic_server_cli/cli.py +20 -16
  4. api_logic_server_cli/create_from_model/api_logic_server_utils.py +10 -1
  5. api_logic_server_cli/manager.py +24 -13
  6. api_logic_server_cli/prototypes/base/.github/.copilot-instructions.md +39 -3
  7. api_logic_server_cli/prototypes/base/config/config.py +15 -0
  8. api_logic_server_cli/prototypes/base/database/alembic/alembic_run.py +98 -0
  9. api_logic_server_cli/prototypes/base/database/alembic/readme_alembic.md +36 -0
  10. api_logic_server_cli/prototypes/base/docs/training/admin_app_1_context.prompt.md +40 -0
  11. api_logic_server_cli/prototypes/base/integration/mcp/mcp_client_executor.py +2 -2
  12. api_logic_server_cli/prototypes/base/venv_setup/requirements-no-cli.txt +5 -4
  13. api_logic_server_cli/prototypes/basic_demo/_config.yml +8 -0
  14. api_logic_server_cli/prototypes/basic_demo/_layouts/redirect.html +15 -0
  15. api_logic_server_cli/prototypes/basic_demo/docs/system-creation-vibe.md +161 -0
  16. api_logic_server_cli/prototypes/basic_demo/logic/declarative-vs-procedural-comparison.html +110 -0
  17. api_logic_server_cli/prototypes/basic_demo/logic/procedural/declarative-vs-procedural-comparison.md +295 -0
  18. api_logic_server_cli/prototypes/manager/.vscode/settings.json +1 -1
  19. api_logic_server_cli/prototypes/manager/{run_sample.sh → samples/docker_samples/run_sample_docker.sh} +4 -4
  20. api_logic_server_cli/prototypes/manager/samples/docker_samples/run_web_genai.sh +5 -0
  21. api_logic_server_cli/prototypes/manager/samples/prompts/add_email.prompt +8 -0
  22. api_logic_server_cli/prototypes/manager/samples/prompts/elections.prompt +3 -0
  23. api_logic_server_cli/prototypes/manager/samples/prompts/emp_dept.prompt +4 -0
  24. api_logic_server_cli/prototypes/manager/samples/prompts/genai_demo.prompt +13 -0
  25. api_logic_server_cli/prototypes/manager/samples/readme_samples.md +25 -11
  26. api_logic_server_cli/prototypes/manager/system/app_model_editor/venv_setup/requirements-no-cli.txt +5 -4
  27. api_logic_server_cli/prototypes/manager/system/genai/app_templates/app_learning/Admin-App-Resource-Learning-Prompt.md +1 -1
  28. api_logic_server_cli/prototypes/manager/system/genai/app_templates/react-admin-template/package.json +1 -0
  29. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/venv_setup/requirements-no-cli.txt +5 -4
  30. api_logic_server_cli/prototypes/manager/system/install-ApiLogicServer-dev/install-ApiLogicServer-dev.ps1 +7 -3
  31. api_logic_server_cli/prototypes/ont_app/ontimize_seed/package.json +2 -2
  32. api_logic_server_cli/sqlacodegen_wrapper/sqlacodegen/sqlacodegen/codegen.py +4 -2
  33. api_logic_server_cli/sqlacodegen_wrapper/sqlacodegen/sqlacodegen/main.py +25 -5
  34. api_logic_server_cli/sqlacodegen_wrapper/sqlacodegen_wrapper.py +30 -10
  35. {apilogicserver-15.0.47.dist-info → apilogicserver-15.0.54.dist-info}/METADATA +6 -5
  36. {apilogicserver-15.0.47.dist-info → apilogicserver-15.0.54.dist-info}/RECORD +40 -111
  37. api_logic_server_cli/create_from_model/__pycache__/__init__.cpython-312.pyc +0 -0
  38. api_logic_server_cli/create_from_model/__pycache__/api_expose_api_models_creator.cpython-312.pyc +0 -0
  39. api_logic_server_cli/create_from_model/__pycache__/api_logic_server_utils.cpython-312.pyc +0 -0
  40. api_logic_server_cli/create_from_model/__pycache__/create_db_from_model.cpython-312.pyc +0 -0
  41. api_logic_server_cli/create_from_model/__pycache__/dbml.cpython-312.pyc +0 -0
  42. api_logic_server_cli/create_from_model/__pycache__/meta_model.cpython-312.pyc +0 -0
  43. api_logic_server_cli/create_from_model/__pycache__/model_creation_services.cpython-312.pyc +0 -0
  44. api_logic_server_cli/create_from_model/__pycache__/ont_build.cpython-312.pyc +0 -0
  45. api_logic_server_cli/create_from_model/__pycache__/ont_create.cpython-312.pyc +0 -0
  46. api_logic_server_cli/create_from_model/__pycache__/ui_admin_creator.cpython-312.pyc +0 -0
  47. api_logic_server_cli/create_from_model/__pycache__/uri_info.cpython-312.pyc +0 -0
  48. api_logic_server_cli/prototypes/base/.devcontainer-option/.copilot-instructions.md +0 -178
  49. api_logic_server_cli/prototypes/base/database/alembic/readme.md +0 -18
  50. api_logic_server_cli/prototypes/base/database/system/SAFRSBaseX.pyZ +0 -73
  51. api_logic_server_cli/prototypes/basic_demo/customizations/database/system/SAFRSBaseX.py +0 -139
  52. api_logic_server_cli/prototypes/manager/run_web_genai.sh +0 -6
  53. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/__pycache__/api_logic_server_run.cpython-312.pyc +0 -0
  54. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/api/__pycache__/__init__.cpython-312.pyc +0 -0
  55. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/api/__pycache__/customize_api.cpython-312.pyc +0 -0
  56. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/api/__pycache__/expose_api_models.cpython-312.pyc +0 -0
  57. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/api/__pycache__/json_encoder.cpython-312.pyc +0 -0
  58. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/api/api_discovery/__pycache__/auto_discovery.cpython-312.pyc +0 -0
  59. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/api/api_discovery/__pycache__/new_service.cpython-312.pyc +0 -0
  60. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/api/api_discovery/__pycache__/newer_service.cpython-312.pyc +0 -0
  61. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/api/api_discovery/__pycache__/ontimize_api.cpython-312.pyc +0 -0
  62. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/api/api_discovery/__pycache__/system.cpython-312.pyc +0 -0
  63. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/api/system/__pycache__/api_utils.cpython-312.pyc +0 -0
  64. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/api/system/__pycache__/custom_endpoint.cpython-312.pyc +0 -0
  65. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/api/system/__pycache__/expression_parser.cpython-312.pyc +0 -0
  66. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/api/system/__pycache__/gen_csv_report.cpython-312.pyc +0 -0
  67. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/api/system/__pycache__/gen_pdf_report.cpython-312.pyc +0 -0
  68. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/api/system/opt_locking/__pycache__/opt_locking.cpython-312.pyc +0 -0
  69. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/config/__pycache__/__init__.cpython-312.pyc +0 -0
  70. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/config/__pycache__/activate_logicbank.cpython-312.pyc +0 -0
  71. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/config/__pycache__/config.cpython-312.pyc +0 -0
  72. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/config/__pycache__/server_setup.cpython-312.pyc +0 -0
  73. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/database/__pycache__/__init__.cpython-312.pyc +0 -0
  74. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/database/__pycache__/bind_dbs.cpython-312.pyc +0 -0
  75. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/database/__pycache__/customize_models.cpython-312.pyc +0 -0
  76. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/database/__pycache__/models.cpython-312.pyc +0 -0
  77. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/database/alembic/__pycache__/env.cpython-312.pyc +0 -0
  78. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/database/database_discovery/__pycache__/authentication_models.cpython-312.pyc +0 -0
  79. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/database/database_discovery/__pycache__/auto_discovery.cpython-312.pyc +0 -0
  80. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/database/db_debug/__pycache__/db_debug.cpython-312.pyc +0 -0
  81. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/database/system/__pycache__/SAFRSBaseX.cpython-312.pyc +0 -0
  82. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/database/test_data/__pycache__/alp_init.cpython-312.pyc +0 -0
  83. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/database/test_data/__pycache__/response2code.cpython-312.pyc +0 -0
  84. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/database/test_data/__pycache__/test_data_preamble.cpython-312.pyc +0 -0
  85. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/devops/keycloak/unused/__pycache__/auth_provider.cpython-312.pyc +0 -0
  86. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/devops/python-anywhere/__pycache__/python_anywhere_wsgi.cpython-312.pyc +0 -0
  87. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/integration/kafka/__pycache__/kafka_consumer.cpython-312.pyc +0 -0
  88. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/integration/kafka/__pycache__/kafka_producer.cpython-312.pyc +0 -0
  89. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/integration/n8n/__pycache__/n8n_producer.cpython-312.pyc +0 -0
  90. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/integration/system/__pycache__/FlaskKafka.cpython-312.pyc +0 -0
  91. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/integration/system/__pycache__/RowDictMapper.cpython-312.pyc +0 -0
  92. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/logic/__pycache__/declare_logic.cpython-312.pyc +0 -0
  93. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/logic/__pycache__/load_verify_rules.cpython-312.pyc +0 -0
  94. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/logic/logic_discovery/__pycache__/auto_discovery.cpython-312.pyc +0 -0
  95. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/security/__pycache__/__init__.cpython-312.pyc +0 -0
  96. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/security/__pycache__/declare_security.cpython-312.pyc +0 -0
  97. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/security/authentication_provider/__pycache__/__init__.cpython-312.pyc +0 -0
  98. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/security/authentication_provider/__pycache__/abstract_authentication_provider.cpython-312.pyc +0 -0
  99. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/security/authentication_provider/keycloak/__pycache__/auth_provider.cpython-312.pyc +0 -0
  100. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/security/authentication_provider/memory/__pycache__/auth_provider.cpython-312.pyc +0 -0
  101. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/security/authentication_provider/memory/__pycache__/auth_provider_no_swagger.cpython-312.pyc +0 -0
  102. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/security/authentication_provider/sql/__pycache__/auth_provider.cpython-312.pyc +0 -0
  103. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/security/system/__pycache__/authentication.cpython-312.pyc +0 -0
  104. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/security/system/__pycache__/authorization.cpython-312.pyc +0 -0
  105. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/test/__pycache__/__init__.cpython-312.pyc +0 -0
  106. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/test/api_logic_server_behave/__pycache__/__init__.cpython-312.pyc +0 -0
  107. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/test/api_logic_server_behave/__pycache__/behave_logic_report.cpython-312.pyc +0 -0
  108. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/test/api_logic_server_behave/__pycache__/behave_run.cpython-312.pyc +0 -0
  109. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/test/api_logic_server_behave/features/steps/__pycache__/about.cpython-312.pyc +0 -0
  110. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/test/api_logic_server_behave/features/steps/__pycache__/test_utils.cpython-312.pyc +0 -0
  111. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/test/basic/__pycache__/server_test.cpython-312.pyc +0 -0
  112. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/ui/__pycache__/__init__.cpython-312.pyc +0 -0
  113. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/ui/admin/__pycache__/admin_loader.cpython-312.pyc +0 -0
  114. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/venv_setup/__pycache__/py.cpython-312.pyc +0 -0
  115. api_logic_server_cli/sqlacodegen_wrapper/__pycache__/__init__.cpython-312.pyc +0 -0
  116. api_logic_server_cli/sqlacodegen_wrapper/__pycache__/sqlacodegen_wrapper.cpython-312.pyc +0 -0
  117. api_logic_server_cli/sqlacodegen_wrapper/sqlacodegen/__pycache__/__init__.cpython-312.pyc +0 -0
  118. api_logic_server_cli/sqlacodegen_wrapper/sqlacodegen/sqlacodegen/__pycache__/__init__.cpython-312.pyc +0 -0
  119. api_logic_server_cli/sqlacodegen_wrapper/sqlacodegen/sqlacodegen/__pycache__/codegen.cpython-312.pyc +0 -0
  120. {apilogicserver-15.0.47.dist-info → apilogicserver-15.0.54.dist-info}/WHEEL +0 -0
  121. {apilogicserver-15.0.47.dist-info → apilogicserver-15.0.54.dist-info}/entry_points.txt +0 -0
  122. {apilogicserver-15.0.47.dist-info → apilogicserver-15.0.54.dist-info}/licenses/LICENSE +0 -0
  123. {apilogicserver-15.0.47.dist-info → apilogicserver-15.0.54.dist-info}/top_level.txt +0 -0
@@ -1,178 +0,0 @@
1
- # GitHub Copilot Instructions for GenAI-Logic (aka API Logic Server) Projects
2
-
3
- ## Project Type: Auto-Generated Microservice
4
-
5
- This is a **GenAI-Logic (aka API Logic Server) project** - a complete, working microservice - auto-generated from a database schema.
6
-
7
- ## ⚠️ IMPORTANT: What's Already Built
8
-
9
- **DO NOT recreate these - they're already working:**
10
-
11
- 1. **Admin Web Application** - Live at `http://localhost:5656`
12
- 2. **REST API Endpoints** - All database tables exposed at `/api/*`
13
- 3. **Database Models** - Complete SQLAlchemy ORM in `database/models.py`
14
- 4. **Authentication System** - JWT-based auth framework
15
- 5. **Business Logic Engine** - Declarative rules system
16
-
17
- ## 🎯 Common Tasks
18
-
19
- If the user asks "what do I do now?", these subsections are good suggestions.
20
-
21
- List these as choices, do not just do all of them at once - that would be overwhelming.
22
-
23
- ### 🚀 To Run This Project
24
-
25
- Use F5 (pre-configured run configuration - supports debugger for server logic), or (when focused on client apps):
26
-
27
- ```bash
28
- python api_logic_server_run.py
29
- # Then open: http://localhost:5656
30
- ```
31
-
32
- ### Adding Business Logic
33
- Use `docs/training` to accept Natural Language logic, and translate it into rules like:
34
-
35
- ```python
36
- # Edit: logic/declare_logic.py
37
- Rule.sum(derive=Customer.Balance, as_sum_of=Order.AmountTotal)
38
- Rule.constraint(validate=Customer, as_condition=lambda row: row.Balance <= row.CreditLimit)
39
- ```
40
-
41
- Generally CoPilot solicits Natural Language logic for translation (see logic/logic_discovery/readme_logic_discovery.md),
42
- but you can also offer to suggest rules.
43
-
44
- ### Adding MCP
45
-
46
- The API is automatically MCP-enabled.
47
-
48
- To add MCP Client (requires OpenAI key):
49
-
50
- ```bash
51
- # Add MCP Client
52
- genai-logic genai-add-mcp-client
53
- ```
54
-
55
- ### Configuring Admin UI
56
-
57
- This is built when project is created - no need to add it.
58
- Customize by editing the underlying yaml.
59
-
60
- ```yaml
61
- # Edit: ui/admin/admin.yaml
62
- resources:
63
- Customer:
64
- attributes:
65
- - name: CompanyName
66
- search: true
67
- sort: true
68
- ```
69
-
70
- ### Create and Customize React Apps
71
-
72
- Complete customization is provided by generating a React Application (requires OpenAI key, Node):
73
-
74
- ```bash
75
- # Create: ui/admin/my-app-name
76
- genai-logic genai-add-app --app-name=my-app-name --vibe
77
- ```
78
-
79
- Then, `npm install` and `npm start`
80
-
81
- Temporary restriction: security must be disabled.
82
-
83
- Customize using CoPilot chat, with `docs/training`.
84
-
85
- ### Security - Role-Based Access Control
86
-
87
- Configure:
88
- ```
89
- als add-auth --provider-type=sql --db-url=
90
- als add-auth --provider-type=sql --db_url=postgresql://postgres:p@localhost/authdb
91
-
92
- als add-auth --provider-type=keycloak --db-url=localhost
93
- als add-auth --provider-type=keycloak --db-url=hardened
94
-
95
- als add-auth --provider-type=None # to disable
96
- ```
97
-
98
- Keycloak quick start [(more information here:)](https://apilogicserver.github.io/Docs/Security-Keycloak/)
99
- ```bash
100
- cd devops/keycloak
101
- docker compose up
102
- als add-auth --provider-type=keycloak --db-url=localhost
103
- ```
104
-
105
- For more on KeyCloak: https://apilogicserver.github.io/Docs/Security-Keycloak/
106
-
107
- Declaration:
108
- ```python
109
- # Edit: security/declare_security.py
110
- Grant(on_entity=Customer, to_role=sales, filter=lambda: Customer.SalesRep == current_user())
111
- ```
112
-
113
- ### Adding Custom API Endpoints
114
- ```python
115
- # Edit: api/customize_api.py
116
- @app.route('/api/custom-endpoint')
117
- def my_endpoint():
118
- return {"message": "Custom endpoint"}
119
- ```
120
-
121
- ### Customize Models - Add Derived attributes
122
-
123
- Here is a sample derived attribute, `proper_salary`:
124
-
125
- ```python
126
-
127
- # add derived attribute: https://github.com/thomaxxl/safrs/blob/master/examples/demo_pythonanywhere_com.py
128
- @add_method(models.Employee)
129
- @jsonapi_attr
130
- def __proper_salary__(self): # type: ignore [no-redef]
131
- import database.models as models
132
- import decimal
133
- if isinstance(self, models.Employee):
134
- rtn_value = self.Salary
135
- if rtn_value is None:
136
- rtn_value = decimal.Decimal('0')
137
- rtn_value = decimal.Decimal('1.25') * rtn_value
138
- self._proper_salary = int(rtn_value)
139
- return self._proper_salary
140
- else:
141
- rtn_value = decimal.Decimal('0')
142
- self._proper_salary = int(rtn_value)
143
- return self._proper_salary
144
-
145
- @add_method(models.Employee)
146
- @__proper_salary__.setter
147
- def _proper_salary(self, value): # type: ignore [no-redef]
148
- self._proper_salary = value
149
- print(f'_proper_salary={self._proper_salary}')
150
- pass
151
-
152
- models.Employee.ProperSalary = __proper_salary__
153
-
154
- ```
155
-
156
- When customizing SQLAlchemy models:
157
-
158
- Don't use direct comparisons with database fields in computed properties
159
- Convert to Python values first using float(), int(), str()
160
- Use property() function instead of @jsonapi_attr for computed properties
161
- Always add error handling for type conversions
162
-
163
- ## 📁 Key Directories
164
-
165
- - `logic/` - Business rules (declarative)
166
- - `api/` - REST API customization
167
- - `security/` - Authentication/authorization
168
- - `database/` - Data models and schemas
169
- - `ui/admin/` - Admin interface configuration
170
- - `ui/app/` - Alternative Angular admin app
171
-
172
- ## 💡 Helpful Context
173
-
174
- - This uses Flask + SQLAlchemy + SAFRS for JSON:API
175
- - Admin UI is React-based with automatic CRUD generation
176
- - Business logic uses LogicBank (declarative rule engine)
177
- - Everything is auto-generated from database introspection
178
- - Focus on CUSTOMIZATION, not re-creation
@@ -1,18 +0,0 @@
1
- The diagram below illustrates a simple path for enacting changes to the data model, and using [Alembic](https://alembic.sqlalchemy.org/en/latest/index.html) to automate the database changes:
2
-
3
- 1. Update `database/models.py` (e.g., add columns, tables)
4
- 2. Use alembic to compute the revisions
5
- ```bash
6
- cd database
7
- alembic revision --autogenerate -m "Added Tables and Columns"
8
- ```
9
- 3. Edit the revision file to signify your understanding (see below)
10
- 4. Activate the change
11
- ```bash
12
- alembic upgrade head
13
- ```
14
-
15
- ![alembic example](https://github.com/ApiLogicServer/Docs/blob/main/docs/images/database/alembic/alembic-overview.png?raw=true)
16
-
17
-
18
- Then, run `rebuild-from-model`. For more information, see [Database Design Changes](https://apilogicserver.github.io/Docs/Database-Changes/).
@@ -1,73 +0,0 @@
1
- from sqlalchemy.ext.declarative import declarative_base
2
- from sqlalchemy import Column, DECIMAL, Date, ForeignKey, Integer, String
3
- from safrs import SAFRSBase
4
- from flask_login import UserMixin
5
- import safrs, flask_sqlalchemy
6
- from safrs import jsonapi_attr
7
- from flask_sqlalchemy import SQLAlchemy
8
- from datetime import datetime
9
-
10
- Base = declarative_base() # type: flask_sqlalchemy.model.DefaultMeta
11
- #vh new x
12
- @classmethod
13
- def jsonapi_filter(cls):
14
- """
15
- Use this to override SAFRS JSON:API filtering
16
-
17
- Returns:
18
- _type_: SQLAlchemy query filter
19
- """
20
- from sqlalchemy import text, or_, and_
21
- from flask import request
22
- expressions = []
23
- sqlWhere = ""
24
- query = cls._s_query
25
- if args := request.args:
26
- from api.system.expression_parser import advancedFilter
27
- expressions, sqlWhere = advancedFilter(cls, args)
28
- if sqlWhere != "":
29
- return query.filter(text(sqlWhere))
30
- else:
31
- return query.filter(or_(*expressions))
32
-
33
- class SAFRSBaseX(SAFRSBase, safrs.DB.Model):
34
- __abstract__ = True
35
- if do_enable_ont_advanced_filters := False:
36
- jsonapi_filter = jsonapi_filter
37
-
38
- def _s_parse_attr_value(self, attr_name: str, attr_val: any):
39
- """
40
- Parse the given jsonapi attribute value so it can be stored in the db
41
- :param attr_name: attribute name
42
- :param attr_val: attribute value
43
- :return: parsed value
44
- """
45
- attr = self.__class__._s_jsonapi_attrs.get(attr_name, None)
46
- if hasattr(attr, "type"): # pragma: no cover
47
-
48
- if str(attr.type) in ["DATE", "DATETIME"] and attr_val:
49
- try:
50
- attr_val = attr_val.replace("T", " ")
51
- datetime.strptime(attr_val, '%Y-%m-%d %H:%M')
52
- attr_val += ":00"
53
- except ValueError:
54
- pass
55
- except Exception as exc:
56
- safrs.log.warning(exc)
57
-
58
-
59
- return super()._s_parse_attr_value(attr_name, attr_val)
60
-
61
- class TestBase(Base):
62
- __abstract__ = True
63
- def __init__(self, *args, **kwargs):
64
- for name, val in kwargs.items():
65
- col = getattr(self.__class__, name)
66
- if 'amount_total' == name:
67
- debug_stop = 'stop'
68
- if val is not None:
69
- if str(col.type) in ["DATE", "DATETIME"]:
70
- pass
71
- else:
72
- kwargs[name] = col.type.python_type(val)
73
- return super().__init__(*args, **kwargs)
@@ -1,139 +0,0 @@
1
- import json
2
- from sqlalchemy.ext.declarative import declarative_base
3
- from sqlalchemy import Column, DECIMAL, Date, ForeignKey, Integer, String
4
- from safrs import SAFRSBase, ValidationError
5
- from flask_login import UserMixin
6
- import safrs, flask_sqlalchemy
7
- from safrs import jsonapi_attr
8
- from flask_sqlalchemy import SQLAlchemy
9
- from datetime import datetime
10
- import operator
11
- import json
12
-
13
-
14
- Base = declarative_base() # type: flask_sqlalchemy.model.DefaultMeta
15
- #vh new x
16
- @classmethod
17
- def jsonapi_filter(cls):
18
- """
19
- Use this to override SAFRS JSON:API filtering
20
-
21
- Returns:
22
- _type_: SQLAlchemy query filter
23
- """
24
- from sqlalchemy import text, or_, and_
25
- from flask import request
26
- expressions = []
27
- sqlWhere = ""
28
- query = cls._s_query
29
- if args := request.args:
30
- from api.system.expression_parser import advancedFilter
31
- expressions, sqlWhere = advancedFilter(cls, args)
32
- if sqlWhere != "":
33
- return query.filter(text(sqlWhere))
34
- else:
35
- return query.filter(and_(*expressions))
36
-
37
- class SAFRSBaseX(SAFRSBase, safrs.DB.Model):
38
- __abstract__ = True
39
- if do_enable_ont_advanced_filters := False:
40
- jsonapi_filter = jsonapi_filter
41
-
42
- def _s_parse_attr_value(self, attr_name: str, attr_val: any):
43
- """
44
- Parse the given jsonapi attribute value so it can be stored in the db
45
- :param attr_name: attribute name
46
- :param attr_val: attribute value
47
- :return: parsed value
48
- """
49
- attr = self.__class__._s_jsonapi_attrs.get(attr_name, None)
50
- if hasattr(attr, "type"): # pragma: no cover
51
-
52
- if str(attr.type) in ["DATE", "DATETIME"] and attr_val:
53
- try:
54
- attr_val = attr_val.replace("T", " ")
55
- datetime.strptime(attr_val, '%Y-%m-%d %H:%M')
56
- attr_val += ":00"
57
- except ValueError:
58
- pass
59
- except Exception as exc:
60
- safrs.log.warning(exc)
61
-
62
-
63
- return super()._s_parse_attr_value(attr_name, attr_val)
64
-
65
-
66
- @classmethod
67
- def _s_filter(cls, *filter_args, **filter_kwargs):
68
- """
69
- Apply a filter to this model
70
- :param filter_args: A list of filters information to apply, passed as a request URL parameter.
71
- Each filter object has the following fields:
72
- - name: The name of the field you want to filter on.
73
- - op: The operation you want to use (all sqlalchemy operations are available). The valid values are:
74
- - like: Invoke SQL like (or "ilike", "match", "notilike")
75
- - eq: check if field is equal to something
76
- - ge: check if field is greater than or equal to something
77
- - gt: check if field is greater than to something
78
- - ne: check if field is not equal to something
79
- - is_: check if field is a value
80
- - is_not: check if field is not a value
81
- - le: check if field is less than or equal to something
82
- - lt: check if field is less than to something
83
- - val: The value that you want to compare.
84
- :return: sqla query object
85
- """
86
- try:
87
- filters = json.loads(filter_args[0])
88
- except json.decoder.JSONDecodeError:
89
- raise ValidationError("Invalid filter format (see https://github.com/thomaxxl/safrs/wiki)")
90
-
91
- if not isinstance(filters, list):
92
- filters = [filters]
93
-
94
- expressions = []
95
- query = cls._s_query
96
-
97
- for filt in filters:
98
- if not isinstance(filt, dict):
99
- safrs.log.warning(f"Invalid filter '{filt}'")
100
- continue
101
- attr_name = filt.get("name")
102
- attr_val = filt.get("val")
103
- if attr_name != "id" and attr_name not in cls._s_jsonapi_attrs:
104
- raise ValidationError(f'Invalid filter "{filt}", unknown attribute "{attr_name}"')
105
-
106
- op_name = filt.get("op", "").strip("_")
107
- attr = cls._s_jsonapi_attrs[attr_name] if attr_name != "id" else cls.id
108
- if op_name in ["in", "notin"]:
109
- op = getattr(attr, op_name + "_")
110
- query = query.filter(op(attr_val))
111
- elif op_name in ["like", "ilike", "match", "notilike"] and hasattr(attr, "like"):
112
- # => attr is Column or InstrumentedAttribute
113
- like = getattr(attr, op_name)
114
- expressions.append(like(attr_val))
115
- elif not hasattr(operator, op_name):
116
- raise ValidationError(f'Invalid filter "{filt}", unknown operator "{op_name}"')
117
- else:
118
- op = getattr(operator, op_name)
119
- expressions.append(op(attr, attr_val))
120
-
121
- if len(filters) > 1:
122
- return query.filter(operator.and_(*expressions))
123
- else:
124
- return query.filter(*expressions)
125
-
126
-
127
- class TestBase(Base):
128
- __abstract__ = True
129
- def __init__(self, *args, **kwargs):
130
- for name, val in kwargs.items():
131
- col = getattr(self.__class__, name)
132
- if 'amount_total' == name:
133
- debug_stop = 'stop'
134
- if val is not None:
135
- if str(col.type) in ["DATE", "DATETIME"]:
136
- pass
137
- else:
138
- kwargs[name] = col.type.python_type(val)
139
- return super().__init__(*args, **kwargs)
@@ -1,6 +0,0 @@
1
- # Run WebGenAI from docker container
2
-
3
- # cd genai-logic-main
4
- # sh run_web_genai.sh
5
-
6
- docker compose -f webgenai/docker-compose-webg.yml up