ApiLogicServer 14.3.25__py3-none-any.whl → 14.5.0__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 (167) hide show
  1. api_logic_server_cli/add_cust/add_cust.py +283 -0
  2. api_logic_server_cli/api_logic_server.py +18 -250
  3. api_logic_server_cli/api_logic_server_info.yaml +3 -3
  4. api_logic_server_cli/cli.py +54 -35
  5. api_logic_server_cli/create_from_model/__pycache__/api_logic_server_utils.cpython-312.pyc +0 -0
  6. api_logic_server_cli/create_from_model/__pycache__/create_db_from_model.cpython-312.pyc +0 -0
  7. api_logic_server_cli/create_from_model/__pycache__/dbml.cpython-312.pyc +0 -0
  8. api_logic_server_cli/create_from_model/__pycache__/ont_build.cpython-312.pyc +0 -0
  9. api_logic_server_cli/create_from_model/__pycache__/ont_create.cpython-312.pyc +0 -0
  10. api_logic_server_cli/create_from_model/api_logic_server_utils.py +47 -0
  11. api_logic_server_cli/create_from_model/create_db_from_model.py +2 -0
  12. api_logic_server_cli/create_from_model/dbml.py +113 -58
  13. api_logic_server_cli/create_from_model/ont_build.py +102 -74
  14. api_logic_server_cli/create_from_model/ont_create.py +7 -6
  15. api_logic_server_cli/create_from_model/safrs-react-admin-npm-build/static/.DS_Store +0 -0
  16. api_logic_server_cli/database/basic_demo.sqlite +0 -0
  17. api_logic_server_cli/database/basic_demo.txt +1 -0
  18. api_logic_server_cli/database/basic_demo_wg.sqlite +0 -0
  19. api_logic_server_cli/database/nw-gold-fix.sql +62 -0
  20. api_logic_server_cli/database/nw-gold.sqlite +0 -0
  21. api_logic_server_cli/{prototypes/manager/webgenai → fragments}/docker-compose.yml +1 -1
  22. api_logic_server_cli/genai/genai.py +42 -11
  23. api_logic_server_cli/genai/genai_graphics.py +252 -38
  24. api_logic_server_cli/genai/genai_svcs.py +20 -12
  25. api_logic_server_cli/manager.py +22 -12
  26. api_logic_server_cli/prototypes/.DS_Store +0 -0
  27. api_logic_server_cli/prototypes/base/.DS_Store +0 -0
  28. api_logic_server_cli/prototypes/base/.vscode/launch.json +22 -2
  29. api_logic_server_cli/prototypes/base/api/expose_api_models.py +3 -1
  30. api_logic_server_cli/prototypes/base/api_logic_server_run.py +5 -2
  31. api_logic_server_cli/prototypes/base/config/activate_logicbank.py +1 -0
  32. api_logic_server_cli/prototypes/base/config/config.py +123 -25
  33. api_logic_server_cli/prototypes/base/config/default.env +7 -1
  34. api_logic_server_cli/prototypes/base/config/logging.yml +1 -0
  35. api_logic_server_cli/prototypes/base/config/server_setup.py +33 -1
  36. api_logic_server_cli/prototypes/base/database/test_data/readme.md +5 -2
  37. api_logic_server_cli/prototypes/base/devops/docker-standard-image/docker-compose-standard-image.yml +7 -2
  38. api_logic_server_cli/prototypes/base/docs/training/logic_bank_api.prompt +314 -0
  39. api_logic_server_cli/prototypes/base/docs/training/logic_example.py +41 -0
  40. api_logic_server_cli/prototypes/base/integration/kafka/kafka_producer.py +12 -5
  41. api_logic_server_cli/prototypes/base/integration/n8n/n8n_producer.py +68 -21
  42. api_logic_server_cli/prototypes/base/integration/n8n/n8n_readme.md +19 -0
  43. api_logic_server_cli/prototypes/base/integration/system/FlaskKafka.py +5 -1
  44. api_logic_server_cli/prototypes/base/test/basic/server_test.py +1 -1
  45. api_logic_server_cli/prototypes/base/ui/templates/bar_chart.jinja +64 -0
  46. api_logic_server_cli/prototypes/basic_demo/README.md +29 -52
  47. api_logic_server_cli/prototypes/basic_demo/customizations/api/.DS_Store +0 -0
  48. api_logic_server_cli/prototypes/basic_demo/customizations/api/api_discovery/mcp_server_executor.py +138 -0
  49. api_logic_server_cli/prototypes/basic_demo/customizations/api/api_discovery/openapi.py +92 -0
  50. api_logic_server_cli/prototypes/basic_demo/customizations/api/api_discovery/proper_update_def.json +71 -0
  51. api_logic_server_cli/prototypes/basic_demo/customizations/config/default.env +13 -0
  52. api_logic_server_cli/prototypes/basic_demo/customizations/database/db.sqlite +0 -0
  53. api_logic_server_cli/prototypes/basic_demo/customizations/database/models.py +131 -0
  54. api_logic_server_cli/prototypes/basic_demo/customizations/integration/.DS_Store +0 -0
  55. api_logic_server_cli/prototypes/basic_demo/customizations/integration/mcp/.DS_Store +0 -0
  56. api_logic_server_cli/prototypes/basic_demo/customizations/integration/mcp/1_langchain_loader.py +71 -0
  57. api_logic_server_cli/prototypes/basic_demo/customizations/integration/mcp/2_gpt_mcp_prompt.txt +19 -0
  58. api_logic_server_cli/prototypes/basic_demo/customizations/integration/mcp/README_mcp.md +13 -0
  59. api_logic_server_cli/prototypes/basic_demo/customizations/integration/mcp/mcp_client_executor.py +295 -0
  60. api_logic_server_cli/prototypes/basic_demo/customizations/integration/mcp/mcp_schema.txt +47 -0
  61. api_logic_server_cli/prototypes/basic_demo/customizations/integration/mcp/mcp_server_discovery.json +9 -0
  62. api_logic_server_cli/prototypes/basic_demo/customizations/integration/mcp/multi_mcp_flow/multi_mcp_flow.png +0 -0
  63. api_logic_server_cli/prototypes/basic_demo/customizations/integration/mcp/multi_mcp_flow/multi_mcp_orchestration.yaml +49 -0
  64. api_logic_server_cli/prototypes/basic_demo/customizations/integration/mcp/multi_mcp_flow/wny mcp flows.png +0 -0
  65. api_logic_server_cli/prototypes/basic_demo/customizations/integration/mcp/natlang_to_api.py +73 -0
  66. api_logic_server_cli/prototypes/basic_demo/customizations/integration/mcp/resources/curl.txt +5 -0
  67. api_logic_server_cli/prototypes/basic_demo/customizations/integration/mcp/resources/images/MCP Overview.png +0 -0
  68. api_logic_server_cli/prototypes/basic_demo/customizations/integration/mcp/resources/images/MCP_Arch.png +0 -0
  69. api_logic_server_cli/prototypes/basic_demo/customizations/integration/mcp/resources/images/MCP_Overview_Executor.png +0 -0
  70. api_logic_server_cli/prototypes/basic_demo/customizations/integration/mcp/resources/invoke_llm/1 - prompt_messages_array.json +10 -0
  71. api_logic_server_cli/prototypes/basic_demo/customizations/integration/mcp/resources/invoke_llm/2 - completion_tool_context.json +12 -0
  72. api_logic_server_cli/prototypes/basic_demo/customizations/integration/mcp/resources/llm_schema.txt +38 -0
  73. api_logic_server_cli/prototypes/basic_demo/customizations/integration/mcp/resources/nw_swagger_2.yaml +17393 -0
  74. api_logic_server_cli/prototypes/basic_demo/customizations/integration/mcp/resources/nw_swagger_3.yaml +16660 -0
  75. api_logic_server_cli/prototypes/basic_demo/customizations/integration/mcp/resources/nw_swagger_3_relaxed.yaml +109 -0
  76. api_logic_server_cli/prototypes/basic_demo/customizations/integration/mcp/resources/proxy_server.py +51 -0
  77. api_logic_server_cli/prototypes/basic_demo/customizations/integration/mcp/resources/proxy_serverZ.py +72 -0
  78. api_logic_server_cli/prototypes/basic_demo/customizations/integration/mcp/resources/validate_jsonapi.py +64 -0
  79. api_logic_server_cli/prototypes/basic_demo/customizations/integration/mcp/run_executor.py +23 -0
  80. api_logic_server_cli/prototypes/basic_demo/customizations/integration/mcp/swagger_converter.py +65 -0
  81. api_logic_server_cli/prototypes/basic_demo/customizations/integration/mcp/z_old/3_executor_test_agent.py +52 -0
  82. api_logic_server_cli/prototypes/basic_demo/customizations/integration/openai_function/3_executor_test_agent.py +52 -0
  83. api_logic_server_cli/prototypes/basic_demo/customizations/integration/openai_function/README_functon.md +201 -0
  84. api_logic_server_cli/prototypes/basic_demo/customizations/integration/openai_function/ai_plugin.json +17 -0
  85. api_logic_server_cli/prototypes/basic_demo/customizations/integration/openai_function/nw-swagger_3.json +1731 -0
  86. api_logic_server_cli/prototypes/basic_demo/customizations/integration/openai_function/snippets.txt +5 -0
  87. api_logic_server_cli/prototypes/basic_demo/customizations/integration/openai_function/swagger_3 genai_demo_with_get.json +1731 -0
  88. api_logic_server_cli/prototypes/basic_demo/customizations/integration/openai_function/swagger_3.json +1782 -0
  89. api_logic_server_cli/prototypes/basic_demo/customizations/integration/openai_function/swagger_3_genai_demo.json +264 -0
  90. api_logic_server_cli/prototypes/basic_demo/customizations/integration/openai_function/swagger_3_genai_demo_with_update.json +1782 -0
  91. api_logic_server_cli/prototypes/basic_demo/customizations/logic/declare_logic.py +62 -44
  92. api_logic_server_cli/prototypes/basic_demo/customizations/security/declare_security.py +11 -12
  93. api_logic_server_cli/prototypes/basic_demo/customizations/ui/admin/admin.yaml +166 -0
  94. api_logic_server_cli/prototypes/basic_demo/iteration/api/{customize_api.py → api_discovery/order_b2b.py} +17 -23
  95. api_logic_server_cli/prototypes/basic_demo/iteration/database/db.sqlite +0 -0
  96. api_logic_server_cli/prototypes/basic_demo/iteration/integration/row_dict_maps/OrderB2B.py +6 -5
  97. api_logic_server_cli/prototypes/basic_demo/iteration/integration/row_dict_maps/OrderShipping.py +4 -4
  98. api_logic_server_cli/prototypes/basic_demo/iteration/logic/declare_logic.py +69 -43
  99. api_logic_server_cli/prototypes/basic_demo/iteration/ui/admin/admin.yaml +125 -50
  100. api_logic_server_cli/prototypes/genai_demo/ui/admin/admin.yaml +1 -1
  101. api_logic_server_cli/prototypes/manager/README.md +30 -4
  102. api_logic_server_cli/prototypes/manager/README_X.md +663 -0
  103. api_logic_server_cli/prototypes/manager/system/genai/.DS_Store +0 -0
  104. api_logic_server_cli/prototypes/manager/system/genai/examples/.DS_Store +0 -0
  105. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/.DS_Store +0 -0
  106. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo.prompt +0 -10
  107. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo.response_example +32 -10
  108. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/docs/002_create_db_models.prompt +4 -4
  109. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/docs/003_create_db_models.response +77 -47
  110. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_informal.prompt +1 -1
  111. api_logic_server_cli/prototypes/manager/system/genai/graphics_templates/dashboard_services.jinja +83 -0
  112. api_logic_server_cli/prototypes/manager/system/genai/graphics_templates/graphics_dashboard_WIP.py +34 -0
  113. api_logic_server_cli/prototypes/manager/system/genai/graphics_templates/{graphics_services.py → graphics_services_api_xxx.py} +0 -9
  114. api_logic_server_cli/prototypes/manager/system/genai/graphics_templates/graphics_services_db.jinja +46 -0
  115. api_logic_server_cli/prototypes/manager/system/genai/graphics_templates/graphics_services_db_each_method.jinja +36 -0
  116. api_logic_server_cli/prototypes/manager/system/genai/prompt_inserts/graphics.prompt +7 -3
  117. api_logic_server_cli/prototypes/manager/system/genai/prompt_inserts/response_format.prompt +8 -1
  118. api_logic_server_cli/prototypes/manager/system/install-ApiLogicServer-dev/install-ApiLogicServer-dev.ps1 +100 -0
  119. api_logic_server_cli/prototypes/manager/system/install-ApiLogicServer-dev/install-ApiLogicServer-dev.sh +116 -0
  120. api_logic_server_cli/prototypes/manager/system/install-ApiLogicServer-dev/readme.md +7 -0
  121. api_logic_server_cli/prototypes/manager/system/style-guide.yaml +2 -2
  122. api_logic_server_cli/prototypes/manager/webgenai/README.md +6 -0
  123. api_logic_server_cli/prototypes/nw/docs/graphics/count_orders_by_category.prompt +1 -0
  124. api_logic_server_cli/prototypes/nw/docs/graphics/order_count_by_month.prompt +1 -0
  125. api_logic_server_cli/prototypes/nw/docs/graphics/request copy.json +892 -0
  126. api_logic_server_cli/prototypes/nw/docs/graphics/request.json +6 -0
  127. api_logic_server_cli/prototypes/nw/docs/graphics/response.json +17 -0
  128. api_logic_server_cli/prototypes/nw/docs/graphics/response.yaml +59 -0
  129. api_logic_server_cli/prototypes/nw/docs/graphics/sales_by_category.prompt +1 -0
  130. api_logic_server_cli/prototypes/nw/ui/admin/home.js +5 -4
  131. api_logic_server_cli/prototypes/nw/ui/app_model_custom.yaml +851 -1082
  132. api_logic_server_cli/prototypes/nw_no_cust/Tutorial.md +45 -26
  133. api_logic_server_cli/prototypes/nw_no_cust/api/api_discovery/openapi.py +130 -0
  134. api_logic_server_cli/prototypes/nw_no_cust/api/api_discovery/proper_update_def.json +71 -0
  135. api_logic_server_cli/prototypes/nw_no_cust/config/default.env +13 -0
  136. api_logic_server_cli/prototypes/nw_no_cust/docs/graphics/count_orders_by_category.prompt +1 -0
  137. api_logic_server_cli/prototypes/nw_no_cust/docs/graphics/sales_by_employee.prompt +1 -0
  138. api_logic_server_cli/prototypes/ont_app/ontimize_seed/nginx/nginx.conf +2 -2
  139. api_logic_server_cli/prototypes/ont_app/ontimize_seed/package-lock.json +9725 -1180
  140. api_logic_server_cli/prototypes/ont_app/ontimize_seed/package.json +6 -9
  141. api_logic_server_cli/prototypes/ont_app/ontimize_seed/src/app/app.config.ts +2 -1
  142. api_logic_server_cli/prototypes/ont_app/ontimize_seed/src/app/shared/app.services.config.ts +1 -1
  143. api_logic_server_cli/prototypes/ont_app/ontimize_seed/src/assets/css/app.scss +4 -0
  144. api_logic_server_cli/prototypes/ont_app/ontimize_seed/src/assets/i18n/en.json +1 -1
  145. api_logic_server_cli/prototypes/ont_app/ontimize_seed/src/assets/i18n/es.json +14 -12
  146. api_logic_server_cli/prototypes/ont_app/ontimize_seed/src/environments/environment.prod.ts +5 -5
  147. api_logic_server_cli/prototypes/ont_app/ontimize_seed/src/environments/environment.ts +5 -5
  148. api_logic_server_cli/prototypes/ont_app/templates/app_config.jinja +1 -1
  149. api_logic_server_cli/prototypes/ont_app/templates/date_template.html +1 -1
  150. api_logic_server_cli/prototypes/ont_app/templates/detail_template.html +1 -1
  151. api_logic_server_cli/prototypes/ont_app/templates/new_template.html +16 -16
  152. api_logic_server_cli/prototypes/ont_app/templates/textarea_template.html +1 -1
  153. api_logic_server_cli/prototypes/ont_app/templates/timestamp_template.html +1 -1
  154. api_logic_server_cli/prototypes/sample_ai/logic/declare_logic.py +30 -13
  155. apilogicserver-14.5.0.dist-info/METADATA +76 -0
  156. {apilogicserver-14.3.25.dist-info → apilogicserver-14.5.0.dist-info}/RECORD +160 -88
  157. {apilogicserver-14.3.25.dist-info → apilogicserver-14.5.0.dist-info}/WHEEL +1 -1
  158. api_logic_server_cli/prototypes/basic_demo/apply_customizations.ps1 +0 -17
  159. api_logic_server_cli/prototypes/basic_demo/apply_customizations.sh +0 -14
  160. api_logic_server_cli/prototypes/basic_demo/apply_iteration.ps1 +0 -20
  161. api_logic_server_cli/prototypes/basic_demo/apply_iteration.sh +0 -15
  162. api_logic_server_cli/prototypes/manager/system/genai/graphics_templates/service_template_jsonapi_rpc.jinja +0 -37
  163. api_logic_server_cli/prototypes/manager/system/genai/graphics_templates/service_template_unused.jinja +0 -38
  164. apilogicserver-14.3.25.dist-info/METADATA +0 -167
  165. {apilogicserver-14.3.25.dist-info → apilogicserver-14.5.0.dist-info}/entry_points.txt +0 -0
  166. {apilogicserver-14.3.25.dist-info → apilogicserver-14.5.0.dist-info}/licenses/LICENSE +0 -0
  167. {apilogicserver-14.3.25.dist-info → apilogicserver-14.5.0.dist-info}/top_level.txt +0 -0
