ApiLogicServer 14.4.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 (95) hide show
  1. api_logic_server_cli/add_cust/add_cust.py +269 -0
  2. api_logic_server_cli/api_logic_server.py +18 -238
  3. api_logic_server_cli/api_logic_server_info.yaml +3 -3
  4. api_logic_server_cli/cli.py +38 -28
  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__/dbml.cpython-312.pyc +0 -0
  7. api_logic_server_cli/create_from_model/__pycache__/ont_build.cpython-312.pyc +0 -0
  8. api_logic_server_cli/create_from_model/__pycache__/ont_create.cpython-312.pyc +0 -0
  9. api_logic_server_cli/create_from_model/api_logic_server_utils.py +47 -0
  10. api_logic_server_cli/create_from_model/dbml.py +113 -58
  11. api_logic_server_cli/create_from_model/ont_build.py +83 -60
  12. api_logic_server_cli/create_from_model/ont_create.py +2 -1
  13. api_logic_server_cli/database/basic_demo.sqlite +0 -0
  14. api_logic_server_cli/database/basic_demo.txt +1 -0
  15. api_logic_server_cli/database/basic_demo_wg.sqlite +0 -0
  16. api_logic_server_cli/manager.py +3 -2
  17. api_logic_server_cli/prototypes/base/.vscode/launch.json +3 -2
  18. api_logic_server_cli/prototypes/base/config/config.py +66 -11
  19. api_logic_server_cli/prototypes/base/config/default.env +7 -1
  20. api_logic_server_cli/prototypes/base/database/test_data/readme.md +2 -1
  21. api_logic_server_cli/prototypes/base/integration/kafka/kafka_producer.py +5 -2
  22. api_logic_server_cli/prototypes/base/integration/n8n/n8n_producer.py +68 -21
  23. api_logic_server_cli/prototypes/base/integration/n8n/n8n_readme.md +19 -0
  24. api_logic_server_cli/prototypes/base/test/basic/server_test.py +1 -1
  25. api_logic_server_cli/prototypes/basic_demo/README.md +29 -52
  26. api_logic_server_cli/prototypes/basic_demo/customizations/api/.DS_Store +0 -0
  27. api_logic_server_cli/prototypes/basic_demo/customizations/api/api_discovery/mcp_discovery.py +139 -0
  28. api_logic_server_cli/prototypes/basic_demo/customizations/api/api_discovery/openapi.py +92 -0
  29. api_logic_server_cli/prototypes/basic_demo/customizations/config/default.env +13 -0
  30. api_logic_server_cli/prototypes/basic_demo/customizations/config/server_setup.py +388 -0
  31. api_logic_server_cli/prototypes/basic_demo/customizations/database/db.sqlite +0 -0
  32. api_logic_server_cli/prototypes/basic_demo/customizations/database/models.py +131 -0
  33. api_logic_server_cli/prototypes/basic_demo/customizations/database/system/SAFRSBaseX.py +136 -0
  34. api_logic_server_cli/prototypes/basic_demo/customizations/integration/.DS_Store +0 -0
  35. api_logic_server_cli/prototypes/basic_demo/customizations/integration/mcp/.DS_Store +0 -0
  36. api_logic_server_cli/prototypes/basic_demo/customizations/integration/mcp/README_mcp.md +15 -0
  37. api_logic_server_cli/prototypes/basic_demo/customizations/integration/mcp/mcp_client_executor.py +350 -0
  38. api_logic_server_cli/prototypes/basic_demo/customizations/integration/mcp/mcp_schema.txt +47 -0
  39. api_logic_server_cli/prototypes/basic_demo/customizations/integration/mcp/mcp_server_discovery.json +9 -0
  40. api_logic_server_cli/prototypes/{nw_no_cust/integration/mcp → basic_demo/customizations/integration/openai_function}/3_executor_test_agent.py +20 -6
  41. api_logic_server_cli/prototypes/basic_demo/customizations/integration/openai_function/README_functon.md +201 -0
  42. api_logic_server_cli/prototypes/basic_demo/customizations/integration/openai_function/ai_plugin.json +17 -0
  43. api_logic_server_cli/prototypes/basic_demo/customizations/integration/openai_function/nw-swagger_3.json +1731 -0
  44. api_logic_server_cli/prototypes/basic_demo/customizations/integration/openai_function/snippets.txt +5 -0
  45. api_logic_server_cli/prototypes/basic_demo/customizations/integration/openai_function/swagger_3 genai_demo_with_get.json +1731 -0
  46. api_logic_server_cli/prototypes/basic_demo/customizations/integration/openai_function/swagger_3.json +1782 -0
  47. api_logic_server_cli/prototypes/basic_demo/customizations/integration/openai_function/swagger_3_genai_demo.json +264 -0
  48. api_logic_server_cli/prototypes/basic_demo/customizations/integration/openai_function/swagger_3_genai_demo_with_update.json +1782 -0
  49. api_logic_server_cli/prototypes/basic_demo/customizations/logic/declare_logic.py +79 -41
  50. api_logic_server_cli/prototypes/basic_demo/customizations/security/declare_security.py +11 -12
  51. api_logic_server_cli/prototypes/basic_demo/customizations/ui/admin/admin.yaml +166 -0
  52. api_logic_server_cli/prototypes/basic_demo/iteration/api/{customize_api.py → api_discovery/order_b2b.py} +17 -23
  53. api_logic_server_cli/prototypes/basic_demo/iteration/database/db.sqlite +0 -0
  54. api_logic_server_cli/prototypes/basic_demo/iteration/integration/row_dict_maps/OrderB2B.py +6 -5
  55. api_logic_server_cli/prototypes/basic_demo/iteration/integration/row_dict_maps/OrderShipping.py +4 -4
  56. api_logic_server_cli/prototypes/basic_demo/iteration/logic/declare_logic.py +69 -43
  57. api_logic_server_cli/prototypes/basic_demo/iteration/ui/admin/admin.yaml +125 -50
  58. api_logic_server_cli/prototypes/manager/README.md +4 -0
  59. api_logic_server_cli/prototypes/nw/logic/declare_logic.py +2 -2
  60. api_logic_server_cli/prototypes/nw_no_cust/.obsidian/app.json +1 -0
  61. api_logic_server_cli/prototypes/nw_no_cust/.obsidian/appearance.json +1 -0
  62. api_logic_server_cli/prototypes/nw_no_cust/.obsidian/core-plugins.json +31 -0
  63. api_logic_server_cli/prototypes/nw_no_cust/.obsidian/workspace.json +166 -0
  64. api_logic_server_cli/prototypes/nw_no_cust/Tutorial.md +45 -26
  65. api_logic_server_cli/prototypes/nw_no_cust/api/api_discovery/openapi.py +130 -0
  66. api_logic_server_cli/prototypes/nw_no_cust/api/api_discovery/proper_update_def.json +71 -0
  67. api_logic_server_cli/prototypes/nw_no_cust/config/default.env +13 -0
  68. api_logic_server_cli/prototypes/ont_app/ontimize_seed/package-lock.json +9725 -1180
  69. api_logic_server_cli/prototypes/ont_app/ontimize_seed/package.json +3 -6
  70. api_logic_server_cli/prototypes/ont_app/ontimize_seed/src/app/shared/app.services.config.ts +1 -1
  71. api_logic_server_cli/prototypes/ont_app/ontimize_seed/src/assets/css/app.scss +4 -0
  72. api_logic_server_cli/prototypes/ont_app/ontimize_seed/src/assets/i18n/en.json +1 -1
  73. api_logic_server_cli/prototypes/ont_app/ontimize_seed/src/assets/i18n/es.json +14 -12
  74. api_logic_server_cli/prototypes/ont_app/templates/app_config.jinja +1 -1
  75. api_logic_server_cli/prototypes/ont_app/templates/date_template.html +1 -1
  76. api_logic_server_cli/prototypes/ont_app/templates/textarea_template.html +1 -1
  77. api_logic_server_cli/prototypes/ont_app/templates/timestamp_template.html +1 -1
  78. api_logic_server_cli/prototypes/sample_ai/logic/declare_logic.py +30 -13
  79. apilogicserver-14.5.3.dist-info/METADATA +168 -0
  80. {apilogicserver-14.4.0.dist-info → apilogicserver-14.5.3.dist-info}/RECORD +84 -61
  81. {apilogicserver-14.4.0.dist-info → apilogicserver-14.5.3.dist-info}/WHEEL +1 -1
  82. api_logic_server_cli/prototypes/basic_demo/apply_customizations.ps1 +0 -17
  83. api_logic_server_cli/prototypes/basic_demo/apply_customizations.sh +0 -14
  84. api_logic_server_cli/prototypes/basic_demo/apply_iteration.ps1 +0 -20
  85. api_logic_server_cli/prototypes/basic_demo/apply_iteration.sh +0 -15
  86. api_logic_server_cli/prototypes/nw_no_cust/integration/mcp/1_langchain_loader.py +0 -19
  87. api_logic_server_cli/prototypes/nw_no_cust/integration/mcp/2_gpt_mcp_prompt.txt +0 -19
  88. api_logic_server_cli/prototypes/nw_no_cust/integration/mcp/README.md +0 -17
  89. api_logic_server_cli/prototypes/nw_no_cust/integration/mcp/resources/curl.txt +0 -4
  90. api_logic_server_cli/prototypes/nw_no_cust/integration/mcp/resources/nw_swagger_3.yaml +0 -16660
  91. api_logic_server_cli/prototypes/nw_no_cust/integration/mcp/run_executor.py +0 -23
  92. apilogicserver-14.4.0.dist-info/METADATA +0 -76
  93. {apilogicserver-14.4.0.dist-info → apilogicserver-14.5.3.dist-info}/entry_points.txt +0 -0
  94. {apilogicserver-14.4.0.dist-info → apilogicserver-14.5.3.dist-info}/licenses/LICENSE +0 -0
  95. {apilogicserver-14.4.0.dist-info → apilogicserver-14.5.3.dist-info}/top_level.txt +0 -0
