ApiLogicServer 14.5.0__py3-none-any.whl → 14.5.3__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 (49) hide show
  1. api_logic_server_cli/add_cust/add_cust.py +7 -21
  2. api_logic_server_cli/api_logic_server.py +4 -2
  3. api_logic_server_cli/api_logic_server_info.yaml +2 -2
  4. api_logic_server_cli/create_from_model/__pycache__/dbml.cpython-312.pyc +0 -0
  5. api_logic_server_cli/create_from_model/__pycache__/ont_build.cpython-312.pyc +0 -0
  6. api_logic_server_cli/prototypes/basic_demo/customizations/api/api_discovery/{mcp_server_executor.py → mcp_discovery.py} +1 -0
  7. api_logic_server_cli/prototypes/basic_demo/customizations/config/server_setup.py +388 -0
  8. api_logic_server_cli/prototypes/basic_demo/customizations/database/system/SAFRSBaseX.py +136 -0
  9. api_logic_server_cli/prototypes/basic_demo/customizations/integration/mcp/.DS_Store +0 -0
  10. api_logic_server_cli/prototypes/basic_demo/customizations/integration/mcp/README_mcp.md +3 -1
  11. api_logic_server_cli/prototypes/basic_demo/customizations/integration/mcp/mcp_client_executor.py +82 -27
  12. api_logic_server_cli/prototypes/basic_demo/customizations/logic/declare_logic.py +22 -2
  13. api_logic_server_cli/prototypes/basic_demo/iteration/logic/declare_logic.py +1 -1
  14. api_logic_server_cli/prototypes/nw/logic/declare_logic.py +2 -2
  15. api_logic_server_cli/prototypes/nw_no_cust/.obsidian/app.json +1 -0
  16. api_logic_server_cli/prototypes/nw_no_cust/.obsidian/appearance.json +1 -0
  17. api_logic_server_cli/prototypes/nw_no_cust/.obsidian/core-plugins.json +31 -0
  18. api_logic_server_cli/prototypes/nw_no_cust/.obsidian/workspace.json +166 -0
  19. apilogicserver-14.5.3.dist-info/METADATA +168 -0
  20. {apilogicserver-14.5.0.dist-info → apilogicserver-14.5.3.dist-info}/RECORD +24 -42
  21. api_logic_server_cli/prototypes/basic_demo/customizations/api/api_discovery/proper_update_def.json +0 -71
  22. api_logic_server_cli/prototypes/basic_demo/customizations/integration/mcp/1_langchain_loader.py +0 -71
  23. api_logic_server_cli/prototypes/basic_demo/customizations/integration/mcp/2_gpt_mcp_prompt.txt +0 -19
  24. api_logic_server_cli/prototypes/basic_demo/customizations/integration/mcp/multi_mcp_flow/multi_mcp_flow.png +0 -0
  25. api_logic_server_cli/prototypes/basic_demo/customizations/integration/mcp/multi_mcp_flow/multi_mcp_orchestration.yaml +0 -49
  26. api_logic_server_cli/prototypes/basic_demo/customizations/integration/mcp/multi_mcp_flow/wny mcp flows.png +0 -0
  27. api_logic_server_cli/prototypes/basic_demo/customizations/integration/mcp/natlang_to_api.py +0 -73
  28. api_logic_server_cli/prototypes/basic_demo/customizations/integration/mcp/resources/curl.txt +0 -5
  29. api_logic_server_cli/prototypes/basic_demo/customizations/integration/mcp/resources/images/MCP Overview.png +0 -0
  30. api_logic_server_cli/prototypes/basic_demo/customizations/integration/mcp/resources/images/MCP_Arch.png +0 -0
  31. api_logic_server_cli/prototypes/basic_demo/customizations/integration/mcp/resources/images/MCP_Overview_Executor.png +0 -0
  32. api_logic_server_cli/prototypes/basic_demo/customizations/integration/mcp/resources/invoke_llm/1 - prompt_messages_array.json +0 -10
  33. api_logic_server_cli/prototypes/basic_demo/customizations/integration/mcp/resources/invoke_llm/2 - completion_tool_context.json +0 -12
  34. api_logic_server_cli/prototypes/basic_demo/customizations/integration/mcp/resources/llm_schema.txt +0 -38
  35. api_logic_server_cli/prototypes/basic_demo/customizations/integration/mcp/resources/nw_swagger_2.yaml +0 -17393
  36. api_logic_server_cli/prototypes/basic_demo/customizations/integration/mcp/resources/nw_swagger_3.yaml +0 -16660
  37. api_logic_server_cli/prototypes/basic_demo/customizations/integration/mcp/resources/nw_swagger_3_relaxed.yaml +0 -109
  38. api_logic_server_cli/prototypes/basic_demo/customizations/integration/mcp/resources/proxy_server.py +0 -51
  39. api_logic_server_cli/prototypes/basic_demo/customizations/integration/mcp/resources/proxy_serverZ.py +0 -72
  40. api_logic_server_cli/prototypes/basic_demo/customizations/integration/mcp/resources/validate_jsonapi.py +0 -64
  41. api_logic_server_cli/prototypes/basic_demo/customizations/integration/mcp/run_executor.py +0 -23
  42. api_logic_server_cli/prototypes/basic_demo/customizations/integration/mcp/swagger_converter.py +0 -65
  43. api_logic_server_cli/prototypes/basic_demo/customizations/integration/mcp/z_old/3_executor_test_agent.py +0 -52
  44. api_logic_server_cli/prototypes/manager/README_X.md +0 -663
  45. apilogicserver-14.5.0.dist-info/METADATA +0 -76
  46. {apilogicserver-14.5.0.dist-info → apilogicserver-14.5.3.dist-info}/WHEEL +0 -0
  47. {apilogicserver-14.5.0.dist-info → apilogicserver-14.5.3.dist-info}/entry_points.txt +0 -0
  48. {apilogicserver-14.5.0.dist-info → apilogicserver-14.5.3.dist-info}/licenses/LICENSE +0 -0
  49. {apilogicserver-14.5.0.dist-info → apilogicserver-14.5.3.dist-info}/top_level.txt +0 -0