@@ -221,7 +221,7 @@ def main(ctx):
221
221
  help="Create sample projects")
222
222
  @click.option('--open-manager/--no-open-manager', "open_manager",
223
223
  default=True, is_flag=True,
224
- help="Overlay existing manager (projects retained)")
224
+ help="Whether to open IDE at Manager")
225
225
  def create_start_manager(ctx, open_with, clean: click.BOOL = True, samples: click.BOOL = True,
226
226
  volume: str = "ApiLogicServer", open_manager: click.BOOL = True):
227
227
  """
@@ -615,14 +615,14 @@ def genai(ctx, using, db_url, repaired_response: str,
615
615
  Creates new customizable project (overwrites).
616
616
  """
617
617
  global command
618
- import api_logic_server_cli.genai.genai as genai_svcs
618
+ import api_logic_server_cli.genai.genai as genai
619
619
  if using is None and repaired_response is None:
620
620
  log.error("Error - must provide --using or --repaired-response")
621
621
  exit(1)
622
622
  defaulted_using = using
623
623
  if defaulted_using == 'genai_demo': # default to genai_demo.prompt
624
624
  defaulted_using = 'system/genai/examples/genai_demo/genai_demo.prompt'
625
- genai_svcs.genai_cli_with_retry(using=defaulted_using, db_url=db_url, repaired_response=repaired_response,
625
+ genai.genai_cli_with_retry(using=defaulted_using, db_url=db_url, repaired_response=repaired_response,
626
626
  genai_version=genai_version, temperature=temperature,
627
627
  retries=retries, opt_locking=opt_locking, genai_active_rules=active_rules,
628
628
  prompt_inserts=prompt_inserts, quote=quote, use_relns=use_relns,
@@ -745,8 +745,11 @@ def genai_logic(ctx, using, genai_version: str, retries: int, suggest: click.BOO
745
745
  @click.option('--genai-version', 'genai_version',
746
746
  default='gpt-4o',
747
747
  help="Eg, gpt-3.5-turbo, gpt-4o")
748
+ @click.option('--replace-with', 'replace_with',
749
+ default='!using',
750
+ help="Replace Graphics with this (*/retry, ''/delete)")
748
751
  @click.pass_context
749
- def genai_graphics(ctx, using, genai_version: str):
752
+ def genai_graphics(ctx, using, genai_version: str, replace_with: str):
750
753
  """
751
754
  Adds (or suggests) logic to current project.
752
755
  """
@@ -771,7 +774,7 @@ def genai_graphics(ctx, using, genai_version: str):
771
774
  log.info(f'... Typical usage - cd into project, use --project_name=. \n')
772
775
  exit (1)
773
776
  from api_logic_server_cli.genai.genai_graphics import GenAIGraphics
774
- genai_graphics = GenAIGraphics(using=using, project=project, genai_version=genai_version)
777
+ genai_graphics = GenAIGraphics(using=using, project=project, genai_version=genai_version, replace_with=replace_with)
775
778
  pass
776
779
  log.info("")
777
780
 
@@ -1451,17 +1454,23 @@ def add_auth_cmd(ctx, bind_key_url_separator: str, provider_type :str, db_url: s
1451
1454
 
1452
1455
  cd existing_project
1453
1456
 
1454
- ApiLogicServer add-auth project_name=.
1457
+ ApiLogicServer add-auth
1458
+
1459
+ ApiLogicServer add-auth --db-url=add-auth
1460
+
1455
1461
  ApiLogicServer add-auth provider_type=keycloak
1456
1462
 
1457
1463
  """
1458
1464
  project_name = resolve_blank_project_name(project_name)
1459
1465
  bind_key = "authentication"
1466
+ auth_db_url = db_url
1467
+ if db_url == "auth" and provider_type == "sql":
1468
+ auth_db_url = "add-auth"
1460
1469
  project = PR.ProjectRun(command="add_security",
1461
1470
  project_name=project_name,
1462
1471
  api_name=api_name,
1463
1472
  db_url="",
1464
- auth_db_url=db_url,
1473
+ auth_db_url=auth_db_url,
1465
1474
  auth_provider_type=provider_type,
1466
1475
  bind_key=bind_key,
1467
1476
  bind_key_url_separator=bind_key_url_separator,
@@ -1586,36 +1595,46 @@ def add_cust(ctx, bind_key_url_separator: str, api_name: str, project_name: str)
1586
1595
  project_name = project.project_directory_path.parent.name if not project.project_directory_path.is_dir() else project.project_directory_path.name
1587
1596
  models_py_path = project.project_directory_path.joinpath('database/models.py')
1588
1597
 
1589
- log.debug(f"\ncli[add-cust] models_py_path={models_py_path}")
1590
- if not models_py_path.exists():
1591
- raise Exception("Customizations are northwind/genai-specific - models.py does not exist")
1598
+ if use_add_cust := True:
1599
+ import api_logic_server_cli.add_cust.add_cust as add_cust
1600
+ add_cust.add_cust(project=project, project_name=project_name, models_py_path=models_py_path)
1601
+ pass
1602
+ else:
1603
+ log.debug(f"\ncli[add-cust] models_py_path={models_py_path}")
1604
+ if not models_py_path.exists():
1605
+ raise Exception("Customizations are northwind/genai-specific - models.py does not exist")
1606
+
1607
+ project_is_genai_demo = False # can't use project.is_genai_demo because this is not the create command...
1608
+ if project.project_directory_path.joinpath('docs/project_is_genai_demo.txt').exists():
1609
+ project_is_genai_demo = True
1610
+
1611
+ project.abs_db_url, project.nw_db_status, project.model_file_name = create_utils.get_abs_db_url("0. Using Sample DB", project)
1612
+
1613
+ if create_utils.does_file_contain(search_for="CategoryTableNameTest", in_file=models_py_path):
1614
+ project.add_nw_customizations(do_security=False)
1615
+ log.info("\nNext step - add authentication:\n $ ApiLogicServer add-auth --db_url=auth\n\n")
1616
+
1617
+ elif project_is_genai_demo and create_utils.does_file_contain(search_for="Customer", in_file=models_py_path):
1618
+ project.add_genai_customizations(do_security=False)
1619
+
1620
+ elif project_name == 'sample_ai' and create_utils.does_file_contain(search_for="CustomerName = Column(Text", in_file=models_py_path):
1621
+ cocktail_napkin_path = project.project_directory_path.joinpath('logic/cocktail-napkin.jpg')
1622
+ is_customized = cocktail_napkin_path.exists()
1623
+ if not is_customized:
1624
+ project.add_sample_ai_customizations()
1625
+ else:
1626
+ project.add_sample_ai_iteration()
1627
+
1628
+ elif project_name == 'basic_demo' and create_utils.does_file_contain(search_for="Customer", in_file=models_py_path):
1629
+ cocktail_napkin_path = project.project_directory_path.joinpath('logic/cocktail-napkin.jpg')
1630
+ is_customized = cocktail_napkin_path.exists()
1631
+ if not is_customized:
1632
+ project.add_basic_demo_customizations()
1633
+ else:
1634
+ project.add_basic_demo_iteration()
1592
1635
 
1593
- project_is_genai_demo = False # can't use project.is_genai_demo because this is not the create command...
1594
- if project.project_directory_path.joinpath('docs/project_is_genai_demo.txt').exists():
1595
- project_is_genai_demo = True
1596
-
1597
- project.abs_db_url, project.nw_db_status, project.model_file_name = create_utils.get_abs_db_url("0. Using Sample DB", project)
1598
- if create_utils.does_file_contain(search_for="CategoryTableNameTest", in_file=models_py_path):
1599
- project.add_nw_customizations(do_security=False)
1600
- log.info("\nNext step - add authentication:\n $ ApiLogicServer add-auth --db_url=auth\n\n")
1601
- elif project_is_genai_demo and create_utils.does_file_contain(search_for="Customer", in_file=models_py_path):
1602
- project.add_genai_customizations(do_security=False)
1603
- elif project_name == 'sample_ai' and create_utils.does_file_contain(search_for="CustomerName = Column(Text", in_file=models_py_path):
1604
- cocktail_napkin_path = project.project_directory_path.joinpath('logic/cocktail-napkin.jpg')
1605
- is_customized = cocktail_napkin_path.exists()
1606
- if not is_customized:
1607
- project.add_sample_ai_customizations()
1608
- else:
1609
- project.add_sample_ai_iteration()
1610
- elif project_name == 'basic_demo' and create_utils.does_file_contain(search_for="Customer", in_file=models_py_path):
1611
- cocktail_napkin_path = project.project_directory_path.joinpath('logic/cocktail-napkin.jpg')
1612
- is_customized = cocktail_napkin_path.exists()
1613
- if not is_customized:
1614
- project.add_basic_demo_customizations()
1615
1636
  else:
1616
- project.add_basic_demo_iteration()
1617
- else:
1618
- raise Exception("Customizations are northwind/genai-specific - models.py has neither CategoryTableNameTest nor Customer")
1637
+ raise Exception("Customizations are northwind/genai-specific - models.py has neither CategoryTableNameTest nor Customer")
1619
1638
 
1620
1639
 
1621
1640
  @main.command("sample-ai", cls=HideDunderCommand, hidden=True)
@@ -1,5 +1,6 @@
1
1
  # -*- coding: utf-8 -*-
2
2
 
3
+ import shutil
3
4
  import subprocess, os, sys
4
5
  from pathlib import Path
5
6
  from os.path import abspath
@@ -335,6 +336,7 @@ def get_config(search_for: str, in_file: str) -> str:
335
336
  f'.. seeking {search_for}\n'
336
337
  f'.. in {in_file}')
337
338
  return file_lines[insert_line].split('=')[1].strip().replace("'","",2)
339
+
338
340
  def get_ontimize_apps(project_dir_path):
339
341
  result = []
340
342
  for name in os.listdir(f"{project_dir_path}/ui"):
@@ -346,6 +348,7 @@ def get_ontimize_apps(project_dir_path):
346
348
  result.append(name)
347
349
  log.debug(f"Found {len(result)} Ontimize app(s)")
348
350
  return result
351
+
349
352
  def does_file_contain(search_for: str, in_file: str) -> bool:
350
353
  """ returns True if <search_for> is <in_file> """
351
354
  with open(Path(in_file), 'r+') as fp:
@@ -482,3 +485,47 @@ def run_command(cmd: str, env=None, msg: str = "", new_line: bool=False,
482
485
  elif result != "" and result != "Downloaded the skeleton app, good coding!":
483
486
  log.debug(f'{log_msg} {cmd_to_run} result: {spaces}{result}')
484
487
  return result.replace('\\n','\n')
488
+
489
+
490
+ def recursive_overwrite(src, dest, ignore=None):
491
+ """
492
+ copyTree, with overwrite
493
+ thanks: https://stackoverflow.com/questions/12683834/how-to-copy-directory-recursively-in-python-and-overwrite-all
494
+ """
495
+ if os.path.isdir(src):
496
+ if not os.path.isdir(dest):
497
+ os.makedirs(dest)
498
+ files = os.listdir(src)
499
+ if ignore is not None:
500
+ ignored = ignore(src, files)
501
+ else:
502
+ ignored = set()
503
+ for f in files:
504
+ if f not in ignored:
505
+ recursive_overwrite(os.path.join(src, f),
506
+ os.path.join(dest, f),
507
+ ignore)
508
+ else:
509
+ shutil.copyfile(src, dest)
510
+
511
+ def find_replace_recursive(directory, find, replace, filePattern):
512
+ """
513
+
514
+ find_replace_recursive("some_dir", "find this", "replace with this", "*.txt")
515
+
516
+ thanks: https://stackoverflow.com/questions/4205854/recursively-find-and-replace-string-in-text-files
517
+
518
+ Args:
519
+ directory (_type_): _description_
520
+ find (_type_): _description_
521
+ replace (_type_): _description_
522
+ filePattern (_type_): _description_
523
+ """
524
+ for path, dirs, files in os.walk(os.path.abspath(directory)):
525
+ for filename in fnmatch.filter(files, filePattern):
526
+ filepath = os.path.join(path, filename)
527
+ with open(filepath) as f:
528
+ s = f.read()
529
+ s = s.replace(find, replace)
530
+ with open(filepath, "w") as f:
531
+ f.write(s)
@@ -12,6 +12,8 @@ log = logging.getLogger('create_from_model.model_creation_services')
12
12
  def create_db(project: Project):
13
13
  """ Create a database from a model file
14
14
 
15
+ Warning - test data failure is not reported here
16
+
15
17
  Args:
16
18
  project (Project): contains the model file and db_url locations
17
19
  """
@@ -1,3 +1,4 @@
1
+ import json
1
2
  import logging
2
3
  from re import X
3
4
  import shutil
@@ -68,51 +69,55 @@ class DBMLCreator(object):
68
69
  self.dbms_lines.append('// Or, https://databasediagram.com/app')
69
70
  self.dbms_lines.append('// Or, view in VSCode with extension: "DBML Live Preview"')
70
71
  self.dbms_lines.append("")
72
+ self.mcp_schema = \
73
+ {
74
+ "tool_type": "json-api",
75
+ "schema_version": "1.0",
76
+ "base_url": "http://localhost:5656/api",
77
+ "description": f"API Logic Project: {self.mod_gen.project.project_name_last_node}",
78
+ "resources": [
79
+ ]
80
+ }
81
+
71
82
 
72
- def create_docs_dbml_file(self):
73
- """ main driver - loop through resources, write admin.yaml - with backup, nw customization
74
-
75
- Table Users {
76
- id integerish
77
- created_at timestamp
78
- }
79
- Ref: users.(id) < follows.(followed_user_id)
83
+ def do_process_resource(self, resource_name: str)-> bool:
84
+ """ filter out resources that are skipped by user, start with ab etc
80
85
  """
86
+ if "ProductDetails_V" in resource_name:
87
+ log.debug("special table") # should not occur (--noviews)
88
+ if resource_name.startswith("ab_"):
89
+ return False # skip admin table: " + table_name + "\n
90
+ elif 'sqlite_sequence' in resource_name:
91
+ return False # skip sqlite_sequence table: " + table_name + "\n
92
+ elif resource_name is None:
93
+ return False # no class (view): " + table_name + "\n
94
+ elif resource_name.startswith("Ab"):
95
+ return False
96
+ return True
81
97
 
82
- ''' decide about rebuild -- can you save positions?
83
- if (self.mod_gen.project.command == "create-ui" or self.mod_gen.project.command.startswith("rebuild")) \
84
- or self.mod_gen.project.command == "add_db":
85
- if self.mod_gen.project.command.startswith("rebuild"):
86
- log.debug(".. .. ..Use existing ui/admin directory")
87
- else:
88
- self.create_admin_app(msg=".. .. ..Create ui/admin")
89
- '''
90
-
91
- sys.path.append(self.mod_gen.project.os_cwd)
92
-
93
- if do_table_descriptions := True:
94
- if len(self.mod_gen.project.table_descriptions) > 0:
95
- self.dbms_lines.append("Project DBML {")
96
- self.dbms_lines.append(" Note: '''")
97
- for each_resource_name in self.mod_gen.resource_list:
98
- if self.do_process_resource(each_resource_name):
99
- each_resource : Resource = self.mod_gen.resource_list[each_resource_name]
100
- description = "missing (requires genai creation)"
101
- table_descriptions = self.mod_gen.project.table_descriptions
102
- if each_resource.table_name in table_descriptions:
103
- # als model desc's: api_logic_server_cli/sqlacodegen_wrapper/sqlacodegen/sqlacodegen/codegen.py
104
- description = table_descriptions[each_resource.table_name]
105
- description = description.replace("Table representing ", "")
106
- description = description.replace("Table storing ", "")
107
- description = description.replace("This table stores ", "")
108
- description = description.replace("This table lists ", "")
109
- description = description.replace("This table records ", "")
110
- self.dbms_lines.append(f"{each_resource_name}: {description}")
111
- self.dbms_lines.append("'''")
112
- self.dbms_lines.append("}")
113
- self.dbms_lines.append("")
114
-
115
-
98
+ def dbml_descriptions(self):
99
+ if len(self.mod_gen.project.table_descriptions) > 0:
100
+ self.dbms_lines.append("Project DBML {")
101
+ self.dbms_lines.append(" Note: '''")
102
+ for each_resource_name in self.mod_gen.resource_list:
103
+ if self.do_process_resource(each_resource_name):
104
+ each_resource : Resource = self.mod_gen.resource_list[each_resource_name]
105
+ description = "missing (requires genai creation)"
106
+ table_descriptions = self.mod_gen.project.table_descriptions
107
+ if each_resource.table_name in table_descriptions:
108
+ # als model desc's: api_logic_server_cli/sqlacodegen_wrapper/sqlacodegen/sqlacodegen/codegen.py
109
+ description = table_descriptions[each_resource.table_name]
110
+ description = description.replace("Table representing ", "")
111
+ description = description.replace("Table storing ", "")
112
+ description = description.replace("This table stores ", "")
113
+ description = description.replace("This table lists ", "")
114
+ description = description.replace("This table records ", "")
115
+ self.dbms_lines.append(f"{each_resource_name}: {description}")
116
+ self.dbms_lines.append("'''")
117
+ self.dbms_lines.append("}")
118
+ self.dbms_lines.append("")
119
+
120
+ def dbml_resources(self):
116
121
  for each_resource_name in self.mod_gen.resource_list:
117
122
  if self.do_process_resource(each_resource_name):
118
123
  each_resource : Resource = self.mod_gen.resource_list[each_resource_name]
@@ -127,9 +132,7 @@ class DBMLCreator(object):
127
132
  self.dbms_lines.append(" }")
128
133
  self.dbms_lines.append("")
129
134
 
130
- self.dbms_lines.append("")
131
- self.dbms_lines.append("")
132
- self.dbms_lines.append("// Relationships") # Ref: users.(id) < follows.(followed_user_id)
135
+ def dbml_relationships(self):
133
136
  for each_resource_name in self.mod_gen.resource_list:
134
137
  if self.do_process_resource(each_resource_name):
135
138
  each_resource : Resource = self.mod_gen.resource_list[each_resource_name]
@@ -152,6 +155,36 @@ class DBMLCreator(object):
152
155
  if each_resource_reln.parent_resource == 'Location': # multi-field key example in nw
153
156
  debug_stop = 'good breakpoint' # ' Ref: Order.(City, Country) < Location.(?, ?)'
154
157
 
158
+ def create_docs_dbml_file(self):
159
+ """ main driver - loop through resources, write admin.yaml - with backup, nw customization
160
+
161
+ Table Users {
162
+ id integerish
163
+ created_at timestamp
164
+ }
165
+ Ref: users.(id) < follows.(followed_user_id)
166
+ """
167
+
168
+ ''' decide about rebuild -- can you save positions?
169
+ if (self.mod_gen.project.command == "create-ui" or self.mod_gen.project.command.startswith("rebuild")) \
170
+ or self.mod_gen.project.command == "add_db":
171
+ if self.mod_gen.project.command.startswith("rebuild"):
172
+ log.debug(".. .. ..Use existing ui/admin directory")
173
+ else:
174
+ self.create_admin_app(msg=".. .. ..Create ui/admin")
175
+ '''
176
+
177
+ sys.path.append(self.mod_gen.project.os_cwd)
178
+
179
+ if do_table_descriptions := True:
180
+ self.dbml_descriptions()
181
+
182
+ self.dbml_resources()
183
+
184
+ self.dbms_lines.append("")
185
+ self.dbms_lines.append("")
186
+ self.dbms_lines.append("// Relationships") # Ref: users.(id) < follows.(followed_user_id)
187
+ self.dbml_relationships()
155
188
 
156
189
  expose_docs_path = Path(self.mod_gen.project_directory).joinpath('docs')
157
190
  expose_docs_path.mkdir(parents=True, exist_ok=True)
@@ -162,20 +195,41 @@ class DBMLCreator(object):
162
195
 
163
196
 
164
197
 
165
- def do_process_resource(self, resource_name: str)-> bool:
166
- """ filter out resources that are skipped by user, start with ab etc
198
+ def create_mcp_json_file(self):
199
+ """ create docs/mcp_schema.json - create self.mcp_schema['resources'] entries like:
200
+
201
+ '''
202
+ {
203
+ "name": "Customer",
204
+ "path": "/Customer",
205
+ "methods": ["GET", "PATCH"],
206
+ "fields": ["id", "name", "balance", "credit_limit"],
207
+ "filterable": ["name", "credit_limit"],
208
+ "example": "List customers with credit over 5000"
209
+ }
210
+ '''
167
211
  """
168
- if "ProductDetails_V" in resource_name:
169
- log.debug("special table") # should not occur (--noviews)
170
- if resource_name.startswith("ab_"):
171
- return False # skip admin table: " + table_name + "\n
172
- elif 'sqlite_sequence' in resource_name:
173
- return False # skip sqlite_sequence table: " + table_name + "\n
174
- elif resource_name is None:
175
- return False # no class (view): " + table_name + "\n
176
- elif resource_name.startswith("Ab"):
177
- return False
178
- return True
212
+
213
+ resources : list = self.mcp_schema['resources']
214
+ for each_resource_name in self.mod_gen.resource_list:
215
+ if self.do_process_resource(each_resource_name):
216
+ each_inserted_resource = {}
217
+ each_resource : Resource = self.mod_gen.resource_list[each_resource_name]
218
+ each_inserted_resource['name'] = each_resource.name
219
+ each_inserted_resource['path'] = '/' + each_resource.name
220
+ each_inserted_resource['methods'] = ["GET", "PATCH", "POST", "DELETE"]
221
+ each_inserted_resource['fields'] = []
222
+ for each_attr in each_resource.attributes:
223
+ each_inserted_resource['fields'].append(each_attr.name)
224
+ each_inserted_resource['filterable'] = each_inserted_resource['fields']
225
+ resources.append(each_inserted_resource)
226
+ docs_path = Path(self.mod_gen.project_directory).joinpath('docs')
227
+ docs_path.mkdir(parents=True, exist_ok=True)
228
+ mcp_schema_path = Path(self.mod_gen.project_directory).joinpath('docs/mcp_schema.json')
229
+ # write self.mcp_schema dict to json file
230
+ with open(mcp_schema_path, 'w') as f:
231
+ json.dump(self.mcp_schema, f, indent=4)
232
+
179
233
 
180
234
 
181
235
  def create(model_creation_services: create_from_model.ModelCreationServices):
@@ -183,4 +237,5 @@ def create(model_creation_services: create_from_model.ModelCreationServices):
183
237
  """
184
238
  dbml_creator = DBMLCreator(model_creation_services)
185
239
  dbml_creator.create_docs_dbml_file()
240
+ dbml_creator.create_mcp_json_file()
186
241