quickdbd-cli 0.3.4__tar.gz → 0.4.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (259) hide show
  1. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/PKG-INFO +6 -6
  2. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/README.md +5 -5
  3. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/pyproject.toml +1 -1
  4. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/scripts/build_gallery.py +2 -1
  5. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/scripts/gen_thumbnails.py +38 -14
  6. quickdbd_cli-0.4.0/src/quickdbd_cli/__init__.py +1 -0
  7. quickdbd_cli-0.4.0/src/quickdbd_cli/assets/icon.svg +1 -0
  8. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/src/quickdbd_cli/cli.py +24 -2
  9. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/src/quickdbd_cli/html.py +7 -0
  10. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/src/quickdbd_cli/share.py +16 -0
  11. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/test_gallery.py +1 -0
  12. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/test_home_hook.py +4 -1
  13. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/test_pipeline.py +2 -0
  14. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/test_share.py +49 -13
  15. quickdbd_cli-0.3.4/src/quickdbd_cli/__init__.py +0 -1
  16. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/.gitignore +0 -0
  17. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/LICENSE +0 -0
  18. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/NOTICE +0 -0
  19. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/examples/quickdbd-sample.txt +0 -0
  20. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/examples/synthetic/finance.txt +0 -0
  21. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/examples/synthetic/hr.txt +0 -0
  22. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/examples/synthetic/inventory.txt +0 -0
  23. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/examples/synthetic/marketing.txt +0 -0
  24. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/examples/synthetic/qdbd.layout.json +0 -0
  25. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/examples/synthetic/sales.txt +0 -0
  26. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/scripts/gen_font_metrics.py +0 -0
  27. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/scripts/gen_schema.py +0 -0
  28. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/scripts/import_dbml_corpus.py +0 -0
  29. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/scripts/release.sh +0 -0
  30. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/src/quickdbd_cli/__main__.py +0 -0
  31. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/src/quickdbd_cli/agent.py +0 -0
  32. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/src/quickdbd_cli/assets/Inter-Bold.ttf +0 -0
  33. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/src/quickdbd_cli/assets/Inter-Bold.woff2 +0 -0
  34. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/src/quickdbd_cli/assets/Inter-LICENSE.txt +0 -0
  35. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/src/quickdbd_cli/assets/Inter-Regular.ttf +0 -0
  36. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/src/quickdbd_cli/assets/Inter-Regular.woff2 +0 -0
  37. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/src/quickdbd_cli/assets/editor.js +0 -0
  38. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/src/quickdbd_cli/assets/elk-LICENSE.md +0 -0
  39. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/src/quickdbd_cli/assets/elk.bundled.js +0 -0
  40. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/src/quickdbd_cli/assets/font-metrics.json +0 -0
  41. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/src/quickdbd_cli/assets/render.js +0 -0
  42. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/src/quickdbd_cli/assets/style.css +0 -0
  43. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/src/quickdbd_cli/assets/syntax-reference.md +0 -0
  44. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/src/quickdbd_cli/assets/viewer.js +0 -0
  45. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/src/quickdbd_cli/convert.py +0 -0
  46. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/src/quickdbd_cli/dbml.py +0 -0
  47. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/src/quickdbd_cli/dbt.py +0 -0
  48. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/src/quickdbd_cli/diff.py +0 -0
  49. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/src/quickdbd_cli/export.py +0 -0
  50. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/src/quickdbd_cli/jsrt.py +0 -0
  51. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/src/quickdbd_cli/layout.py +0 -0
  52. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/src/quickdbd_cli/mcp.py +0 -0
  53. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/src/quickdbd_cli/measure.py +0 -0
  54. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/src/quickdbd_cli/model.py +0 -0
  55. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/src/quickdbd_cli/parser.py +0 -0
  56. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/src/quickdbd_cli/project.py +0 -0
  57. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/src/quickdbd_cli/serve.py +0 -0
  58. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/src/quickdbd_cli/tags.py +0 -0
  59. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/src/quickdbd_cli/targets.py +0 -0
  60. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/fixtures/dbml/team.dbml +0 -0
  61. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/fixtures/dbml-ref/LICENSE +0 -0
  62. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/fixtures/dbml-ref/README.md +0 -0
  63. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/fixtures/dbml-ref/binder/alias_of_duplicated_names.dbml +0 -0
  64. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/fixtures/dbml-ref/binder/alias_of_duplicated_names.json +0 -0
  65. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/fixtures/dbml-ref/binder/dep.dbml +0 -0
  66. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/fixtures/dbml-ref/binder/dep.json +0 -0
  67. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/fixtures/dbml-ref/binder/duplicate_columns.dbml +0 -0
  68. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/fixtures/dbml-ref/binder/duplicate_columns.json +0 -0
  69. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/fixtures/dbml-ref/binder/duplicate_enum_field.dbml +0 -0
  70. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/fixtures/dbml-ref/binder/duplicate_enum_field.json +0 -0
  71. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/fixtures/dbml-ref/binder/duplicate_name.dbml +0 -0
  72. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/fixtures/dbml-ref/binder/duplicate_name.json +0 -0
  73. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/fixtures/dbml-ref/binder/duplicate_names.dbml +0 -0
  74. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/fixtures/dbml-ref/binder/duplicate_names.json +0 -0
  75. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/fixtures/dbml-ref/binder/duplicate_table_partial_injections.dbml +0 -0
  76. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/fixtures/dbml-ref/binder/duplicate_table_partial_injections.json +0 -0
  77. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/fixtures/dbml-ref/binder/enum_as_default_column_value.dbml +0 -0
  78. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/fixtures/dbml-ref/binder/enum_as_default_column_value.json +0 -0
  79. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/fixtures/dbml-ref/binder/enum_name.dbml +0 -0
  80. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/fixtures/dbml-ref/binder/enum_name.json +0 -0
  81. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/fixtures/dbml-ref/binder/erroneous.dbml +0 -0
  82. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/fixtures/dbml-ref/binder/erroneous.json +0 -0
  83. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/fixtures/dbml-ref/binder/multiple_notes_in_table_group.dbml +0 -0
  84. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/fixtures/dbml-ref/binder/multiple_notes_in_table_group.json +0 -0
  85. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/fixtures/dbml-ref/binder/nonexisting_column_in_index.dbml +0 -0
  86. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/fixtures/dbml-ref/binder/nonexisting_column_in_index.json +0 -0
  87. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/fixtures/dbml-ref/binder/nonexisting_column_in_index_table_partial.dbml +0 -0
  88. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/fixtures/dbml-ref/binder/nonexisting_column_in_index_table_partial.json +0 -0
  89. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/fixtures/dbml-ref/binder/nonexisting_inline_ref_column_in_table.dbml +0 -0
  90. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/fixtures/dbml-ref/binder/nonexisting_inline_ref_column_in_table.json +0 -0
  91. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/fixtures/dbml-ref/binder/nonexisting_inline_ref_column_in_table_partial.dbml +0 -0
  92. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/fixtures/dbml-ref/binder/nonexisting_inline_ref_column_in_table_partial.json +0 -0
  93. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/fixtures/dbml-ref/binder/ref_validator.dbml +0 -0
  94. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/fixtures/dbml-ref/binder/ref_validator.json +0 -0
  95. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/fixtures/dbml-ref/binder/sticky_notes_validator.dbml +0 -0
  96. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/fixtures/dbml-ref/binder/sticky_notes_validator.json +0 -0
  97. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/fixtures/dbml-ref/binder/table_partial.dbml +0 -0
  98. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/fixtures/dbml-ref/binder/table_partial.json +0 -0
  99. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/fixtures/dbml-ref/binder/unknown_table_group_field.dbml +0 -0
  100. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/fixtures/dbml-ref/binder/unknown_table_group_field.json +0 -0
  101. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/fixtures/dbml-ref/interpreter/array_type.dbml +0 -0
  102. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/fixtures/dbml-ref/interpreter/array_type.json +0 -0
  103. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/fixtures/dbml-ref/interpreter/checks.dbml +0 -0
  104. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/fixtures/dbml-ref/interpreter/checks.json +0 -0
  105. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/fixtures/dbml-ref/interpreter/circular_ref_1_inline_1_element.dbml +0 -0
  106. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/fixtures/dbml-ref/interpreter/circular_ref_1_inline_1_element.json +0 -0
  107. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/fixtures/dbml-ref/interpreter/circular_ref_2_elements.dbml +0 -0
  108. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/fixtures/dbml-ref/interpreter/circular_ref_2_elements.json +0 -0
  109. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/fixtures/dbml-ref/interpreter/circular_ref_2_inlines.dbml +0 -0
  110. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/fixtures/dbml-ref/interpreter/circular_ref_2_inlines.json +0 -0
  111. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/fixtures/dbml-ref/interpreter/column_caller_type.dbml +0 -0
  112. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/fixtures/dbml-ref/interpreter/column_caller_type.json +0 -0
  113. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/fixtures/dbml-ref/interpreter/comment.dbml +0 -0
  114. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/fixtures/dbml-ref/interpreter/comment.json +0 -0
  115. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/fixtures/dbml-ref/interpreter/composite_pk.dbml +0 -0
  116. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/fixtures/dbml-ref/interpreter/composite_pk.json +0 -0
  117. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/fixtures/dbml-ref/interpreter/default_tables.dbml +0 -0
  118. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/fixtures/dbml-ref/interpreter/default_tables.json +0 -0
  119. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/fixtures/dbml-ref/interpreter/dep.dbml +0 -0
  120. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/fixtures/dbml-ref/interpreter/dep.json +0 -0
  121. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/fixtures/dbml-ref/interpreter/dep_color.dbml +0 -0
  122. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/fixtures/dbml-ref/interpreter/dep_color.json +0 -0
  123. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/fixtures/dbml-ref/interpreter/dep_duplicate.dbml +0 -0
  124. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/fixtures/dbml-ref/interpreter/dep_duplicate.json +0 -0
  125. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/fixtures/dbml-ref/interpreter/dep_pipeline.dbml +0 -0
  126. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/fixtures/dbml-ref/interpreter/dep_pipeline.json +0 -0
  127. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/fixtures/dbml-ref/interpreter/enum_as_default_column_value.dbml +0 -0
  128. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/fixtures/dbml-ref/interpreter/enum_as_default_column_value.json +0 -0
  129. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/fixtures/dbml-ref/interpreter/enum_tables.dbml +0 -0
  130. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/fixtures/dbml-ref/interpreter/enum_tables.json +0 -0
  131. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/fixtures/dbml-ref/interpreter/erroneous.dbml +0 -0
  132. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/fixtures/dbml-ref/interpreter/erroneous.json +0 -0
  133. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/fixtures/dbml-ref/interpreter/general_schema.dbml +0 -0
  134. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/fixtures/dbml-ref/interpreter/general_schema.json +0 -0
  135. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/fixtures/dbml-ref/interpreter/header_color_tables.dbml +0 -0
  136. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/fixtures/dbml-ref/interpreter/header_color_tables.json +0 -0
  137. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/fixtures/dbml-ref/interpreter/index_table_partial.dbml +0 -0
  138. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/fixtures/dbml-ref/interpreter/index_table_partial.json +0 -0
  139. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/fixtures/dbml-ref/interpreter/index_tables.dbml +0 -0
  140. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/fixtures/dbml-ref/interpreter/index_tables.json +0 -0
  141. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/fixtures/dbml-ref/interpreter/metadata.dbml +0 -0
  142. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/fixtures/dbml-ref/interpreter/metadata.json +0 -0
  143. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/fixtures/dbml-ref/interpreter/metadata_errors.dbml +0 -0
  144. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/fixtures/dbml-ref/interpreter/metadata_errors.json +0 -0
  145. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/fixtures/dbml-ref/interpreter/multi_notes.dbml +0 -0
  146. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/fixtures/dbml-ref/interpreter/multi_notes.json +0 -0
  147. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/fixtures/dbml-ref/interpreter/multiline_string.dbml +0 -0
  148. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/fixtures/dbml-ref/interpreter/multiline_string.json +0 -0
  149. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/fixtures/dbml-ref/interpreter/negative_number.dbml +0 -0
  150. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/fixtures/dbml-ref/interpreter/negative_number.json +0 -0
  151. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/fixtures/dbml-ref/interpreter/note_normalize.dbml +0 -0
  152. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/fixtures/dbml-ref/interpreter/note_normalize.json +0 -0
  153. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/fixtures/dbml-ref/interpreter/note_normalize_with_top_empty_lines.dbml +0 -0
  154. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/fixtures/dbml-ref/interpreter/note_normalize_with_top_empty_lines.json +0 -0
  155. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/fixtures/dbml-ref/interpreter/old_undocumented_syntax.dbml +0 -0
  156. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/fixtures/dbml-ref/interpreter/old_undocumented_syntax.json +0 -0
  157. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/fixtures/dbml-ref/interpreter/primary_key.dbml +0 -0
  158. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/fixtures/dbml-ref/interpreter/primary_key.json +0 -0
  159. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/fixtures/dbml-ref/interpreter/project.dbml +0 -0
  160. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/fixtures/dbml-ref/interpreter/project.json +0 -0
  161. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/fixtures/dbml-ref/interpreter/ref_name_and_color_setting.dbml +0 -0
  162. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/fixtures/dbml-ref/interpreter/ref_name_and_color_setting.json +0 -0
  163. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/fixtures/dbml-ref/interpreter/ref_settings.dbml +0 -0
  164. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/fixtures/dbml-ref/interpreter/ref_settings.json +0 -0
  165. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/fixtures/dbml-ref/interpreter/referential_actions.dbml +0 -0
  166. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/fixtures/dbml-ref/interpreter/referential_actions.json +0 -0
  167. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/fixtures/dbml-ref/interpreter/self_referential_ref_in_tablepartial.dbml +0 -0
  168. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/fixtures/dbml-ref/interpreter/self_referential_ref_in_tablepartial.json +0 -0
  169. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/fixtures/dbml-ref/interpreter/sticky_notes.dbml +0 -0
  170. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/fixtures/dbml-ref/interpreter/sticky_notes.json +0 -0
  171. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/fixtures/dbml-ref/interpreter/table_element.dbml +0 -0
  172. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/fixtures/dbml-ref/interpreter/table_element.json +0 -0
  173. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/fixtures/dbml-ref/interpreter/table_group.dbml +0 -0
  174. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/fixtures/dbml-ref/interpreter/table_group.json +0 -0
  175. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/fixtures/dbml-ref/interpreter/table_group_element.dbml +0 -0
  176. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/fixtures/dbml-ref/interpreter/table_group_element.json +0 -0
  177. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/fixtures/dbml-ref/interpreter/table_group_settings.dbml +0 -0
  178. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/fixtures/dbml-ref/interpreter/table_group_settings.json +0 -0
  179. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/fixtures/dbml-ref/interpreter/table_partial.dbml +0 -0
  180. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/fixtures/dbml-ref/interpreter/table_partial.json +0 -0
  181. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/fixtures/dbml-ref/interpreter/table_reappear_tablegroup.dbml +0 -0
  182. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/fixtures/dbml-ref/interpreter/table_reappear_tablegroup.json +0 -0
  183. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/fixtures/dbml-ref/interpreter/table_settings.dbml +0 -0
  184. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/fixtures/dbml-ref/interpreter/table_settings.json +0 -0
  185. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/fixtures/dbml-ref/interpreter/tablepartial_causing_circular_ref.dbml +0 -0
  186. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/fixtures/dbml-ref/interpreter/tablepartial_causing_circular_ref.json +0 -0
  187. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/fixtures/dbml-ref/interpreter/two_inline_refs.dbml +0 -0
  188. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/fixtures/dbml-ref/interpreter/two_inline_refs.json +0 -0
  189. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/fixtures/dbml-ref/parser/call_expression.dbml +0 -0
  190. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/fixtures/dbml-ref/parser/call_expression.json +0 -0
  191. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/fixtures/dbml-ref/parser/element_in_simple_body.dbml +0 -0
  192. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/fixtures/dbml-ref/parser/element_in_simple_body.json +0 -0
  193. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/fixtures/dbml-ref/parser/erroneous_setting.dbml +0 -0
  194. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/fixtures/dbml-ref/parser/erroneous_setting.json +0 -0
  195. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/fixtures/dbml-ref/parser/expression.dbml +0 -0
  196. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/fixtures/dbml-ref/parser/expression.json +0 -0
  197. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/fixtures/dbml-ref/parser/last_invalid_number.dbml +0 -0
  198. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/fixtures/dbml-ref/parser/last_invalid_number.json +0 -0
  199. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/fixtures/dbml-ref/parser/list_expression.dbml +0 -0
  200. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/fixtures/dbml-ref/parser/list_expression.json +0 -0
  201. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/fixtures/dbml-ref/parser/trailing_comments.dbml +0 -0
  202. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/fixtures/dbml-ref/parser/trailing_comments.json +0 -0
  203. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/fixtures/dbml-ref/parser/tuple_expression.dbml +0 -0
  204. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/fixtures/dbml-ref/parser/tuple_expression.json +0 -0
  205. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/fixtures/dbml-ref/validator/checks.dbml +0 -0
  206. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/fixtures/dbml-ref/validator/checks.json +0 -0
  207. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/fixtures/dbml-ref/validator/complex_names.dbml +0 -0
  208. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/fixtures/dbml-ref/validator/complex_names.json +0 -0
  209. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/fixtures/dbml-ref/validator/dep.dbml +0 -0
  210. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/fixtures/dbml-ref/validator/dep.json +0 -0
  211. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/fixtures/dbml-ref/validator/enum.dbml +0 -0
  212. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/fixtures/dbml-ref/validator/enum.json +0 -0
  213. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/fixtures/dbml-ref/validator/invalid_args.dbml +0 -0
  214. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/fixtures/dbml-ref/validator/invalid_args.json +0 -0
  215. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/fixtures/dbml-ref/validator/public_schema.dbml +0 -0
  216. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/fixtures/dbml-ref/validator/public_schema.json +0 -0
  217. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/fixtures/dbml-ref/validator/redefined_note.dbml +0 -0
  218. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/fixtures/dbml-ref/validator/redefined_note.json +0 -0
  219. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/fixtures/dbml-ref/validator/ref_error_setting.dbml +0 -0
  220. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/fixtures/dbml-ref/validator/ref_error_setting.json +0 -0
  221. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/fixtures/dbml-ref/validator/ref_in_table.dbml +0 -0
  222. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/fixtures/dbml-ref/validator/ref_in_table.json +0 -0
  223. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/fixtures/dbml-ref/validator/schema_nested_tablegroup.dbml +0 -0
  224. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/fixtures/dbml-ref/validator/schema_nested_tablegroup.json +0 -0
  225. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/fixtures/dbml-ref/validator/table_group_settings.dbml +0 -0
  226. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/fixtures/dbml-ref/validator/table_group_settings.json +0 -0
  227. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/fixtures/dbml-ref/validator/table_partial_check.dbml +0 -0
  228. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/fixtures/dbml-ref/validator/table_partial_check.json +0 -0
  229. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/fixtures/dbml-ref/validator/table_partial_settings_general.dbml +0 -0
  230. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/fixtures/dbml-ref/validator/table_partial_settings_general.json +0 -0
  231. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/fixtures/dbml-ref/validator/table_settings_check.dbml +0 -0
  232. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/fixtures/dbml-ref/validator/table_settings_check.json +0 -0
  233. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/fixtures/dbml-ref/validator/table_settings_general.dbml +0 -0
  234. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/fixtures/dbml-ref/validator/table_settings_general.json +0 -0
  235. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/fixtures/dbml-ref/validator/wrong_sub_element_declarations.dbml +0 -0
  236. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/fixtures/dbml-ref/validator/wrong_sub_element_declarations.json +0 -0
  237. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/fixtures/dbml-ref/validator/wrong_table_partial_injection_syntax.dbml +0 -0
  238. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/fixtures/dbml-ref/validator/wrong_table_partial_injection_syntax.json +0 -0
  239. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/fixtures/jaffle/LICENSE +0 -0
  240. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/fixtures/jaffle/README.md +0 -0
  241. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/fixtures/jaffle/catalog.json +0 -0
  242. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/fixtures/jaffle/manifest.json +0 -0
  243. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/fixtures/targets/cases.json +0 -0
  244. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/test_agent.py +0 -0
  245. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/test_convert.py +0 -0
  246. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/test_dbml.py +0 -0
  247. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/test_dbml_pipeline.py +0 -0
  248. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/test_dbt.py +0 -0
  249. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/test_diff.py +0 -0
  250. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/test_mcp.py +0 -0
  251. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/test_packaging.py +0 -0
  252. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/test_parser.py +0 -0
  253. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/test_path.py +0 -0
  254. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/test_render.py +0 -0
  255. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/test_select.py +0 -0
  256. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/test_serve.py +0 -0
  257. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/test_tags.py +0 -0
  258. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/test_targets.py +0 -0
  259. {quickdbd_cli-0.3.4 → quickdbd_cli-0.4.0}/tests/test_viewer_contract.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: quickdbd-cli