@@ -20,6 +20,7 @@ ToDo - email example is incomplete:
20
20
 
21
21
  import json
22
22
  import os
23
+ import re
23
24
  import openai
24
25
  import requests
25
26
 
@@ -83,16 +84,22 @@ def discover_mcp_servers():
83
84
 
84
85
 
85
86
  def get_user_nl_query():
86
- """ Get the natural language query from the user. """
87
+ """ Get the natural language query from the user.
88
+
89
+ """
87
90
 
88
91
  global test_type
89
- # this doesn't work -- missing commands for mcp_server_executor....
90
- default_request = "List the orders created more than 30 days ago, and post an email message to the order's customer offering a discount"
91
92
 
92
93
  default_request = "List the orders created more than 30 days ago, and send a discount email to the customer for each one."
93
- # date range? curl -X GET "http://localhost:5656/api/Order?filter=[{\’name\'}: {\’CreatedOn\’}, {\’op\’}: {\’gt\’}, {\’val\’}: {\’2022-05-14\’}]
94
+ # eg, curl -qg 'http://localhost:5656/api/Order?filter=[{"name":"date_shipped","op":"gt","val":"2023-07-14"}]'
95
+ # eg, curl -qg 'http://localhost:5656/api/Order?filter=[{"name":"date_shipped","op":"eq","val":null}]'
96
+ # eg, curl -qg 'http://localhost:5656/api/Order?filter=[{"name":"date_shipped","op":"eq","val":null},{"name":"CreatedOn","op":"lt","val":"2023-07-14"}]'
97
+ # eg, curl -qg 'http://localhost:5656/api/Customer?filter=[{"name":"credit_limit","op":"gt","val":"1000"}]'
98
+
99
+ # curl -qg 'http://localhost:5656/api/Order?filter=[{"name":%20"date_shipped",%20"op":%20"eq",%20"val":%20null},%20{"name":%20"CreatedOn",%20"op":%20"lt",%20"val":%20"2023-07-14"}]'
94
100
 
95
101
  default_request = "List the orders for customer 5, and send a discount email to the customer for each one."
102
+ default_request = "List the unshipped orders created before 2023-07-14, and send a discount email to the customer for each one."
96
103
 
97
104
  if test_type != 'orchestration':
98
105
  default_request = "List customers with credit over 1000"