@@ -1595,36 +1595,46 @@ def add_cust(ctx, bind_key_url_separator: str, api_name: str, project_name: str)
1595
1595
  project_name = project.project_directory_path.parent.name if not project.project_directory_path.is_dir() else project.project_directory_path.name
1596
1596
  models_py_path = project.project_directory_path.joinpath('database/models.py')
1597
1597
 
1598
- log.debug(f"\ncli[add-cust] models_py_path={models_py_path}")
1599
- if not models_py_path.exists():
1600
- 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()
1601
1635
 
1602
- project_is_genai_demo = False # can't use project.is_genai_demo because this is not the create command...
1603
- if project.project_directory_path.joinpath('docs/project_is_genai_demo.txt').exists():
1604
- project_is_genai_demo = True
1605
-
1606
- project.abs_db_url, project.nw_db_status, project.model_file_name = create_utils.get_abs_db_url("0. Using Sample DB", project)
1607
- if create_utils.does_file_contain(search_for="CategoryTableNameTest", in_file=models_py_path):
1608
- project.add_nw_customizations(do_security=False)
1609
- log.info("\nNext step - add authentication:\n $ ApiLogicServer add-auth --db_url=auth\n\n")
1610
- elif project_is_genai_demo and create_utils.does_file_contain(search_for="Customer", in_file=models_py_path):
1611
- project.add_genai_customizations(do_security=False)
1612
- elif project_name == 'sample_ai' and create_utils.does_file_contain(search_for="CustomerName = Column(Text", in_file=models_py_path):
1613
- cocktail_napkin_path = project.project_directory_path.joinpath('logic/cocktail-napkin.jpg')
1614
- is_customized = cocktail_napkin_path.exists()
1615
- if not is_customized:
1616
- project.add_sample_ai_customizations()
1617
- else:
1618
- project.add_sample_ai_iteration()
1619
- elif project_name == 'basic_demo' and create_utils.does_file_contain(search_for="Customer", in_file=models_py_path):
1620
- cocktail_napkin_path = project.project_directory_path.joinpath('logic/cocktail-napkin.jpg')
1621
- is_customized = cocktail_napkin_path.exists()
1622
- if not is_customized:
1623
- project.add_basic_demo_customizations()
1624
1636
  else:
1625
- project.add_basic_demo_iteration()
1626
- else:
1627
- 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")
1628
1638
 
1629
1639
 
1630
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)
@@ -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