3
- Version: 0.3.4
3
+ Version: 0.4.0
4
4
  Summary: Compile QuickDBD-syntax schema files into interactive HTML ER diagrams, with no table limit.
5
5
  Project-URL: Homepage, https://qdbd.dev/
6
6
  Project-URL: Documentation, https://qdbd.dev/guide/
@@ -65,10 +65,10 @@ Description-Content-Type: text/markdown
65
65
  </p>
66
66
 
67
67
  <p align="center">
68
- <a href="https://qdbd.dev/demo/adventureworks/#t=SalesOrderHeader"><img src="https://raw.githubusercontent.com/MarkPhamm/quickdbd-cli/main/docs/assets/img/hero.png" alt="The AdventureWorks sample database as a qdbd diagram, with the SalesOrderHeader table selected" width="760"></a>
68
+ <a href="https://qdbd.dev/demo/adventureworks-dw/#t=FactInternetSales"><img src="https://raw.githubusercontent.com/MarkPhamm/quickdbd-cli/main/docs/assets/img/hero.png" alt="The AdventureWorks DW star schema as a qdbd diagram, with the FactInternetSales table selected" width="760"></a>
69
69
  </p>
70
70
  <p align="center">
71
- <em>AdventureWorks (68 tables) with its column descriptions, built by qdbd. <a href="https://qdbd.dev/demo/adventureworks/#t=SalesOrderHeader">Try it live →</a></em>
71
+ <em>AdventureWorks DW (28 tables), a star schema in five regions, built by qdbd. <a href="https://qdbd.dev/demo/adventureworks-dw/#t=FactInternetSales">Try it live →</a></em>
72
72
  </p>