@@ -102,7 +109,7 @@ def get_user_nl_query():
102
109
  query += """
103
110
  Respond with a JSON array of tool context blocks using:
104
111
  - tool: 'json-api'
105
- - JSON:API-compliant filtering (e.g., filter[CreatedOn][lt])
112
+ - JSON:API custom filtering (e.g., filter=[{"name":"date_shipped","op":"gt","val":"2023-07-14"}])
106
113
  - Use {{ order.customer_id }} as a placeholder in the second step.
107
114
  - Include method, url, query_params or body, headers, expected_output.
108
115
  """
@@ -138,26 +145,37 @@ def query_llm_with_nl(nl_query):
138
145
  "method": "GET",
139
146
  "url": "http://localhost:5656/api/Order",
140
147
  "query_params": {
141
- "filter[customer_id]": 5
148
+ "filter": [
149
+ {
150
+ "name": "date_shipped",
151
+ "op": "eq",
152
+ "val": None
153
+ },
154
+ {
155
+ "name": "date_created",
156
+ "op": "lt",
157
+ "val": "2023-07-14"
158
+ }
159
+ ]
142
160
  },
143
161
  "headers": {
144
- "Content-Type": "application/vnd.api+json"
162
+ "Content-Type": "application/json"
145
163
  },
146
- "expected_output": "JSON array of orders for customer 5"
164
+ "expected_output": "JSON array of unshipped orders created before 2023-07-14"
147
165
  },
148
166
  {
149
167
  "tool": "email",
150
168
  "method": "POST",
151
- "url": "http://localhost:5656/api/Email",
169
+ "url": "http://localhost:5656/api/sendEmail",
152
170
  "body": {
153
- "to": "{{ order.customer_id }}",
171
+ "customer_id": "{{ order.customer_id }}",
154
172
  "subject": "Discount Offer",
155
- "message": "Dear Customer, We are offering a discount on your recent orders. Please check your account for more details."
173
+ "message": "You have a new discount offer for your unshipped order."
156
174
  },
157
175
  "headers": {
158
176
  "Content-Type": "application/json"
159
177
  },
160
- "expected_output": "Email sent confirmation"
178
+ "expected_output": "Confirmation of email sent"
161
179
  }
162
180
  ]
163
181
  else: # simple get request - list customers with credit over 4000
@@ -213,26 +231,61 @@ def process_tool_context(tool_context):
213
231
 
214
232
  def get_query_param_filter(query_params):
215
233
  """ return json:api filter
234
+
235
+ see api_logic_server_cli/prototypes/base/api/system/expression_parser.py (doc?)
236
+
237
+ eg
238
+ curl -qg 'http://localhost:5656/api/Order?filter=[{"name":"date_shipped","op":"eq","val":null},{"name":"CreatedOn","op":"gt","val":"2023-07-14"}]'
216
239
 
217
- query_params might be:
240
+ query_params might be simple:
218
241
  "query_params": {
219
242
  "filter[credit_limit][gt]": 1000 }
220
- or:
243
+ ==> ?filter=[{"name":"credit_limit","op":"gt","val":"1000"}]
244
+ or a list:
221
245
  "query_params": {
222
- "filter[customer_id]": 5},
223
-
246
+ "filter": [
247
+ {
248
+ "name": "date_shipped",
249
+ "op": "eq",
250
+ "val": null
251
+ },
252
+ {
253
+ "name": "date_created",
254
+ "op": "lt",
255
+ "val": "2023-07-14"
256
+ }
257
+ ]
258
+ },
224
259
  """
260
+
261
+ added_rows = 0
262
+
225
263
  query_param_filter = ''
226
264
  if isinstance(query_params, dict):
227
- for each_key, each_value in query_params.items():
228
- if isinstance(each_value, dict):
229
- for sub_key, sub_value in each_value.items():
230
- query_param_filter += f"&{each_key}[{sub_key}]={sub_value}"
231
- else:
232
- query_param_filter += f"&{each_key}={each_value}"
265
+ if "filter" not in query_params: # simple - "query_params": {"filter[credit_limit][gt]": 1000 }
266
+ for each_key, each_value in query_params.items():
267
+ assert not isinstance(each_value, dict), "Unexpected dict in simple query_params"
268
+ # convert {"filter[credit_limit][gt]": 1000 } to ?filter=[{"name":"credit_limit","op":"gt","val":"1000"}]
269
+ match = re.match(r"filter\[(\w+)\]\[(\w+)\]", each_key)
270
+ if match:
271
+ name, op = match.groups()
272
+ filter_json = json.dumps([{"name": name, "op": op, "val": str(each_value)}])
273
+ query_param_filter += f"&filter={filter_json}"
274
+ else:
275
+ query_param_filter += f"&{each_key}={each_value}"
276
+
277
+ else: # complex - "query_params": {"filter": ...
278
+ assert isinstance(query_params["filter"], list), "Query Params filter expected to be a list"
279
+ query_param_filter = 'filter=' + str(query_params["filter"])
280
+ # use urlencode to convert to JSON:API format...
281
+ # val urllib.parse.quote() or urllib.parse.urlencode()
282
+ # tool instructions... filtering, email etc
283
+ query_param_filter = query_param_filter.replace("'", '"') # convert single quotes to double quotes
284
+ query_param_filter = query_param_filter.replace("None", 'null')
285
+ query_param_filter = query_param_filter.replace("date_created", 'CreatedOn') # TODO - why this name?
233
286
  # query_params = ''
234
- elif isinstance(query_params, dict):
235
- assert False, "Query Params dict tbd"
287
+ else:
288
+ assert False, "Query Params not a dict"
236
289
  return query_param_filter
237
290
 
238
291
 
@@ -259,12 +312,12 @@ def process_tool_context(tool_context):
259
312
  )
260
313
  context_data = mcp_response.json()['data'] # result rows...
261
314
  elif each_block["method"] in ["POST"]:
262
- add_rows = 0
263
315
  for each_order in context_data:
264
316
  url = each_block["url"]
317
+ url = url.replace("sendEmail", "Email") # TODO name fix
265
318
  json_update_data = { 'data': {"type": "Email", 'attributes': {} } }
266
319
  json_update_data_attributes = json_update_data["data"]["attributes"]
267
- json_update_data_attributes["customer_id"] = context_data[0]['attributes']["customer_id"]
320
+ json_update_data_attributes["customer_id"] = context_data[0]['attributes']["customer_id"] # TODO - fix
268
321
  json_update_data_attributes["message"] = each_block["body"]["message"]
269
322
  # eg: POST http://localhost:5656/api/Email {'data': {'type': 'Email', 'attributes': {'customer_id': 5, 'message': {'to': '{{ order.customer_id }}', 'subject': 'Discount for your order', 'body': 'Dear customer, you have a discount for your recent order. Thank you for shopping with us.'}}}}
270
323
  mcp_response = requests.post(
@@ -272,12 +325,14 @@ def process_tool_context(tool_context):
272
325
  headers=each_block["headers"],
273
326
  json=json_update_data
274
327
  )
275
- add_rows += 1
328
+ added_rows += 1
276
329
  pass
277
330
  else:
278
331
  print("Invalid tool context format. Expected a dictionary or a list.")
279
332
  return None
280
333
  print("\n3. MCP Server (als) Response:\n", mcp_response.text)
334
+ if added_rows > 0:
335
+ print(f"...Added {added_rows} rows to the database; last row (only) shown above.")
281
336
  return mcp_response
282
337
 
283
338
 
@@ -9,6 +9,7 @@ import api.system.opt_locking.opt_locking as opt_locking
9
9
  from security.system.authorization import Grant, Security
10
10
  from logic.load_verify_rules import load_verify_rules
11
11
  import integration.kafka.kafka_producer as kafka_producer
12
+ from integration.n8n.n8n_producer import send_n8n_message
12
13
  import logging
13
14
 
14
15
  app_logger = logging.getLogger(__name__)
@@ -32,7 +33,7 @@ def declare_logic():
32
33
  discover_logic()
33
34
 
34
35
  # Logic from GenAI: (or, use your IDE w/ code completion)
35
- from database.models import Product, Order, Item, Customer
36
+ from database.models import Product, Order, Item, Customer, Email
36
37
 
37
38
  # Ensure the customer's balance is less than their credit limit
38
39
  Rule.constraint(validate=Customer, as_condition=lambda row: row.balance <= row.credit_limit, error_msg="Customer balance ({row.balance}) exceeds credit limit ({row.credit_limit})")
@@ -54,6 +55,25 @@ def declare_logic():
54
55
 
55
56
  # End Logic from GenAI
56
57
 