73
73
 
74
74
  ## What is qdbd?
@@ -169,7 +169,7 @@ In VS Code (or Cursor), the [extension](https://qdbd.dev/vscode/) does the same
169
169
  ```sh
170
170
  qdbd build schema.txt -o schema.html # one self-contained page
171
171
  qdbd export schema.txt -o schema.png # or .svg, .drawio
172
- qdbd share schema.txt # a link to the page, via a GitHub gist
172
+ QDBD_ALLOW_SHARE=1 qdbd share schema.txt # a link via a GitHub gist: off by default, see the disclaimer
173
173
  ```
174
174
 
175
175
  ## Run in CI
@@ -186,7 +186,7 @@ jobs:
186
186
  permissions: { contents: read, pull-requests: write }
187
187
  steps:
188
188
  - uses: actions/checkout@v4
189
- - uses: MarkPhamm/quickdbd-cli@v0.3.4
189
+ - uses: MarkPhamm/quickdbd-cli@v0.4.0
190
190
  with:
191
191
  path: erd/ # schema file(s) or folder(s)
192
192
  output: site/index.html
@@ -257,7 +257,7 @@ No. qdbd only borrows the text syntax.
257
257
  No. It reads `.txt` / `.dbml` schema files or a dbt `manifest.json`. Nothing connects to a warehouse.
258
258
 
259
259
  **Does my schema leave my machine?**
260
- Only if you run `qdbd share`, which uploads the page to a GitHub gist in your account (secret by default), or connect an AI agent through `qdbd mcp`, whose answers go to your AI provider. `qdbd serve` loads its code editor from a CDN; the built pages load nothing.
260
+ Only if you turn sharing on (`QDBD_ALLOW_SHARE=1`, or `quickdbd.allowSharing` in VS Code) and run `qdbd share`, which uploads the page to a GitHub gist in your account (secret by default), publish it yourself (a tunnel, GitHub Pages), or connect an AI agent through `qdbd mcp`, whose answers go to your AI provider. `qdbd serve` loads its code editor from a CDN; the built pages load nothing.
261
261
 
262
262
  **How big can a diagram get?**
263
263
  The demos go up to 200 tables. Search, selectors, regions and collapsed views keep large diagrams workable; `--select` builds a page with just the part you need.
@@ -27,10 +27,10 @@
27
27
  </p>
28
28
 
29
29
  <p align="center">
30
- <a href="https://qdbd.dev/demo/adventureworks/#t=SalesOrderHeader"><img src="https://raw.githubusercontent.com/MarkPhamm/quickdbd-cli/main/docs/assets/img/hero.png" alt="The AdventureWorks sample database as a qdbd diagram, with the SalesOrderHeader table selected" width="760"></a>
30
+ <a href="https://qdbd.dev/demo/adventureworks-dw/#t=FactInternetSales"><img src="https://raw.githubusercontent.com/MarkPhamm/quickdbd-cli/main/docs/assets/img/hero.png" alt="The AdventureWorks DW star schema as a qdbd diagram, with the FactInternetSales table selected" width="760"></a>
31
31
  </p>
32
32
  <p align="center">
33
- <em>AdventureWorks (68 tables) with its column descriptions, built by qdbd. <a href="https://qdbd.dev/demo/adventureworks/#t=SalesOrderHeader">Try it live →</a></em>
33
+ <em>AdventureWorks DW (28 tables), a star schema in five regions, built by qdbd. <a href="https://qdbd.dev/demo/adventureworks-dw/#t=FactInternetSales">Try it live →</a></em>
34
34
  </p>
35
35
 
36
36
  ## What is qdbd?
@@ -131,7 +131,7 @@ In VS Code (or Cursor), the [extension](https://qdbd.dev/vscode/) does the same
131
131
  ```sh
132
132
  qdbd build schema.txt -o schema.html # one self-contained page
133
133
  qdbd export schema.txt -o schema.png # or .svg, .drawio
134
- qdbd share schema.txt # a link to the page, via a GitHub gist
134
+ QDBD_ALLOW_SHARE=1 qdbd share schema.txt # a link via a GitHub gist: off by default, see the disclaimer
135
135
  ```
136
136
 
137
137
  ## Run in CI
@@ -148,7 +148,7 @@ jobs:
148
148
  permissions: { contents: read, pull-requests: write }
149
149
  steps:
150
150
  - uses: actions/checkout@v4
151
- - uses: MarkPhamm/quickdbd-cli@v0.3.4
151
+ - uses: MarkPhamm/quickdbd-cli@v0.4.0
152
152
  with:
153
153
  path: erd/ # schema file(s) or folder(s)
154
154
  output: site/index.html
@@ -219,7 +219,7 @@ No. qdbd only borrows the text syntax.
219
219
  No. It reads `.txt` / `.dbml` schema files or a dbt `manifest.json`. Nothing connects to a warehouse.
220
220
 
221
221
  **Does my schema leave my machine?**
222
- Only if you run `qdbd share`, which uploads the page to a GitHub gist in your account (secret by default), or connect an AI agent through `qdbd mcp`, whose answers go to your AI provider. `qdbd serve` loads its code editor from a CDN; the built pages load nothing.
222
+ Only if you turn sharing on (`QDBD_ALLOW_SHARE=1`, or `quickdbd.allowSharing` in VS Code) and run `qdbd share`, which uploads the page to a GitHub gist in your account (secret by default), publish it yourself (a tunnel, GitHub Pages), or connect an AI agent through `qdbd mcp`, whose answers go to your AI provider. `qdbd serve` loads its code editor from a CDN; the built pages load nothing.
223
223
 
224
224
  **How big can a diagram get?**
225
225
  The demos go up to 200 tables. Search, selectors, regions and collapsed views keep large diagrams workable; `--select` builds a page with just the part you need.
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "quickdbd-cli"
7
- version = "0.3.4"
7
+ version = "0.4.0"
8
8
  description = "Compile QuickDBD-syntax schema files into interactive HTML ER diagrams, with no table limit."
9
9
  readme = "README.md"
10
10
  license = "Apache-2.0"
@@ -19,7 +19,7 @@ from pathlib import Path
19
19
  from quickdbd_cli import __version__, diff
20
20
  from quickdbd_cli.dbt import import_dbt
21
21
  from quickdbd_cli.export import font_css
22
- from quickdbd_cli.html import _escape, _json_for_script, render_page
22
+ from quickdbd_cli.html import _escape, _json_for_script, favicon, render_page
23
23
  from quickdbd_cli.parser import compile_sources
24
24
  from quickdbd_cli.project import Project
25
25
 
@@ -175,6 +175,7 @@ def gallery_page(catalog: Catalog, stats: dict[str, dict]) -> str:
175
175
  html = TEMPLATE.read_text(encoding="utf-8")
176
176
  return (
177
177
  html.replace("/*FONT_CSS*/", font_css())
178
+ .replace("<!--FAVICON-->", favicon())
178
179
  .replace("__VERSION__", _escape(__version__))
179
180
  .replace("__DATA__", _json_for_script(data))
180
181
  )
@@ -3,6 +3,7 @@
3
3
  python scripts/gen_thumbnails.py # every demo
4
4
  python scripts/gen_thumbnails.py diff tags # just these
5
5
  python scripts/gen_thumbnails.py hero # the README hero (docs/assets/img/hero.png)
6
+ python scripts/gen_thumbnails.py path-sql # the home page's path-to-SQL shot (docs/assets/img/path-sql.png)
6
7
 
7
8
  Dev-only: needs Playwright (`uv pip install -p .venv playwright`) and drives the system Chrome, so no
8
9
  browser download. Each demo is opened at its `view` + `shot` URL hash; the screenshot is framed in a card
@@ -24,28 +25,37 @@ from quickdbd_cli.html import _escape
24
25
 
25
26
  W, H = 1200, 630
26
27
  SHOT_W, SHOT_H = 1280, 820
28
+ # The home page's "Every relationship is a JOIN" section; hooks/home.py asks join_path for the same two tables.
29
+ PATH_SHOT = ("sakila", "t=payment&p=country")
27
30
  # Hidden in the screenshot: the table list, toolbar, minimap and hint. The details panel and diff bar stay.
28
31
  CLEAN = ".explorer, .bar, .minimap, .hint { display: none !important; }"
29
32
 
30
- CARD = """<!doctype html><html><head><meta charset="utf-8"><style>{font}
33
+ CARD = """<!doctype html><html><head><meta charset="utf-8">
34
+ <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Geist:wght@500;600&family=Geist+Mono&display=swap">
35
+ <style>{font}
31
36
  * {{ box-sizing: border-box; margin: 0; }}
32
- body {{ width: {w}px; height: {h}px; overflow: hidden; font-family: Inter, sans-serif; color: #0f1b2d;
33
- background: #eef3fb; background-image: linear-gradient(#dfe7f3 1px, transparent 1px),
34
- linear-gradient(90deg, #dfe7f3 1px, transparent 1px); background-size: 28px 28px; position: relative; }}
35
- .text {{ position: absolute; left: 56px; top: 64px; width: 360px; }}
36
- .brand {{ display: flex; align-items: center; gap: 10px; font-weight: 700; font-size: 26px; margin-bottom: 44px; }}
37
- .brand svg {{ color: #2563eb; }}
38
- h1 {{ display: inline; font-size: 46px; line-height: 1.32; font-weight: 700; color: #fff; background: #2563eb;
39
- padding: 2px 10px; -webkit-box-decoration-break: clone; box-decoration-break: clone; }}
40
- p {{ margin-top: 26px; font-size: 21px; line-height: 1.5; color: #42526b; }}
41
- .shot {{ position: absolute; left: 460px; top: 56px; width: {sw}px; border-radius: 14px; overflow: hidden;
42
- border: 1px solid #cfd8e6; box-shadow: 0 18px 50px rgba(15, 27, 45, .18); background: #fff; }}
37
+ body {{ width: {w}px; height: {h}px; overflow: hidden; font-family: Geist, Inter, sans-serif; color: #15181e;
38
+ position: relative; --a: rgba(21, 24, 30, .07); --b: rgba(21, 24, 30, .04); background: #f2f2ee;
39
+ background-image: linear-gradient(var(--a) 1px, #0000 1px), linear-gradient(90deg, var(--a) 1px, #0000 1px),
40
+ linear-gradient(var(--b) 1px, #0000 1px), linear-gradient(90deg, var(--b) 1px, #0000 1px);
41
+ background-size: 120px 120px, 120px 120px, 24px 24px, 24px 24px; background-position: -1px -1px; }}
42
+ .text {{ position: absolute; left: 56px; top: 60px; width: 360px; }}
43
+ .brand {{ display: flex; align-items: center; gap: 10px; font-weight: 600; font-size: 26px; letter-spacing: -.02em;
44
+ margin-bottom: 40px; }}
45
+ .brand svg {{ color: #2f5bea; }}
46
+ .brand span {{ font: 16px "Geist Mono", monospace; color: #646a75; border: 1px solid rgba(21, 24, 30, .24);
47
+ border-radius: 6px; padding: 3px 8px; margin-left: 4px; letter-spacing: 0; }}
48
+ h1 {{ font-size: 48px; line-height: 1.04; font-weight: 600; letter-spacing: -.04em; }}
49
+ p {{ margin-top: 22px; font-size: 21px; line-height: 1.5; color: #4a505b; }}
50
+ .shot {{ position: absolute; left: 460px; top: 56px; width: {sw}px; border-radius: 12px; overflow: hidden;
51
+ border: 1px solid rgba(21, 24, 30, .24); box-shadow: 0 18px 40px -18px rgba(21, 24, 30, .28); background: #fff; }}
43
52
  .shot img {{ display: block; width: 100%; }}
44
53
  </style></head><body>
45
54
  <div class="text">
46
55
  <div class="brand"><svg width="30" height="30" viewBox="0 0 24 24"><rect x="2" y="2.5" width="10" height="8" rx="2"
47
56
  fill="currentColor"/><rect x="12" y="13.5" width="10" height="8" rx="2" fill="currentColor" opacity=".55"/><path
48
- d="M7 10.5v3.5a3.5 3.5 0 0 0 3.5 3.5H12" stroke="currentColor" stroke-width="2" fill="none"/></svg>qdbd</div>
57
+ d="M7 10.5v3.5a3.5 3.5 0 0 0 3.5 3.5H12" stroke="currentColor" stroke-width="2" fill="none"/></svg>qdbd
58
+ <span>demo</span></div>
49
59
  <h1>{title}</h1>
50
60
  <p>{description}</p>
51
61
  </div>
@@ -85,7 +95,7 @@ def main(argv: list[str]) -> int:
85
95
  img=img,
86
96
  )
87
97
  )
88
- card.wait_for_timeout(100)
98
+ card.evaluate("document.fonts.ready.then(() => true)") # Geist comes from Google Fonts
89
99
  dst = THUMBS / f"{d.id}.png"
90
100
  card.screenshot(path=str(dst))
91
101
  print(f"Wrote {dst.relative_to(THUMBS.parents[3])}")
@@ -98,6 +108,20 @@ def main(argv: list[str]) -> int:
98
108
  dst = ROOT / "docs" / "assets" / "img" / "hero.png"
99
109
  page.screenshot(path=str(dst))
100
110
  print(f"Wrote {dst.relative_to(ROOT)}")
111
+ if "path-sql" in (set(argv) or {"path-sql"}):
112
+ page.set_viewport_size({"width": 1440, "height": 860})
113
+ page.goto((out / PATH_SHOT[0] / "index.html").as_uri() + f"#{PATH_SHOT[1]}")
114
+ page.wait_for_timeout(800)
115
+ page.get_by_text("Show only this path").click()
116
+ # the home page shows the SQL beside the shot, so the panel goes and the whole path shows
117
+ page.add_style_tag(content=".details, .hint { display: none !important; }")
118
+ page.click("#zfit")
119
+ page.click("#zout") # fit counts tables only; the payment edge loops out to the right
120
+ page.mouse.move(700, 820)
121
+ page.wait_for_timeout(800)
122
+ dst = ROOT / "docs" / "assets" / "img" / "path-sql.png"
123
+ page.screenshot(path=str(dst))
124
+ print(f"Wrote {dst.relative_to(ROOT)}")
101
125
  browser.close()
102
126
  return 0
103
127
 
@@ -0,0 +1 @@
1
+ __version__ = "0.4.0"
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 128 128"><rect width="128" height="128" rx="28" fill="#2563eb"/><rect x="22" y="22" width="42" height="36" rx="9" fill="#fff"/><path d="M44 58v19a10 10 0 0 0 10 10h12" fill="none" stroke="#fff" stroke-width="8"/><rect x="64" y="70" width="42" height="33" rx="8" fill="#a8c1f7"/></svg>
@@ -158,10 +158,28 @@ def cmd_build(args) -> int:
158
158
  def cmd_share(args) -> int:
159
159
  from . import share
160
160
 
161
+ if not share.allowed():
162
+ print(
163
+ "error: sharing is off. qdbd share uploads the diagram (every table and column name) to a GitHub gist"
164
+ f" that anyone with the link can open. If your data policy allows that, set {share.ALLOW_ENV}=1"
165
+ " (doing so accepts https://qdbd.dev/sharing/#disclaimer).",
166
+ file=sys.stderr,
167
+ )
168
+ return 2
161
169
  res = _built_page(args)
162
170
  if isinstance(res, int):
163
171
  return res
164
172
  page, model = res
173
+ print(share.DISCLAIMER, file=sys.stderr)
174
+ if not args.yes:
175
+ if not sys.stdin.isatty():
176
+ print("error: no terminal to confirm in: add --yes to accept the disclaimer and share", file=sys.stderr)
177
+ return 2
178
+ kind = "public" if args.public else "secret"
179
+ print(f"Share {len(model['tables'])} tables as a {kind} gist? [y/N] ", end="", file=sys.stderr, flush=True)
180
+ if sys.stdin.readline().strip().lower() not in ("y", "yes"):
181
+ print("Not shared.", file=sys.stderr)
182
+ return 2
165
183
  key = share.share_key(args.paths, selector_expr(args.select, args.exclude))
166
184
  try:
167
185
  r = share.publish(page, _title(_open(args)), key, public=args.public, new=args.new)
@@ -571,7 +589,10 @@ def build_parser() -> argparse.ArgumentParser:
571
589
  sp.add_argument("--strict", action="store_true")
572
590
  sp.set_defaults(func=cmd_build)
573
591
 
574
- sp = sub.add_parser("share", help="publish the diagram as a GitHub gist and print a link (needs the gh CLI)")
592
+ sp = sub.add_parser(
593
+ "share",
594
+ help="publish the diagram as a GitHub gist and print a link (off unless QDBD_ALLOW_SHARE=1; needs the gh CLI)",
595
+ )
575
596
  paths(sp)
576
597
  selectors(sp)
577
598
  sp.add_argument(
@@ -582,6 +603,7 @@ def build_parser() -> argparse.ArgumentParser:
582
603
  sp.add_argument("--strict", action="store_true")
583
604
  sp.add_argument("--public", action="store_true", help="list the gist publicly (default: secret, link-only)")
584
605
  sp.add_argument("--new", action="store_true", help="make a new gist instead of updating the last one")
606
+ sp.add_argument("-y", "--yes", action="store_true", help="accept the disclaimer without asking (for scripts)")
585
607
  sp.set_defaults(func=cmd_share)
586
608
 
587
609
  sp = sub.add_parser("export", help="write a PNG, SVG or draw.io file")
@@ -665,7 +687,7 @@ def build_parser() -> argparse.ArgumentParser:
665
687
  sp.add_argument(
666
688
  "--read-only",
667
689
  action="store_true",
668
- help="live view only: no editor, nothing saved; safe to share through a tunnel",
690
+ help="live view only: no editor, nothing saved; viewers can't change anything",
669
691
  )
670
692
  sp.add_argument(
671
693
  "--embed",
@@ -4,6 +4,7 @@ from __future__ import annotations
4
4
 
5
5
  import json
6
6
  from importlib import resources
7
+ from urllib.parse import quote
7
8
 
8
9
  from .export import font_css
9
10
 
@@ -14,6 +15,11 @@ def _asset(name: str) -> str:
14
15
  return resources.files("quickdbd_cli").joinpath(f"assets/{name}").read_text(encoding="utf-8")
15
16
 
16
17
 
18
+ def favicon() -> str:
19
+ """The VS Code extension's icon as an inline SVG data URL, so pages stay single-file."""
20
+ return f'<link rel="icon" href="data:image/svg+xml,{quote(_asset("icon.svg").strip(), safe=" /=:")}">'
21
+
22
+
17
23
  def _json_for_script(obj) -> str:
18
24
  # Safe inside <script type="application/json">: no "</" sequences.
19
25
  return json.dumps(obj, sort_keys=True, separators=(",", ":"), ensure_ascii=False).replace("</", "<\\/")
@@ -171,6 +177,7 @@ def render_page(
171
177
  '<!doctype html>\n<html lang="en"><head><meta charset="utf-8">'
172
178
  '<meta name="viewport" content="width=device-width, initial-scale=1">'
173
179
  '<meta name="generator" content="qdbd">'
180
+ f"{favicon()}"
174
181
  f"<title>{_escape(title)}</title>"
175
182
  f"<script>{THEME_JS}</script>"
176
183
  # The font CSS lives in its own <style> so the viewer can reuse it for SVG/PNG export
@@ -4,6 +4,10 @@ Uses the GitHub CLI (``gh api``), so it inherits the user's login. Gists are sec
4
4
  ``public``. The gist made for each input/selection is remembered in the user's cache directory, so
5
5
  sharing again updates the same gist and the link stays the same. The VS Code extension does the same
6
6
  without gh (vscode/src/gist.ts) and shares the cache: keep the two in step.
7
+
8
+ Off unless ``QDBD_ALLOW_SHARE`` is set: a gist puts the schema outside the organisation's control, which a
9
+ client's data agreements may not allow. The extension's own switch is the ``quickdbd.allowSharing`` setting.
10
+ Even then, every share shows ``DISCLAIMER`` and asks first; the extension's dialog (export.ts) says the same.
7
11
  """
8
12
 
9
13
  from __future__ import annotations
@@ -15,11 +19,23 @@ import subprocess
15
19
  from dataclasses import dataclass
16
20
  from pathlib import Path
17
21
 
22
+ ALLOW_ENV = "QDBD_ALLOW_SHARE"
23
+ DISCLAIMER = """\
24
+ Before you share: this uploads the diagram (every table and column name, type, key, relationship
25
+ and comment) to a GitHub gist. Anyone with the link can open it, and copies can outlive the gist.
26
+ By sharing, you confirm that you have the right to publish this schema, that your organisation's
27
+ policies and any client agreements allow it, and that qdbd's authors are not liable for any
28
+ disclosure. Full disclaimer: https://qdbd.dev/sharing/#disclaimer"""
29
+
18
30
 
19
31
  class ShareError(Exception):
20
32
  pass
21
33
 
22
34
 
35
+ def allowed() -> bool:
36
+ return os.environ.get(ALLOW_ENV, "").strip().lower() in ("1", "true", "yes", "on")
37
+
38
+
23
39
  @dataclass
24
40
  class Shared:
25
41
  link: str # gistpreview: renders the gist's HTML, keeps the #view part of the URL
@@ -96,6 +96,7 @@ def test_sample_databases_and_dbt_projects(built):
96
96
  assert len(m["tables"]) == n and m["rels"], d
97
97
  dw = _model(built / "adventureworks-dw" / "index.html")
98
98
  assert {"dim", "fact"} <= {t["name"] for t in dw["tags"]} # coloured by the Dim/Fact name prefixes
99
+ assert dw["regions"] and len({t["group"] for t in dw["tables"]}) == 5 # one region per business process
99
100
  aw = _model(built / "adventureworks" / "index.html")
100
101
  assert aw["regions"] and any(t.get("doc") for t in aw["tables"]) # MS_Description -> tooltips
101
102
 
@@ -49,4 +49,7 @@ def test_build_tour(tmp_path):
49
49
  assert page.exists()
50
50
  text = page.read_text(encoding="utf-8")
51
51
  model = json.loads(re.search(r'id="qdbd-data">(.*?)</script>', text, re.S).group(1))["model"]
52
- assert len(model["tables"]) == 68
52
+ assert len(model["tables"]) == 28 and model["regions"]
53
+ # the tables docs/javascripts/home-tour.js types, clicks and paths between
54
+ driven = {"FactInternetSales", "DimCustomer", "FactResellerSales", "DimProductCategory"}
55
+ assert driven <= {t["id"] for t in model["tables"]}
@@ -248,6 +248,8 @@ def test_build_is_deterministic_and_does_not_write_sidecar(tmp_path):
248
248
  assert not (work / "qdbd.layout.json").exists()
249
249
  html = a.read_text()
250
250
  assert "<title>s</title>" in html and '"serve":false' in html
251
+ # the VS Code icon, inline so the page stays one file
252
+ assert '<link rel="icon" href="data:image/svg+xml,%3Csvg ' in html
251
253
 
252
254
 
253
255
  def test_layout_command_writes_sidecar_and_reset(tmp_path):
@@ -1,5 +1,6 @@
1
1
  """`qdbd share`, with `gh api` faked (no network)."""
2
2
 
3
+ import io
3
4
  import json
4
5
  import subprocess
5
6
 
@@ -42,6 +43,7 @@ def gh(monkeypatch, tmp_path):
42
43
  fake = FakeGh()
43
44
  monkeypatch.setattr(share.subprocess, "run", fake)
44
45
  monkeypatch.setenv("QDBD_CACHE_DIR", str(tmp_path / "cache"))
46
+ monkeypatch.setenv("QDBD_ALLOW_SHARE", "1")
45
47
  return fake
46
48
 
47
49
 
@@ -53,8 +55,9 @@ def schema(tmp_path):
53
55
 
54
56
 
55
57
  def test_share_creates_a_secret_gist_and_prints_links(gh, schema, capsys):
56
- assert main(["share", str(schema)]) == 0
57
- out = capsys.readouterr().out
58
+ assert main(["share", "--yes", str(schema)]) == 0
59
+ out, err = capsys.readouterr()
60
+ assert "Before you share" in err and "https://qdbd.dev/sharing/#disclaimer" in err
58
61
  method, endpoint, payload = gh.calls[0]
59
62
  assert (method, endpoint, payload["public"]) == ("POST", "/gists", False)
60
63
  assert list(payload["files"]) == ["shop.html"]
@@ -64,10 +67,43 @@ def test_share_creates_a_secret_gist_and_prints_links(gh, schema, capsys):
64
67
  assert "https://gist.githack.com/me/g1/raw/shop.html" in out
65
68
 
66
69
 
70
+ @pytest.mark.parametrize("value", [None, "", "0", "false"])
71
+ def test_sharing_is_off_unless_allowed(gh, schema, capsys, monkeypatch, value):
72
+ if value is None:
73
+ monkeypatch.delenv("QDBD_ALLOW_SHARE")
74
+ else:
75
+ monkeypatch.setenv("QDBD_ALLOW_SHARE", value)
76
+ assert main(["share", "--yes", str(schema)]) == 2 # --yes accepts the disclaimer, not the switch
77
+ assert gh.calls == []
78
+ assert "set QDBD_ALLOW_SHARE=1" in capsys.readouterr().err
79
+
80
+
81
+ class Tty(io.StringIO):
82
+ def isatty(self):
83
+ return True
84
+
85
+
86
+ @pytest.mark.parametrize(("answer", "code", "uploads"), [("y\n", 0, 1), ("yes\n", 0, 1), ("n\n", 2, 0), ("\n", 2, 0)])
87
+ def test_asks_before_sharing(gh, schema, capsys, monkeypatch, answer, code, uploads):
88
+ monkeypatch.setattr("sys.stdin", Tty(answer))
89
+ assert main(["share", str(schema)]) == code
90
+ assert len(gh.calls) == uploads
91
+ err = capsys.readouterr().err
92
+ assert "Before you share" in err
93
+ assert "Share 2 tables as a secret gist? [y/N]" in err
94
+
95
+
96
+ def test_no_terminal_needs_yes(gh, schema, capsys, monkeypatch):
97
+ monkeypatch.setattr("sys.stdin", io.StringIO("y\n")) # piped input doesn't count as consent
98
+ assert main(["share", str(schema)]) == 2
99
+ assert gh.calls == []
100
+ assert "add --yes" in capsys.readouterr().err
101
+
102
+
67
103
  def test_sharing_again_updates_the_same_gist(gh, schema, capsys):
68
- main(["share", str(schema)])
104
+ main(["share", "--yes", str(schema)])
69
105
  schema.write_text(SCHEMA + "\nProduct\n-\nId PK int\n")
70
- assert main(["share", str(schema)]) == 0
106
+ assert main(["share", "--yes", str(schema)]) == 0
71
107
  assert [c[0] for c in gh.calls] == ["POST", "PATCH"]
72
108
  assert gh.calls[1][1] == "/gists/g1"
73
109
  assert "Product" in gh.gists["g1"]["files"]["shop.html"]["content"]
@@ -75,37 +111,37 @@ def test_sharing_again_updates_the_same_gist(gh, schema, capsys):
75
111
 
76
112
 
77
113
  def test_new_and_selection_make_separate_gists(gh, schema):
78
- main(["share", str(schema)])
79
- main(["share", str(schema), "--new"])
80
- main(["share", str(schema), "-s", "Order+"])
114
+ main(["share", "--yes", str(schema)])
115
+ main(["share", "--yes", str(schema), "--new"])
116
+ main(["share", "--yes", str(schema), "-s", "Order+"])
81
117
  assert [c[0] for c in gh.calls] == ["POST", "POST", "POST"]
82
- main(["share", str(schema), "-s", "Order+"])
118
+ main(["share", "--yes", str(schema), "-s", "Order+"])
83
119
  assert gh.calls[-1][:2] == ("PATCH", "/gists/g3")
84
120
 
85
121
 
86
122
  def test_deleted_gist_is_recreated(gh, schema):
87
- main(["share", str(schema)])
123
+ main(["share", "--yes", str(schema)])
88
124
  gh.gists.clear()
89
- assert main(["share", str(schema)]) == 0
125
+ assert main(["share", "--yes", str(schema)]) == 0
90
126
  assert [c[0] for c in gh.calls] == ["POST", "PATCH", "POST"]
91
127
 
92
128
 
93
129
  def test_public_flag(gh, schema, capsys):
94
- main(["share", str(schema), "--public"])
130
+ main(["share", "--yes", str(schema), "--public"])
95
131
  assert gh.calls[0][2]["public"] is True
96
132
  assert "(public gist" in capsys.readouterr().out
97
133
 
98
134
 
99
135
  def test_errors(gh, schema, capsys, monkeypatch):
100
136
  gh.fail = "To get started with GitHub CLI, please run: gh auth login"
101
- assert main(["share", str(schema)]) == 2
137
+ assert main(["share", "--yes", str(schema)]) == 2
102
138
  assert "run gh auth login" in capsys.readouterr().err
103
139
 
104
140
  def missing(*a, **k):
105
141
  raise FileNotFoundError
106
142
 
107
143
  monkeypatch.setattr(share.subprocess, "run", missing)
108
- assert main(["share", str(schema)]) == 2
144
+ assert main(["share", "--yes", str(schema)]) == 2
109
145
  assert "needs the GitHub CLI" in capsys.readouterr().err
110
146
 
111
147
 
@@ -1 +0,0 @@
1
- __version__ = "0.3.4"
File without changes
File without changes
File without changes