58
+ def send_mail(row: Email, old_row: Email, logic_row: LogicRow):
59
+ """
60
+
61
+ #als: Send N8N email message (also see discovery/integration.py)
62
+
63
+ Args:
64
+ row (Email): inserted Email
65
+ old_row (Email): n/a
66
+ logic_row (LogicRow): bundles curr/old row, with ins/upd/dlt logic
67
+ """
68
+ if logic_row.is_inserted():
69
+ customer = row.customer # parent accessor
70
+ if customer.email_opt_out:
71
+ logic_row.log("customer opted out of email")
72
+ return
73
+ logic_row.log(f"send email {row.message} to {customer.email} (stub, eg use N8N") # see in log
74
+
75
+ Rule.after_flush_row_event(on_class=Email, calling=send_mail) # see above
76
+
57
77
 
58
78
  def handle_all(logic_row: LogicRow): # #als: TIME / DATE STAMPING, OPTIMISTIC LOCKING
59
79
  """
@@ -77,7 +97,7 @@ def declare_logic():
77
97
  Grant.process_updates(logic_row=logic_row)
78
98
 
79
99
  did_stamping = False
80
- if enable_stamping := False: # #als: DATE / USER STAMPING
100
+ if enable_stamping := True: # #als: DATE / USER STAMPING
81
101
  row = logic_row.row
82
102
  if logic_row.ins_upd_dlt == "ins" and hasattr(row, "CreatedOn"):
83
103
  row.CreatedOn = datetime.datetime.now()
@@ -119,7 +119,7 @@ def declare_logic():
119
119
  Grant.process_updates(logic_row=logic_row)
120
120
 
121
121
  did_stamping = False
122
- if enable_stamping := False: # #als: DATE / USER STAMPING
122
+ if enable_stamping := True: # #als: DATE / USER STAMPING
123
123
  row = logic_row.row
124
124
  if logic_row.ins_upd_dlt == "ins" and hasattr(row, "CreatedOn"):
125
125
  row.CreatedOn = datetime.datetime.now()
@@ -148,8 +148,8 @@ def declare_logic():
148
148
  "Order Date": row.OrderDate,
149
149
  #"items": [row.OrderDetailList]
150
150
  },
151
- ins_upd_dlt="upd", wh_entity="Order",
152
- msg="1. /Webhook integration.py: n8n, sending ready Order payload")
151
+ ins_upd_dlt="upd", wh_entity="Order",
152
+ msg="1. /Webhook integration.py: n8n, sending ready Order payload")
153
153
 
154
154
  logic_row.log("send_order_to_shipping - sent order to shipping and N8N/sendgrid") # see in log
155
155
 
@@ -0,0 +1,31 @@
1
+ {
2
+ "file-explorer": true,
3
+ "global-search": true,
4
+ "switcher": true,
5
+ "graph": true,
6
+ "backlink": true,
7
+ "canvas": true,
8
+ "outgoing-link": true,
9
+ "tag-pane": true,
10
+ "properties": false,
11
+ "page-preview": true,
12
+ "daily-notes": true,
13
+ "templates": true,
14
+ "note-composer": true,
15
+ "command-palette": true,
16
+ "slash-command": false,
17
+ "editor-status": true,
18
+ "bookmarks": true,
19
+ "markdown-importer": false,
20
+ "zk-prefixer": false,
21
+ "random-note": false,
22
+ "outline": true,
23
+ "word-count": true,
24
+ "slides": false,
25
+ "audio-recorder": false,
26
+ "workspaces": false,
27
+ "file-recovery": true,
28
+ "publish": false,
29
+ "sync": true,
30
+ "webviewer": false
31
+ }
@@ -0,0 +1,166 @@
1
+ {
2
+ "main": {
3
+ "id": "286a834d839adefc",
4
+ "type": "split",
5
+ "children": [
6
+ {
7
+ "id": "dd6d74d8e8e2033a",
8
+ "type": "tabs",
9
+ "children": [
10
+ {
11
+ "id": "27459de4487926a5",
12
+ "type": "leaf",
13
+ "state": {
14
+ "type": "empty",
15
+ "state": {},
16
+ "icon": "lucide-file",
17
+ "title": "New tab"
18
+ }
19
+ }
20
+ ]
21
+ }
22
+ ],
23
+ "direction": "vertical"
24
+ },
25
+ "left": {
26
+ "id": "46df2b3e60483310",
27
+ "type": "split",
28
+ "children": [
29
+ {
30
+ "id": "b1e255effaa8b3c7",
31
+ "type": "tabs",
32
+ "children": [
33
+ {
34
+ "id": "5d955bc80fce9623",
35
+ "type": "leaf",
36
+ "state": {
37
+ "type": "file-explorer",
38
+ "state": {
39
+ "sortOrder": "alphabetical",
40
+ "autoReveal": false
41
+ },
42
+ "icon": "lucide-folder-closed",
43
+ "title": "Files"
44
+ }
45
+ },
46
+ {
47
+ "id": "28074419fd6a8eda",
48
+ "type": "leaf",
49
+ "state": {
50
+ "type": "search",
51
+ "state": {
52
+ "query": "",
53
+ "matchingCase": false,
54
+ "explainSearch": false,
55
+ "collapseAll": false,
56
+ "extraContext": false,
57
+ "sortOrder": "alphabetical"
58
+ },
59
+ "icon": "lucide-search",
60
+ "title": "Search"
61
+ }
62
+ },
63
+ {
64
+ "id": "17e52ebf5918c581",
65
+ "type": "leaf",
66
+ "state": {
67
+ "type": "bookmarks",
68
+ "state": {},
69
+ "icon": "lucide-bookmark",
70
+ "title": "Bookmarks"
71
+ }
72
+ }
73
+ ]
74
+ }
75
+ ],
76
+ "direction": "horizontal",
77
+ "width": 300
78
+ },
79
+ "right": {
80
+ "id": "4089a9f1f65dc943",
81
+ "type": "split",
82
+ "children": [
83
+ {
84
+ "id": "55c5ab028d9835b4",
85
+ "type": "tabs",
86
+ "children": [
87
+ {
88
+ "id": "4b91ab7bf798a851",
89
+ "type": "leaf",
90
+ "state": {
91
+ "type": "backlink",
92
+ "state": {
93
+ "collapseAll": false,
94
+ "extraContext": false,
95
+ "sortOrder": "alphabetical",
96
+ "showSearch": false,
97
+ "searchQuery": "",
98
+ "backlinkCollapsed": false,
99
+ "unlinkedCollapsed": true
100
+ },
101
+ "icon": "links-coming-in",
102
+ "title": "Backlinks"
103
+ }
104
+ },
105
+ {
106
+ "id": "990860d64994582e",
107
+ "type": "leaf",
108
+ "state": {
109
+ "type": "outgoing-link",
110
+ "state": {
111
+ "linksCollapsed": false,
112
+ "unlinkedCollapsed": true
113
+ },
114
+ "icon": "links-going-out",
115
+ "title": "Outgoing links"
116
+ }
117
+ },
118
+ {
119
+ "id": "320704f56a6b4c3e",
120
+ "type": "leaf",
121
+ "state": {
122
+ "type": "tag",
123
+ "state": {
124
+ "sortOrder": "frequency",
125
+ "useHierarchy": true,
126
+ "showSearch": false,
127
+ "searchQuery": ""
128
+ },
129
+ "icon": "lucide-tags",
130
+ "title": "Tags"
131
+ }
132
+ },
133
+ {
134
+ "id": "2abbfb3e874500e0",
135
+ "type": "leaf",
136
+ "state": {
137
+ "type": "outline",
138
+ "state": {
139
+ "followCursor": false,
140
+ "showSearch": false,
141
+ "searchQuery": ""
142
+ },
143
+ "icon": "lucide-list",
144
+ "title": "Outline"
145
+ }
146
+ }
147
+ ]
148
+ }
149
+ ],
150
+ "direction": "horizontal",
151
+ "width": 300,
152
+ "collapsed": true
153
+ },
154
+ "left-ribbon": {
155
+ "hiddenItems": {
156
+ "switcher:Open quick switcher": false,
157
+ "graph:Open graph view": false,
158
+ "canvas:Create new canvas": false,
159
+ "daily-notes:Open today's daily note": false,
160
+ "templates:Insert template": false,
161
+ "command-palette:Open command palette": false
162
+ }
163
+ },
164
+ "active": "27459de4487926a5",
165
+ "lastOpenFiles": []
166
+ }
@@ -0,0 +1,168 @@
1
+ Metadata-Version: 2.4
2
+ Name: ApiLogicServer
3
+ Version: 14.5.3
4
+ Author-email: Val Huber <apilogicserver@gmail.com>
5
+ License: BSD-3-Clause
6
+ Project-URL: Homepage, https://www.genai-logic.com
7
+ Project-URL: Docs, https://apilogicserver.github.io/Docs/Doc-Home/
8
+ Project-URL: Source, https://github.com/ApiLogicServer/ApiLogicServer-src
9
+ Project-URL: Issues, https://github.com/ApiLogicServer/ApiLogicServer-src/issues
10
+ Keywords: Flask,SQLAlchemy,Rules,WebApp,Microservice,ReactAdmin,Angular
11
+ Classifier: Development Status :: 5 - Production/Stable
12
+ Classifier: Environment :: Web Environment
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: License :: OSI Approved :: BSD License
15
+ Classifier: Operating System :: OS Independent
16
+ Classifier: Programming Language :: Python :: 3.12
17
+ Classifier: Programming Language :: Python :: 3.11
18
+ Classifier: Programming Language :: Python :: 3.10
19
+ Classifier: Programming Language :: Python :: 3.9
20
+ Classifier: Programming Language :: Python :: 3.8
21
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
22
+ Requires-Python: >=3.10
23
+ Description-Content-Type: text/markdown
24
+ License-File: LICENSE
25
+ Requires-Dist: PyJWT==2.6.0
26
+ Requires-Dist: python-dateutil==2.8.2
27
+ Requires-Dist: SQLAlchemy-Utils==0.38.2
28
+ Requires-Dist: logicbankutils==0.6.0
29
+ Requires-Dist: inflect==5.0.2
30
+ Requires-Dist: inflection==0.5.1
31
+ Requires-Dist: Flask==2.3.2
32
+ Requires-Dist: Flask-Cors==3.0.10
33
+ Requires-Dist: Flask-RESTful>=0.3.9
34
+ Requires-Dist: flask-restful-swagger-2>=0.35
35
+ Requires-Dist: Flask-SQLAlchemy==3.0.3
36
+ Requires-Dist: flask-swagger-ui>=4.11.1
37
+ Requires-Dist: flask_bcrypt==1.0.1
38
+ Requires-Dist: itsdangerous==2.1.2
39
+ Requires-Dist: Jinja2==3.1.5
40
+ Requires-Dist: MarkupSafe==2.1.3
41
+ Requires-Dist: six==1.16.0
42
+ Requires-Dist: SQLAlchemy==2.0.15
43
+ Requires-Dist: Werkzeug==2.3.3
44
+ Requires-Dist: safrs>=3.1.7
45
+ Requires-Dist: Flask-Admin==1.5.7
46
+ Requires-Dist: Flask-JWT-Extended==4.4.4
47
+ Requires-Dist: Flask-Login==0.6.2
48
+ Requires-Dist: Flask-OpenID==1.3.0
49
+ Requires-Dist: python-dotenv==0.15.0
50
+ Requires-Dist: email-validator==1.1.1
51
+ Requires-Dist: LogicBank>=1.20.26
52
+ Requires-Dist: cryptography==36.0.1
53
+ Requires-Dist: rsa
54
+ Requires-Dist: PyMySQL==1.0.3
55
+ Requires-Dist: oracledb==2.1.2
56
+ Requires-Dist: requests==2.31.0
57
+ Requires-Dist: gunicorn==20.1.0
58
+ Requires-Dist: psycopg2-binary==2.9.9
59
+ Requires-Dist: dotmap==1.3.25
60
+ Requires-Dist: WTForms==2.3.3
61
+ Requires-Dist: behave==1.2.6
62
+ Requires-Dist: alembic==1.7.7
63
+ Requires-Dist: python-ulid==2.7.0
64
+ Requires-Dist: psutil==6.0.0
65
+ Requires-Dist: pandas==2.2.2
66
+ Requires-Dist: openpyxl==3.1.5
67
+ Requires-Dist: GeoAlchemy2==0.12.5
68
+ Requires-Dist: confluent-kafka==2.3.0
69
+ Requires-Dist: translate==3.6.1
70
+ Requires-Dist: libretranslatepy==2.1.1
71
+ Requires-Dist: reportlab==4.2.0
72
+ Requires-Dist: xlsxwriter==3.2.0
73
+ Requires-Dist: natsort==8.4.0
74
+ Requires-Dist: astor==0.8.1
75
+ Requires-Dist: colorama==0.4.6
76
+ Requires-Dist: openai==1.55.3
77
+ Dynamic: license-file
78
+
79
+ [![Downloads](https://pepy.tech/badge/apilogicserver)](https://pepy.tech/project/apilogicserver)
80
+ [![Latest Version](https://img.shields.io/pypi/v/apilogicserver.svg)](https://pypi.python.org/pypi/apilogicserver/)
81
+ [![Supported Python versions](https://img.shields.io/pypi/pyversions/apilogicserver.svg)](https://pypi.python.org/pypi/apilogicserver/)
82
+
83
+ &nbsp;
84
+
85
+ # TL;DR
86
+
87
+ Create an executable project (API and Admin App) from a database or natural language prompt with 1 command, customize with declarative rules and Python in your IDE, containerize and deploy.
88
+
89
+ &nbsp;
90
+
91
+ <details markdown>
92
+
93
+ <summary>Video Overview (4 min)</summary>
94
+
95
+ &nbsp;
96
+
97
+ See how **Microservice Automation** creates and runs a microservice - a multi-page app, and an API.
98
+
99
+ * Here is a microservice -- api and admin app -- **created / running in 5 seconds**
100
+
101
+ * It would be similar for your databases
102
+
103
+ * Then, customize in your IDE with Python and **Logic Automation:** spreadsheet-like rules
104
+
105
+ [![GenAI Automation](https://raw.githubusercontent.com/ApiLogicServer/Docs/main/docs/images/sample-ai/copilot/genai-automation-video.png)](https://www.youtube.com/watch?v=7I33Fa9Ulos "Microservice Automation")
106
+
107
+ </details>
108
+
109
+ &nbsp;
110
+
111
+ # Quickstart
112
+
113
+ If you have a supported Python (version 3.10 - 3.12), install is standard, typically:
114
+
115
+ ```bash title="Install API Logic Server in a Virtual Environment"
116
+ python3 -m venv venv # windows: python -m venv venv
117
+ source venv/bin/activate # windows: venv\Scripts\activate
118
+ python -m pip install ApiLogicServer
119
+ ```
120
+
121
+ <br>Now, verify it's working - open the Project Manager for instructions (readme), and run the demo:
122
+
123
+ ```bash title="Start Manager"
124
+ ApiLogicServer start
125
+ ```
126
+
127
+ Find the [user documentation here](https://apilogicserver.github.io/Docs/). Use this for normal installation, to create and customize API Logic Projects.
128
+
129
+ To install the ***dev*** version, [see here](https://apilogicserver.github.io/Docs/Architecture-Internals). This installs the source of API Logic Server, so you can explore or extend it.
130
+
131
+ &nbsp;
132
+
133
+ # Welcome to API Logic Server
134
+
135
+ For Developers and their organizations seeking to **increase business agility,**
136
+
137
+ API Logic Server provides ***Microservice Automation:*** create executable projects with 1 command:
138
+
139
+ 1. ***API Automation:*** crud for each table, with pagination, optimistic locking, filtering and sorting, and
140
+
141
+ 2. ***App Automation:*** a multi-page, multi-table Admin App. <br>
142
+
143
+ **Customize in your IDE:** use standard tools (Python, Flask, SQLAlchemy, GitHub and Docker), plus<br>
144
+
145
+ 3. ***Logic Automation:*** unique **rules - 40X** more concise multi-table derivations and constraints.
146
+
147
+ Unlike frameworks, weeks-to-months of complex development is no longer necessary. <br>
148
+ API Logic Server provides unique automation **for instant integrations and app backends**.
149
+
150
+
151
+ &nbsp;
152
+
153
+ For more information, including install procedures, [please see the docs](https://apilogicserver.github.io/Docs/).
154
+
155
+ &nbsp;
156
+
157
+ ### Making Contributions
158
+
159
+ This is an open source project. We are open to suggestions. Some of our ideas include:
160
+
161
+ | Component | Provides | Consider Adding |
162
+ |:---------------------------|:-----------------|:-------------------------------------------------------------------------------|
163
+ | 1. JSON:**API** and Swagger | API Execution | Serverless, Kubernetes |
164
+ | 2. Transactional **Logic** | Rule Enforcement | Recompute Derivations |
165
+ | 3. This project | API Logic Project Creation | General support - see issues |
166
+ | 3. GenAI | Web version | Create projects with logic |
167
+
168
+ &nbsp;