├── .cargo ├── config.toml └── insta.yaml ├── .config └── nextest.toml ├── .devcontainer.json ├── .env.example ├── .envrc ├── .github ├── actions │ └── devenv │ │ └── action.yml └── workflows │ ├── assets.yml │ └── ci.yml ├── .gitignore ├── .release-plz.toml ├── Cargo.lock ├── Cargo.toml ├── changelog.md ├── crates ├── gelx │ ├── Cargo.toml │ ├── changelog.md │ ├── queries │ │ ├── insert_location.edgeql │ │ ├── insert_user.edgeql │ │ ├── invalid.edgeql │ │ ├── remove_user.edgeql │ │ ├── select_simple_location.edgeql │ │ └── select_user.edgeql │ ├── readme.md │ ├── src │ │ ├── geometry.rs │ │ └── lib.rs │ └── tests │ │ ├── codegen.rs │ │ ├── compile.rs │ │ ├── compile │ │ ├── codegen │ │ │ ├── .gitkeep │ │ │ ├── case_01_str.rs │ │ │ ├── case_02_bool.rs │ │ │ ├── case_03_int64.rs │ │ │ ├── case_04_float64.rs │ │ │ ├── case_05_bigint.rs │ │ │ ├── case_06_decimal.rs │ │ │ ├── case_07_uuid.rs │ │ │ ├── case_08_datetime.rs │ │ │ ├── case_09_duration.rs │ │ │ ├── case_10_array.rs │ │ │ ├── case_11_tuple.rs │ │ │ ├── case_12_named_tuple.rs │ │ │ ├── case_13_set.rs │ │ │ ├── case_14_empty_set.rs │ │ │ ├── case_15_input_shape.rs │ │ │ ├── case_16_input_shape_with_args.rs │ │ │ ├── case_17_object_shape.rs │ │ │ ├── case_18_object_shape_with_args.rs │ │ │ ├── case_19_enums.rs │ │ │ ├── case_20_types_query.rs │ │ │ ├── case_21_bytes.rs │ │ │ ├── case_22_geometry.rs │ │ │ ├── case_23_geography.rs │ │ │ ├── insert_user.rs │ │ │ └── remove_user.rs │ │ └── macros │ │ │ ├── absolute_file.rs │ │ │ ├── absolute_file.stderr │ │ │ ├── extra_args.rs │ │ │ ├── extra_args.stderr │ │ │ ├── incorrect_args.rs │ │ │ ├── incorrect_args.stderr │ │ │ ├── input_tuple.rs │ │ │ ├── input_tuple.stderr │ │ │ ├── invalid_query.rs │ │ │ ├── invalid_query.stderr │ │ │ ├── invalid_query_file.rs │ │ │ ├── invalid_query_file.stderr │ │ │ ├── missing_file.rs │ │ │ ├── missing_file.stderr │ │ │ ├── no_args.rs │ │ │ └── no_args.stderr │ │ ├── query.rs │ │ └── snapshots │ │ ├── codegen__can_generate_aliased_enums@aliased_enums.snap │ │ ├── codegen__can_generate_aliased_enums@aliased_enums__builder_query_serde_strum.snap │ │ ├── codegen__can_generate_enums@enums.snap │ │ ├── codegen__can_generate_enums@enums__builder_query_serde_strum.snap │ │ ├── codegen__codegen_files@insert_user.snap │ │ ├── codegen__codegen_files@insert_user__builder_query_serde_strum.snap │ │ ├── codegen__codegen_files@remove_user.snap │ │ ├── codegen__codegen_files@remove_user__builder_query_serde_strum.snap │ │ ├── codegen__codegen_literals@case_01_str.snap │ │ ├── codegen__codegen_literals@case_01_str__builder_query_serde_strum.snap │ │ ├── codegen__codegen_literals@case_02_bool.snap │ │ ├── codegen__codegen_literals@case_02_bool__builder_query_serde_strum.snap │ │ ├── codegen__codegen_literals@case_03_int64.snap │ │ ├── codegen__codegen_literals@case_03_int64__builder_query_serde_strum.snap │ │ ├── codegen__codegen_literals@case_04_float64.snap │ │ ├── codegen__codegen_literals@case_04_float64__builder_query_serde_strum.snap │ │ ├── codegen__codegen_literals@case_05_bigint.snap │ │ ├── codegen__codegen_literals@case_05_bigint__builder_query_serde_strum.snap │ │ ├── codegen__codegen_literals@case_06_decimal.snap │ │ ├── codegen__codegen_literals@case_06_decimal__builder_query_serde_strum.snap │ │ ├── codegen__codegen_literals@case_07_uuid.snap │ │ ├── codegen__codegen_literals@case_07_uuid__builder_query_serde_strum.snap │ │ ├── codegen__codegen_literals@case_08_datetime.snap │ │ ├── codegen__codegen_literals@case_08_datetime__builder_query_serde_strum.snap │ │ ├── codegen__codegen_literals@case_09_duration.snap │ │ ├── codegen__codegen_literals@case_09_duration__builder_query_serde_strum.snap │ │ ├── codegen__codegen_literals@case_10_array.snap │ │ ├── codegen__codegen_literals@case_10_array__builder_query_serde_strum.snap │ │ ├── codegen__codegen_literals@case_11_tuple.snap │ │ ├── codegen__codegen_literals@case_11_tuple__builder_query_serde_strum.snap │ │ ├── codegen__codegen_literals@case_12_named_tuple.snap │ │ ├── codegen__codegen_literals@case_12_named_tuple__builder_query_serde_strum.snap │ │ ├── codegen__codegen_literals@case_13_set.snap │ │ ├── codegen__codegen_literals@case_13_set__builder_query_serde_strum.snap │ │ ├── codegen__codegen_literals@case_14_empty_set.snap │ │ ├── codegen__codegen_literals@case_14_empty_set__builder_query_serde_strum.snap │ │ ├── codegen__codegen_literals@case_15_input_shape.snap │ │ ├── codegen__codegen_literals@case_15_input_shape__builder_query_serde_strum.snap │ │ ├── codegen__codegen_literals@case_16_input_shape_with_args.snap │ │ ├── codegen__codegen_literals@case_16_input_shape_with_args__builder_query_serde_strum.snap │ │ ├── codegen__codegen_literals@case_17_object_shape.snap │ │ ├── codegen__codegen_literals@case_17_object_shape__builder_query_serde_strum.snap │ │ ├── codegen__codegen_literals@case_18_object_shape_with_args.snap │ │ ├── codegen__codegen_literals@case_18_object_shape_with_args__builder_query_serde_strum.snap │ │ ├── codegen__codegen_literals@case_19_enums.snap │ │ ├── codegen__codegen_literals@case_19_enums__builder_query_serde_strum.snap │ │ ├── codegen__codegen_literals@case_20_types_query.snap │ │ ├── codegen__codegen_literals@case_20_types_query__builder_query_serde_strum.snap │ │ ├── codegen__codegen_literals@case_21_bytes.snap │ │ ├── codegen__codegen_literals@case_21_bytes__builder_query_serde_strum.snap │ │ ├── codegen__codegen_literals@case_21_range.snap │ │ ├── codegen__codegen_literals@case_21_range__builder_query_serde_strum.snap │ │ ├── codegen__codegen_literals@case_22_geometry.snap │ │ ├── codegen__codegen_literals@case_22_geometry__builder_query_serde_strum.snap │ │ ├── codegen__codegen_literals@case_23_geography.snap │ │ └── codegen__codegen_literals@case_23_geography__builder_query_serde_strum.snap ├── gelx_build │ ├── Cargo.toml │ ├── changelog.md │ ├── readme.md │ ├── src │ │ └── lib.rs │ └── tests │ │ ├── build.rs │ │ └── snapshots │ │ ├── build__build.snap │ │ └── build__build_sync.snap ├── gelx_cli │ ├── Cargo.toml │ ├── changelog.md │ ├── readme.md │ ├── src │ │ ├── lib.rs │ │ └── main.rs │ └── tests │ │ ├── cli.rs │ │ └── snapshots │ │ ├── cli__check.snap │ │ ├── cli__cwd.snap │ │ ├── cli__generate_files.snap │ │ ├── cli__generate_stdout.snap │ │ ├── cli__invalid_cwd.snap │ │ └── cli__invalid_cwd_check.snap ├── gelx_core │ ├── Cargo.toml │ ├── changelog.md │ ├── fixtures │ │ └── gel.toml │ ├── readme.md │ └── src │ │ ├── constants.rs │ │ ├── errors.rs │ │ ├── lib.rs │ │ ├── metadata.rs │ │ ├── snapshots │ │ └── gelx_core__utils__tests__can_format_file.snap │ │ ├── types.rs │ │ └── utils.rs └── gelx_macros │ ├── Cargo.toml │ ├── changelog.md │ ├── readme.md │ └── src │ └── lib.rs ├── dbschema ├── additional.gel ├── default.gel └── migrations │ ├── 00001-m1k7o3t.edgeql │ ├── 00002-m15h5hl.edgeql │ ├── 00003-m1umlyt.edgeql │ └── 00004-m14fgr2.edgeql ├── deny.toml ├── devenv.lock ├── devenv.nix ├── devenv.yaml ├── dprint.json ├── examples └── gelx_example │ ├── Cargo.toml │ ├── queries │ ├── insert_location.edgeql │ ├── insert_user.edgeql │ ├── remove_user.edgeql │ ├── select_accounts.edgeql │ └── select_user.edgeql │ └── src │ ├── db │ ├── additional.rs │ ├── default.rs │ └── mod.rs │ └── main.rs ├── gel.toml ├── license ├── readme.md ├── rust-toolchain.toml ├── rustfmt.toml └── setup ├── assets ├── logo.png └── logo.svg ├── editors ├── helix │ └── languages.toml └── vscode │ ├── extensions.json │ └── settings.json └── scripts └── nextest_setup.sh /.cargo/config.toml: -------------------------------------------------------------------------------- 1 | [alias] 2 | # bins 3 | deny = ["bin", "cargo-deny"] 4 | insta = ["bin", "cargo-insta"] 5 | llvm-cov = ["bin", "cargo-llvm-cov"] 6 | nextest = ["bin", "cargo-nextest"] 7 | 8 | # testing 9 | test_all_features = ["nextest", "run", "--all-features"] 10 | test_no_features = ["nextest", "run", "--package", "gelx"] 11 | test_docs = ["test", "--doc", "--all-features"] 12 | coverage_all_features = ["llvm-cov", "--no-report", "--all-features"] 13 | coverage_no_features = ["llvm-cov", "--no-report", "--package", "gelx"] 14 | coverage_docs = ["llvm-cov", "--no-report", "--doc", "--all-features"] 15 | coverage_report = ["llvm-cov", "report", "--doctests", "--codecov", "--output-path", "codecov.json"] 16 | coverage_html = ["llvm-cov", "report", "--doctests", "--output-dir", "coverage", "--html", "--open"] 17 | -------------------------------------------------------------------------------- /.cargo/insta.yaml: -------------------------------------------------------------------------------- 1 | test: 2 | runner: nextest 3 | -------------------------------------------------------------------------------- /.devcontainer.json: -------------------------------------------------------------------------------- 1 | { 2 | "customizations": { 3 | "vscode": { 4 | "extensions": [ 5 | "mkhl.direnv" 6 | ] 7 | } 8 | }, 9 | "image": "ghcr.io/cachix/devenv:latest", 10 | "overrideCommand": false, 11 | "updateContentCommand": "devenv test" 12 | } 13 | -------------------------------------------------------------------------------- /.env.example: -------------------------------------------------------------------------------- 1 | GEL_INSTANCE="gelx" 2 | GEL_BRANCH="main" 3 | -------------------------------------------------------------------------------- /.envrc: -------------------------------------------------------------------------------- 1 | export DIRENV_WARN_TIMEOUT=20s 2 | 3 | eval "$(devenv direnvrc)" 4 | 5 | dotenv_if_exists 6 | # The use_devenv function supports passing flags to the devenv command 7 | # For example: use devenv --impure --option services.postgres.enable:bool true 8 | use devenv 9 | -------------------------------------------------------------------------------- /.github/actions/devenv/action.yml: -------------------------------------------------------------------------------- 1 | name: devenv 2 | description: "Setup development environment with devenv" 3 | inputs: 4 | github-token: 5 | description: Provide a github token 6 | required: true 7 | 8 | nix-cache: 9 | description: The location of the nix cache 10 | required: true 11 | 12 | runs: 13 | using: composite 14 | steps: 15 | - name: cache nix store 16 | uses: actions/cache@v4 17 | id: nix-cache 18 | with: 19 | path: ${{ inputs.nix-cache }} 20 | key: ${{ runner.os }}-nix-cache-${{ hashFiles('**/devenv.nix', '**/devenv.yaml', '**/devenv.lock') }} 21 | restore-keys: ${{ runner.os }}-nix-cache- 22 | 23 | - name: install nix 24 | uses: cachix/install-nix-action@v31 25 | with: 26 | github_access_token: ${{ inputs.github-token }} 27 | 28 | - name: import nix store cache 29 | if: steps.nix-cache.outputs.cache-hit == 'true' 30 | run: nix-store --import < ${{ inputs.nix-cache }} 31 | shell: bash 32 | 33 | - name: enable cachix 34 | uses: cachix/cachix-action@v16 35 | with: 36 | name: devenv 37 | 38 | - name: install devenv.sh 39 | run: | 40 | cachix use devenv 41 | nix profile install nixpkgs#devenv 42 | shell: bash 43 | 44 | - name: build developer environment 45 | run: devenv test 46 | shell: bash 47 | 48 | - name: export nix store cache 49 | if: steps.nix-cache.outputs.cache-hit != 'true' 50 | run: nix-store --export $(find /nix/store -maxdepth 1 -name '*-*')> ${{ inputs.nix-cache }} 51 | shell: bash 52 | 53 | - name: cache rust dependencies 54 | uses: Swatinem/rust-cache@v2 55 | with: 56 | key: ${{ runner.os }} 57 | 58 | - name: cache cargo binaries 59 | uses: actions/cache@v4 60 | with: 61 | path: ./.bin 62 | key: ${{ runner.os }}-cargo-bin-${{ hashFiles('rust-toolchain.toml') }}-${{ env.RUSTUP_TOOLCHAIN }} 63 | restore-keys: | 64 | ${{ runner.os }}-cargo-bin- 65 | 66 | - name: install dependencies 67 | run: install:all 68 | shell: devenv shell bash -- -e {0} 69 | 70 | - name: setup database 71 | run: db:setup 72 | shell: devenv shell bash -- -e {0} 73 | -------------------------------------------------------------------------------- /.github/workflows/assets.yml: -------------------------------------------------------------------------------- 1 | on: 2 | release: 3 | types: [created] 4 | 5 | jobs: 6 | upload_assets: 7 | strategy: 8 | matrix: 9 | include: 10 | - target: x86_64-unknown-linux-gnu 11 | os: ubuntu-latest 12 | - target: x86_64-apple-darwin 13 | os: macos-latest 14 | - target: aarch64-apple-darwin 15 | os: macos-latest 16 | - target: x86_64-pc-windows-msvc 17 | os: windows-latest 18 | runs-on: ${{ matrix.os }} 19 | steps: 20 | - name: checkout 21 | uses: actions/checkout@v4 22 | 23 | - name: upload binaries 24 | uses: taiki-e/upload-rust-binary-action@v1 25 | with: 26 | # (required) Comma-separated list of binary names (non-extension portion of filename) to build and upload. 27 | # Note that glob pattern is not supported yet. 28 | bin: gelx 29 | # (optional) Target triple, default is host triple. 30 | # This is optional but it is recommended that this always be set to 31 | # clarify which target you are building for if macOS is included in 32 | # the matrix because GitHub Actions changed the default architecture 33 | # of macos-latest since macos-14. 34 | target: ${{ matrix.target }} 35 | # (optional) On which platform to distribute the `.tar.gz` file. 36 | # [default value: unix] 37 | # [possible values: all, unix, windows, none] 38 | tar: unix 39 | # (optional) On which platform to distribute the `.zip` file. 40 | # [default value: windows] 41 | # [possible values: all, unix, windows, none] 42 | zip: windows 43 | # (required) GitHub token for uploading assets to GitHub Releases. 44 | token: ${{ secrets.GITHUB_TOKEN }} 45 | checksum: sha512 46 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | /programs/target 3 | /.helix 4 | /result 5 | /.direnv 6 | **/rustc-ice-*.txt 7 | 8 | # Devenv 9 | .devenv* 10 | devenv.local.nix 11 | 12 | **/dist/** 13 | 14 | # insta snapshots 15 | *.pending-snap 16 | *.snap.new 17 | 18 | # setup 19 | /.helix 20 | /.vscode 21 | /programs/.vscode 22 | 23 | **/tmp** 24 | **/temp**.bin/ 25 | node_modules/ 26 | /.bin/ 27 | /.sass-cache/ 28 | /.test-results/ 29 | /test-results/ 30 | /playwright-report/ 31 | 32 | # misc 33 | .DS_Store 34 | *.pem 35 | 36 | **/*.tsbuildinfo 37 | /prisma.db 38 | 39 | .env 40 | **/.env 41 | 42 | **/*.rs.bk 43 | /.wallet.json 44 | /.anchor 45 | /test-ledger 46 | 47 | **/*.pem 48 | lcov.info 49 | codecov.json 50 | /coverage -------------------------------------------------------------------------------- /.release-plz.toml: -------------------------------------------------------------------------------- 1 | [workspace] 2 | git_release_name = "v{{ version }}" 3 | git_tag_name = "v{{ version }}" 4 | publish = false 5 | release = false 6 | git_release_enable = false 7 | git_tag_enable = false 8 | 9 | [[package]] 10 | name = "gelx" 11 | changelog_path = "crates/gelx/changelog.md" 12 | publish = true 13 | release = true 14 | git_tag_enable = true 15 | git_release_enable = true 16 | 17 | [[package]] 18 | name = "gelx_build" 19 | changelog_path = "crates/gelx_build/changelog.md" 20 | publish = true 21 | release = true 22 | 23 | [[package]] 24 | name = "gelx_cli" 25 | changelog_path = "crates/gelx_cli/changelog.md" 26 | publish = true 27 | release = true 28 | 29 | [[package]] 30 | name = "gelx_core" 31 | changelog_path = "crates/gelx_core/changelog.md" 32 | publish = true 33 | release = true 34 | 35 | [[package]] 36 | name = "gelx_macros" 37 | changelog_path = "crates/gelx_macros/changelog.md" 38 | publish = true 39 | release = true 40 | 41 | [changelog] 42 | commit_parsers = [ 43 | { message = "^feat", group = "🎉 Added" }, 44 | { message = "^changed", group = "📝 Changed" }, 45 | { message = "^fix", group = "🐛 Bug Fixes" }, 46 | { message = "^deprecated", group = "🗑️ Deprecated" }, 47 | { message = "^doc", group = "📚 Documentation" }, 48 | { message = "^perf", group = "⚡ Performance" }, 49 | { message = "^refactor\\(clippy\\)", skip = true }, 50 | { message = "^refactor", group = "🚜 Refactor" }, 51 | { message = "^style", group = "🎨 Styling" }, 52 | { message = "^test", group = "🧪 Testing" }, 53 | { message = "^chore\\(release\\):", skip = true }, 54 | { message = "^chore: release", skip = true }, 55 | { message = "^chore\\(deps.*\\)", skip = true }, 56 | { message = "^chore\\(pr\\)", skip = true }, 57 | { message = "^chore\\(pull\\)", skip = true }, 58 | { message = "^chore\\(npm\\).*yarn\\.lock", skip = true }, 59 | { message = "^chore|^ci", group = "⚙️ Miscellaneous Tasks" }, 60 | { body = ".*security", group = "🛡️ Security" }, 61 | { message = "^revert", group = "◀️ Revert" }, 62 | ] 63 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [workspace] 2 | members = ["crates/*", "examples/gelx_example"] 3 | resolver = "2" 4 | 5 | [workspace.package] 6 | version = "0.7.0" 7 | authors = ["Ifiok Jr. "] 8 | edition = "2024" 9 | homepage = "https://geldata.com" 10 | license = "Unlicense" 11 | repository = "https://github.com/ifiokjr/gelx" 12 | rust-version = "1.85.0" 13 | 14 | [workspace.dependencies] 15 | assert2 = "0.3" 16 | base64 = "0.22" 17 | bigdecimal = "0.4" 18 | bitflags = "2" 19 | bytes = "1" 20 | cfg-if = "1" 21 | check_keyword = "0.4" 22 | chrono = "0.4" 23 | clap = "4.5.38" 24 | derive_more = "2" 25 | document-features = "0.2" 26 | futures = "0.3" 27 | gel-derive = "0.7" 28 | gel-errors = "0.5" 29 | gel-protocol = "0.8" 30 | gel-tokio = "0.10" 31 | geo = "0.30" 32 | geo-traits = "0.3" 33 | geo-types = "0.7" 34 | heck = "0.5" 35 | indexmap = "2" 36 | insta = "1" 37 | insta-cmd = "0.6" 38 | log = "0.4" 39 | num-bigint = "0.4" 40 | num-traits = "0.2" 41 | prettyplease = "0.2" 42 | proc-macro2 = "1" 43 | quote = "1" 44 | regex = "1" 45 | rstest = "0.25" 46 | rustversion = "1" 47 | serde = "1" 48 | serde_bytes = "0.11" 49 | serde_json = "1" 50 | serde_with = "3" 51 | similar = "2" 52 | strum = "0.27" 53 | syn = "2" 54 | test-log = "0.2" 55 | thiserror = "2" 56 | tokio = "1" 57 | toml = "0.8" 58 | toml_edit = "0.22" 59 | trybuild = "1" 60 | typed-builder = "0.21" 61 | uuid = "1" 62 | wkb = "0.9" 63 | 64 | # crates 65 | gelx = { path = "./crates/gelx", version = "0.7.0" } 66 | gelx_build = { path = "./crates/gelx_build", version = "0.7.0" } 67 | gelx_cli = { path = "./crates/gelx_cli", version = "0.7.0" } 68 | gelx_core = { path = "./crates/gelx_core", version = "0.7.0" } 69 | gelx_macros = { path = "./crates/gelx_macros", version = "0.7.0" } 70 | 71 | [workspace.metadata.bin] 72 | cargo-deny = { version = "0.18.2" } 73 | cargo-insta = { version = "1.43.1" } 74 | cargo-llvm-cov = { version = "0.6.16" } 75 | cargo-nextest = { version = "0.9.96" } 76 | 77 | [workspace.lints.rust] 78 | # Group lints 79 | rust_2021_compatibility = { level = "warn", priority = -1 } 80 | rust_2024_compatibility = { level = "warn", priority = -1 } 81 | 82 | # Individual lints 83 | unsafe_code = "deny" 84 | unstable_features = "deny" 85 | unused_extern_crates = "warn" 86 | unused_import_braces = "warn" 87 | unused_lifetimes = "warn" 88 | unused_macro_rules = "warn" 89 | unused_qualifications = "warn" 90 | variant_size_differences = "warn" 91 | edition_2024_expr_fragment_specifier = "allow" 92 | 93 | [workspace.lints.clippy] 94 | # Group lints 95 | complexity = { level = "warn", priority = -1 } 96 | correctness = { level = "deny", priority = -1 } 97 | pedantic = { level = "warn", priority = -1 } 98 | perf = { level = "warn", priority = -1 } 99 | style = { level = "warn", priority = -1 } 100 | suspicious = { level = "warn", priority = -1 } 101 | 102 | # Individual lints 103 | blocks_in_conditions = "allow" 104 | cargo_common_metadata = "allow" 105 | cast_possible_truncation = "allow" 106 | cast_possible_wrap = "allow" 107 | cast_precision_loss = "allow" 108 | cast_sign_loss = "allow" 109 | expl_impl_clone_on_copy = "allow" 110 | items_after_statements = "allow" 111 | missing_errors_doc = "allow" 112 | missing_panics_doc = "allow" 113 | module_name_repetitions = "allow" 114 | must_use_candidate = "allow" 115 | no_effect_underscore_binding = "allow" 116 | tabs-in-doc-comments = "allow" 117 | too_many_lines = "allow" 118 | wildcard_dependencies = "deny" 119 | wildcard_imports = "allow" 120 | large_futures = "allow" 121 | -------------------------------------------------------------------------------- /changelog.md: -------------------------------------------------------------------------------- 1 | crates/gelx/changelog.md -------------------------------------------------------------------------------- /crates/gelx/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "gelx" 3 | version = { workspace = true } 4 | authors = { workspace = true } 5 | categories = ["database"] 6 | edition = { workspace = true } 7 | homepage = { workspace = true } 8 | keywords = ["gel", "database", "typesafe", "macros", "codegen"] 9 | license = { workspace = true } 10 | readme = "readme.md" 11 | repository = { workspace = true } 12 | rust-version = { workspace = true } 13 | description = "Generate fully typed rust code from your gel schema and inline queries." 14 | 15 | [package.metadata.docs.rs] 16 | all-features = true 17 | rustdoc-args = ["--cfg", "docsrs"] 18 | 19 | [dependencies] 20 | bigdecimal = { workspace = true, optional = true } 21 | bytes = { workspace = true } 22 | cfg-if = { workspace = true } 23 | chrono = { workspace = true, optional = true } 24 | derive_more = { workspace = true, features = ["from", "into", "deref", "deref_mut"] } 25 | document-features = { workspace = true } 26 | gel-derive = { workspace = true, optional = true } 27 | gel-errors = { workspace = true } 28 | gel-protocol = { workspace = true } 29 | gel-tokio = { workspace = true, features = ["unstable", "derive"], optional = true } 30 | gelx_macros = { workspace = true } 31 | geo = { workspace = true, optional = true } 32 | geo-traits = { workspace = true, optional = true } 33 | geo-types = { workspace = true, optional = true } 34 | num-bigint = { workspace = true, optional = true } 35 | num-traits = { workspace = true, optional = true } 36 | serde = { workspace = true, features = ["derive"], optional = true } 37 | serde_bytes = { workspace = true, optional = true } 38 | strum = { workspace = true, features = ["derive"], optional = true } 39 | typed-builder = { workspace = true, optional = true } 40 | uuid = { workspace = true } 41 | wkb = { workspace = true, optional = true } 42 | 43 | [dev-dependencies] 44 | assert2 = { workspace = true } 45 | gelx_core = { workspace = true } 46 | insta = { workspace = true, features = ["ron", "json", "redactions"] } 47 | proc-macro2 = { workspace = true } 48 | rstest = { workspace = true } 49 | rustversion = { workspace = true } 50 | test-log = { workspace = true, features = ["log", "trace"] } 51 | tokio = { workspace = true, features = ["time", "test-util", "fs"] } 52 | trybuild = { workspace = true } 53 | 54 | [features] 55 | # ! #### Default 56 | 57 | ## The default feature is `with_all`. 58 | default = [ 59 | "with_all", 60 | ] 61 | 62 | # ! #### Types 63 | 64 | ## Include the `num-bigint` dependency. 65 | with_bigint = [ 66 | "dep:num-bigint", 67 | "dep:num-traits", 68 | "gel-protocol/with-num-bigint", 69 | ] 70 | 71 | ## Use the `bigdecimal` crate. 72 | with_bigdecimal = [ 73 | "dep:bigdecimal", 74 | "dep:num-bigint", 75 | "dep:num-traits", 76 | "gel-protocol/with-bigdecimal", 77 | ] 78 | 79 | ## Use the `chrono` crate for all dates. 80 | with_chrono = [ 81 | "dep:chrono", 82 | "gel-protocol/with-chrono", 83 | ] 84 | 85 | ## Use the `geo-types` crate for all geo types. 86 | with_geo = [ 87 | "dep:geo-traits", 88 | "dep:geo-types", 89 | "dep:geo", 90 | "dep:wkb", 91 | ] 92 | 93 | ## Include all additional types. This is included by default. Use `default-features = false` to disable. 94 | with_all = [ 95 | "with_bigint", 96 | "with_bigdecimal", 97 | "with_chrono", 98 | "with_geo", 99 | "gel-protocol/all-types", 100 | ] 101 | 102 | # ! #### Behavior 103 | 104 | ## Use the `typed-builder` crate to generate the builders for the generated `Input` structs. 105 | builder = [ 106 | "dep:typed-builder", 107 | "gelx_macros/builder", 108 | ] 109 | 110 | ## Turn on the `query` and `transaction` methods and anything that relies on `gel-tokio`. 111 | ## The reason to separate this feature is to enable usage of this macro in browser environments 112 | ## where `gel-tokio` is not feasible. 113 | ## 114 | ## Adding this feature requires adding the `gel-protocol` dependency to your project. 115 | ## This is because the `Queryable` derive macro requires the `gel-protocol` crate to be present 116 | ## in the consuming crate. 117 | query = [ 118 | "gelx_macros/query", 119 | "dep:gel-tokio", 120 | "dep:gel-derive", 121 | ] 122 | 123 | ## Enable serde for the generated code. 124 | serde = [ 125 | "chrono/serde", 126 | "dep:serde_bytes", 127 | "dep:serde", 128 | "gel-protocol/with-serde", 129 | "gelx_macros/serde", 130 | "geo-types?/serde", 131 | "geo?/use-serde", 132 | "uuid/serde", 133 | ] 134 | 135 | ## Enable strum for the generated code. 136 | ## 137 | ## Adding this feature requires adding the `strum` dependency to your project. 138 | strum = [ 139 | "gelx_macros/strum", 140 | "dep:strum", 141 | ] 142 | 143 | [lints] 144 | workspace = true 145 | -------------------------------------------------------------------------------- /crates/gelx/queries/insert_location.edgeql: -------------------------------------------------------------------------------- 1 | with NewLocation := (insert Location { 2 | point := $point, 3 | area := $area, 4 | }) 5 | select NewLocation { 6 | point, 7 | area, 8 | }; -------------------------------------------------------------------------------- /crates/gelx/queries/insert_user.edgeql: -------------------------------------------------------------------------------- 1 | with NewUser := (insert User { 2 | name := $name, 3 | bio := $bio, 4 | slug := $slug, 5 | }) 6 | select NewUser { 7 | id, 8 | name, 9 | bio, 10 | slug, 11 | }; 12 | -------------------------------------------------------------------------------- /crates/gelx/queries/invalid.edgeql: -------------------------------------------------------------------------------- 1 | invalid query -------------------------------------------------------------------------------- /crates/gelx/queries/remove_user.edgeql: -------------------------------------------------------------------------------- 1 | delete User filter .id = $id; 2 | -------------------------------------------------------------------------------- /crates/gelx/queries/select_simple_location.edgeql: -------------------------------------------------------------------------------- 1 | select ext::postgis::makepoint(1.0, 1.0); -------------------------------------------------------------------------------- /crates/gelx/queries/select_user.edgeql: -------------------------------------------------------------------------------- 1 | select User { 2 | id, 3 | name, 4 | bio, 5 | slug, 6 | } filter .slug = $slug; -------------------------------------------------------------------------------- /crates/gelx/src/geometry.rs: -------------------------------------------------------------------------------- 1 | use bytes::Bytes; 2 | use gel_protocol::codec::POSTGIS_GEOGRAPHY; 3 | use gel_protocol::codec::POSTGIS_GEOMETRY; 4 | use gel_protocol::descriptors::Descriptor; 5 | use gel_protocol::descriptors::TypePos; 6 | use gel_protocol::errors; 7 | use gel_protocol::errors::DecodeError; 8 | use gel_protocol::queryable::Decoder; 9 | use gel_protocol::queryable::DescriptorContext; 10 | use gel_protocol::queryable::DescriptorMismatch; 11 | use gel_protocol::queryable::Queryable; 12 | use gel_protocol::value::Value; 13 | use geo_traits::to_geo::ToGeoGeometry; 14 | use uuid::Uuid; 15 | use wkb::Endianness; 16 | use wkb::reader::read_wkb; 17 | use wkb::writer::WriteOptions; 18 | use wkb::writer::write_geometry; 19 | 20 | #[derive( 21 | Debug, Clone, derive_more::Deref, derive_more::DerefMut, derive_more::From, derive_more::Into, 22 | )] 23 | #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] 24 | pub struct Geometry(pub geo::Geometry); 25 | 26 | impl Queryable for Geometry { 27 | type Args = (); 28 | 29 | fn decode(_: &Decoder, (): &Self::Args, buf: &[u8]) -> Result { 30 | let geometry: geo::Geometry = match read_wkb(buf) { 31 | Ok(value) => { 32 | let Some(value) = value.try_to_geometry() else { 33 | return errors::MissingRequiredElement.fail(); 34 | }; 35 | value 36 | } 37 | Err(_) => return errors::MissingRequiredElement.fail(), 38 | }; 39 | 40 | Ok(Self(geometry)) 41 | } 42 | 43 | fn check_descriptor( 44 | ctx: &DescriptorContext, 45 | type_pos: TypePos, 46 | ) -> Result { 47 | check_scalar(ctx, type_pos, POSTGIS_GEOMETRY, "ext::postgis::geometry")?; 48 | Ok(()) 49 | } 50 | } 51 | 52 | impl From for Value { 53 | fn from(value: Geometry) -> Self { 54 | let mut buf = vec![]; 55 | 56 | write_geometry( 57 | &mut buf, 58 | &value.0, 59 | &WriteOptions { 60 | endianness: Endianness::BigEndian, 61 | }, 62 | ) 63 | .unwrap(); 64 | 65 | Value::PostGisGeometry(Bytes::from(buf)) 66 | } 67 | } 68 | 69 | #[derive( 70 | Debug, Clone, derive_more::Deref, derive_more::DerefMut, derive_more::From, derive_more::Into, 71 | )] 72 | #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] 73 | pub struct Geography(pub geo::Geometry); 74 | 75 | impl Queryable for Geography { 76 | type Args = (); 77 | 78 | fn decode(_: &Decoder, (): &Self::Args, buf: &[u8]) -> Result { 79 | let geometry: geo::Geometry = match read_wkb(buf) { 80 | Ok(value) => { 81 | let Some(value) = value.try_to_geometry() else { 82 | return errors::MissingRequiredElement.fail(); 83 | }; 84 | value 85 | } 86 | Err(_) => return errors::MissingRequiredElement.fail(), 87 | }; 88 | 89 | Ok(Self(geometry)) 90 | } 91 | 92 | fn check_descriptor( 93 | ctx: &DescriptorContext, 94 | type_pos: TypePos, 95 | ) -> Result { 96 | check_scalar(ctx, type_pos, POSTGIS_GEOGRAPHY, "ext::postgis::geography")?; 97 | Ok(()) 98 | } 99 | } 100 | 101 | impl From for Value { 102 | fn from(value: Geography) -> Self { 103 | let mut buf = vec![]; 104 | 105 | write_geometry( 106 | &mut buf, 107 | &value.0, 108 | &WriteOptions { 109 | endianness: Endianness::BigEndian, 110 | }, 111 | ) 112 | .unwrap(); 113 | 114 | Value::PostGisGeography(Bytes::from(buf)) 115 | } 116 | } 117 | 118 | fn check_scalar( 119 | ctx: &DescriptorContext, 120 | type_pos: TypePos, 121 | type_id: Uuid, 122 | name: &str, 123 | ) -> Result<(), DescriptorMismatch> { 124 | let desc = ctx.get(type_pos)?; 125 | 126 | match desc { 127 | Descriptor::Scalar(scalar) if scalar.base_type_pos.is_some() => { 128 | return check_scalar(ctx, scalar.base_type_pos.unwrap(), type_id, name); 129 | } 130 | 131 | Descriptor::Scalar(scalar) if *scalar.id == type_id => { 132 | return Ok(()); 133 | } 134 | 135 | Descriptor::BaseScalar(base) if *base.id == type_id => { 136 | return Ok(()); 137 | } 138 | _ => {} 139 | } 140 | 141 | Err(ctx.wrong_type(desc, name)) 142 | } 143 | -------------------------------------------------------------------------------- /crates/gelx/tests/compile.rs: -------------------------------------------------------------------------------- 1 | #![cfg(all( 2 | feature = "builder", 3 | feature = "query", 4 | feature = "serde", 5 | feature = "strum" 6 | ))] 7 | use std::thread; 8 | 9 | use rstest::fixture; 10 | use trybuild::TestCases; 11 | 12 | #[fixture] 13 | fn t() -> TestCases { 14 | TestCases::new() 15 | } 16 | 17 | #[fixture] 18 | pub fn testname() -> String { 19 | thread::current() 20 | .name() 21 | .unwrap() 22 | .split("::") 23 | .last() 24 | .unwrap() 25 | .to_string() 26 | } 27 | 28 | #[cfg_attr(miri, ignore = "incompatible with miri")] 29 | #[test] 30 | fn check_compilation() { 31 | let t = TestCases::new(); 32 | 33 | t.compile_fail("tests/compile/macros/*.rs"); 34 | t.pass("tests/compile/codegen/*.rs"); 35 | } 36 | -------------------------------------------------------------------------------- /crates/gelx/tests/compile/codegen/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ifiokjr/gelx/5e69e2e0b0afab90854c4ba2f9f8b4d9c5bb2714/crates/gelx/tests/compile/codegen/.gitkeep -------------------------------------------------------------------------------- /crates/gelx/tests/compile/codegen/case_01_str.rs: -------------------------------------------------------------------------------- 1 | pub mod example { 2 | use ::gelx::exports as __g; 3 | /// Execute the desired query. 4 | pub async fn query( 5 | client: &__g::gel_tokio::Client, 6 | ) -> ::core::result::Result { 7 | client.query_required_single(QUERY, &()).await 8 | } 9 | /// Compose the query as part of a larger transaction. 10 | pub async fn transaction( 11 | conn: &mut __g::gel_tokio::Transaction, 12 | ) -> ::core::result::Result { 13 | conn.query_required_single(QUERY, &()).await 14 | } 15 | pub type Input = (); 16 | pub type Output = String; 17 | /// The original query string provided to the macro. Can be reused in your codebase. 18 | pub const QUERY: &str = "select 'i ❤\u{fe0f} gel'"; 19 | } 20 | fn main() {} 21 | -------------------------------------------------------------------------------- /crates/gelx/tests/compile/codegen/case_02_bool.rs: -------------------------------------------------------------------------------- 1 | pub mod example { 2 | use ::gelx::exports as __g; 3 | /// Execute the desired query. 4 | pub async fn query( 5 | client: &__g::gel_tokio::Client, 6 | ) -> ::core::result::Result { 7 | client.query_required_single(QUERY, &()).await 8 | } 9 | /// Compose the query as part of a larger transaction. 10 | pub async fn transaction( 11 | conn: &mut __g::gel_tokio::Transaction, 12 | ) -> ::core::result::Result { 13 | conn.query_required_single(QUERY, &()).await 14 | } 15 | pub type Input = (); 16 | pub type Output = bool; 17 | /// The original query string provided to the macro. Can be reused in your codebase. 18 | pub const QUERY: &str = "select true"; 19 | } 20 | fn main() {} 21 | -------------------------------------------------------------------------------- /crates/gelx/tests/compile/codegen/case_03_int64.rs: -------------------------------------------------------------------------------- 1 | pub mod example { 2 | use ::gelx::exports as __g; 3 | /// Execute the desired query. 4 | pub async fn query( 5 | client: &__g::gel_tokio::Client, 6 | ) -> ::core::result::Result { 7 | client.query_required_single(QUERY, &()).await 8 | } 9 | /// Compose the query as part of a larger transaction. 10 | pub async fn transaction( 11 | conn: &mut __g::gel_tokio::Transaction, 12 | ) -> ::core::result::Result { 13 | conn.query_required_single(QUERY, &()).await 14 | } 15 | pub type Input = (); 16 | pub type Output = i64; 17 | /// The original query string provided to the macro. Can be reused in your codebase. 18 | pub const QUERY: &str = "select 3"; 19 | } 20 | fn main() {} 21 | -------------------------------------------------------------------------------- /crates/gelx/tests/compile/codegen/case_04_float64.rs: -------------------------------------------------------------------------------- 1 | pub mod example { 2 | use ::gelx::exports as __g; 3 | /// Execute the desired query. 4 | pub async fn query( 5 | client: &__g::gel_tokio::Client, 6 | ) -> ::core::result::Result { 7 | client.query_required_single(QUERY, &()).await 8 | } 9 | /// Compose the query as part of a larger transaction. 10 | pub async fn transaction( 11 | conn: &mut __g::gel_tokio::Transaction, 12 | ) -> ::core::result::Result { 13 | conn.query_required_single(QUERY, &()).await 14 | } 15 | pub type Input = (); 16 | pub type Output = f64; 17 | /// The original query string provided to the macro. Can be reused in your codebase. 18 | pub const QUERY: &str = "select 314e-2"; 19 | } 20 | fn main() {} 21 | -------------------------------------------------------------------------------- /crates/gelx/tests/compile/codegen/case_05_bigint.rs: -------------------------------------------------------------------------------- 1 | pub mod example { 2 | use ::gelx::exports as __g; 3 | /// Execute the desired query. 4 | pub async fn query( 5 | client: &__g::gel_tokio::Client, 6 | ) -> ::core::result::Result { 7 | client.query_required_single(QUERY, &()).await 8 | } 9 | /// Compose the query as part of a larger transaction. 10 | pub async fn transaction( 11 | conn: &mut __g::gel_tokio::Transaction, 12 | ) -> ::core::result::Result { 13 | conn.query_required_single(QUERY, &()).await 14 | } 15 | pub type Input = (); 16 | pub type Output = __g::BigIntAlias; 17 | /// The original query string provided to the macro. Can be reused in your codebase. 18 | pub const QUERY: &str = "select 42n"; 19 | } 20 | fn main() {} 21 | -------------------------------------------------------------------------------- /crates/gelx/tests/compile/codegen/case_06_decimal.rs: -------------------------------------------------------------------------------- 1 | pub mod example { 2 | use ::gelx::exports as __g; 3 | /// Execute the desired query. 4 | pub async fn query( 5 | client: &__g::gel_tokio::Client, 6 | ) -> ::core::result::Result { 7 | client.query_required_single(QUERY, &()).await 8 | } 9 | /// Compose the query as part of a larger transaction. 10 | pub async fn transaction( 11 | conn: &mut __g::gel_tokio::Transaction, 12 | ) -> ::core::result::Result { 13 | conn.query_required_single(QUERY, &()).await 14 | } 15 | pub type Input = (); 16 | pub type Output = __g::BigIntAlias; 17 | /// The original query string provided to the macro. Can be reused in your codebase. 18 | pub const QUERY: &str = "select 42e+100n"; 19 | } 20 | fn main() {} 21 | -------------------------------------------------------------------------------- /crates/gelx/tests/compile/codegen/case_07_uuid.rs: -------------------------------------------------------------------------------- 1 | pub mod example { 2 | use ::gelx::exports as __g; 3 | /// Execute the desired query. 4 | pub async fn query( 5 | client: &__g::gel_tokio::Client, 6 | ) -> ::core::result::Result { 7 | client.query_required_single(QUERY, &()).await 8 | } 9 | /// Compose the query as part of a larger transaction. 10 | pub async fn transaction( 11 | conn: &mut __g::gel_tokio::Transaction, 12 | ) -> ::core::result::Result { 13 | conn.query_required_single(QUERY, &()).await 14 | } 15 | pub type Input = (); 16 | pub type Output = __g::uuid::Uuid; 17 | /// The original query string provided to the macro. Can be reused in your codebase. 18 | pub const QUERY: &str = "select 'a5ea6360-75bd-4c20-b69c-8f317b0d2857'"; 19 | } 20 | fn main() {} 21 | -------------------------------------------------------------------------------- /crates/gelx/tests/compile/codegen/case_08_datetime.rs: -------------------------------------------------------------------------------- 1 | pub mod example { 2 | use ::gelx::exports as __g; 3 | /// Execute the desired query. 4 | pub async fn query( 5 | client: &__g::gel_tokio::Client, 6 | ) -> ::core::result::Result { 7 | client.query_required_single(QUERY, &()).await 8 | } 9 | /// Compose the query as part of a larger transaction. 10 | pub async fn transaction( 11 | conn: &mut __g::gel_tokio::Transaction, 12 | ) -> ::core::result::Result { 13 | conn.query_required_single(QUERY, &()).await 14 | } 15 | pub type Input = (); 16 | pub type Output = __g::DateTimeAlias; 17 | /// The original query string provided to the macro. Can be reused in your codebase. 18 | pub const QUERY: &str = "select '1999-03-31T15:17:00Z'"; 19 | } 20 | fn main() {} 21 | -------------------------------------------------------------------------------- /crates/gelx/tests/compile/codegen/case_09_duration.rs: -------------------------------------------------------------------------------- 1 | pub mod example { 2 | use ::gelx::exports as __g; 3 | /// Execute the desired query. 4 | pub async fn query( 5 | client: &__g::gel_tokio::Client, 6 | ) -> ::core::result::Result { 7 | client.query_required_single(QUERY, &()).await 8 | } 9 | /// Compose the query as part of a larger transaction. 10 | pub async fn transaction( 11 | conn: &mut __g::gel_tokio::Transaction, 12 | ) -> ::core::result::Result { 13 | conn.query_required_single(QUERY, &()).await 14 | } 15 | pub type Input = (); 16 | pub type Output = __g::gel_protocol::model::Duration; 17 | /// The original query string provided to the macro. Can be reused in your codebase. 18 | pub const QUERY: &str = "select '45.6 seconds'"; 19 | } 20 | fn main() {} 21 | -------------------------------------------------------------------------------- /crates/gelx/tests/compile/codegen/case_10_array.rs: -------------------------------------------------------------------------------- 1 | pub mod example { 2 | use ::gelx::exports as __g; 3 | /// Execute the desired query. 4 | pub async fn query( 5 | client: &__g::gel_tokio::Client, 6 | ) -> ::core::result::Result { 7 | client.query_required_single(QUERY, &()).await 8 | } 9 | /// Compose the query as part of a larger transaction. 10 | pub async fn transaction( 11 | conn: &mut __g::gel_tokio::Transaction, 12 | ) -> ::core::result::Result { 13 | conn.query_required_single(QUERY, &()).await 14 | } 15 | pub type Input = (); 16 | pub type Output = Vec; 17 | /// The original query string provided to the macro. Can be reused in your codebase. 18 | pub const QUERY: &str = "select [1, 2, 3]"; 19 | } 20 | fn main() {} 21 | -------------------------------------------------------------------------------- /crates/gelx/tests/compile/codegen/case_11_tuple.rs: -------------------------------------------------------------------------------- 1 | pub mod example { 2 | use ::gelx::exports as __g; 3 | /// Execute the desired query. 4 | pub async fn query( 5 | client: &__g::gel_tokio::Client, 6 | ) -> ::core::result::Result { 7 | client.query_required_single(QUERY, &()).await 8 | } 9 | /// Compose the query as part of a larger transaction. 10 | pub async fn transaction( 11 | conn: &mut __g::gel_tokio::Transaction, 12 | ) -> ::core::result::Result { 13 | conn.query_required_single(QUERY, &()).await 14 | } 15 | pub type Input = (); 16 | pub type Output = (String, i64, bool); 17 | /// The original query string provided to the macro. Can be reused in your codebase. 18 | pub const QUERY: &str = "select ('Apple', 7, true)"; 19 | } 20 | fn main() {} 21 | -------------------------------------------------------------------------------- /crates/gelx/tests/compile/codegen/case_12_named_tuple.rs: -------------------------------------------------------------------------------- 1 | pub mod example { 2 | use ::gelx::exports as __g; 3 | /// Execute the desired query. 4 | pub async fn query( 5 | client: &__g::gel_tokio::Client, 6 | ) -> ::core::result::Result { 7 | client.query_required_single(QUERY, &()).await 8 | } 9 | /// Compose the query as part of a larger transaction. 10 | pub async fn transaction( 11 | conn: &mut __g::gel_tokio::Transaction, 12 | ) -> ::core::result::Result { 13 | conn.query_required_single(QUERY, &()).await 14 | } 15 | pub type Input = (); 16 | #[derive( 17 | Debug, 18 | Clone, 19 | __g::serde::Serialize, 20 | __g::serde::Deserialize, 21 | __g::gel_derive::Queryable 22 | )] 23 | pub struct Output { 24 | pub fruit: String, 25 | pub quantity: f64, 26 | pub fresh: bool, 27 | } 28 | /// The original query string provided to the macro. Can be reused in your codebase. 29 | pub const QUERY: &str = "select (fruit := 'Apple', quantity := 3.14, fresh := true)"; 30 | } 31 | fn main() {} 32 | -------------------------------------------------------------------------------- /crates/gelx/tests/compile/codegen/case_13_set.rs: -------------------------------------------------------------------------------- 1 | pub mod example { 2 | use ::gelx::exports as __g; 3 | /// Execute the desired query. 4 | pub async fn query( 5 | client: &__g::gel_tokio::Client, 6 | ) -> ::core::result::Result, __g::gel_errors::Error> { 7 | client.query(QUERY, &()).await 8 | } 9 | /// Compose the query as part of a larger transaction. 10 | pub async fn transaction( 11 | conn: &mut __g::gel_tokio::Transaction, 12 | ) -> ::core::result::Result, __g::gel_errors::Error> { 13 | conn.query(QUERY, &()).await 14 | } 15 | pub type Input = (); 16 | pub type Output = String; 17 | /// The original query string provided to the macro. Can be reused in your codebase. 18 | pub const QUERY: &str = "select {\"set\", \"of\", \"strings\"}"; 19 | } 20 | fn main() {} 21 | -------------------------------------------------------------------------------- /crates/gelx/tests/compile/codegen/case_14_empty_set.rs: -------------------------------------------------------------------------------- 1 | pub mod example { 2 | use ::gelx::exports as __g; 3 | /// Execute the desired query. 4 | pub async fn query( 5 | client: &__g::gel_tokio::Client, 6 | ) -> ::core::result::Result, __g::gel_errors::Error> { 7 | client.query_single(QUERY, &()).await 8 | } 9 | /// Compose the query as part of a larger transaction. 10 | pub async fn transaction( 11 | conn: &mut __g::gel_tokio::Transaction, 12 | ) -> ::core::result::Result, __g::gel_errors::Error> { 13 | conn.query_single(QUERY, &()).await 14 | } 15 | pub type Input = (); 16 | pub type Output = i64; 17 | /// The original query string provided to the macro. Can be reused in your codebase. 18 | pub const QUERY: &str = "select {}"; 19 | } 20 | fn main() {} 21 | -------------------------------------------------------------------------------- /crates/gelx/tests/compile/codegen/case_15_input_shape.rs: -------------------------------------------------------------------------------- 1 | pub mod example { 2 | use ::gelx::exports as __g; 3 | /// Execute the desired query. 4 | pub async fn query( 5 | client: &__g::gel_tokio::Client, 6 | ) -> ::core::result::Result { 7 | client.query_required_single(QUERY, &()).await 8 | } 9 | /// Compose the query as part of a larger transaction. 10 | pub async fn transaction( 11 | conn: &mut __g::gel_tokio::Transaction, 12 | ) -> ::core::result::Result { 13 | conn.query_required_single(QUERY, &()).await 14 | } 15 | pub type Input = (); 16 | #[derive( 17 | Debug, 18 | Clone, 19 | Copy, 20 | __g::serde::Serialize, 21 | __g::serde::Deserialize, 22 | __g::gel_derive::Queryable, 23 | __g::strum::AsRefStr, 24 | __g::strum::Display, 25 | __g::strum::EnumString, 26 | __g::strum::EnumIs, 27 | __g::strum::FromRepr, 28 | __g::strum::IntoStaticStr 29 | )] 30 | pub enum DefaultRelationshipType { 31 | Follow, 32 | Block, 33 | Mute, 34 | } 35 | impl From for __g::gel_protocol::value::Value { 36 | fn from(value: DefaultRelationshipType) -> Self { 37 | __g::gel_protocol::value::Value::Enum(value.as_ref().into()) 38 | } 39 | } 40 | #[derive( 41 | Debug, 42 | Clone, 43 | __g::serde::Serialize, 44 | __g::serde::Deserialize, 45 | __g::gel_derive::Queryable 46 | )] 47 | pub struct Output { 48 | pub my_string: DefaultRelationshipType, 49 | pub my_number: i64, 50 | pub several_numbers: Vec, 51 | pub array: Vec, 52 | } 53 | /// The original query string provided to the macro. Can be reused in your codebase. 54 | pub const QUERY: &str = "select { my_string := RelationshipType.Follow, my_number := 42, several_numbers := {1, 2, 3}, array := [1, 2, 3] };"; 55 | } 56 | fn main() {} 57 | -------------------------------------------------------------------------------- /crates/gelx/tests/compile/codegen/case_16_input_shape_with_args.rs: -------------------------------------------------------------------------------- 1 | pub mod example { 2 | use ::gelx::exports as __g; 3 | /// Execute the desired query. 4 | pub async fn query( 5 | client: &__g::gel_tokio::Client, 6 | props: &Input, 7 | ) -> ::core::result::Result { 8 | client.query_required_single(QUERY, props).await 9 | } 10 | /// Compose the query as part of a larger transaction. 11 | pub async fn transaction( 12 | conn: &mut __g::gel_tokio::Transaction, 13 | props: &Input, 14 | ) -> ::core::result::Result { 15 | conn.query_required_single(QUERY, props).await 16 | } 17 | #[derive( 18 | Debug, 19 | Clone, 20 | __g::serde::Serialize, 21 | __g::serde::Deserialize, 22 | __g::typed_builder::TypedBuilder, 23 | __g::gel_derive::Queryable 24 | )] 25 | pub struct Input { 26 | #[builder(setter(into))] 27 | pub custom: String, 28 | } 29 | impl __g::gel_protocol::query_arg::QueryArgs for Input { 30 | fn encode( 31 | &self, 32 | encoder: &mut __g::gel_protocol::query_arg::Encoder, 33 | ) -> core::result::Result<(), __g::gel_errors::Error> { 34 | let map = __g::gel_protocol::named_args! { 35 | "custom" => self.custom.clone(), 36 | }; 37 | map.encode(encoder) 38 | } 39 | } 40 | #[derive( 41 | Debug, 42 | Clone, 43 | __g::serde::Serialize, 44 | __g::serde::Deserialize, 45 | __g::gel_derive::Queryable 46 | )] 47 | pub struct Output { 48 | pub hello: String, 49 | pub custom: String, 50 | } 51 | /// The original query string provided to the macro. Can be reused in your codebase. 52 | pub const QUERY: &str = "select { hello := \"world\", custom := $custom }"; 53 | } 54 | fn main() {} 55 | -------------------------------------------------------------------------------- /crates/gelx/tests/compile/codegen/case_17_object_shape.rs: -------------------------------------------------------------------------------- 1 | pub mod example { 2 | use ::gelx::exports as __g; 3 | /// Execute the desired query. 4 | pub async fn query( 5 | client: &__g::gel_tokio::Client, 6 | ) -> ::core::result::Result, __g::gel_errors::Error> { 7 | client.query(QUERY, &()).await 8 | } 9 | /// Compose the query as part of a larger transaction. 10 | pub async fn transaction( 11 | conn: &mut __g::gel_tokio::Transaction, 12 | ) -> ::core::result::Result, __g::gel_errors::Error> { 13 | conn.query(QUERY, &()).await 14 | } 15 | pub type Input = (); 16 | #[derive( 17 | Debug, 18 | Clone, 19 | __g::serde::Serialize, 20 | __g::serde::Deserialize, 21 | __g::gel_derive::Queryable 22 | )] 23 | pub struct OutputWalletsSet { 24 | pub created_at: __g::DateTimeAlias, 25 | pub id: __g::uuid::Uuid, 26 | pub updated_at: __g::DateTimeAlias, 27 | pub primary: bool, 28 | pub description: Option, 29 | pub name: Option, 30 | pub pubkey: String, 31 | } 32 | #[derive( 33 | Debug, 34 | Clone, 35 | __g::serde::Serialize, 36 | __g::serde::Deserialize, 37 | __g::gel_derive::Queryable 38 | )] 39 | pub struct Output { 40 | pub slug: String, 41 | pub id: __g::uuid::Uuid, 42 | pub created_at: __g::DateTimeAlias, 43 | pub updated_at: __g::DateTimeAlias, 44 | pub description: Option, 45 | pub name: String, 46 | pub wallets: Vec, 47 | } 48 | /// The original query string provided to the macro. Can be reused in your codebase. 49 | pub const QUERY: &str = "select Team {**}"; 50 | } 51 | fn main() {} 52 | -------------------------------------------------------------------------------- /crates/gelx/tests/compile/codegen/case_18_object_shape_with_args.rs: -------------------------------------------------------------------------------- 1 | pub mod example { 2 | use ::gelx::exports as __g; 3 | /// Execute the desired query. 4 | pub async fn query( 5 | client: &__g::gel_tokio::Client, 6 | props: &Input, 7 | ) -> ::core::result::Result, __g::gel_errors::Error> { 8 | client.query(QUERY, props).await 9 | } 10 | /// Compose the query as part of a larger transaction. 11 | pub async fn transaction( 12 | conn: &mut __g::gel_tokio::Transaction, 13 | props: &Input, 14 | ) -> ::core::result::Result, __g::gel_errors::Error> { 15 | conn.query(QUERY, props).await 16 | } 17 | #[derive( 18 | Debug, 19 | Clone, 20 | __g::serde::Serialize, 21 | __g::serde::Deserialize, 22 | __g::typed_builder::TypedBuilder, 23 | __g::gel_derive::Queryable 24 | )] 25 | pub struct Input { 26 | #[builder(setter(into))] 27 | pub starts_with: String, 28 | #[builder(setter(into))] 29 | pub ends_with: String, 30 | } 31 | impl __g::gel_protocol::query_arg::QueryArgs for Input { 32 | fn encode( 33 | &self, 34 | encoder: &mut __g::gel_protocol::query_arg::Encoder, 35 | ) -> core::result::Result<(), __g::gel_errors::Error> { 36 | let map = __g::gel_protocol::named_args! { 37 | "starts_with" => self.starts_with.clone(), "ends_with" => self.ends_with 38 | .clone(), 39 | }; 40 | map.encode(encoder) 41 | } 42 | } 43 | #[derive( 44 | Debug, 45 | Clone, 46 | __g::serde::Serialize, 47 | __g::serde::Deserialize, 48 | __g::gel_derive::Queryable 49 | )] 50 | pub struct OutputWalletsSet { 51 | pub created_at: __g::DateTimeAlias, 52 | pub id: __g::uuid::Uuid, 53 | pub updated_at: __g::DateTimeAlias, 54 | pub primary: bool, 55 | pub description: Option, 56 | pub name: Option, 57 | pub pubkey: String, 58 | } 59 | #[derive( 60 | Debug, 61 | Clone, 62 | __g::serde::Serialize, 63 | __g::serde::Deserialize, 64 | __g::gel_derive::Queryable 65 | )] 66 | pub struct Output { 67 | pub slug: String, 68 | pub id: __g::uuid::Uuid, 69 | pub created_at: __g::DateTimeAlias, 70 | pub updated_at: __g::DateTimeAlias, 71 | pub description: Option, 72 | pub name: String, 73 | pub wallets: Vec, 74 | } 75 | /// The original query string provided to the macro. Can be reused in your codebase. 76 | pub const QUERY: &str = "select Team {**} filter .name like $starts_with ++ '%' and .description like '%' ++ $ends_with;"; 77 | } 78 | fn main() {} 79 | -------------------------------------------------------------------------------- /crates/gelx/tests/compile/codegen/case_19_enums.rs: -------------------------------------------------------------------------------- 1 | pub mod example { 2 | use ::gelx::exports as __g; 3 | /// Execute the desired query. 4 | pub async fn query( 5 | client: &__g::gel_tokio::Client, 6 | ) -> ::core::result::Result, __g::gel_errors::Error> { 7 | client.query(QUERY, &()).await 8 | } 9 | /// Compose the query as part of a larger transaction. 10 | pub async fn transaction( 11 | conn: &mut __g::gel_tokio::Transaction, 12 | ) -> ::core::result::Result, __g::gel_errors::Error> { 13 | conn.query(QUERY, &()).await 14 | } 15 | pub type Input = (); 16 | #[derive( 17 | Debug, 18 | Clone, 19 | Copy, 20 | __g::serde::Serialize, 21 | __g::serde::Deserialize, 22 | __g::gel_derive::Queryable, 23 | __g::strum::AsRefStr, 24 | __g::strum::Display, 25 | __g::strum::EnumString, 26 | __g::strum::EnumIs, 27 | __g::strum::FromRepr, 28 | __g::strum::IntoStaticStr 29 | )] 30 | pub enum DefaultAccountProvider { 31 | Github, 32 | } 33 | impl From for __g::gel_protocol::value::Value { 34 | fn from(value: DefaultAccountProvider) -> Self { 35 | __g::gel_protocol::value::Value::Enum(value.as_ref().into()) 36 | } 37 | } 38 | #[derive( 39 | Debug, 40 | Clone, 41 | __g::serde::Serialize, 42 | __g::serde::Deserialize, 43 | __g::gel_derive::Queryable 44 | )] 45 | pub struct Output { 46 | pub provider: DefaultAccountProvider, 47 | } 48 | /// The original query string provided to the macro. Can be reused in your codebase. 49 | pub const QUERY: &str = "select Account { provider }"; 50 | } 51 | fn main() {} 52 | -------------------------------------------------------------------------------- /crates/gelx/tests/compile/codegen/case_21_bytes.rs: -------------------------------------------------------------------------------- 1 | pub mod example { 2 | use ::gelx::exports as __g; 3 | /// Execute the desired query. 4 | pub async fn query( 5 | client: &__g::gel_tokio::Client, 6 | ) -> ::core::result::Result { 7 | client.query_required_single(QUERY, &()).await 8 | } 9 | /// Compose the query as part of a larger transaction. 10 | pub async fn transaction( 11 | conn: &mut __g::gel_tokio::Transaction, 12 | ) -> ::core::result::Result { 13 | conn.query_required_single(QUERY, &()).await 14 | } 15 | pub type Input = (); 16 | pub type Output = __g::bytes::Bytes; 17 | /// The original query string provided to the macro. Can be reused in your codebase. 18 | pub const QUERY: &str = "select b'bina\\x01ry'"; 19 | } 20 | fn main() {} 21 | -------------------------------------------------------------------------------- /crates/gelx/tests/compile/codegen/case_22_geometry.rs: -------------------------------------------------------------------------------- 1 | pub mod example { 2 | use ::gelx::exports as __g; 3 | /// Execute the desired query. 4 | pub async fn query( 5 | client: &__g::gel_tokio::Client, 6 | ) -> ::core::result::Result { 7 | client.query_required_single(QUERY, &()).await 8 | } 9 | /// Compose the query as part of a larger transaction. 10 | pub async fn transaction( 11 | conn: &mut __g::gel_tokio::Transaction, 12 | ) -> ::core::result::Result { 13 | conn.query_required_single(QUERY, &()).await 14 | } 15 | pub type Input = (); 16 | pub type Output = __g::Geometry; 17 | /// The original query string provided to the macro. Can be reused in your codebase. 18 | pub const QUERY: &str = "select ext::postgis::makepoint(1.0, 1.0)"; 19 | } 20 | fn main() {} 21 | -------------------------------------------------------------------------------- /crates/gelx/tests/compile/codegen/case_23_geography.rs: -------------------------------------------------------------------------------- 1 | pub mod example { 2 | use ::gelx::exports as __g; 3 | /// Execute the desired query. 4 | pub async fn query( 5 | client: &__g::gel_tokio::Client, 6 | ) -> ::core::result::Result { 7 | client.query_required_single(QUERY, &()).await 8 | } 9 | /// Compose the query as part of a larger transaction. 10 | pub async fn transaction( 11 | conn: &mut __g::gel_tokio::Transaction, 12 | ) -> ::core::result::Result { 13 | conn.query_required_single(QUERY, &()).await 14 | } 15 | pub type Input = (); 16 | pub type Output = __g::Geography; 17 | /// The original query string provided to the macro. Can be reused in your codebase. 18 | pub const QUERY: &str = "select ext::postgis::makepoint(1.0, 1.0)"; 19 | } 20 | fn main() {} 21 | -------------------------------------------------------------------------------- /crates/gelx/tests/compile/codegen/insert_user.rs: -------------------------------------------------------------------------------- 1 | pub mod example { 2 | use ::gelx::exports as __g; 3 | /// Execute the desired query. 4 | pub async fn query( 5 | client: &__g::gel_tokio::Client, 6 | props: &Input, 7 | ) -> ::core::result::Result { 8 | client.query_required_single(QUERY, props).await 9 | } 10 | /// Compose the query as part of a larger transaction. 11 | pub async fn transaction( 12 | conn: &mut __g::gel_tokio::Transaction, 13 | props: &Input, 14 | ) -> ::core::result::Result { 15 | conn.query_required_single(QUERY, props).await 16 | } 17 | #[derive( 18 | Debug, 19 | Clone, 20 | __g::serde::Serialize, 21 | __g::serde::Deserialize, 22 | __g::typed_builder::TypedBuilder, 23 | __g::gel_derive::Queryable 24 | )] 25 | pub struct Input { 26 | #[builder(setter(into))] 27 | pub name: String, 28 | #[builder(setter(into))] 29 | pub bio: String, 30 | #[builder(setter(into))] 31 | pub slug: String, 32 | } 33 | impl __g::gel_protocol::query_arg::QueryArgs for Input { 34 | fn encode( 35 | &self, 36 | encoder: &mut __g::gel_protocol::query_arg::Encoder, 37 | ) -> core::result::Result<(), __g::gel_errors::Error> { 38 | let map = __g::gel_protocol::named_args! { 39 | "name" => self.name.clone(), "bio" => self.bio.clone(), "slug" => self 40 | .slug.clone(), 41 | }; 42 | map.encode(encoder) 43 | } 44 | } 45 | #[derive( 46 | Debug, 47 | Clone, 48 | __g::serde::Serialize, 49 | __g::serde::Deserialize, 50 | __g::gel_derive::Queryable 51 | )] 52 | pub struct Output { 53 | pub id: __g::uuid::Uuid, 54 | pub name: Option, 55 | pub bio: Option, 56 | pub slug: String, 57 | } 58 | /// The original query string provided to the macro. Can be reused in your codebase. 59 | pub const QUERY: &str = "with NewUser := (insert User {\n name := $name,\n bio := $bio,\n slug := $slug,\n})\nselect NewUser {\n id,\n name,\n bio,\n slug,\n};\n"; 60 | } 61 | fn main() {} 62 | -------------------------------------------------------------------------------- /crates/gelx/tests/compile/codegen/remove_user.rs: -------------------------------------------------------------------------------- 1 | pub mod example { 2 | use ::gelx::exports as __g; 3 | /// Execute the desired query. 4 | pub async fn query( 5 | client: &__g::gel_tokio::Client, 6 | props: &Input, 7 | ) -> ::core::result::Result, __g::gel_errors::Error> { 8 | client.query_single(QUERY, props).await 9 | } 10 | /// Compose the query as part of a larger transaction. 11 | pub async fn transaction( 12 | conn: &mut __g::gel_tokio::Transaction, 13 | props: &Input, 14 | ) -> ::core::result::Result, __g::gel_errors::Error> { 15 | conn.query_single(QUERY, props).await 16 | } 17 | #[derive( 18 | Debug, 19 | Clone, 20 | __g::serde::Serialize, 21 | __g::serde::Deserialize, 22 | __g::typed_builder::TypedBuilder, 23 | __g::gel_derive::Queryable 24 | )] 25 | pub struct Input { 26 | #[builder(setter(into))] 27 | pub id: __g::uuid::Uuid, 28 | } 29 | impl __g::gel_protocol::query_arg::QueryArgs for Input { 30 | fn encode( 31 | &self, 32 | encoder: &mut __g::gel_protocol::query_arg::Encoder, 33 | ) -> core::result::Result<(), __g::gel_errors::Error> { 34 | let map = __g::gel_protocol::named_args! { 35 | "id" => self.id.clone(), 36 | }; 37 | map.encode(encoder) 38 | } 39 | } 40 | #[derive( 41 | Debug, 42 | Clone, 43 | __g::serde::Serialize, 44 | __g::serde::Deserialize, 45 | __g::gel_derive::Queryable 46 | )] 47 | pub struct Output { 48 | pub id: __g::uuid::Uuid, 49 | } 50 | /// The original query string provided to the macro. Can be reused in your codebase. 51 | pub const QUERY: &str = "delete User filter .id = $id;\n"; 52 | } 53 | fn main() {} 54 | -------------------------------------------------------------------------------- /crates/gelx/tests/compile/macros/absolute_file.rs: -------------------------------------------------------------------------------- 1 | use gelx_macros::gelx_raw; 2 | 3 | fn main() { 4 | gelx_raw!(insert_user, file: "/absolute/path/to/queries/insert_user.edgeql"); 5 | } 6 | -------------------------------------------------------------------------------- /crates/gelx/tests/compile/macros/absolute_file.stderr: -------------------------------------------------------------------------------- 1 | error: absolute paths will only work on the current machine 2 | --> tests/compile/macros/absolute_file.rs:4:31 3 | | 4 | 4 | gelx_raw!(insert_user, file: "/absolute/path/to/queries/insert_user.edgeql"); 5 | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 6 | -------------------------------------------------------------------------------- /crates/gelx/tests/compile/macros/extra_args.rs: -------------------------------------------------------------------------------- 1 | use gelx_macros::gelx_raw; 2 | 3 | fn main() { 4 | gelx_raw!(example, query: "select bool", "more stuff", that is, "not allowed"); 5 | } 6 | -------------------------------------------------------------------------------- /crates/gelx/tests/compile/macros/extra_args.stderr: -------------------------------------------------------------------------------- 1 | error: unexpected token 2 | --> tests/compile/macros/extra_args.rs:4:41 3 | | 4 | 4 | gelx_raw!(example, query: "select bool", "more stuff", that is, "not allowed"); 5 | | ^ 6 | -------------------------------------------------------------------------------- /crates/gelx/tests/compile/macros/incorrect_args.rs: -------------------------------------------------------------------------------- 1 | use gelx::gelx; 2 | 3 | fn main() { 4 | gelx!(example_module, invalid); 5 | } 6 | -------------------------------------------------------------------------------- /crates/gelx/tests/compile/macros/incorrect_args.stderr: -------------------------------------------------------------------------------- 1 | error: no rules expected `invalid` 2 | --> tests/compile/macros/incorrect_args.rs:4:24 3 | | 4 | 4 | gelx!(example_module, invalid); 5 | | ^^^^^^^ no rules expected this token in macro call 6 | | 7 | note: while trying to match meta-variable `$query:literal` 8 | --> src/lib.rs 9 | | 10 | | ($module:ident, $query:literal) => { 11 | | ^^^^^^^^^^^^^^ 12 | -------------------------------------------------------------------------------- /crates/gelx/tests/compile/macros/input_tuple.rs: -------------------------------------------------------------------------------- 1 | use gelx::gelx; 2 | 3 | fn main() { 4 | gelx!(example, "select $0"); 5 | } 6 | -------------------------------------------------------------------------------- /crates/gelx/tests/compile/macros/input_tuple.stderr: -------------------------------------------------------------------------------- 1 | error: proc macro panicked 2 | --> tests/compile/macros/input_tuple.rs:4:2 3 | | 4 | 4 | gelx!(example, "select $0"); 5 | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 6 | | 7 | = help: message: `"0"` is not a valid identifier 8 | = note: this error originates in the macro `gelx` (in Nightly builds, run with -Z macro-backtrace for more info) 9 | -------------------------------------------------------------------------------- /crates/gelx/tests/compile/macros/invalid_query.rs: -------------------------------------------------------------------------------- 1 | use gelx::gelx; 2 | 3 | fn main() { 4 | gelx!(example_module, "invalid"); 5 | } 6 | -------------------------------------------------------------------------------- /crates/gelx/tests/compile/macros/invalid_query.stderr: -------------------------------------------------------------------------------- 1 | error: EdgeQLSyntaxError: Unexpected 'invalid' (on line 1, column 1) 2 | --> tests/compile/macros/invalid_query.rs:4:2 3 | | 4 | 4 | gelx!(example_module, "invalid"); 5 | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 6 | | 7 | = note: this error originates in the macro `$crate::exports::gelx_macros::gelx_raw` which comes from the expansion of the macro `gelx` (in Nightly builds, run with -Z macro-backtrace for more info) 8 | -------------------------------------------------------------------------------- /crates/gelx/tests/compile/macros/invalid_query_file.rs: -------------------------------------------------------------------------------- 1 | use gelx::gelx; 2 | 3 | fn main() { 4 | gelx!(invalid); 5 | } 6 | -------------------------------------------------------------------------------- /crates/gelx/tests/compile/macros/invalid_query_file.stderr: -------------------------------------------------------------------------------- 1 | error: failed to read query file at $WORKSPACE/target/tests/trybuild/gelx/queries/invalid.edgeql: No such file or directory (os error 2) 2 | --> tests/compile/macros/invalid_query_file.rs:4:8 3 | | 4 | 4 | gelx!(invalid); 5 | | ^^^^^^^ 6 | -------------------------------------------------------------------------------- /crates/gelx/tests/compile/macros/missing_file.rs: -------------------------------------------------------------------------------- 1 | use gelx::gelx; 2 | 3 | fn main() { 4 | gelx!(example_module); 5 | } 6 | -------------------------------------------------------------------------------- /crates/gelx/tests/compile/macros/missing_file.stderr: -------------------------------------------------------------------------------- 1 | error: failed to read query file at $WORKSPACE/target/tests/trybuild/gelx/queries/example_module.edgeql: No such file or directory (os error 2) 2 | --> tests/compile/macros/missing_file.rs:4:8 3 | | 4 | 4 | gelx!(example_module); 5 | | ^^^^^^^^^^^^^^ 6 | -------------------------------------------------------------------------------- /crates/gelx/tests/compile/macros/no_args.rs: -------------------------------------------------------------------------------- 1 | use gelx::gelx; 2 | 3 | fn main() { 4 | gelx!(); 5 | } 6 | -------------------------------------------------------------------------------- /crates/gelx/tests/compile/macros/no_args.stderr: -------------------------------------------------------------------------------- 1 | error: unexpected end of macro invocation 2 | --> tests/compile/macros/no_args.rs:4:2 3 | | 4 | 4 | gelx!(); 5 | | ^^^^^^^ missing tokens in macro arguments 6 | | 7 | note: while trying to match meta-variable `$module:ident` 8 | --> src/lib.rs 9 | | 10 | | ($module:ident, $query:literal) => { 11 | | ^^^^^^^^^^^^^ 12 | -------------------------------------------------------------------------------- /crates/gelx/tests/snapshots/codegen__can_generate_aliased_enums@aliased_enums.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/gelx/tests/codegen.rs 3 | expression: value 4 | --- 5 | mod.rs 6 | //! This file is generated by `gelx generate`. 7 | //! It is not intended for manual editing. 8 | //! To update it, run `gelx generate`. 9 | #![cfg_attr(rustfmt, rustfmt_skip)] 10 | #![allow(unused)] 11 | #![allow(unused_qualifications)] 12 | #![allow(clippy::all)] 13 | use ::gelx::exports as __g; 14 | pub use default::*; 15 | #[path = "additional.rs"] 16 | pub mod additional; 17 | #[path = "default.rs"] 18 | pub mod default; 19 | 20 | 21 | additional.rs 22 | //! This file is generated by `gelx generate`. 23 | //! It is not intended for manual editing. 24 | //! To update it, run `gelx generate`. 25 | #![cfg_attr(rustfmt, rustfmt_skip)] 26 | #![allow(unused)] 27 | #![allow(unused_qualifications)] 28 | #![allow(clippy::all)] 29 | use super::*; 30 | #[derive(Debug, Clone, Copy, __g::serde::Serialize, __g::serde::Deserialize)] 31 | #[cfg_attr( 32 | feature = "ssr", 33 | derive( 34 | __g::gel_derive::Queryable, 35 | __g::strum::AsRefStr, 36 | __g::strum::Display, 37 | __g::strum::EnumString, 38 | __g::strum::EnumIs, 39 | __g::strum::FromRepr, 40 | __g::strum::IntoStaticStr 41 | ) 42 | )] 43 | pub enum Awesomeness { 44 | Very, 45 | Somewhat, 46 | NotReally, 47 | } 48 | #[cfg(feature = "ssr")] 49 | impl From for __g::gel_protocol::value::Value { 50 | fn from(value: Awesomeness) -> Self { 51 | __g::gel_protocol::value::Value::Enum(value.as_ref().into()) 52 | } 53 | } 54 | #[derive(Debug, Clone, Copy, __g::serde::Serialize, __g::serde::Deserialize)] 55 | #[cfg_attr( 56 | feature = "ssr", 57 | derive( 58 | __g::gel_derive::Queryable, 59 | __g::strum::AsRefStr, 60 | __g::strum::Display, 61 | __g::strum::EnumString, 62 | __g::strum::EnumIs, 63 | __g::strum::FromRepr, 64 | __g::strum::IntoStaticStr 65 | ) 66 | )] 67 | pub enum Smartness { 68 | #[serde(rename = "low")] 69 | #[cfg_attr(feature = "ssr", strum(serialize = "low"))] 70 | Low, 71 | #[serde(rename = "mid")] 72 | #[cfg_attr(feature = "ssr", strum(serialize = "mid"))] 73 | Mid, 74 | #[serde(rename = "genius")] 75 | #[cfg_attr(feature = "ssr", strum(serialize = "genius"))] 76 | Genius, 77 | } 78 | #[cfg(feature = "ssr")] 79 | impl From for __g::gel_protocol::value::Value { 80 | fn from(value: Smartness) -> Self { 81 | __g::gel_protocol::value::Value::Enum(value.as_ref().into()) 82 | } 83 | } 84 | 85 | 86 | default.rs 87 | //! This file is generated by `gelx generate`. 88 | //! It is not intended for manual editing. 89 | //! To update it, run `gelx generate`. 90 | #![cfg_attr(rustfmt, rustfmt_skip)] 91 | #![allow(unused)] 92 | #![allow(unused_qualifications)] 93 | #![allow(clippy::all)] 94 | use super::*; 95 | #[derive(Debug, Clone, Copy, __g::serde::Serialize, __g::serde::Deserialize)] 96 | #[cfg_attr( 97 | feature = "ssr", 98 | derive( 99 | __g::gel_derive::Queryable, 100 | __g::strum::AsRefStr, 101 | __g::strum::Display, 102 | __g::strum::EnumString, 103 | __g::strum::EnumIs, 104 | __g::strum::FromRepr, 105 | __g::strum::IntoStaticStr 106 | ) 107 | )] 108 | pub enum AccountProvider { 109 | Github, 110 | } 111 | #[cfg(feature = "ssr")] 112 | impl From for __g::gel_protocol::value::Value { 113 | fn from(value: AccountProvider) -> Self { 114 | __g::gel_protocol::value::Value::Enum(value.as_ref().into()) 115 | } 116 | } 117 | #[derive(Debug, Clone, Copy, __g::serde::Serialize, __g::serde::Deserialize)] 118 | #[cfg_attr( 119 | feature = "ssr", 120 | derive( 121 | __g::gel_derive::Queryable, 122 | __g::strum::AsRefStr, 123 | __g::strum::Display, 124 | __g::strum::EnumString, 125 | __g::strum::EnumIs, 126 | __g::strum::FromRepr, 127 | __g::strum::IntoStaticStr 128 | ) 129 | )] 130 | pub enum RelationshipType { 131 | Follow, 132 | Block, 133 | Mute, 134 | } 135 | #[cfg(feature = "ssr")] 136 | impl From for __g::gel_protocol::value::Value { 137 | fn from(value: RelationshipType) -> Self { 138 | __g::gel_protocol::value::Value::Enum(value.as_ref().into()) 139 | } 140 | } 141 | #[derive(Debug, Clone, Copy, __g::serde::Serialize, __g::serde::Deserialize)] 142 | #[cfg_attr( 143 | feature = "ssr", 144 | derive( 145 | __g::gel_derive::Queryable, 146 | __g::strum::AsRefStr, 147 | __g::strum::Display, 148 | __g::strum::EnumString, 149 | __g::strum::EnumIs, 150 | __g::strum::FromRepr, 151 | __g::strum::IntoStaticStr 152 | ) 153 | )] 154 | pub enum Role { 155 | None, 156 | Editor, 157 | Moderator, 158 | Admin, 159 | Owner, 160 | } 161 | #[cfg(feature = "ssr")] 162 | impl From for __g::gel_protocol::value::Value { 163 | fn from(value: Role) -> Self { 164 | __g::gel_protocol::value::Value::Enum(value.as_ref().into()) 165 | } 166 | } 167 | -------------------------------------------------------------------------------- /crates/gelx/tests/snapshots/codegen__can_generate_enums@enums.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/gelx/tests/codegen.rs 3 | expression: value 4 | --- 5 | mod.rs 6 | //! This file is generated by `gelx generate`. 7 | //! It is not intended for manual editing. 8 | //! To update it, run `gelx generate`. 9 | #![cfg_attr(rustfmt, rustfmt_skip)] 10 | #![allow(unused)] 11 | #![allow(unused_qualifications)] 12 | #![allow(clippy::all)] 13 | use ::gelx::exports as __g; 14 | pub use default::*; 15 | #[path = "additional.rs"] 16 | pub mod additional; 17 | #[path = "default.rs"] 18 | pub mod default; 19 | 20 | 21 | additional.rs 22 | //! This file is generated by `gelx generate`. 23 | //! It is not intended for manual editing. 24 | //! To update it, run `gelx generate`. 25 | #![cfg_attr(rustfmt, rustfmt_skip)] 26 | #![allow(unused)] 27 | #![allow(unused_qualifications)] 28 | #![allow(clippy::all)] 29 | use super::*; 30 | #[derive( 31 | Debug, 32 | Clone, 33 | Copy, 34 | __g::serde::Serialize, 35 | __g::serde::Deserialize, 36 | __g::gel_derive::Queryable, 37 | __g::strum::AsRefStr, 38 | __g::strum::Display, 39 | __g::strum::EnumString, 40 | __g::strum::EnumIs, 41 | __g::strum::FromRepr, 42 | __g::strum::IntoStaticStr 43 | )] 44 | pub enum Awesomeness { 45 | Very, 46 | Somewhat, 47 | NotReally, 48 | } 49 | impl From for __g::gel_protocol::value::Value { 50 | fn from(value: Awesomeness) -> Self { 51 | __g::gel_protocol::value::Value::Enum(value.as_ref().into()) 52 | } 53 | } 54 | #[derive( 55 | Debug, 56 | Clone, 57 | Copy, 58 | __g::serde::Serialize, 59 | __g::serde::Deserialize, 60 | __g::gel_derive::Queryable, 61 | __g::strum::AsRefStr, 62 | __g::strum::Display, 63 | __g::strum::EnumString, 64 | __g::strum::EnumIs, 65 | __g::strum::FromRepr, 66 | __g::strum::IntoStaticStr 67 | )] 68 | pub enum Smartness { 69 | #[serde(rename = "low")] 70 | #[strum(serialize = "low")] 71 | Low, 72 | #[serde(rename = "mid")] 73 | #[strum(serialize = "mid")] 74 | Mid, 75 | #[serde(rename = "genius")] 76 | #[strum(serialize = "genius")] 77 | Genius, 78 | } 79 | impl From for __g::gel_protocol::value::Value { 80 | fn from(value: Smartness) -> Self { 81 | __g::gel_protocol::value::Value::Enum(value.as_ref().into()) 82 | } 83 | } 84 | 85 | 86 | default.rs 87 | //! This file is generated by `gelx generate`. 88 | //! It is not intended for manual editing. 89 | //! To update it, run `gelx generate`. 90 | #![cfg_attr(rustfmt, rustfmt_skip)] 91 | #![allow(unused)] 92 | #![allow(unused_qualifications)] 93 | #![allow(clippy::all)] 94 | use super::*; 95 | #[derive( 96 | Debug, 97 | Clone, 98 | Copy, 99 | __g::serde::Serialize, 100 | __g::serde::Deserialize, 101 | __g::gel_derive::Queryable, 102 | __g::strum::AsRefStr, 103 | __g::strum::Display, 104 | __g::strum::EnumString, 105 | __g::strum::EnumIs, 106 | __g::strum::FromRepr, 107 | __g::strum::IntoStaticStr 108 | )] 109 | pub enum AccountProvider { 110 | Github, 111 | } 112 | impl From for __g::gel_protocol::value::Value { 113 | fn from(value: AccountProvider) -> Self { 114 | __g::gel_protocol::value::Value::Enum(value.as_ref().into()) 115 | } 116 | } 117 | #[derive( 118 | Debug, 119 | Clone, 120 | Copy, 121 | __g::serde::Serialize, 122 | __g::serde::Deserialize, 123 | __g::gel_derive::Queryable, 124 | __g::strum::AsRefStr, 125 | __g::strum::Display, 126 | __g::strum::EnumString, 127 | __g::strum::EnumIs, 128 | __g::strum::FromRepr, 129 | __g::strum::IntoStaticStr 130 | )] 131 | pub enum RelationshipType { 132 | Follow, 133 | Block, 134 | Mute, 135 | } 136 | impl From for __g::gel_protocol::value::Value { 137 | fn from(value: RelationshipType) -> Self { 138 | __g::gel_protocol::value::Value::Enum(value.as_ref().into()) 139 | } 140 | } 141 | #[derive( 142 | Debug, 143 | Clone, 144 | Copy, 145 | __g::serde::Serialize, 146 | __g::serde::Deserialize, 147 | __g::gel_derive::Queryable, 148 | __g::strum::AsRefStr, 149 | __g::strum::Display, 150 | __g::strum::EnumString, 151 | __g::strum::EnumIs, 152 | __g::strum::FromRepr, 153 | __g::strum::IntoStaticStr 154 | )] 155 | pub enum Role { 156 | None, 157 | Editor, 158 | Moderator, 159 | Admin, 160 | Owner, 161 | } 162 | impl From for __g::gel_protocol::value::Value { 163 | fn from(value: Role) -> Self { 164 | __g::gel_protocol::value::Value::Enum(value.as_ref().into()) 165 | } 166 | } 167 | -------------------------------------------------------------------------------- /crates/gelx/tests/snapshots/codegen__can_generate_enums@enums__builder_query_serde_strum.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/gelx/tests/codegen.rs 3 | expression: value 4 | --- 5 | mod.rs 6 | //! This file is generated by `gelx generate`. 7 | //! It is not intended for manual editing. 8 | //! To update it, run `gelx generate`. 9 | #![cfg_attr(rustfmt, rustfmt_skip)] 10 | #![allow(unused)] 11 | #![allow(unused_qualifications)] 12 | #![allow(clippy::all)] 13 | use ::gelx::exports as __g; 14 | pub use default::*; 15 | #[path = "additional.rs"] 16 | pub mod additional; 17 | #[path = "default.rs"] 18 | pub mod default; 19 | 20 | 21 | additional.rs 22 | //! This file is generated by `gelx generate`. 23 | //! It is not intended for manual editing. 24 | //! To update it, run `gelx generate`. 25 | #![cfg_attr(rustfmt, rustfmt_skip)] 26 | #![allow(unused)] 27 | #![allow(unused_qualifications)] 28 | #![allow(clippy::all)] 29 | use super::*; 30 | #[derive( 31 | Debug, 32 | Clone, 33 | Copy, 34 | __g::serde::Serialize, 35 | __g::serde::Deserialize, 36 | __g::gel_derive::Queryable, 37 | __g::strum::AsRefStr, 38 | __g::strum::Display, 39 | __g::strum::EnumString, 40 | __g::strum::EnumIs, 41 | __g::strum::FromRepr, 42 | __g::strum::IntoStaticStr 43 | )] 44 | pub enum Awesomeness { 45 | Very, 46 | Somewhat, 47 | NotReally, 48 | } 49 | impl From for __g::gel_protocol::value::Value { 50 | fn from(value: Awesomeness) -> Self { 51 | __g::gel_protocol::value::Value::Enum(value.as_ref().into()) 52 | } 53 | } 54 | #[derive( 55 | Debug, 56 | Clone, 57 | Copy, 58 | __g::serde::Serialize, 59 | __g::serde::Deserialize, 60 | __g::gel_derive::Queryable, 61 | __g::strum::AsRefStr, 62 | __g::strum::Display, 63 | __g::strum::EnumString, 64 | __g::strum::EnumIs, 65 | __g::strum::FromRepr, 66 | __g::strum::IntoStaticStr 67 | )] 68 | pub enum Smartness { 69 | #[serde(rename = "low")] 70 | #[strum(serialize = "low")] 71 | Low, 72 | #[serde(rename = "mid")] 73 | #[strum(serialize = "mid")] 74 | Mid, 75 | #[serde(rename = "genius")] 76 | #[strum(serialize = "genius")] 77 | Genius, 78 | } 79 | impl From for __g::gel_protocol::value::Value { 80 | fn from(value: Smartness) -> Self { 81 | __g::gel_protocol::value::Value::Enum(value.as_ref().into()) 82 | } 83 | } 84 | 85 | 86 | default.rs 87 | //! This file is generated by `gelx generate`. 88 | //! It is not intended for manual editing. 89 | //! To update it, run `gelx generate`. 90 | #![cfg_attr(rustfmt, rustfmt_skip)] 91 | #![allow(unused)] 92 | #![allow(unused_qualifications)] 93 | #![allow(clippy::all)] 94 | use super::*; 95 | #[derive( 96 | Debug, 97 | Clone, 98 | Copy, 99 | __g::serde::Serialize, 100 | __g::serde::Deserialize, 101 | __g::gel_derive::Queryable, 102 | __g::strum::AsRefStr, 103 | __g::strum::Display, 104 | __g::strum::EnumString, 105 | __g::strum::EnumIs, 106 | __g::strum::FromRepr, 107 | __g::strum::IntoStaticStr 108 | )] 109 | pub enum AccountProvider { 110 | Github, 111 | } 112 | impl From for __g::gel_protocol::value::Value { 113 | fn from(value: AccountProvider) -> Self { 114 | __g::gel_protocol::value::Value::Enum(value.as_ref().into()) 115 | } 116 | } 117 | #[derive( 118 | Debug, 119 | Clone, 120 | Copy, 121 | __g::serde::Serialize, 122 | __g::serde::Deserialize, 123 | __g::gel_derive::Queryable, 124 | __g::strum::AsRefStr, 125 | __g::strum::Display, 126 | __g::strum::EnumString, 127 | __g::strum::EnumIs, 128 | __g::strum::FromRepr, 129 | __g::strum::IntoStaticStr 130 | )] 131 | pub enum RelationshipType { 132 | Follow, 133 | Block, 134 | Mute, 135 | } 136 | impl From for __g::gel_protocol::value::Value { 137 | fn from(value: RelationshipType) -> Self { 138 | __g::gel_protocol::value::Value::Enum(value.as_ref().into()) 139 | } 140 | } 141 | #[derive( 142 | Debug, 143 | Clone, 144 | Copy, 145 | __g::serde::Serialize, 146 | __g::serde::Deserialize, 147 | __g::gel_derive::Queryable, 148 | __g::strum::AsRefStr, 149 | __g::strum::Display, 150 | __g::strum::EnumString, 151 | __g::strum::EnumIs, 152 | __g::strum::FromRepr, 153 | __g::strum::IntoStaticStr 154 | )] 155 | pub enum Role { 156 | None, 157 | Editor, 158 | Moderator, 159 | Admin, 160 | Owner, 161 | } 162 | impl From for __g::gel_protocol::value::Value { 163 | fn from(value: Role) -> Self { 164 | __g::gel_protocol::value::Value::Enum(value.as_ref().into()) 165 | } 166 | } 167 | -------------------------------------------------------------------------------- /crates/gelx/tests/snapshots/codegen__codegen_files@insert_user.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/gelx/tests/codegen.rs 3 | expression: "&content" 4 | --- 5 | pub mod example { 6 | use ::gelx::exports as __g; 7 | /// Execute the desired query. 8 | pub async fn query( 9 | client: &__g::gel_tokio::Client, 10 | props: &Input, 11 | ) -> ::core::result::Result { 12 | client.query_required_single(QUERY, props).await 13 | } 14 | /// Compose the query as part of a larger transaction. 15 | pub async fn transaction( 16 | conn: &mut __g::gel_tokio::Transaction, 17 | props: &Input, 18 | ) -> ::core::result::Result { 19 | conn.query_required_single(QUERY, props).await 20 | } 21 | #[derive(Debug, Clone)] 22 | pub struct Input { 23 | pub name: String, 24 | pub bio: String, 25 | pub slug: String, 26 | } 27 | impl __g::gel_protocol::query_arg::QueryArgs for Input { 28 | fn encode( 29 | &self, 30 | encoder: &mut __g::gel_protocol::query_arg::Encoder, 31 | ) -> core::result::Result<(), __g::gel_errors::Error> { 32 | let map = __g::gel_protocol::named_args! { 33 | "name" => self.name.clone(), "bio" => self.bio.clone(), "slug" => self 34 | .slug.clone(), 35 | }; 36 | map.encode(encoder) 37 | } 38 | } 39 | #[derive(Debug, Clone)] 40 | pub struct Output { 41 | pub id: __g::uuid::Uuid, 42 | pub name: Option, 43 | pub bio: Option, 44 | pub slug: String, 45 | } 46 | /// The original query string provided to the macro. Can be reused in your codebase. 47 | pub const QUERY: &str = "with NewUser := (insert User {\n name := $name,\n bio := $bio,\n slug := $slug,\n})\nselect NewUser {\n id,\n name,\n bio,\n slug,\n};\n"; 48 | } 49 | -------------------------------------------------------------------------------- /crates/gelx/tests/snapshots/codegen__codegen_files@insert_user__builder_query_serde_strum.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/gelx/tests/codegen.rs 3 | expression: "&content" 4 | --- 5 | pub mod example { 6 | use ::gelx::exports as __g; 7 | /// Execute the desired query. 8 | pub async fn query( 9 | client: &__g::gel_tokio::Client, 10 | props: &Input, 11 | ) -> ::core::result::Result { 12 | client.query_required_single(QUERY, props).await 13 | } 14 | /// Compose the query as part of a larger transaction. 15 | pub async fn transaction( 16 | conn: &mut __g::gel_tokio::Transaction, 17 | props: &Input, 18 | ) -> ::core::result::Result { 19 | conn.query_required_single(QUERY, props).await 20 | } 21 | #[derive( 22 | Debug, 23 | Clone, 24 | __g::serde::Serialize, 25 | __g::serde::Deserialize, 26 | __g::typed_builder::TypedBuilder, 27 | __g::gel_derive::Queryable 28 | )] 29 | pub struct Input { 30 | #[builder(setter(into))] 31 | pub name: String, 32 | #[builder(setter(into))] 33 | pub bio: String, 34 | #[builder(setter(into))] 35 | pub slug: String, 36 | } 37 | impl __g::gel_protocol::query_arg::QueryArgs for Input { 38 | fn encode( 39 | &self, 40 | encoder: &mut __g::gel_protocol::query_arg::Encoder, 41 | ) -> core::result::Result<(), __g::gel_errors::Error> { 42 | let map = __g::gel_protocol::named_args! { 43 | "name" => self.name.clone(), "bio" => self.bio.clone(), "slug" => self 44 | .slug.clone(), 45 | }; 46 | map.encode(encoder) 47 | } 48 | } 49 | #[derive( 50 | Debug, 51 | Clone, 52 | __g::serde::Serialize, 53 | __g::serde::Deserialize, 54 | __g::gel_derive::Queryable 55 | )] 56 | pub struct Output { 57 | pub id: __g::uuid::Uuid, 58 | pub name: Option, 59 | pub bio: Option, 60 | pub slug: String, 61 | } 62 | /// The original query string provided to the macro. Can be reused in your codebase. 63 | pub const QUERY: &str = "with NewUser := (insert User {\n name := $name,\n bio := $bio,\n slug := $slug,\n})\nselect NewUser {\n id,\n name,\n bio,\n slug,\n};\n"; 64 | } 65 | -------------------------------------------------------------------------------- /crates/gelx/tests/snapshots/codegen__codegen_files@remove_user.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/gelx/tests/codegen.rs 3 | expression: "&content" 4 | --- 5 | pub mod example { 6 | use ::gelx::exports as __g; 7 | /// Execute the desired query. 8 | pub async fn query( 9 | client: &__g::gel_tokio::Client, 10 | props: &Input, 11 | ) -> ::core::result::Result, __g::gel_errors::Error> { 12 | client.query_single(QUERY, props).await 13 | } 14 | /// Compose the query as part of a larger transaction. 15 | pub async fn transaction( 16 | conn: &mut __g::gel_tokio::Transaction, 17 | props: &Input, 18 | ) -> ::core::result::Result, __g::gel_errors::Error> { 19 | conn.query_single(QUERY, props).await 20 | } 21 | #[derive(Debug, Clone)] 22 | pub struct Input { 23 | pub id: __g::uuid::Uuid, 24 | } 25 | impl __g::gel_protocol::query_arg::QueryArgs for Input { 26 | fn encode( 27 | &self, 28 | encoder: &mut __g::gel_protocol::query_arg::Encoder, 29 | ) -> core::result::Result<(), __g::gel_errors::Error> { 30 | let map = __g::gel_protocol::named_args! { 31 | "id" => self.id.clone(), 32 | }; 33 | map.encode(encoder) 34 | } 35 | } 36 | #[derive(Debug, Clone)] 37 | pub struct Output { 38 | pub id: __g::uuid::Uuid, 39 | } 40 | /// The original query string provided to the macro. Can be reused in your codebase. 41 | pub const QUERY: &str = "delete User filter .id = $id;\n"; 42 | } 43 | -------------------------------------------------------------------------------- /crates/gelx/tests/snapshots/codegen__codegen_files@remove_user__builder_query_serde_strum.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/gelx/tests/codegen.rs 3 | expression: "&content" 4 | --- 5 | pub mod example { 6 | use ::gelx::exports as __g; 7 | /// Execute the desired query. 8 | pub async fn query( 9 | client: &__g::gel_tokio::Client, 10 | props: &Input, 11 | ) -> ::core::result::Result, __g::gel_errors::Error> { 12 | client.query_single(QUERY, props).await 13 | } 14 | /// Compose the query as part of a larger transaction. 15 | pub async fn transaction( 16 | conn: &mut __g::gel_tokio::Transaction, 17 | props: &Input, 18 | ) -> ::core::result::Result, __g::gel_errors::Error> { 19 | conn.query_single(QUERY, props).await 20 | } 21 | #[derive( 22 | Debug, 23 | Clone, 24 | __g::serde::Serialize, 25 | __g::serde::Deserialize, 26 | __g::typed_builder::TypedBuilder, 27 | __g::gel_derive::Queryable 28 | )] 29 | pub struct Input { 30 | #[builder(setter(into))] 31 | pub id: __g::uuid::Uuid, 32 | } 33 | impl __g::gel_protocol::query_arg::QueryArgs for Input { 34 | fn encode( 35 | &self, 36 | encoder: &mut __g::gel_protocol::query_arg::Encoder, 37 | ) -> core::result::Result<(), __g::gel_errors::Error> { 38 | let map = __g::gel_protocol::named_args! { 39 | "id" => self.id.clone(), 40 | }; 41 | map.encode(encoder) 42 | } 43 | } 44 | #[derive( 45 | Debug, 46 | Clone, 47 | __g::serde::Serialize, 48 | __g::serde::Deserialize, 49 | __g::gel_derive::Queryable 50 | )] 51 | pub struct Output { 52 | pub id: __g::uuid::Uuid, 53 | } 54 | /// The original query string provided to the macro. Can be reused in your codebase. 55 | pub const QUERY: &str = "delete User filter .id = $id;\n"; 56 | } 57 | -------------------------------------------------------------------------------- /crates/gelx/tests/snapshots/codegen__codegen_literals@case_01_str.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/gelx/tests/codegen.rs 3 | expression: "&content" 4 | --- 5 | pub mod example { 6 | use ::gelx::exports as __g; 7 | /// Execute the desired query. 8 | pub async fn query( 9 | client: &__g::gel_tokio::Client, 10 | ) -> ::core::result::Result { 11 | client.query_required_single(QUERY, &()).await 12 | } 13 | /// Compose the query as part of a larger transaction. 14 | pub async fn transaction( 15 | conn: &mut __g::gel_tokio::Transaction, 16 | ) -> ::core::result::Result { 17 | conn.query_required_single(QUERY, &()).await 18 | } 19 | pub type Input = (); 20 | pub type Output = String; 21 | /// The original query string provided to the macro. Can be reused in your codebase. 22 | pub const QUERY: &str = "select 'i ❤\u{fe0f} gel'"; 23 | } 24 | -------------------------------------------------------------------------------- /crates/gelx/tests/snapshots/codegen__codegen_literals@case_01_str__builder_query_serde_strum.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/gelx/tests/codegen.rs 3 | expression: "&content" 4 | --- 5 | pub mod example { 6 | use ::gelx::exports as __g; 7 | /// Execute the desired query. 8 | pub async fn query( 9 | client: &__g::gel_tokio::Client, 10 | ) -> ::core::result::Result { 11 | client.query_required_single(QUERY, &()).await 12 | } 13 | /// Compose the query as part of a larger transaction. 14 | pub async fn transaction( 15 | conn: &mut __g::gel_tokio::Transaction, 16 | ) -> ::core::result::Result { 17 | conn.query_required_single(QUERY, &()).await 18 | } 19 | pub type Input = (); 20 | pub type Output = String; 21 | /// The original query string provided to the macro. Can be reused in your codebase. 22 | pub const QUERY: &str = "select 'i ❤\u{fe0f} gel'"; 23 | } 24 | -------------------------------------------------------------------------------- /crates/gelx/tests/snapshots/codegen__codegen_literals@case_02_bool.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/gelx/tests/codegen.rs 3 | expression: "&content" 4 | --- 5 | pub mod example { 6 | use ::gelx::exports as __g; 7 | /// Execute the desired query. 8 | pub async fn query( 9 | client: &__g::gel_tokio::Client, 10 | ) -> ::core::result::Result { 11 | client.query_required_single(QUERY, &()).await 12 | } 13 | /// Compose the query as part of a larger transaction. 14 | pub async fn transaction( 15 | conn: &mut __g::gel_tokio::Transaction, 16 | ) -> ::core::result::Result { 17 | conn.query_required_single(QUERY, &()).await 18 | } 19 | pub type Input = (); 20 | pub type Output = bool; 21 | /// The original query string provided to the macro. Can be reused in your codebase. 22 | pub const QUERY: &str = "select true"; 23 | } 24 | -------------------------------------------------------------------------------- /crates/gelx/tests/snapshots/codegen__codegen_literals@case_02_bool__builder_query_serde_strum.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/gelx/tests/codegen.rs 3 | expression: "&content" 4 | --- 5 | pub mod example { 6 | use ::gelx::exports as __g; 7 | /// Execute the desired query. 8 | pub async fn query( 9 | client: &__g::gel_tokio::Client, 10 | ) -> ::core::result::Result { 11 | client.query_required_single(QUERY, &()).await 12 | } 13 | /// Compose the query as part of a larger transaction. 14 | pub async fn transaction( 15 | conn: &mut __g::gel_tokio::Transaction, 16 | ) -> ::core::result::Result { 17 | conn.query_required_single(QUERY, &()).await 18 | } 19 | pub type Input = (); 20 | pub type Output = bool; 21 | /// The original query string provided to the macro. Can be reused in your codebase. 22 | pub const QUERY: &str = "select true"; 23 | } 24 | -------------------------------------------------------------------------------- /crates/gelx/tests/snapshots/codegen__codegen_literals@case_03_int64.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/gelx/tests/codegen.rs 3 | expression: "&content" 4 | --- 5 | pub mod example { 6 | use ::gelx::exports as __g; 7 | /// Execute the desired query. 8 | pub async fn query( 9 | client: &__g::gel_tokio::Client, 10 | ) -> ::core::result::Result { 11 | client.query_required_single(QUERY, &()).await 12 | } 13 | /// Compose the query as part of a larger transaction. 14 | pub async fn transaction( 15 | conn: &mut __g::gel_tokio::Transaction, 16 | ) -> ::core::result::Result { 17 | conn.query_required_single(QUERY, &()).await 18 | } 19 | pub type Input = (); 20 | pub type Output = i64; 21 | /// The original query string provided to the macro. Can be reused in your codebase. 22 | pub const QUERY: &str = "select 3"; 23 | } 24 | -------------------------------------------------------------------------------- /crates/gelx/tests/snapshots/codegen__codegen_literals@case_03_int64__builder_query_serde_strum.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/gelx/tests/codegen.rs 3 | expression: "&content" 4 | --- 5 | pub mod example { 6 | use ::gelx::exports as __g; 7 | /// Execute the desired query. 8 | pub async fn query( 9 | client: &__g::gel_tokio::Client, 10 | ) -> ::core::result::Result { 11 | client.query_required_single(QUERY, &()).await 12 | } 13 | /// Compose the query as part of a larger transaction. 14 | pub async fn transaction( 15 | conn: &mut __g::gel_tokio::Transaction, 16 | ) -> ::core::result::Result { 17 | conn.query_required_single(QUERY, &()).await 18 | } 19 | pub type Input = (); 20 | pub type Output = i64; 21 | /// The original query string provided to the macro. Can be reused in your codebase. 22 | pub const QUERY: &str = "select 3"; 23 | } 24 | -------------------------------------------------------------------------------- /crates/gelx/tests/snapshots/codegen__codegen_literals@case_04_float64.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/gelx/tests/codegen.rs 3 | expression: "&content" 4 | --- 5 | pub mod example { 6 | use ::gelx::exports as __g; 7 | /// Execute the desired query. 8 | pub async fn query( 9 | client: &__g::gel_tokio::Client, 10 | ) -> ::core::result::Result { 11 | client.query_required_single(QUERY, &()).await 12 | } 13 | /// Compose the query as part of a larger transaction. 14 | pub async fn transaction( 15 | conn: &mut __g::gel_tokio::Transaction, 16 | ) -> ::core::result::Result { 17 | conn.query_required_single(QUERY, &()).await 18 | } 19 | pub type Input = (); 20 | pub type Output = f64; 21 | /// The original query string provided to the macro. Can be reused in your codebase. 22 | pub const QUERY: &str = "select 314e-2"; 23 | } 24 | -------------------------------------------------------------------------------- /crates/gelx/tests/snapshots/codegen__codegen_literals@case_04_float64__builder_query_serde_strum.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/gelx/tests/codegen.rs 3 | expression: "&content" 4 | --- 5 | pub mod example { 6 | use ::gelx::exports as __g; 7 | /// Execute the desired query. 8 | pub async fn query( 9 | client: &__g::gel_tokio::Client, 10 | ) -> ::core::result::Result { 11 | client.query_required_single(QUERY, &()).await 12 | } 13 | /// Compose the query as part of a larger transaction. 14 | pub async fn transaction( 15 | conn: &mut __g::gel_tokio::Transaction, 16 | ) -> ::core::result::Result { 17 | conn.query_required_single(QUERY, &()).await 18 | } 19 | pub type Input = (); 20 | pub type Output = f64; 21 | /// The original query string provided to the macro. Can be reused in your codebase. 22 | pub const QUERY: &str = "select 314e-2"; 23 | } 24 | -------------------------------------------------------------------------------- /crates/gelx/tests/snapshots/codegen__codegen_literals@case_05_bigint.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/gelx/tests/codegen.rs 3 | expression: "&content" 4 | --- 5 | pub mod example { 6 | use ::gelx::exports as __g; 7 | /// Execute the desired query. 8 | pub async fn query( 9 | client: &__g::gel_tokio::Client, 10 | ) -> ::core::result::Result { 11 | client.query_required_single(QUERY, &()).await 12 | } 13 | /// Compose the query as part of a larger transaction. 14 | pub async fn transaction( 15 | conn: &mut __g::gel_tokio::Transaction, 16 | ) -> ::core::result::Result { 17 | conn.query_required_single(QUERY, &()).await 18 | } 19 | pub type Input = (); 20 | pub type Output = __g::BigIntAlias; 21 | /// The original query string provided to the macro. Can be reused in your codebase. 22 | pub const QUERY: &str = "select 42n"; 23 | } 24 | -------------------------------------------------------------------------------- /crates/gelx/tests/snapshots/codegen__codegen_literals@case_05_bigint__builder_query_serde_strum.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/gelx/tests/codegen.rs 3 | expression: "&content" 4 | --- 5 | pub mod example { 6 | use ::gelx::exports as __g; 7 | /// Execute the desired query. 8 | pub async fn query( 9 | client: &__g::gel_tokio::Client, 10 | ) -> ::core::result::Result { 11 | client.query_required_single(QUERY, &()).await 12 | } 13 | /// Compose the query as part of a larger transaction. 14 | pub async fn transaction( 15 | conn: &mut __g::gel_tokio::Transaction, 16 | ) -> ::core::result::Result { 17 | conn.query_required_single(QUERY, &()).await 18 | } 19 | pub type Input = (); 20 | pub type Output = __g::BigIntAlias; 21 | /// The original query string provided to the macro. Can be reused in your codebase. 22 | pub const QUERY: &str = "select 42n"; 23 | } 24 | -------------------------------------------------------------------------------- /crates/gelx/tests/snapshots/codegen__codegen_literals@case_06_decimal.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/gelx/tests/codegen.rs 3 | expression: "&content" 4 | --- 5 | pub mod example { 6 | use ::gelx::exports as __g; 7 | /// Execute the desired query. 8 | pub async fn query( 9 | client: &__g::gel_tokio::Client, 10 | ) -> ::core::result::Result { 11 | client.query_required_single(QUERY, &()).await 12 | } 13 | /// Compose the query as part of a larger transaction. 14 | pub async fn transaction( 15 | conn: &mut __g::gel_tokio::Transaction, 16 | ) -> ::core::result::Result { 17 | conn.query_required_single(QUERY, &()).await 18 | } 19 | pub type Input = (); 20 | pub type Output = __g::BigIntAlias; 21 | /// The original query string provided to the macro. Can be reused in your codebase. 22 | pub const QUERY: &str = "select 42e+100n"; 23 | } 24 | -------------------------------------------------------------------------------- /crates/gelx/tests/snapshots/codegen__codegen_literals@case_06_decimal__builder_query_serde_strum.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/gelx/tests/codegen.rs 3 | expression: "&content" 4 | --- 5 | pub mod example { 6 | use ::gelx::exports as __g; 7 | /// Execute the desired query. 8 | pub async fn query( 9 | client: &__g::gel_tokio::Client, 10 | ) -> ::core::result::Result { 11 | client.query_required_single(QUERY, &()).await 12 | } 13 | /// Compose the query as part of a larger transaction. 14 | pub async fn transaction( 15 | conn: &mut __g::gel_tokio::Transaction, 16 | ) -> ::core::result::Result { 17 | conn.query_required_single(QUERY, &()).await 18 | } 19 | pub type Input = (); 20 | pub type Output = __g::BigIntAlias; 21 | /// The original query string provided to the macro. Can be reused in your codebase. 22 | pub const QUERY: &str = "select 42e+100n"; 23 | } 24 | -------------------------------------------------------------------------------- /crates/gelx/tests/snapshots/codegen__codegen_literals@case_07_uuid.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/gelx/tests/codegen.rs 3 | expression: "&content" 4 | --- 5 | pub mod example { 6 | use ::gelx::exports as __g; 7 | /// Execute the desired query. 8 | pub async fn query( 9 | client: &__g::gel_tokio::Client, 10 | ) -> ::core::result::Result { 11 | client.query_required_single(QUERY, &()).await 12 | } 13 | /// Compose the query as part of a larger transaction. 14 | pub async fn transaction( 15 | conn: &mut __g::gel_tokio::Transaction, 16 | ) -> ::core::result::Result { 17 | conn.query_required_single(QUERY, &()).await 18 | } 19 | pub type Input = (); 20 | pub type Output = __g::uuid::Uuid; 21 | /// The original query string provided to the macro. Can be reused in your codebase. 22 | pub const QUERY: &str = "select 'a5ea6360-75bd-4c20-b69c-8f317b0d2857'"; 23 | } 24 | -------------------------------------------------------------------------------- /crates/gelx/tests/snapshots/codegen__codegen_literals@case_07_uuid__builder_query_serde_strum.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/gelx/tests/codegen.rs 3 | expression: "&content" 4 | --- 5 | pub mod example { 6 | use ::gelx::exports as __g; 7 | /// Execute the desired query. 8 | pub async fn query( 9 | client: &__g::gel_tokio::Client, 10 | ) -> ::core::result::Result { 11 | client.query_required_single(QUERY, &()).await 12 | } 13 | /// Compose the query as part of a larger transaction. 14 | pub async fn transaction( 15 | conn: &mut __g::gel_tokio::Transaction, 16 | ) -> ::core::result::Result { 17 | conn.query_required_single(QUERY, &()).await 18 | } 19 | pub type Input = (); 20 | pub type Output = __g::uuid::Uuid; 21 | /// The original query string provided to the macro. Can be reused in your codebase. 22 | pub const QUERY: &str = "select 'a5ea6360-75bd-4c20-b69c-8f317b0d2857'"; 23 | } 24 | -------------------------------------------------------------------------------- /crates/gelx/tests/snapshots/codegen__codegen_literals@case_08_datetime.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/gelx/tests/codegen.rs 3 | expression: "&content" 4 | --- 5 | pub mod example { 6 | use ::gelx::exports as __g; 7 | /// Execute the desired query. 8 | pub async fn query( 9 | client: &__g::gel_tokio::Client, 10 | ) -> ::core::result::Result { 11 | client.query_required_single(QUERY, &()).await 12 | } 13 | /// Compose the query as part of a larger transaction. 14 | pub async fn transaction( 15 | conn: &mut __g::gel_tokio::Transaction, 16 | ) -> ::core::result::Result { 17 | conn.query_required_single(QUERY, &()).await 18 | } 19 | pub type Input = (); 20 | pub type Output = __g::DateTimeAlias; 21 | /// The original query string provided to the macro. Can be reused in your codebase. 22 | pub const QUERY: &str = "select '1999-03-31T15:17:00Z'"; 23 | } 24 | -------------------------------------------------------------------------------- /crates/gelx/tests/snapshots/codegen__codegen_literals@case_08_datetime__builder_query_serde_strum.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/gelx/tests/codegen.rs 3 | expression: "&content" 4 | --- 5 | pub mod example { 6 | use ::gelx::exports as __g; 7 | /// Execute the desired query. 8 | pub async fn query( 9 | client: &__g::gel_tokio::Client, 10 | ) -> ::core::result::Result { 11 | client.query_required_single(QUERY, &()).await 12 | } 13 | /// Compose the query as part of a larger transaction. 14 | pub async fn transaction( 15 | conn: &mut __g::gel_tokio::Transaction, 16 | ) -> ::core::result::Result { 17 | conn.query_required_single(QUERY, &()).await 18 | } 19 | pub type Input = (); 20 | pub type Output = __g::DateTimeAlias; 21 | /// The original query string provided to the macro. Can be reused in your codebase. 22 | pub const QUERY: &str = "select '1999-03-31T15:17:00Z'"; 23 | } 24 | -------------------------------------------------------------------------------- /crates/gelx/tests/snapshots/codegen__codegen_literals@case_09_duration.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/gelx/tests/codegen.rs 3 | expression: "&content" 4 | --- 5 | pub mod example { 6 | use ::gelx::exports as __g; 7 | /// Execute the desired query. 8 | pub async fn query( 9 | client: &__g::gel_tokio::Client, 10 | ) -> ::core::result::Result { 11 | client.query_required_single(QUERY, &()).await 12 | } 13 | /// Compose the query as part of a larger transaction. 14 | pub async fn transaction( 15 | conn: &mut __g::gel_tokio::Transaction, 16 | ) -> ::core::result::Result { 17 | conn.query_required_single(QUERY, &()).await 18 | } 19 | pub type Input = (); 20 | pub type Output = __g::gel_protocol::model::Duration; 21 | /// The original query string provided to the macro. Can be reused in your codebase. 22 | pub const QUERY: &str = "select '45.6 seconds'"; 23 | } 24 | -------------------------------------------------------------------------------- /crates/gelx/tests/snapshots/codegen__codegen_literals@case_09_duration__builder_query_serde_strum.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/gelx/tests/codegen.rs 3 | expression: "&content" 4 | --- 5 | pub mod example { 6 | use ::gelx::exports as __g; 7 | /// Execute the desired query. 8 | pub async fn query( 9 | client: &__g::gel_tokio::Client, 10 | ) -> ::core::result::Result { 11 | client.query_required_single(QUERY, &()).await 12 | } 13 | /// Compose the query as part of a larger transaction. 14 | pub async fn transaction( 15 | conn: &mut __g::gel_tokio::Transaction, 16 | ) -> ::core::result::Result { 17 | conn.query_required_single(QUERY, &()).await 18 | } 19 | pub type Input = (); 20 | pub type Output = __g::gel_protocol::model::Duration; 21 | /// The original query string provided to the macro. Can be reused in your codebase. 22 | pub const QUERY: &str = "select '45.6 seconds'"; 23 | } 24 | -------------------------------------------------------------------------------- /crates/gelx/tests/snapshots/codegen__codegen_literals@case_10_array.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/gelx/tests/codegen.rs 3 | expression: "&content" 4 | --- 5 | pub mod example { 6 | use ::gelx::exports as __g; 7 | /// Execute the desired query. 8 | pub async fn query( 9 | client: &__g::gel_tokio::Client, 10 | ) -> ::core::result::Result { 11 | client.query_required_single(QUERY, &()).await 12 | } 13 | /// Compose the query as part of a larger transaction. 14 | pub async fn transaction( 15 | conn: &mut __g::gel_tokio::Transaction, 16 | ) -> ::core::result::Result { 17 | conn.query_required_single(QUERY, &()).await 18 | } 19 | pub type Input = (); 20 | pub type Output = Vec; 21 | /// The original query string provided to the macro. Can be reused in your codebase. 22 | pub const QUERY: &str = "select [1, 2, 3]"; 23 | } 24 | -------------------------------------------------------------------------------- /crates/gelx/tests/snapshots/codegen__codegen_literals@case_10_array__builder_query_serde_strum.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/gelx/tests/codegen.rs 3 | expression: "&content" 4 | --- 5 | pub mod example { 6 | use ::gelx::exports as __g; 7 | /// Execute the desired query. 8 | pub async fn query( 9 | client: &__g::gel_tokio::Client, 10 | ) -> ::core::result::Result { 11 | client.query_required_single(QUERY, &()).await 12 | } 13 | /// Compose the query as part of a larger transaction. 14 | pub async fn transaction( 15 | conn: &mut __g::gel_tokio::Transaction, 16 | ) -> ::core::result::Result { 17 | conn.query_required_single(QUERY, &()).await 18 | } 19 | pub type Input = (); 20 | pub type Output = Vec; 21 | /// The original query string provided to the macro. Can be reused in your codebase. 22 | pub const QUERY: &str = "select [1, 2, 3]"; 23 | } 24 | -------------------------------------------------------------------------------- /crates/gelx/tests/snapshots/codegen__codegen_literals@case_11_tuple.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/gelx/tests/codegen.rs 3 | expression: "&content" 4 | --- 5 | pub mod example { 6 | use ::gelx::exports as __g; 7 | /// Execute the desired query. 8 | pub async fn query( 9 | client: &__g::gel_tokio::Client, 10 | ) -> ::core::result::Result { 11 | client.query_required_single(QUERY, &()).await 12 | } 13 | /// Compose the query as part of a larger transaction. 14 | pub async fn transaction( 15 | conn: &mut __g::gel_tokio::Transaction, 16 | ) -> ::core::result::Result { 17 | conn.query_required_single(QUERY, &()).await 18 | } 19 | pub type Input = (); 20 | pub type Output = (String, i64, bool); 21 | /// The original query string provided to the macro. Can be reused in your codebase. 22 | pub const QUERY: &str = "select ('Apple', 7, true)"; 23 | } 24 | -------------------------------------------------------------------------------- /crates/gelx/tests/snapshots/codegen__codegen_literals@case_11_tuple__builder_query_serde_strum.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/gelx/tests/codegen.rs 3 | expression: "&content" 4 | --- 5 | pub mod example { 6 | use ::gelx::exports as __g; 7 | /// Execute the desired query. 8 | pub async fn query( 9 | client: &__g::gel_tokio::Client, 10 | ) -> ::core::result::Result { 11 | client.query_required_single(QUERY, &()).await 12 | } 13 | /// Compose the query as part of a larger transaction. 14 | pub async fn transaction( 15 | conn: &mut __g::gel_tokio::Transaction, 16 | ) -> ::core::result::Result { 17 | conn.query_required_single(QUERY, &()).await 18 | } 19 | pub type Input = (); 20 | pub type Output = (String, i64, bool); 21 | /// The original query string provided to the macro. Can be reused in your codebase. 22 | pub const QUERY: &str = "select ('Apple', 7, true)"; 23 | } 24 | -------------------------------------------------------------------------------- /crates/gelx/tests/snapshots/codegen__codegen_literals@case_12_named_tuple.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/gelx/tests/codegen.rs 3 | expression: "&content" 4 | --- 5 | pub mod example { 6 | use ::gelx::exports as __g; 7 | /// Execute the desired query. 8 | pub async fn query( 9 | client: &__g::gel_tokio::Client, 10 | ) -> ::core::result::Result { 11 | client.query_required_single(QUERY, &()).await 12 | } 13 | /// Compose the query as part of a larger transaction. 14 | pub async fn transaction( 15 | conn: &mut __g::gel_tokio::Transaction, 16 | ) -> ::core::result::Result { 17 | conn.query_required_single(QUERY, &()).await 18 | } 19 | pub type Input = (); 20 | #[derive(Debug, Clone)] 21 | pub struct Output { 22 | pub fruit: String, 23 | pub quantity: f64, 24 | pub fresh: bool, 25 | } 26 | /// The original query string provided to the macro. Can be reused in your codebase. 27 | pub const QUERY: &str = "select (fruit := 'Apple', quantity := 3.14, fresh := true)"; 28 | } 29 | -------------------------------------------------------------------------------- /crates/gelx/tests/snapshots/codegen__codegen_literals@case_12_named_tuple__builder_query_serde_strum.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/gelx/tests/codegen.rs 3 | expression: "&content" 4 | --- 5 | pub mod example { 6 | use ::gelx::exports as __g; 7 | /// Execute the desired query. 8 | pub async fn query( 9 | client: &__g::gel_tokio::Client, 10 | ) -> ::core::result::Result { 11 | client.query_required_single(QUERY, &()).await 12 | } 13 | /// Compose the query as part of a larger transaction. 14 | pub async fn transaction( 15 | conn: &mut __g::gel_tokio::Transaction, 16 | ) -> ::core::result::Result { 17 | conn.query_required_single(QUERY, &()).await 18 | } 19 | pub type Input = (); 20 | #[derive( 21 | Debug, 22 | Clone, 23 | __g::serde::Serialize, 24 | __g::serde::Deserialize, 25 | __g::gel_derive::Queryable 26 | )] 27 | pub struct Output { 28 | pub fruit: String, 29 | pub quantity: f64, 30 | pub fresh: bool, 31 | } 32 | /// The original query string provided to the macro. Can be reused in your codebase. 33 | pub const QUERY: &str = "select (fruit := 'Apple', quantity := 3.14, fresh := true)"; 34 | } 35 | -------------------------------------------------------------------------------- /crates/gelx/tests/snapshots/codegen__codegen_literals@case_13_set.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/gelx/tests/codegen.rs 3 | expression: "&content" 4 | --- 5 | pub mod example { 6 | use ::gelx::exports as __g; 7 | /// Execute the desired query. 8 | pub async fn query( 9 | client: &__g::gel_tokio::Client, 10 | ) -> ::core::result::Result, __g::gel_errors::Error> { 11 | client.query(QUERY, &()).await 12 | } 13 | /// Compose the query as part of a larger transaction. 14 | pub async fn transaction( 15 | conn: &mut __g::gel_tokio::Transaction, 16 | ) -> ::core::result::Result, __g::gel_errors::Error> { 17 | conn.query(QUERY, &()).await 18 | } 19 | pub type Input = (); 20 | pub type Output = String; 21 | /// The original query string provided to the macro. Can be reused in your codebase. 22 | pub const QUERY: &str = "select {\"set\", \"of\", \"strings\"}"; 23 | } 24 | -------------------------------------------------------------------------------- /crates/gelx/tests/snapshots/codegen__codegen_literals@case_13_set__builder_query_serde_strum.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/gelx/tests/codegen.rs 3 | expression: "&content" 4 | --- 5 | pub mod example { 6 | use ::gelx::exports as __g; 7 | /// Execute the desired query. 8 | pub async fn query( 9 | client: &__g::gel_tokio::Client, 10 | ) -> ::core::result::Result, __g::gel_errors::Error> { 11 | client.query(QUERY, &()).await 12 | } 13 | /// Compose the query as part of a larger transaction. 14 | pub async fn transaction( 15 | conn: &mut __g::gel_tokio::Transaction, 16 | ) -> ::core::result::Result, __g::gel_errors::Error> { 17 | conn.query(QUERY, &()).await 18 | } 19 | pub type Input = (); 20 | pub type Output = String; 21 | /// The original query string provided to the macro. Can be reused in your codebase. 22 | pub const QUERY: &str = "select {\"set\", \"of\", \"strings\"}"; 23 | } 24 | -------------------------------------------------------------------------------- /crates/gelx/tests/snapshots/codegen__codegen_literals@case_14_empty_set.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/gelx/tests/codegen.rs 3 | expression: "&content" 4 | --- 5 | pub mod example { 6 | use ::gelx::exports as __g; 7 | /// Execute the desired query. 8 | pub async fn query( 9 | client: &__g::gel_tokio::Client, 10 | ) -> ::core::result::Result, __g::gel_errors::Error> { 11 | client.query_single(QUERY, &()).await 12 | } 13 | /// Compose the query as part of a larger transaction. 14 | pub async fn transaction( 15 | conn: &mut __g::gel_tokio::Transaction, 16 | ) -> ::core::result::Result, __g::gel_errors::Error> { 17 | conn.query_single(QUERY, &()).await 18 | } 19 | pub type Input = (); 20 | pub type Output = i64; 21 | /// The original query string provided to the macro. Can be reused in your codebase. 22 | pub const QUERY: &str = "select {}"; 23 | } 24 | -------------------------------------------------------------------------------- /crates/gelx/tests/snapshots/codegen__codegen_literals@case_14_empty_set__builder_query_serde_strum.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/gelx/tests/codegen.rs 3 | expression: "&content" 4 | --- 5 | pub mod example { 6 | use ::gelx::exports as __g; 7 | /// Execute the desired query. 8 | pub async fn query( 9 | client: &__g::gel_tokio::Client, 10 | ) -> ::core::result::Result, __g::gel_errors::Error> { 11 | client.query_single(QUERY, &()).await 12 | } 13 | /// Compose the query as part of a larger transaction. 14 | pub async fn transaction( 15 | conn: &mut __g::gel_tokio::Transaction, 16 | ) -> ::core::result::Result, __g::gel_errors::Error> { 17 | conn.query_single(QUERY, &()).await 18 | } 19 | pub type Input = (); 20 | pub type Output = i64; 21 | /// The original query string provided to the macro. Can be reused in your codebase. 22 | pub const QUERY: &str = "select {}"; 23 | } 24 | -------------------------------------------------------------------------------- /crates/gelx/tests/snapshots/codegen__codegen_literals@case_15_input_shape.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/gelx/tests/codegen.rs 3 | expression: "&content" 4 | --- 5 | pub mod example { 6 | use ::gelx::exports as __g; 7 | /// Execute the desired query. 8 | pub async fn query( 9 | client: &__g::gel_tokio::Client, 10 | ) -> ::core::result::Result { 11 | client.query_required_single(QUERY, &()).await 12 | } 13 | /// Compose the query as part of a larger transaction. 14 | pub async fn transaction( 15 | conn: &mut __g::gel_tokio::Transaction, 16 | ) -> ::core::result::Result { 17 | conn.query_required_single(QUERY, &()).await 18 | } 19 | pub type Input = (); 20 | #[derive(Debug, Clone, Copy)] 21 | pub enum DefaultRelationshipType { 22 | Follow, 23 | Block, 24 | Mute, 25 | } 26 | impl From for __g::gel_protocol::value::Value { 27 | fn from(value: DefaultRelationshipType) -> Self { 28 | __g::gel_protocol::value::Value::Enum(value.as_ref().into()) 29 | } 30 | } 31 | #[derive(Debug, Clone)] 32 | pub struct Output { 33 | pub my_string: DefaultRelationshipType, 34 | pub my_number: i64, 35 | pub several_numbers: Vec, 36 | pub array: Vec, 37 | } 38 | /// The original query string provided to the macro. Can be reused in your codebase. 39 | pub const QUERY: &str = "select { my_string := RelationshipType.Follow, my_number := 42, several_numbers := {1, 2, 3}, array := [1, 2, 3] };"; 40 | } 41 | -------------------------------------------------------------------------------- /crates/gelx/tests/snapshots/codegen__codegen_literals@case_15_input_shape__builder_query_serde_strum.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/gelx/tests/codegen.rs 3 | expression: "&content" 4 | --- 5 | pub mod example { 6 | use ::gelx::exports as __g; 7 | /// Execute the desired query. 8 | pub async fn query( 9 | client: &__g::gel_tokio::Client, 10 | ) -> ::core::result::Result { 11 | client.query_required_single(QUERY, &()).await 12 | } 13 | /// Compose the query as part of a larger transaction. 14 | pub async fn transaction( 15 | conn: &mut __g::gel_tokio::Transaction, 16 | ) -> ::core::result::Result { 17 | conn.query_required_single(QUERY, &()).await 18 | } 19 | pub type Input = (); 20 | #[derive( 21 | Debug, 22 | Clone, 23 | Copy, 24 | __g::serde::Serialize, 25 | __g::serde::Deserialize, 26 | __g::gel_derive::Queryable, 27 | __g::strum::AsRefStr, 28 | __g::strum::Display, 29 | __g::strum::EnumString, 30 | __g::strum::EnumIs, 31 | __g::strum::FromRepr, 32 | __g::strum::IntoStaticStr 33 | )] 34 | pub enum DefaultRelationshipType { 35 | Follow, 36 | Block, 37 | Mute, 38 | } 39 | impl From for __g::gel_protocol::value::Value { 40 | fn from(value: DefaultRelationshipType) -> Self { 41 | __g::gel_protocol::value::Value::Enum(value.as_ref().into()) 42 | } 43 | } 44 | #[derive( 45 | Debug, 46 | Clone, 47 | __g::serde::Serialize, 48 | __g::serde::Deserialize, 49 | __g::gel_derive::Queryable 50 | )] 51 | pub struct Output { 52 | pub my_string: DefaultRelationshipType, 53 | pub my_number: i64, 54 | pub several_numbers: Vec, 55 | pub array: Vec, 56 | } 57 | /// The original query string provided to the macro. Can be reused in your codebase. 58 | pub const QUERY: &str = "select { my_string := RelationshipType.Follow, my_number := 42, several_numbers := {1, 2, 3}, array := [1, 2, 3] };"; 59 | } 60 | -------------------------------------------------------------------------------- /crates/gelx/tests/snapshots/codegen__codegen_literals@case_16_input_shape_with_args.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/gelx/tests/codegen.rs 3 | expression: "&content" 4 | --- 5 | pub mod example { 6 | use ::gelx::exports as __g; 7 | /// Execute the desired query. 8 | pub async fn query( 9 | client: &__g::gel_tokio::Client, 10 | props: &Input, 11 | ) -> ::core::result::Result { 12 | client.query_required_single(QUERY, props).await 13 | } 14 | /// Compose the query as part of a larger transaction. 15 | pub async fn transaction( 16 | conn: &mut __g::gel_tokio::Transaction, 17 | props: &Input, 18 | ) -> ::core::result::Result { 19 | conn.query_required_single(QUERY, props).await 20 | } 21 | #[derive(Debug, Clone)] 22 | pub struct Input { 23 | pub custom: String, 24 | } 25 | impl __g::gel_protocol::query_arg::QueryArgs for Input { 26 | fn encode( 27 | &self, 28 | encoder: &mut __g::gel_protocol::query_arg::Encoder, 29 | ) -> core::result::Result<(), __g::gel_errors::Error> { 30 | let map = __g::gel_protocol::named_args! { 31 | "custom" => self.custom.clone(), 32 | }; 33 | map.encode(encoder) 34 | } 35 | } 36 | #[derive(Debug, Clone)] 37 | pub struct Output { 38 | pub hello: String, 39 | pub custom: String, 40 | } 41 | /// The original query string provided to the macro. Can be reused in your codebase. 42 | pub const QUERY: &str = "select { hello := \"world\", custom := $custom }"; 43 | } 44 | -------------------------------------------------------------------------------- /crates/gelx/tests/snapshots/codegen__codegen_literals@case_16_input_shape_with_args__builder_query_serde_strum.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/gelx/tests/codegen.rs 3 | expression: "&content" 4 | --- 5 | pub mod example { 6 | use ::gelx::exports as __g; 7 | /// Execute the desired query. 8 | pub async fn query( 9 | client: &__g::gel_tokio::Client, 10 | props: &Input, 11 | ) -> ::core::result::Result { 12 | client.query_required_single(QUERY, props).await 13 | } 14 | /// Compose the query as part of a larger transaction. 15 | pub async fn transaction( 16 | conn: &mut __g::gel_tokio::Transaction, 17 | props: &Input, 18 | ) -> ::core::result::Result { 19 | conn.query_required_single(QUERY, props).await 20 | } 21 | #[derive( 22 | Debug, 23 | Clone, 24 | __g::serde::Serialize, 25 | __g::serde::Deserialize, 26 | __g::typed_builder::TypedBuilder, 27 | __g::gel_derive::Queryable 28 | )] 29 | pub struct Input { 30 | #[builder(setter(into))] 31 | pub custom: String, 32 | } 33 | impl __g::gel_protocol::query_arg::QueryArgs for Input { 34 | fn encode( 35 | &self, 36 | encoder: &mut __g::gel_protocol::query_arg::Encoder, 37 | ) -> core::result::Result<(), __g::gel_errors::Error> { 38 | let map = __g::gel_protocol::named_args! { 39 | "custom" => self.custom.clone(), 40 | }; 41 | map.encode(encoder) 42 | } 43 | } 44 | #[derive( 45 | Debug, 46 | Clone, 47 | __g::serde::Serialize, 48 | __g::serde::Deserialize, 49 | __g::gel_derive::Queryable 50 | )] 51 | pub struct Output { 52 | pub hello: String, 53 | pub custom: String, 54 | } 55 | /// The original query string provided to the macro. Can be reused in your codebase. 56 | pub const QUERY: &str = "select { hello := \"world\", custom := $custom }"; 57 | } 58 | -------------------------------------------------------------------------------- /crates/gelx/tests/snapshots/codegen__codegen_literals@case_17_object_shape.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/gelx/tests/codegen.rs 3 | expression: "&content" 4 | --- 5 | pub mod example { 6 | use ::gelx::exports as __g; 7 | /// Execute the desired query. 8 | pub async fn query( 9 | client: &__g::gel_tokio::Client, 10 | ) -> ::core::result::Result, __g::gel_errors::Error> { 11 | client.query(QUERY, &()).await 12 | } 13 | /// Compose the query as part of a larger transaction. 14 | pub async fn transaction( 15 | conn: &mut __g::gel_tokio::Transaction, 16 | ) -> ::core::result::Result, __g::gel_errors::Error> { 17 | conn.query(QUERY, &()).await 18 | } 19 | pub type Input = (); 20 | #[derive(Debug, Clone)] 21 | pub struct OutputWalletsSet { 22 | pub created_at: __g::DateTimeAlias, 23 | pub id: __g::uuid::Uuid, 24 | pub updated_at: __g::DateTimeAlias, 25 | pub primary: bool, 26 | pub description: Option, 27 | pub name: Option, 28 | pub pubkey: String, 29 | } 30 | #[derive(Debug, Clone)] 31 | pub struct Output { 32 | pub slug: String, 33 | pub id: __g::uuid::Uuid, 34 | pub created_at: __g::DateTimeAlias, 35 | pub updated_at: __g::DateTimeAlias, 36 | pub description: Option, 37 | pub name: String, 38 | pub wallets: Vec, 39 | } 40 | /// The original query string provided to the macro. Can be reused in your codebase. 41 | pub const QUERY: &str = "select Team {**}"; 42 | } 43 | -------------------------------------------------------------------------------- /crates/gelx/tests/snapshots/codegen__codegen_literals@case_17_object_shape__builder_query_serde_strum.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/gelx/tests/codegen.rs 3 | expression: "&content" 4 | --- 5 | pub mod example { 6 | use ::gelx::exports as __g; 7 | /// Execute the desired query. 8 | pub async fn query( 9 | client: &__g::gel_tokio::Client, 10 | ) -> ::core::result::Result, __g::gel_errors::Error> { 11 | client.query(QUERY, &()).await 12 | } 13 | /// Compose the query as part of a larger transaction. 14 | pub async fn transaction( 15 | conn: &mut __g::gel_tokio::Transaction, 16 | ) -> ::core::result::Result, __g::gel_errors::Error> { 17 | conn.query(QUERY, &()).await 18 | } 19 | pub type Input = (); 20 | #[derive( 21 | Debug, 22 | Clone, 23 | __g::serde::Serialize, 24 | __g::serde::Deserialize, 25 | __g::gel_derive::Queryable 26 | )] 27 | pub struct OutputWalletsSet { 28 | pub created_at: __g::DateTimeAlias, 29 | pub id: __g::uuid::Uuid, 30 | pub updated_at: __g::DateTimeAlias, 31 | pub primary: bool, 32 | pub description: Option, 33 | pub name: Option, 34 | pub pubkey: String, 35 | } 36 | #[derive( 37 | Debug, 38 | Clone, 39 | __g::serde::Serialize, 40 | __g::serde::Deserialize, 41 | __g::gel_derive::Queryable 42 | )] 43 | pub struct Output { 44 | pub slug: String, 45 | pub id: __g::uuid::Uuid, 46 | pub created_at: __g::DateTimeAlias, 47 | pub updated_at: __g::DateTimeAlias, 48 | pub description: Option, 49 | pub name: String, 50 | pub wallets: Vec, 51 | } 52 | /// The original query string provided to the macro. Can be reused in your codebase. 53 | pub const QUERY: &str = "select Team {**}"; 54 | } 55 | -------------------------------------------------------------------------------- /crates/gelx/tests/snapshots/codegen__codegen_literals@case_18_object_shape_with_args.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/gelx/tests/codegen.rs 3 | expression: "&content" 4 | --- 5 | pub mod example { 6 | use ::gelx::exports as __g; 7 | /// Execute the desired query. 8 | pub async fn query( 9 | client: &__g::gel_tokio::Client, 10 | props: &Input, 11 | ) -> ::core::result::Result, __g::gel_errors::Error> { 12 | client.query(QUERY, props).await 13 | } 14 | /// Compose the query as part of a larger transaction. 15 | pub async fn transaction( 16 | conn: &mut __g::gel_tokio::Transaction, 17 | props: &Input, 18 | ) -> ::core::result::Result, __g::gel_errors::Error> { 19 | conn.query(QUERY, props).await 20 | } 21 | #[derive(Debug, Clone)] 22 | pub struct Input { 23 | pub starts_with: String, 24 | pub ends_with: String, 25 | } 26 | impl __g::gel_protocol::query_arg::QueryArgs for Input { 27 | fn encode( 28 | &self, 29 | encoder: &mut __g::gel_protocol::query_arg::Encoder, 30 | ) -> core::result::Result<(), __g::gel_errors::Error> { 31 | let map = __g::gel_protocol::named_args! { 32 | "starts_with" => self.starts_with.clone(), "ends_with" => self.ends_with 33 | .clone(), 34 | }; 35 | map.encode(encoder) 36 | } 37 | } 38 | #[derive(Debug, Clone)] 39 | pub struct OutputWalletsSet { 40 | pub created_at: __g::DateTimeAlias, 41 | pub id: __g::uuid::Uuid, 42 | pub updated_at: __g::DateTimeAlias, 43 | pub primary: bool, 44 | pub description: Option, 45 | pub name: Option, 46 | pub pubkey: String, 47 | } 48 | #[derive(Debug, Clone)] 49 | pub struct Output { 50 | pub slug: String, 51 | pub id: __g::uuid::Uuid, 52 | pub created_at: __g::DateTimeAlias, 53 | pub updated_at: __g::DateTimeAlias, 54 | pub description: Option, 55 | pub name: String, 56 | pub wallets: Vec, 57 | } 58 | /// The original query string provided to the macro. Can be reused in your codebase. 59 | pub const QUERY: &str = "select Team {**} filter .name like $starts_with ++ '%' and .description like '%' ++ $ends_with;"; 60 | } 61 | -------------------------------------------------------------------------------- /crates/gelx/tests/snapshots/codegen__codegen_literals@case_18_object_shape_with_args__builder_query_serde_strum.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/gelx/tests/codegen.rs 3 | expression: "&content" 4 | --- 5 | pub mod example { 6 | use ::gelx::exports as __g; 7 | /// Execute the desired query. 8 | pub async fn query( 9 | client: &__g::gel_tokio::Client, 10 | props: &Input, 11 | ) -> ::core::result::Result, __g::gel_errors::Error> { 12 | client.query(QUERY, props).await 13 | } 14 | /// Compose the query as part of a larger transaction. 15 | pub async fn transaction( 16 | conn: &mut __g::gel_tokio::Transaction, 17 | props: &Input, 18 | ) -> ::core::result::Result, __g::gel_errors::Error> { 19 | conn.query(QUERY, props).await 20 | } 21 | #[derive( 22 | Debug, 23 | Clone, 24 | __g::serde::Serialize, 25 | __g::serde::Deserialize, 26 | __g::typed_builder::TypedBuilder, 27 | __g::gel_derive::Queryable 28 | )] 29 | pub struct Input { 30 | #[builder(setter(into))] 31 | pub starts_with: String, 32 | #[builder(setter(into))] 33 | pub ends_with: String, 34 | } 35 | impl __g::gel_protocol::query_arg::QueryArgs for Input { 36 | fn encode( 37 | &self, 38 | encoder: &mut __g::gel_protocol::query_arg::Encoder, 39 | ) -> core::result::Result<(), __g::gel_errors::Error> { 40 | let map = __g::gel_protocol::named_args! { 41 | "starts_with" => self.starts_with.clone(), "ends_with" => self.ends_with 42 | .clone(), 43 | }; 44 | map.encode(encoder) 45 | } 46 | } 47 | #[derive( 48 | Debug, 49 | Clone, 50 | __g::serde::Serialize, 51 | __g::serde::Deserialize, 52 | __g::gel_derive::Queryable 53 | )] 54 | pub struct OutputWalletsSet { 55 | pub created_at: __g::DateTimeAlias, 56 | pub id: __g::uuid::Uuid, 57 | pub updated_at: __g::DateTimeAlias, 58 | pub primary: bool, 59 | pub description: Option, 60 | pub name: Option, 61 | pub pubkey: String, 62 | } 63 | #[derive( 64 | Debug, 65 | Clone, 66 | __g::serde::Serialize, 67 | __g::serde::Deserialize, 68 | __g::gel_derive::Queryable 69 | )] 70 | pub struct Output { 71 | pub slug: String, 72 | pub id: __g::uuid::Uuid, 73 | pub created_at: __g::DateTimeAlias, 74 | pub updated_at: __g::DateTimeAlias, 75 | pub description: Option, 76 | pub name: String, 77 | pub wallets: Vec, 78 | } 79 | /// The original query string provided to the macro. Can be reused in your codebase. 80 | pub const QUERY: &str = "select Team {**} filter .name like $starts_with ++ '%' and .description like '%' ++ $ends_with;"; 81 | } 82 | -------------------------------------------------------------------------------- /crates/gelx/tests/snapshots/codegen__codegen_literals@case_19_enums.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/gelx/tests/codegen.rs 3 | expression: "&content" 4 | --- 5 | pub mod example { 6 | use ::gelx::exports as __g; 7 | /// Execute the desired query. 8 | pub async fn query( 9 | client: &__g::gel_tokio::Client, 10 | ) -> ::core::result::Result, __g::gel_errors::Error> { 11 | client.query(QUERY, &()).await 12 | } 13 | /// Compose the query as part of a larger transaction. 14 | pub async fn transaction( 15 | conn: &mut __g::gel_tokio::Transaction, 16 | ) -> ::core::result::Result, __g::gel_errors::Error> { 17 | conn.query(QUERY, &()).await 18 | } 19 | pub type Input = (); 20 | #[derive(Debug, Clone, Copy)] 21 | pub enum DefaultAccountProvider { 22 | Github, 23 | } 24 | impl From for __g::gel_protocol::value::Value { 25 | fn from(value: DefaultAccountProvider) -> Self { 26 | __g::gel_protocol::value::Value::Enum(value.as_ref().into()) 27 | } 28 | } 29 | #[derive(Debug, Clone)] 30 | pub struct Output { 31 | pub provider: DefaultAccountProvider, 32 | } 33 | /// The original query string provided to the macro. Can be reused in your codebase. 34 | pub const QUERY: &str = "select Account { provider }"; 35 | } 36 | -------------------------------------------------------------------------------- /crates/gelx/tests/snapshots/codegen__codegen_literals@case_19_enums__builder_query_serde_strum.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/gelx/tests/codegen.rs 3 | expression: "&content" 4 | --- 5 | pub mod example { 6 | use ::gelx::exports as __g; 7 | /// Execute the desired query. 8 | pub async fn query( 9 | client: &__g::gel_tokio::Client, 10 | ) -> ::core::result::Result, __g::gel_errors::Error> { 11 | client.query(QUERY, &()).await 12 | } 13 | /// Compose the query as part of a larger transaction. 14 | pub async fn transaction( 15 | conn: &mut __g::gel_tokio::Transaction, 16 | ) -> ::core::result::Result, __g::gel_errors::Error> { 17 | conn.query(QUERY, &()).await 18 | } 19 | pub type Input = (); 20 | #[derive( 21 | Debug, 22 | Clone, 23 | Copy, 24 | __g::serde::Serialize, 25 | __g::serde::Deserialize, 26 | __g::gel_derive::Queryable, 27 | __g::strum::AsRefStr, 28 | __g::strum::Display, 29 | __g::strum::EnumString, 30 | __g::strum::EnumIs, 31 | __g::strum::FromRepr, 32 | __g::strum::IntoStaticStr 33 | )] 34 | pub enum DefaultAccountProvider { 35 | Github, 36 | } 37 | impl From for __g::gel_protocol::value::Value { 38 | fn from(value: DefaultAccountProvider) -> Self { 39 | __g::gel_protocol::value::Value::Enum(value.as_ref().into()) 40 | } 41 | } 42 | #[derive( 43 | Debug, 44 | Clone, 45 | __g::serde::Serialize, 46 | __g::serde::Deserialize, 47 | __g::gel_derive::Queryable 48 | )] 49 | pub struct Output { 50 | pub provider: DefaultAccountProvider, 51 | } 52 | /// The original query string provided to the macro. Can be reused in your codebase. 53 | pub const QUERY: &str = "select Account { provider }"; 54 | } 55 | -------------------------------------------------------------------------------- /crates/gelx/tests/snapshots/codegen__codegen_literals@case_21_bytes.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/gelx/tests/codegen.rs 3 | expression: "&content" 4 | --- 5 | pub mod example { 6 | use ::gelx::exports as __g; 7 | /// Execute the desired query. 8 | pub async fn query( 9 | client: &__g::gel_tokio::Client, 10 | ) -> ::core::result::Result { 11 | client.query_required_single(QUERY, &()).await 12 | } 13 | /// Compose the query as part of a larger transaction. 14 | pub async fn transaction( 15 | conn: &mut __g::gel_tokio::Transaction, 16 | ) -> ::core::result::Result { 17 | conn.query_required_single(QUERY, &()).await 18 | } 19 | pub type Input = (); 20 | pub type Output = __g::bytes::Bytes; 21 | /// The original query string provided to the macro. Can be reused in your codebase. 22 | pub const QUERY: &str = "select b'bina\\x01ry'"; 23 | } 24 | -------------------------------------------------------------------------------- /crates/gelx/tests/snapshots/codegen__codegen_literals@case_21_bytes__builder_query_serde_strum.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/gelx/tests/codegen.rs 3 | expression: "&content" 4 | --- 5 | pub mod example { 6 | use ::gelx::exports as __g; 7 | /// Execute the desired query. 8 | pub async fn query( 9 | client: &__g::gel_tokio::Client, 10 | ) -> ::core::result::Result { 11 | client.query_required_single(QUERY, &()).await 12 | } 13 | /// Compose the query as part of a larger transaction. 14 | pub async fn transaction( 15 | conn: &mut __g::gel_tokio::Transaction, 16 | ) -> ::core::result::Result { 17 | conn.query_required_single(QUERY, &()).await 18 | } 19 | pub type Input = (); 20 | pub type Output = __g::bytes::Bytes; 21 | /// The original query string provided to the macro. Can be reused in your codebase. 22 | pub const QUERY: &str = "select b'bina\\x01ry'"; 23 | } 24 | -------------------------------------------------------------------------------- /crates/gelx/tests/snapshots/codegen__codegen_literals@case_21_range.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/gelx/tests/codegen.rs 3 | expression: "&content" 4 | --- 5 | pub mod example { 6 | use ::gelx::exports as __g; 7 | /// Execute the desired query. 8 | pub async fn query( 9 | client: &__g::gel_tokio::Client, 10 | ) -> ::core::result::Result { 11 | client.query_required_single(QUERY, &()).await 12 | } 13 | /// Compose the query as part of a larger transaction. 14 | pub async fn transaction( 15 | conn: &mut __g::gel_tokio::Transaction, 16 | ) -> ::core::result::Result { 17 | conn.query_required_single(QUERY, &()).await 18 | } 19 | pub type Input = (); 20 | pub type Output = __g::gel_protocol::model::Range; 21 | /// The original query string provided to the macro. Can be reused in your codebase. 22 | pub const QUERY: &str = "select range(0, 10)"; 23 | } 24 | -------------------------------------------------------------------------------- /crates/gelx/tests/snapshots/codegen__codegen_literals@case_21_range__builder_query_serde_strum.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/gelx/tests/codegen.rs 3 | expression: "&content" 4 | --- 5 | pub mod example { 6 | use ::gelx::exports as __g; 7 | /// Execute the desired query. 8 | pub async fn query( 9 | client: &__g::gel_tokio::Client, 10 | ) -> ::core::result::Result { 11 | client.query_required_single(QUERY, &()).await 12 | } 13 | /// Compose the query as part of a larger transaction. 14 | pub async fn transaction( 15 | conn: &mut __g::gel_tokio::Transaction, 16 | ) -> ::core::result::Result { 17 | conn.query_required_single(QUERY, &()).await 18 | } 19 | pub type Input = (); 20 | pub type Output = __g::gel_protocol::model::Range; 21 | /// The original query string provided to the macro. Can be reused in your codebase. 22 | pub const QUERY: &str = "select range(0, 10)"; 23 | } 24 | -------------------------------------------------------------------------------- /crates/gelx/tests/snapshots/codegen__codegen_literals@case_22_geometry.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/gelx/tests/codegen.rs 3 | expression: "&content" 4 | --- 5 | pub mod example { 6 | use ::gelx::exports as __g; 7 | /// Execute the desired query. 8 | pub async fn query( 9 | client: &__g::gel_tokio::Client, 10 | ) -> ::core::result::Result { 11 | client.query_required_single(QUERY, &()).await 12 | } 13 | /// Compose the query as part of a larger transaction. 14 | pub async fn transaction( 15 | conn: &mut __g::gel_tokio::Transaction, 16 | ) -> ::core::result::Result { 17 | conn.query_required_single(QUERY, &()).await 18 | } 19 | pub type Input = (); 20 | pub type Output = __g::Geometry; 21 | /// The original query string provided to the macro. Can be reused in your codebase. 22 | pub const QUERY: &str = "select ext::postgis::makepoint(1.0, 1.0)"; 23 | } 24 | -------------------------------------------------------------------------------- /crates/gelx/tests/snapshots/codegen__codegen_literals@case_22_geometry__builder_query_serde_strum.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/gelx/tests/codegen.rs 3 | expression: "&content" 4 | --- 5 | pub mod example { 6 | use ::gelx::exports as __g; 7 | /// Execute the desired query. 8 | pub async fn query( 9 | client: &__g::gel_tokio::Client, 10 | ) -> ::core::result::Result { 11 | client.query_required_single(QUERY, &()).await 12 | } 13 | /// Compose the query as part of a larger transaction. 14 | pub async fn transaction( 15 | conn: &mut __g::gel_tokio::Transaction, 16 | ) -> ::core::result::Result { 17 | conn.query_required_single(QUERY, &()).await 18 | } 19 | pub type Input = (); 20 | pub type Output = __g::Geometry; 21 | /// The original query string provided to the macro. Can be reused in your codebase. 22 | pub const QUERY: &str = "select ext::postgis::makepoint(1.0, 1.0)"; 23 | } 24 | -------------------------------------------------------------------------------- /crates/gelx/tests/snapshots/codegen__codegen_literals@case_23_geography.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/gelx/tests/codegen.rs 3 | expression: "&content" 4 | --- 5 | pub mod example { 6 | use ::gelx::exports as __g; 7 | /// Execute the desired query. 8 | pub async fn query( 9 | client: &__g::gel_tokio::Client, 10 | ) -> ::core::result::Result { 11 | client.query_required_single(QUERY, &()).await 12 | } 13 | /// Compose the query as part of a larger transaction. 14 | pub async fn transaction( 15 | conn: &mut __g::gel_tokio::Transaction, 16 | ) -> ::core::result::Result { 17 | conn.query_required_single(QUERY, &()).await 18 | } 19 | pub type Input = (); 20 | pub type Output = __g::Geography; 21 | /// The original query string provided to the macro. Can be reused in your codebase. 22 | pub const QUERY: &str = "select ext::postgis::makepoint(1.0, 1.0)"; 23 | } 24 | -------------------------------------------------------------------------------- /crates/gelx/tests/snapshots/codegen__codegen_literals@case_23_geography__builder_query_serde_strum.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/gelx/tests/codegen.rs 3 | expression: "&content" 4 | --- 5 | pub mod example { 6 | use ::gelx::exports as __g; 7 | /// Execute the desired query. 8 | pub async fn query( 9 | client: &__g::gel_tokio::Client, 10 | ) -> ::core::result::Result { 11 | client.query_required_single(QUERY, &()).await 12 | } 13 | /// Compose the query as part of a larger transaction. 14 | pub async fn transaction( 15 | conn: &mut __g::gel_tokio::Transaction, 16 | ) -> ::core::result::Result { 17 | conn.query_required_single(QUERY, &()).await 18 | } 19 | pub type Input = (); 20 | pub type Output = __g::Geography; 21 | /// The original query string provided to the macro. Can be reused in your codebase. 22 | pub const QUERY: &str = "select ext::postgis::makepoint(1.0, 1.0)"; 23 | } 24 | -------------------------------------------------------------------------------- /crates/gelx_build/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "gelx_build" 3 | version = { workspace = true } 4 | authors = { workspace = true } 5 | categories = ["database"] 6 | edition = { workspace = true } 7 | homepage = { workspace = true } 8 | keywords = ["gel", "database", "typesafe", "checked", "macros"] 9 | license = { workspace = true } 10 | repository = { workspace = true } 11 | rust-version = { workspace = true } 12 | description = "Enable reading from the configuration in the `Cargo.toml` file while using the `gelx` macros" 13 | 14 | [dependencies] 15 | base64 = { workspace = true } 16 | gelx_core = { workspace = true } 17 | tokio = { workspace = true, features = ["macros", "rt-multi-thread", "process"] } 18 | 19 | [dev-dependencies] 20 | insta = { workspace = true } 21 | insta-cmd = { workspace = true } 22 | tokio = { workspace = true, features = ["time", "test-util", "fs"] } 23 | 24 | [lints] 25 | workspace = true 26 | 27 | [package.metadata.gelx] 28 | queries_path = "./queries" 29 | features = { query = "ssr", strum = "ssr", builder = "ssr" } 30 | -------------------------------------------------------------------------------- /crates/gelx_build/changelog.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | All notable changes to this project will be documented in this file. 4 | 5 | The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), 6 | and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). 7 | 8 | ## [Unreleased] 9 | 10 | ## [0.7.0](https://github.com/ifiokjr/gelx/compare/v0.6.0...v0.7.0) - 2025-05-26 11 | 12 | ### 🎉 Added 13 | 14 | - feat!(gelx_core): remove `create_gel_config` and add `GelxMetadata::gel_config(&self)` 15 | -------------------------------------------------------------------------------- /crates/gelx_build/readme.md: -------------------------------------------------------------------------------- 1 | # `gelx_build` 2 | 3 |
4 | 5 | > By default the `gelx` macros can't read the configuration from the `Cargo.toml` file. This crate provides a way to read the configuration from the `Cargo.toml` file using the build.rs script. 6 | 7 |
8 | 9 | [![Crate][crate-image]][crate-link] [![Docs][docs-image]][docs-link] [![Status][ci-status-image]][ci-status-link] [![Unlicense][unlicense-image]][unlicense-link] [![codecov][codecov-image]][codecov-link] 10 | 11 | ## Overview 12 | 13 | The `gelx_build` crate provides a way to read the configuration from the `Cargo.toml` file using the `build.rs` script. 14 | 15 | This crate is only needed if you want to customise the configuration of the `gelx` macros. 16 | 17 | ## Installation 18 | 19 | ```toml 20 | [build-dependencies] 21 | gelx_build = "0.6" 22 | ``` 23 | 24 | or via the command line: 25 | 26 | ```bash 27 | cargo add --build gelx_build 28 | ``` 29 | 30 | ## Usage 31 | 32 | ```rust 33 | // build.rs 34 | 35 | use gelx_build::gelx_build_sync; 36 | 37 | fn main() { 38 | let _ = gelx_build_sync(); 39 | } 40 | ``` 41 | 42 | The above code will read the configuration from the `Cargo.toml` file and create an environment variable called `GELX_METADATA_BASE64` that contains the json configuration. The `GELX_METADATA_BASE64` environment variable is then used by the `gelx_macros` crate to read the configuration and use it when generating code. 43 | 44 | If you would like to use the async version, you can use the `gelx_build` function instead. 45 | 46 | ```rust 47 | // build.rs 48 | 49 | use gelx_build::gelx_build; 50 | use gelx_build::tokio; 51 | 52 | #[tokio::main] 53 | async fn main() { 54 | let _ = gelx_build().await; 55 | } 56 | ``` 57 | 58 | ## Contributing 59 | 60 | This crate is part of the `gelx` workspace. Please refer to the [main project\'s contributing guide](https://github.com/ifiokjr/gelx/blob/main/readme.md#contributing) for details on how to set up the development environment and contribute. 61 | 62 | ## License 63 | 64 | Unlicense, see the [license file](https://github.com/ifiokjr/gelx/blob/main/license) in the root of the workspace. 65 | 66 | [crate-image]: https://img.shields.io/crates/v/gelx_build.svg 67 | [crate-link]: https://crates.io/crates/gelx_build 68 | [docs-image]: https://docs.rs/gelx_build/badge.svg 69 | [docs-link]: https://docs.rs/gelx_build/ 70 | [ci-status-image]: https://github.com/ifiokjr/gelx/workflows/ci/badge.svg?branch=main 71 | [ci-status-link]: https://github.com/ifiokjr/gelx/actions?query=workflow%3Aci+branch%3Amain 72 | [unlicense-image]: https://img.shields.io/badge/license-Unlicense-blue.svg 73 | [unlicense-link]: https://github.com/ifiokjr/gelx/blob/main/LICENSE 74 | [codecov-image]: https://codecov.io/github/ifiokjr/gelx/graph/badge.svg?token=87K799Q78I 75 | [codecov-link]: https://codecov.io/github/ifiokjr/gelx 76 | -------------------------------------------------------------------------------- /crates/gelx_build/src/lib.rs: -------------------------------------------------------------------------------- 1 | #![cfg_attr(docsrs, feature(doc_cfg))] 2 | #![doc(html_logo_url = "https://raw.githubusercontent.com/ifiokjr/gelx/main/setup/assets/logo.png")] 3 | #![doc = include_str!(concat!(env!("CARGO_MANIFEST_DIR"), "/readme.md"))] 4 | 5 | use std::env; 6 | use std::path::PathBuf; 7 | 8 | pub use gelx_core::GelxCoreError; 9 | pub use gelx_core::GelxCoreResult; 10 | pub use gelx_core::GelxMetadata; 11 | pub use tokio; 12 | use tokio::fs; 13 | use tokio::runtime::Runtime; 14 | 15 | /// Enables reading from the configuration in the `Cargo.toml`. This returns the 16 | /// [`GelxMetadata`] struct which can be used to customise the generated code 17 | /// via [`set_metadata_env`]. 18 | /// 19 | /// ``` 20 | /// // build.rs 21 | /// use gelx_build::GelxCoreResult; 22 | /// use gelx_build::gelx_build; 23 | /// use gelx_build::tokio; 24 | /// 25 | /// #[tokio::main] 26 | /// async fn main() -> GelxCoreResult<()> { 27 | /// gelx_build().await?; 28 | /// Ok(()) 29 | /// } 30 | /// ``` 31 | /// 32 | /// To customise the generated code, you can use the [`GelxMetadata`] struct 33 | /// to set the [`GelxMetadata::queries_path`] and [`GelxMetadata::features`] 34 | /// fields. 35 | /// 36 | /// ``` 37 | /// // build.rs 38 | /// use std::path::PathBuf; 39 | /// 40 | /// use gelx_build::GelxCoreResult; 41 | /// use gelx_build::gelx_build; 42 | /// use gelx_build::set_metadata_env; 43 | /// use gelx_build::tokio; 44 | /// use gelx_core::GelxFeatures; 45 | /// 46 | /// #[tokio::main] 47 | /// async fn main() -> GelxCoreResult<()> { 48 | /// let mut metadata = gelx_build().await?; 49 | /// metadata.queries_path = PathBuf::from("queries"); 50 | /// metadata.features = GelxFeatures::default(); 51 | /// set_metadata_env(&metadata)?; 52 | /// 53 | /// Ok(()) 54 | /// } 55 | /// ``` 56 | pub async fn gelx_build() -> GelxCoreResult { 57 | let manifest_dir = 58 | PathBuf::from(env::var("CARGO_MANIFEST_DIR").expect("CARGO_MANIFEST_DIR not set")); 59 | let cargo_toml_path = manifest_dir.join("Cargo.toml"); 60 | println!("cargo::rerun-if-changed={}", cargo_toml_path.display()); 61 | let cargo_toml_contents = fs::read_to_string(&cargo_toml_path).await?; 62 | // TODO: support output to OUT_DIR with shared enums rather than generating the 63 | // enum every time. 64 | let metadata = GelxMetadata::try_from(&cargo_toml_contents).unwrap_or_default(); 65 | set_metadata_env(&metadata)?; 66 | 67 | Ok(metadata) 68 | } 69 | 70 | /// Sets the `GELX_METADATA_BASE64` environment variable to the base64 encoded 71 | /// [`GelxMetadata`] struct. 72 | pub fn set_metadata_env(metadata: &GelxMetadata) -> GelxCoreResult<()> { 73 | let metadata_base64 = metadata.try_to_base64()?; 74 | println!("cargo::rustc-env=GELX_METADATA_BASE64={metadata_base64}"); 75 | Ok(()) 76 | } 77 | 78 | /// Enables reading from the configuration in the `Cargo.toml` in a sync 79 | /// environment. See [`gelx_build`] for more information. 80 | /// 81 | /// ``` 82 | /// // build.rs 83 | /// use gelx_build::gelx_build_sync; 84 | /// use gelx_core::GelxCoreResult; 85 | /// 86 | /// fn main() -> GelxCoreResult<()> { 87 | /// let metadata = gelx_build_sync()?; 88 | /// Ok(()) 89 | /// } 90 | /// ``` 91 | pub fn gelx_build_sync() -> GelxCoreResult { 92 | let rt = Runtime::new()?; 93 | rt.block_on(async { gelx_build().await }) 94 | } 95 | -------------------------------------------------------------------------------- /crates/gelx_build/tests/build.rs: -------------------------------------------------------------------------------- 1 | use gelx_build::gelx_build; 2 | use gelx_build::gelx_build_sync; 3 | use gelx_core::GelxCoreResult; 4 | 5 | #[tokio::test] 6 | async fn build() -> GelxCoreResult<()> { 7 | insta::assert_snapshot!(gelx_build().await?); 8 | 9 | Ok(()) 10 | } 11 | 12 | #[test] 13 | fn build_sync() -> GelxCoreResult<()> { 14 | insta::assert_snapshot!(gelx_build_sync()?); 15 | 16 | Ok(()) 17 | } 18 | -------------------------------------------------------------------------------- /crates/gelx_build/tests/snapshots/build__build.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/gelx_build/tests/build.rs 3 | expression: gelx_build().await? 4 | --- 5 | queries_path = "./queries" 6 | output_path = "src/db" 7 | input_struct_name = "Input" 8 | output_struct_name = "Output" 9 | query_function_name = "query" 10 | transaction_function_name = "transaction" 11 | query_constant_name = "QUERY" 12 | exports_alias = "__g" 13 | struct_derive_macros = ["Debug", "Clone"] 14 | enum_derive_macros = ["Debug", "Clone", "Copy"] 15 | 16 | [features] 17 | query = "ssr" 18 | strum = "ssr" 19 | builder = "ssr" 20 | serde = true 21 | -------------------------------------------------------------------------------- /crates/gelx_build/tests/snapshots/build__build_sync.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/gelx_build/tests/build.rs 3 | expression: gelx_build_sync()? 4 | --- 5 | queries_path = "./queries" 6 | output_path = "src/db" 7 | input_struct_name = "Input" 8 | output_struct_name = "Output" 9 | query_function_name = "query" 10 | transaction_function_name = "transaction" 11 | query_constant_name = "QUERY" 12 | exports_alias = "__g" 13 | struct_derive_macros = ["Debug", "Clone"] 14 | enum_derive_macros = ["Debug", "Clone", "Copy"] 15 | 16 | [features] 17 | query = "ssr" 18 | strum = "ssr" 19 | builder = "ssr" 20 | serde = true 21 | -------------------------------------------------------------------------------- /crates/gelx_cli/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "gelx_cli" 3 | version = { workspace = true } 4 | authors = { workspace = true } 5 | categories = ["database", "command-line-interface"] 6 | edition = { workspace = true } 7 | homepage = { workspace = true } 8 | keywords = ["gel", "database", "typesafe", "codegen", "edgedb"] 9 | license = { workspace = true } 10 | publish = true 11 | readme = "readme.md" 12 | repository = { workspace = true } 13 | rust-version = { workspace = true } 14 | description = "Generate fully typed rust code from your gel schema and inline queries." 15 | 16 | [[bin]] 17 | name = "gelx" 18 | path = "src/main.rs" 19 | 20 | [dependencies] 21 | clap = { workspace = true, features = ["derive"] } 22 | futures = { workspace = true } 23 | gelx_core = { workspace = true } 24 | heck = { workspace = true } 25 | proc-macro2 = { workspace = true } 26 | serde_json = { workspace = true } 27 | similar = { workspace = true } 28 | tokio = { workspace = true, features = ["full"] } 29 | toml = { workspace = true } 30 | 31 | [dev-dependencies] 32 | insta = { workspace = true } 33 | insta-cmd = { workspace = true } 34 | 35 | [lints] 36 | workspace = true 37 | -------------------------------------------------------------------------------- /crates/gelx_cli/changelog.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | All notable changes to this project will be documented in this file. 4 | 5 | The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). 6 | 7 | ## [Unreleased] 8 | 9 | ## [0.7.0](https://github.com/ifiokjr/gelx/compare/v0.6.0...v0.7.0) - 2025-05-26 10 | 11 | ### 🎉 Added 12 | 13 | - *(gelx_core)* generated enums can now be used as `Input` fields 14 | - feat!(gelx_core): remove `create_gel_config` and add `GelxMetadata::gel_config(&self)` 15 | - feat!(gelx_cli): make `gelx_cli` useable as a library 16 | - add support for postgis via `geo` 17 | 18 | ### 🧪 Testing 19 | 20 | - *(coverage)* clean coverage outputs before run 21 | - *(gelx_cli)* improve test coverage 22 | 23 | ### ⚙️ Miscellaneous Tasks 24 | 25 | - add `gelx_cli` crate to workspace and enable publishing 26 | 27 | ## [0.6.0](https://github.com/ifiokjr/gelx/compare/v0.5.1...v0.6.0) - 2025-05-24 28 | 29 | ### 🎉 Added 30 | 31 | - *(gelx)* update config to `output_path` and generate code in folder rather than file 32 | - *(gelx_core)* add derive macros configuration for structs and enums 33 | 34 | ### 🚜 Refactor 35 | 36 | - remove `vfs` and complete refactor 37 | 38 | ### 🧪 Testing 39 | 40 | - *(gelx)* improve feature testing 41 | 42 | ## [0.5.0](https://github.com/ifiokjr/gelx/compare/v0.4.0...v0.5.0) - 2025-05-20 43 | 44 | ### 🎉 Added 45 | 46 | - _(gelx)_ deprecate `gelx_file` macro 47 | - _(gelx_core)_ add `query_constant_name` metadata option 48 | - _(gelx_core)_ make `exports_alias` customisable 49 | - _(gelx_cli)_ add `--stdout` option for code generation 50 | - _(gelx)_ `gelx!` can now take a custom path to the query 51 | 52 | ### 📚 Documentation 53 | 54 | - update installation instructions share readme across crates 55 | - update installation instructions share readme across crates 56 | 57 | ### 🧪 Testing 58 | 59 | - _(gelx_cli)_ hardcode `gelx` binary from `devenv` in test 60 | 61 | ## [0.4.0](https://github.com/ifiokjr/gelx/releases/tag/v0.4.0) - 2025-05-19 62 | 63 | ### 🎉 Added 64 | 65 | - _(cli)_ add `--cwd` to set directory for command 66 | - [**breaking**] code the CLI for generating and checking code 67 | - add `GelxMetadata` and improve everything 68 | - add `gelx_example` crate 69 | - add enum generation from schema 70 | - add `regex` dependency and refactor code generation functions 71 | - add `gelx_cli` crate and integrate `clap` for command-line interface 72 | 73 | ### 📚 Documentation 74 | 75 | - small improvements 76 | 77 | ### 🧪 Testing 78 | 79 | - fix broken doc tests 80 | -------------------------------------------------------------------------------- /crates/gelx_cli/src/main.rs: -------------------------------------------------------------------------------- 1 | #![doc(html_logo_url = "https://raw.githubusercontent.com/ifiokjr/gelx/main/setup/assets/logo.png")] 2 | 3 | use gelx_cli::Cli; 4 | use gelx_cli::prelude::*; 5 | use gelx_core::GelxCoreResult; 6 | 7 | #[tokio::main] 8 | async fn main() -> GelxCoreResult<()> { 9 | let cli = Cli::parse(); 10 | 11 | match cli.run().await { 12 | Ok(()) => std::process::exit(0), 13 | Err(_) => std::process::exit(1), 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /crates/gelx_cli/tests/cli.rs: -------------------------------------------------------------------------------- 1 | use std::path::PathBuf; 2 | use std::process::Command; 3 | use std::process::Stdio; 4 | 5 | const CRATE_DIR: &str = env!("CARGO_MANIFEST_DIR"); 6 | 7 | fn cli() -> Command { 8 | Command::new(insta_cmd::get_cargo_bin("gelx")) 9 | } 10 | 11 | fn example_path() -> PathBuf { 12 | PathBuf::from(CRATE_DIR).join("../../examples/gelx_example") 13 | } 14 | 15 | #[test] 16 | fn invalid_cwd() { 17 | insta_cmd::assert_cmd_snapshot!( 18 | cli() 19 | .arg("generate") 20 | .arg("--cwd") 21 | .arg("../../examples/gelx_example/does/not/exist") 22 | .stderr(Stdio::null()) 23 | ); 24 | } 25 | 26 | #[test] 27 | fn cwd() { 28 | insta_cmd::assert_cmd_snapshot!( 29 | cli() 30 | .arg("generate") 31 | .arg("--cwd") 32 | .arg("../../examples/gelx_example") 33 | .stderr(Stdio::null()) 34 | ); 35 | } 36 | 37 | #[test] 38 | fn generate_stdout() { 39 | insta_cmd::assert_cmd_snapshot!( 40 | cli() 41 | .arg("generate") 42 | .arg("--json") 43 | .current_dir(example_path()) 44 | .stderr(Stdio::null()) 45 | ); 46 | } 47 | 48 | #[test] 49 | fn generate_files() { 50 | insta_cmd::assert_cmd_snapshot!( 51 | cli() 52 | .arg("generate") 53 | .current_dir(example_path()) 54 | .stderr(Stdio::null()) 55 | ); 56 | } 57 | 58 | #[test] 59 | fn check() { 60 | insta_cmd::assert_cmd_snapshot!( 61 | cli() 62 | .arg("check") 63 | .current_dir(example_path()) 64 | .stderr(Stdio::null()) 65 | ); 66 | } 67 | 68 | #[test] 69 | fn invalid_cwd_check() { 70 | insta_cmd::assert_cmd_snapshot!( 71 | cli() 72 | .arg("check") 73 | .arg("--cwd") 74 | .arg("../../examples/gelx_example/does/not/exist") 75 | .stderr(Stdio::null()) 76 | ); 77 | } 78 | -------------------------------------------------------------------------------- /crates/gelx_cli/tests/snapshots/cli__check.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/gelx_cli/tests/cli.rs 3 | info: 4 | program: gelx 5 | args: 6 | - check 7 | --- 8 | success: true 9 | exit_code: 0 10 | ----- stdout ----- 11 | 12 | ----- stderr ----- 13 | -------------------------------------------------------------------------------- /crates/gelx_cli/tests/snapshots/cli__cwd.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/gelx_cli/tests/cli.rs 3 | info: 4 | program: gelx 5 | args: 6 | - generate 7 | - "--cwd" 8 | - "../../examples/gelx_example" 9 | --- 10 | success: true 11 | exit_code: 0 12 | ----- stdout ----- 13 | 14 | ----- stderr ----- 15 | -------------------------------------------------------------------------------- /crates/gelx_cli/tests/snapshots/cli__generate_files.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/gelx_cli/tests/cli.rs 3 | info: 4 | program: gelx 5 | args: 6 | - generate 7 | --- 8 | success: true 9 | exit_code: 0 10 | ----- stdout ----- 11 | 12 | ----- stderr ----- 13 | -------------------------------------------------------------------------------- /crates/gelx_cli/tests/snapshots/cli__invalid_cwd.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/gelx_cli/tests/cli.rs 3 | info: 4 | program: gelx 5 | args: 6 | - generate 7 | - "--cwd" 8 | - "../../examples/gelx_example/does/not/exist" 9 | --- 10 | success: false 11 | exit_code: 1 12 | ----- stdout ----- 13 | 14 | ----- stderr ----- 15 | -------------------------------------------------------------------------------- /crates/gelx_cli/tests/snapshots/cli__invalid_cwd_check.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/gelx_cli/tests/cli.rs 3 | info: 4 | program: gelx 5 | args: 6 | - check 7 | - "--cwd" 8 | - "../../examples/gelx_example/does/not/exist" 9 | --- 10 | success: false 11 | exit_code: 1 12 | ----- stdout ----- 13 | 14 | ----- stderr ----- 15 | -------------------------------------------------------------------------------- /crates/gelx_core/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "gelx_core" 3 | version = { workspace = true } 4 | authors = { workspace = true } 5 | categories = ["database"] 6 | edition = { workspace = true } 7 | homepage = { workspace = true } 8 | keywords = ["gel", "database", "typesafe", "checked", "macros"] 9 | license = { workspace = true } 10 | readme = "readme.md" 11 | repository = { workspace = true } 12 | rust-version = { workspace = true } 13 | description = "Utilities for codegen in the `gelx` crate." 14 | 15 | [dependencies] 16 | base64 = { workspace = true } 17 | bitflags = { workspace = true } 18 | check_keyword = { workspace = true } 19 | derive_more = { workspace = true, features = ["from", "into", "into_iterator", "deref", "deref_mut"] } 20 | futures = { workspace = true } 21 | gel-derive = { workspace = true } 22 | gel-errors = { workspace = true } 23 | gel-protocol = { workspace = true, features = ["all-types", "with-serde"] } 24 | gel-tokio = { workspace = true, features = ["unstable", "derive"] } 25 | heck = { workspace = true } 26 | indexmap = { workspace = true, features = ["serde"] } 27 | log = { workspace = true } 28 | prettyplease = { workspace = true } 29 | proc-macro2 = { workspace = true } 30 | quote = { workspace = true } 31 | regex = { workspace = true } 32 | serde = { workspace = true, features = ["derive"] } 33 | serde_json = { workspace = true } 34 | serde_with = { workspace = true } 35 | strum = { workspace = true, features = ["derive"] } 36 | syn = { workspace = true, features = ["extra-traits"] } 37 | thiserror = { workspace = true } 38 | tokio = { workspace = true, features = ["macros", "rt-multi-thread", "process"] } 39 | toml = { workspace = true } 40 | toml_edit = { workspace = true } 41 | typed-builder = { workspace = true } 42 | uuid = { workspace = true, features = ["serde"] } 43 | 44 | [dev-dependencies] 45 | assert2 = { workspace = true } 46 | insta = { workspace = true } 47 | tokio = { workspace = true, features = ["time", "test-util"] } 48 | 49 | [features] 50 | query = [] 51 | serde = [] 52 | builder = [] 53 | strum = [] 54 | 55 | [lints] 56 | workspace = true 57 | -------------------------------------------------------------------------------- /crates/gelx_core/changelog.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | All notable changes to this project will be documented in this file. 4 | 5 | The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). 6 | 7 | ## [Unreleased] 8 | 9 | ## [0.7.0](https://github.com/ifiokjr/gelx/compare/v0.6.0...v0.7.0) - 2025-05-26 10 | 11 | ### 🎉 Added 12 | 13 | - *(gelx_core)* generated enums can now be used as `Input` fields 14 | - feat!(gelx_core): remove `create_gel_config` and add `GelxMetadata::gel_config(&self)` 15 | - feat!(gelx_core): remove unused exports `IdentConst` and `Char` 16 | - feat!(gelx_build): add `gelx_build` crate for reading configuration in macros 17 | - add support for postgis via `geo` 18 | 19 | ### 🐛 Bug Fixes 20 | 21 | - *(gelx_core)* remove unused `gelx_core` `with_*` features 22 | 23 | ## [0.6.0](https://github.com/ifiokjr/gelx/compare/v0.5.1...v0.6.0) - 2025-05-24 24 | 25 | ### 🎉 Added 26 | 27 | - *(gelx)* update config to `output_path` and generate code in folder rather than file 28 | - *(gelx_core)* add derive macros configuration for structs and enums 29 | 30 | ### 🚜 Refactor 31 | 32 | - remove `vfs` and complete refactor 33 | - *(gelx_core)* implement `TryFrom<`&str>` for `GelxMetadata` 34 | 35 | ### 🧪 Testing 36 | 37 | - *(gelx)* improve feature testing 38 | 39 | ## [0.5.0](https://github.com/ifiokjr/gelx/compare/v0.4.0...v0.5.0) - 2025-05-20 40 | 41 | ### 🎉 Added 42 | 43 | - _(gelx)_ deprecate `gelx_file` macro 44 | - _(gelx_core)_ add `query_constant_name` metadata option 45 | - _(gelx_core)_ make `exports_alias` customisable 46 | - _(gelx_cli)_ add `--stdout` option for code generation 47 | - _(gelx)_ `gelx!` can now take a custom path to the query 48 | 49 | ### 📚 Documentation 50 | 51 | - update installation instructions share readme across crates 52 | - update installation instructions share readme across crates 53 | 54 | ### 🧪 Testing 55 | 56 | - _(gelx_cli)_ hardcode `gelx` binary from `devenv` in test 57 | 58 | ## [0.4.0](https://github.com/ifiokjr/gelx/compare/v0.3.0...v0.4.0) - 2025-05-19 59 | 60 | ### 🎉 Added 61 | 62 | - _(cli)_ add `--cwd` to set directory for command 63 | - [**breaking**] code the CLI for generating and checking code 64 | - add `GelxMetadata` and improve everything 65 | - add `gelx_example` crate 66 | - add enum generation from schema 67 | - add `regex` dependency and refactor code generation functions 68 | - add `gelx_cli` crate and integrate `clap` for command-line interface 69 | 70 | ### 📚 Documentation 71 | 72 | - small improvements 73 | 74 | ### 🧪 Testing 75 | 76 | - fix broken doc tests 77 | 78 | ## [0.3.0](https://github.com/ifiokjr/gelx/compare/v0.2.1...v0.3.0) - 2025-05-16 79 | 80 | ### 🎉 Added 81 | 82 | - [**breaking**] rename `edgedb_codegen` to `gelx` 83 | - [**breaking**] rename `edgedb_codegen_macros` to `gelx_macros` 84 | - [**breaking**] rename `edgedb_codegen_core` to `gelx_core` 85 | - [**breaking**] upgrade all `gel` libraries to latest versions as a replacement for previous `edgedb` dependencies 86 | 87 | ### 📚 Documentation 88 | 89 | - improve main readme 90 | 91 | ## [0.2.0](https://github.com/ifiokjr/gelx/compare/v0.1.2...v0.2.0) - 2024-08-28 92 | 93 | ### 🎉 Added 94 | 95 | - [**breaking**] add optional `builder` feature limited to `Input` 96 | 97 | ### 📚 Documentation 98 | 99 | - reorder package fields 100 | 101 | ### 🧪 Testing 102 | 103 | - improve coverage 104 | 105 | ## [0.1.2](https://github.com/ifiokjr/gelx/compare/v0.1.1...v0.1.2) - 2024-08-27 106 | 107 | ### 🎉 Added 108 | 109 | - _(gelx_core)_ add `prettyplease` format option 110 | 111 | ### 🐛 Bug Fixes 112 | 113 | - increase minimum rust version 114 | 115 | ### ⚙️ Miscellaneous Tasks 116 | 117 | - update coverage files 118 | - support testing multiple rust versions 119 | 120 | ## [0.1.1](https://github.com/ifiokjr/gelx/compare/0.1.0...0.1.1) - 2024-08-26 121 | 122 | ### 🎉 Added 123 | 124 | - add support for `Range` types 125 | 126 | ### ⚙️ Miscellaneous Tasks 127 | 128 | - improve changelog generation 129 | 130 | ## [0.1.0](https://github.com/ifiokjr/gelx/releases/tag/gelx_core-v0.1.0) - 2024-08-25 131 | 132 | ### 🎉 Added 133 | 134 | - Initial release 135 | -------------------------------------------------------------------------------- /crates/gelx_core/fixtures/gel.toml: -------------------------------------------------------------------------------- 1 | [instance] 2 | server-version = "6.7" 3 | -------------------------------------------------------------------------------- /crates/gelx_core/readme.md: -------------------------------------------------------------------------------- 1 | # `gelx_core` 2 | 3 |
4 | 5 | > Core utilities and logic for `gelx` code generation, powering both the `gelx` procedural macro and the `gelx_cli`. 6 | 7 |
8 | 9 | [![Crate][crate-image]][crate-link] [![Docs][docs-image]][docs-link] [![Status][ci-status-image]][ci-status-link] [![Unlicense][unlicense-image]][unlicense-link] [![codecov][codecov-image]][codecov-link] 10 | 11 | ## Overview 12 | 13 | The `gelx_core` crate is the engine behind the `gelx` ecosystem. It provides the foundational components and functionalities required for: 14 | 15 | - Parsing Gel query files (`.edgeql`). 16 | - Connecting to a Gel instance to introspect schemas and query types. 17 | - Translating Gel query descriptions into Rust `TokenStream`s. 18 | - Handling `gelx` configuration from `Cargo.toml` (`[package.metadata.gelx]`). 19 | - Defining common types, error handling, and utility functions used by both `gelx` (the macro crate) and `gelx_cli` (the command-line tool). 20 | 21 | This crate is not typically used directly by end-users but serves as an internal library for the other `gelx` tools. If you are looking to generate Rust code from Gel queries, you should use either the [`gelx` macro](https://crates.io/crates/gelx) for inline queries or the [`gelx_cli`](https://crates.io/crates/gelx_cli) for file-based generation. 22 | 23 | ## Functionality 24 | 25 | Key functionalities provided by `gelx_core` include: 26 | 27 | - **Descriptor Fetching**: `get_descriptor_sync` and `get_descriptor` functions to fetch query data descriptions from a running Gel instance. 28 | - **Token Stream Generation**: `generate_query_token_stream` which takes a query description and generates the corresponding Rust code (structs for input/output, and query functions). 29 | - **Metadata Handling**: Structures and functions to parse and manage `GelxMetadata` from `Cargo.toml`. 30 | - **Type Mapping**: Logic to map Gel types to appropriate Rust types (e.g., `String`, `Uuid`, `DateTime`, custom enums, and object shapes). 31 | - **Configuration**: Utilities for resolving Gel connection parameters. 32 | - **Error Handling**: Common error types for the `gelx` ecosystem. 33 | 34 | ## Features 35 | 36 | `gelx_core` exposes several features that can be toggled by dependent crates (like `gelx` and `gelx_macros`): 37 | 38 | - `with_bigint`: Enables support for `BigInt`. 39 | - `with_bigdecimal`: Enables support for `BigDecimal`. 40 | - `with_chrono`: Enables support for `chrono` date/time types. 41 | - `with_all`: A convenience feature that enables all `with_*` features. 42 | - `query`: Enables generation of query execution functions (depends on `gel-tokio`). 43 | - `serde`: Enables `#[derive(Serialize, Deserialize)]` for generated structs. 44 | - `builder`: Enables `#[derive(TypedBuilder)]` for generated input structs. 45 | - `strum`: Enables `#[derive(EnumString, Display)]` for generated enums. 46 | 47 | These features are typically controlled via the `gelx` crate's own features. 48 | 49 | ## Contributing 50 | 51 | This crate is part of the `gelx` workspace. Please refer to the [main project\'s contributing guide](https://github.com/ifiokjr/gelx/blob/main/readme.md#contributing) for details on how to set up the development environment and contribute. 52 | 53 | ## License 54 | 55 | Unlicense, see the [license file](https://github.com/ifiokjr/gelx/blob/main/license) in the root of the workspace. 56 | 57 | [crate-image]: https://img.shields.io/crates/v/gelx_core.svg 58 | [crate-link]: https://crates.io/crates/gelx_core 59 | [docs-image]: https://docs.rs/gelx_core/badge.svg 60 | [docs-link]: https://docs.rs/gelx_core/ 61 | [ci-status-image]: https://github.com/ifiokjr/gelx/workflows/ci/badge.svg?branch=main 62 | [ci-status-link]: https://github.com/ifiokjr/gelx/actions?query=workflow%3Aci+branch%3Amain 63 | [unlicense-image]: https://img.shields.io/badge/license-Unlicense-blue.svg 64 | [unlicense-link]: https://github.com/ifiokjr/gelx/blob/main/LICENSE 65 | [codecov-image]: https://codecov.io/github/ifiokjr/gelx/graph/badge.svg?token=87K799Q78I 66 | [codecov-link]: https://codecov.io/github/ifiokjr/gelx 67 | -------------------------------------------------------------------------------- /crates/gelx_core/src/constants.rs: -------------------------------------------------------------------------------- 1 | /// Query to get all types in the database. 2 | pub const TYPES_QUERY: &str = r#"WITH 3 | MODULE schema, 4 | material_scalars := ( 5 | SELECT ScalarType 6 | FILTER NOT .abstract 7 | AND NOT EXISTS .enum_values 8 | AND NOT EXISTS (SELECT .ancestors FILTER NOT .abstract) 9 | ) 10 | 11 | SELECT Type { 12 | id, 13 | name := 14 | array_join(array_agg([IS ObjectType].union_of.name), ' | ') 15 | IF EXISTS [IS ObjectType].union_of 16 | ELSE .name, 17 | is_abstract := .abstract, 18 | 19 | kind := 'object' IF Type IS ObjectType ELSE 20 | 'scalar' IF Type IS ScalarType ELSE 21 | 'array' IF Type IS Array ELSE 22 | 'tuple' IF Type IS Tuple ELSE 23 | 'multirange' IF Type IS MultiRange ELSE 24 | 'unknown', 25 | 26 | [IS ScalarType].enum_values, 27 | is_seq := 'std::sequence' in [IS ScalarType].ancestors.name, 28 | # for sequence (abstract type that has non-abstract ancestor) 29 | single material_id := ( 30 | SELECT x := Type[IS ScalarType].ancestors 31 | FILTER x IN material_scalars 32 | LIMIT 1 33 | ).id, 34 | 35 | [IS InheritingObject].bases: { 36 | id 37 | } ORDER BY @index ASC, 38 | 39 | [IS ObjectType].union_of, 40 | [IS ObjectType].intersection_of, 41 | [IS ObjectType].pointers: { 42 | card := ('One' IF .required ELSE 'AtMostOne') IF .cardinality = 'One' ELSE ('AtLeastOne' IF .required ELSE 'Many'), 43 | name, 44 | target_id := .target.id, 45 | kind := 'link' IF .__type__.name = 'schema::Link' ELSE 'property', 46 | is_exclusive := exists (select .constraints filter .name = 'std::exclusive'), 47 | is_computed := len(.computed_fields) != 0, 48 | is_readonly := .readonly, 49 | has_default := EXISTS .default or ('std::sequence' in .target[IS ScalarType].ancestors.name), 50 | [IS Link].pointers: { 51 | card := ('One' IF .required ELSE 'AtMostOne') IF .cardinality = "One" ELSE ('AtLeastOne' IF .required ELSE 'Many'), 52 | name := '@' ++ .name, 53 | target_id := .target.id, 54 | kind := 'link' IF .__type__.name = 'schema::Link' ELSE 'property', 55 | is_computed := len(.computed_fields) != 0, 56 | is_readonly := .readonly 57 | } filter .name != '@source' and .name != '@target', 58 | } FILTER @is_owned, 59 | exclusives := assert_distinct(( 60 | [is schema::ObjectType].constraints 61 | union 62 | [is schema::ObjectType].pointers.constraints 63 | ) { 64 | target := (.subject[is schema::Property].name ?? .subject[is schema::Link].name ?? .subjectexpr) 65 | } filter .name = 'std::exclusive'), 66 | backlinks := ( 67 | SELECT DETACHED Link 68 | FILTER .target = Type 69 | AND NOT EXISTS .source[IS ObjectType].union_of 70 | ) { 71 | card := 'AtMostOne' 72 | IF 73 | EXISTS (select .constraints filter .name = 'std::exclusive') 74 | ELSE 75 | 'Many', 76 | name := '<' ++ .name ++ '[is ' ++ assert_exists(.source.name) ++ ']', 77 | stub := .name, 78 | target_id := .source.id, 79 | kind := 'link', 80 | is_exclusive := (EXISTS (select .constraints filter .name = 'std::exclusive')) AND .cardinality = 'One', 81 | }, 82 | backlink_stubs := array_agg(( 83 | WITH 84 | stubs := DISTINCT (SELECT DETACHED Link FILTER .target = Type).name, 85 | baseObjectId := (SELECT DETACHED ObjectType FILTER .name = 'std::BaseObject' LIMIT 1).id 86 | FOR stub in { stubs } 87 | UNION ( 88 | SELECT { 89 | card := 'Many', 90 | name := '<' ++ stub, 91 | target_id := baseObjectId, 92 | kind := 'link', 93 | is_exclusive := false, 94 | } 95 | ) 96 | )), 97 | array_element_id := [IS Array].element_type.id, 98 | 99 | tuple_elements := (SELECT [IS Tuple].element_types { 100 | target_id := .type.id, 101 | name 102 | } ORDER BY @index ASC), 103 | multirange_element_id := [IS MultiRange].element_type.id, 104 | } 105 | ORDER BY .name; 106 | "#; 107 | 108 | /// Name of the query function. 109 | pub const QUERY_PROP_NAME: &str = "client"; 110 | pub const TRANSACTION_PROP_NAME: &str = "conn"; 111 | pub const PROPS_NAME: &str = "props"; 112 | -------------------------------------------------------------------------------- /crates/gelx_core/src/errors.rs: -------------------------------------------------------------------------------- 1 | use gel_protocol::errors::DecodeError; 2 | use gel_tokio::dsn::error::ParseError; 3 | use proc_macro2::Span; 4 | use thiserror::Error as ThisError; 5 | 6 | /// The error type for the `gelx_core` crate. 7 | /// 8 | /// Note: This error type is not exhaustive since it will be extended in the 9 | /// future with several automated from implementations. 10 | #[non_exhaustive] 11 | #[derive(Debug, ThisError)] 12 | pub enum GelxCoreError { 13 | #[error("{0}")] 14 | Syn(#[from] syn::Error), 15 | #[error("{0}")] 16 | Gel(#[from] gel_errors::Error), 17 | #[error("{0}")] 18 | GelDsn(#[from] ParseError), 19 | #[error("{0}")] 20 | Decode(#[from] DecodeError), 21 | #[error("{0}")] 22 | Io(#[from] std::io::Error), 23 | #[error("{0}")] 24 | Toml(#[from] toml::de::Error), 25 | #[error("{0}")] 26 | TomlDisplay(#[from] toml::ser::Error), 27 | #[error("{0}")] 28 | TomlEdit(#[from] toml_edit::TomlError), 29 | #[error("{0}")] 30 | SerdeJson(#[from] serde_json::Error), 31 | #[error("{0}")] 32 | ProcMacro2(#[from] proc_macro2::LexError), 33 | #[error("{0}")] 34 | Base64(#[from] base64::DecodeError), 35 | #[error("{0}")] 36 | Utf8(#[from] std::string::FromUtf8Error), 37 | #[error("{0}")] 38 | Custom(String), 39 | } 40 | 41 | macro_rules! gelx_error { 42 | ($($args:expr),*) => { 43 | GelxCoreError::Custom(format!($($args),*)) 44 | }; 45 | } 46 | 47 | pub(crate) use gelx_error; 48 | 49 | pub type GelxCoreResult = Result; 50 | 51 | impl From for syn::Error { 52 | fn from(error: GelxCoreError) -> Self { 53 | match error { 54 | GelxCoreError::Syn(error) => error, 55 | _ => syn::Error::new(Span::call_site(), error.to_string()), 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /crates/gelx_core/src/snapshots/gelx_core__utils__tests__can_format_file.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/gelx_core/src/utils.rs 3 | expression: formatted 4 | --- 5 | struct Foo { 6 | content: String, 7 | allowed: bool, 8 | times: u64, 9 | } 10 | -------------------------------------------------------------------------------- /crates/gelx_core/src/utils.rs: -------------------------------------------------------------------------------- 1 | use std::env; 2 | use std::path::Path; 3 | use std::path::PathBuf; 4 | 5 | use proc_macro2::Span; 6 | 7 | /// Taken from 8 | pub fn resolve_path(path: impl AsRef, error_span: Span) -> syn::Result { 9 | let path = path.as_ref(); 10 | 11 | if path.is_absolute() { 12 | return Err(syn::Error::new( 13 | error_span, 14 | "absolute paths will only work on the current machine", 15 | )); 16 | } 17 | 18 | // requires `proc_macro::SourceFile::path()` to be stable 19 | // https://github.com/rust-lang/rust/issues/54725 20 | if path.is_relative() 21 | && path 22 | .parent() 23 | .is_none_or(|parent| parent.as_os_str().is_empty()) 24 | { 25 | return Err(syn::Error::new( 26 | error_span, 27 | "paths relative to the current file's directory are not currently supported", 28 | )); 29 | } 30 | 31 | let base_dir = env::var("CARGO_MANIFEST_DIR").map_err(|_| { 32 | syn::Error::new( 33 | error_span, 34 | "CARGO_MANIFEST_DIR is not set; please use Cargo to build", 35 | ) 36 | })?; 37 | let base_dir_path = Path::new(&base_dir); 38 | 39 | Ok(base_dir_path.join(path)) 40 | } 41 | 42 | /// Will format the given source code using `prettyplease`. 43 | pub fn prettify(source: &str) -> syn::Result { 44 | Ok(prettyplease::unparse(&syn::parse_str(source)?)) 45 | } 46 | 47 | #[cfg(test)] 48 | mod tests { 49 | use assert2::check; 50 | 51 | use super::*; 52 | use crate::GelxCoreResult; 53 | 54 | #[test] 55 | fn can_format_file() -> GelxCoreResult<()> { 56 | let content = "struct Foo { content: String, allowed: bool, times: u64 }"; 57 | let formatted = prettify(content)?; 58 | 59 | insta::assert_snapshot!(formatted); 60 | 61 | Ok(()) 62 | } 63 | 64 | #[test] 65 | fn error_when_formatting_invalid_rust() { 66 | let content = "struct Foo { content: String, allowed: bool, times: u64,,,,, INVALID}"; 67 | let result = prettify(content); 68 | 69 | check!(result.is_err(), "result should be an error"); 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /crates/gelx_macros/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "gelx_macros" 3 | version = { workspace = true } 4 | authors = { workspace = true } 5 | categories = ["database"] 6 | edition = { workspace = true } 7 | homepage = { workspace = true } 8 | keywords = ["gel", "database", "typesafe", "checked", "macros"] 9 | license = { workspace = true } 10 | readme = "readme.md" 11 | repository = { workspace = true } 12 | rust-version = { workspace = true } 13 | description = "The proc-macro crate for the `gelx` crate." 14 | 15 | [lib] 16 | proc-macro = true 17 | 18 | [dependencies] 19 | gelx_core = { workspace = true } 20 | proc-macro2 = { workspace = true } 21 | quote = { workspace = true } 22 | syn = { workspace = true } 23 | 24 | [features] 25 | query = ["gelx_core/query"] 26 | serde = ["gelx_core/serde"] 27 | builder = ["gelx_core/builder"] 28 | strum = ["gelx_core/strum"] 29 | 30 | [lints] 31 | workspace = true 32 | -------------------------------------------------------------------------------- /crates/gelx_macros/changelog.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | All notable changes to this project will be documented in this file. 4 | 5 | The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). 6 | 7 | ## [Unreleased] 8 | 9 | ## [0.7.0](https://github.com/ifiokjr/gelx/compare/v0.6.0...v0.7.0) - 2025-05-26 10 | 11 | ### 🎉 Added 12 | 13 | - feat!(gelx_build): add `gelx_build` crate for reading configuration in macros 14 | - add support for postgis via `geo` 15 | 16 | ### 🐛 Bug Fixes 17 | 18 | - *(gelx_core)* remove unused `gelx_core` `with_*` features 19 | 20 | ## [0.5.0](https://github.com/ifiokjr/gelx/compare/v0.4.0...v0.5.0) - 2025-05-20 21 | 22 | ### 🎉 Added 23 | 24 | - _(gelx)_ deprecate `gelx_file` macro 25 | - _(gelx_core)_ add `query_constant_name` metadata option 26 | - _(gelx_core)_ make `exports_alias` customisable 27 | - _(gelx_cli)_ add `--stdout` option for code generation 28 | - _(gelx)_ `gelx!` can now take a custom path to the query 29 | 30 | ### 📚 Documentation 31 | 32 | - update installation instructions share readme across crates 33 | - update installation instructions share readme across crates 34 | 35 | ### 🧪 Testing 36 | 37 | - _(gelx_cli)_ hardcode `gelx` binary from `devenv` in test 38 | 39 | ## [0.4.0](https://github.com/ifiokjr/gelx/compare/v0.3.0...v0.4.0) - 2025-05-19 40 | 41 | ### 🎉 Added 42 | 43 | - add `GelxMetadata` and improve everything 44 | - add strum support 45 | - add `regex` dependency and refactor code generation functions 46 | - add `gelx_cli` crate and integrate `clap` for command-line interface 47 | 48 | ### 📚 Documentation 49 | 50 | - small improvements 51 | 52 | ## [0.3.0](https://github.com/ifiokjr/gelx/compare/v0.2.1...v0.3.0) - 2025-05-16 53 | 54 | ### 🎉 Added 55 | 56 | - [**breaking**] rename `edgedb_codegen` to `gelx` 57 | - [**breaking**] rename `edgedb_codegen_macros` to `gelx_macros` 58 | - [**breaking**] rename `edgedb_codegen_core` to `gelx_core` 59 | - [**breaking**] upgrade all `gel` libraries to latest versions as a replacement for previous `edgedb` dependencies 60 | 61 | ### 📚 Documentation 62 | 63 | - improve main readme 64 | 65 | ## [0.2.0](https://github.com/ifiokjr/gelx/compare/v0.1.2...v0.2.0) - 2024-08-28 66 | 67 | ### 🎉 Added 68 | 69 | - [**breaking**] add optional `builder` feature limited to `Input` 70 | 71 | ### 📚 Documentation 72 | 73 | - reorder package fields 74 | 75 | ## [0.1.1](https://github.com/ifiokjr/gelx/compare/0.1.0...0.1.1) - 2024-08-26 76 | 77 | ### ⚙️ Miscellaneous Tasks 78 | 79 | - improve changelog generation 80 | 81 | ## [0.1.0](https://github.com/ifiokjr/gelx/releases/tag/gelx_macros-v0.1.0) - 2024-08-25 82 | 83 | ### 🎉 Added 84 | 85 | - Initial release 86 | -------------------------------------------------------------------------------- /crates/gelx_macros/readme.md: -------------------------------------------------------------------------------- 1 | # `gelx_macros` 2 | 3 |
4 | 5 | > Procedural macros for the `gelx` crate, enabling compile-time generation of typed Rust code from Gel queries. 6 | 7 |
8 | 9 | [![Crate][crate-image]][crate-link] [![Docs][docs-image]][docs-link] [![Status][ci-status-image]][ci-status-link] [![Unlicense][unlicense-image]][unlicense-link] [![codecov][codecov-image]][codecov-link] 10 | 11 | ## Overview 12 | 13 | The `gelx_macros` crate provides the `gelx_raw!` procedural macro, which is the primary way users interact with `gelx` for inline query code generation. 14 | 15 | When you use `gelx_raw!(module_name, query: "select ...")` or `gelx_raw!(module_name, file: "path/to/query.edgeql")` in your Rust code, this crate is responsible for: 16 | 17 | - Parsing the macro input (module name and query string or file path). 18 | - Invoking `gelx_core` to fetch query descriptions from a Gel instance. 19 | - Utilizing `gelx_core` to generate the Rust `TokenStream` for the query module, including input/output structs and query functions. 20 | - Returning the generated `TokenStream` to the Rust compiler to be included in your crate. 21 | 22 | This crate is an internal dependency of the main `gelx` crate and is not intended to be used directly by end-users, other than through the `gelx!` macro re-exported by the `gelx` crate. 23 | 24 | ## Macro Usage 25 | 26 | The main macro provided is `gelx!`. It can be used in two ways: 27 | 28 | 1. **Inline Query:** 29 | ```rust 30 | use gelx::gelx; // Assuming gelx re-exports the macro 31 | 32 | gelx!(my_query_module, "SELECT { message := $arg }"); 33 | 34 | // This generates a `my_query_module` with Input/Output structs and query 35 | // functions. 36 | ``` 37 | 38 | 2. **File-based Query:** 39 | ```rust 40 | use gelx::gelx; 41 | 42 | // Assuming a file `queries/get_user.edgeql` exists relative to your Cargo.toml 43 | gelx!(get_user_module, file: "queries/get_user.edgeql"); 44 | 45 | // Or, if the filename matches the module name (e.g., 46 | // `queries/my_module.edgeql`): 47 | gelx!(my_module); 48 | ``` 49 | 50 | For detailed usage examples and configuration, please refer to the documentation of the main [`gelx` crate](https://crates.io/crates/gelx). 51 | 52 | ## Features 53 | 54 | `gelx_macros` forwards its features to `gelx_core`. The available features are: 55 | 56 | - `with_bigint` 57 | - `with_bigdecimal` 58 | - `with_chrono` 59 | - `with_all` 60 | - `query` 61 | - `serde` 62 | - `builder` 63 | - `strum` 64 | 65 | These features are typically controlled via the `gelx` crate's own features when you add `gelx` as a dependency. 66 | 67 | ## Contributing 68 | 69 | This crate is part of the `gelx` workspace. Please refer to the [main project's contributing guide](https://github.com/ifiokjr/gelx/blob/main/readme.md#contributing) for details on how to set up the development environment and contribute. 70 | 71 | ## License 72 | 73 | Unlicense, see the [license file](https://github.com/ifiokjr/gelx/blob/main/license) in the root of the workspace. 74 | 75 | [crate-image]: https://img.shields.io/crates/v/gelx_macros.svg 76 | [crate-link]: https://crates.io/crates/gelx_macros 77 | [docs-image]: https://docs.rs/gelx_macros/badge.svg 78 | [docs-link]: https://docs.rs/gelx_macros/ 79 | [ci-status-image]: https://github.com/ifiokjr/gelx/workflows/ci/badge.svg?branch=main 80 | [ci-status-link]: https://github.com/ifiokjr/gelx/actions?query=workflow%3Aci+branch%3Amain 81 | [unlicense-image]: https://img.shields.io/badge/license-Unlicense-blue.svg 82 | [unlicense-link]: https://github.com/ifiokjr/gelx/blob/main/LICENSE 83 | [codecov-image]: https://codecov.io/github/ifiokjr/gelx/graph/badge.svg?token=87K799Q78I 84 | [codecov-link]: https://codecov.io/github/ifiokjr/gelx 85 | -------------------------------------------------------------------------------- /crates/gelx_macros/src/lib.rs: -------------------------------------------------------------------------------- 1 | #![doc(html_logo_url = "https://raw.githubusercontent.com/ifiokjr/gelx/main/setup/assets/logo.png")] 2 | 3 | use gelx_core::GelxMetadata; 4 | use gelx_core::generate_query_token_stream; 5 | use gelx_core::get_descriptor_sync; 6 | use gelx_core::resolve_path; 7 | use proc_macro::TokenStream; 8 | use proc_macro2::Span; 9 | use quote::ToTokens; 10 | use syn::Token; 11 | use syn::parse::Parse; 12 | use syn::parse_macro_input; 13 | 14 | /// Generates a query module from a query string. 15 | /// 16 | /// It supports inline code: 17 | /// 18 | /// ```ignore 19 | /// use gelx_macros::gelx_raw; 20 | /// 21 | /// gelx_raw!(get_users, query: "select User {**}"); 22 | /// ``` 23 | /// 24 | /// It also supports file-based queries: 25 | /// 26 | /// ```ignore 27 | /// use gelx_macros::gelx_raw; 28 | /// 29 | /// gelx_raw!(insert_user, file: "../gelx/queries/insert_user.edgeql"); 30 | /// ``` 31 | #[proc_macro] 32 | pub fn gelx_raw(input: TokenStream) -> TokenStream { 33 | parse_macro_input!(input as GelQueryInput) 34 | .to_token_stream() 35 | .into() 36 | } 37 | 38 | pub(crate) struct GelQueryInput { 39 | pub(crate) module: syn::Ident, 40 | pub(crate) query: String, 41 | } 42 | 43 | impl Parse for GelQueryInput { 44 | fn parse(input: syn::parse::ParseStream) -> syn::Result { 45 | let module: syn::Ident = input.parse()?; 46 | 47 | let query_content = if input.peek(Token![,]) { 48 | input.parse::()?; 49 | 50 | let marker: syn::Ident = input.parse()?; 51 | input.parse::()?; 52 | let raw_content: syn::LitStr = input.parse()?; 53 | 54 | if marker == "file" { 55 | QueryContent::File(raw_content.value(), raw_content.span()) 56 | } else if marker == "query" { 57 | QueryContent::Query(raw_content.value()) 58 | } else { 59 | let message = format!("unexpected marker token: {marker}"); 60 | return Err(syn::Error::new_spanned(marker, message)); 61 | } 62 | } else { 63 | QueryContent::File(format!("queries/{module}.edgeql"), module.span()) 64 | }; 65 | 66 | let query = query_content.resolve()?; 67 | Ok(Self { module, query }) 68 | } 69 | } 70 | 71 | impl ToTokens for GelQueryInput { 72 | fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) { 73 | let metadata: GelxMetadata = std::env::var("GELX_METADATA_BASE64") 74 | .ok() 75 | .and_then(|value| GelxMetadata::try_from_base64(value).ok()) 76 | .unwrap_or_default(); 77 | let module_name = self.module.to_string(); 78 | let token_stream = get_descriptor_sync(&self.query, &metadata) 79 | .and_then(|descriptor| { 80 | generate_query_token_stream(&descriptor, &module_name, &self.query, &metadata, true) 81 | }) 82 | .unwrap_or_else(|error| syn::Error::from(error).to_compile_error()); 83 | 84 | tokens.extend(token_stream); 85 | } 86 | } 87 | 88 | #[derive(Debug)] 89 | pub(crate) enum QueryContent { 90 | Query(String), 91 | File(String, Span), 92 | } 93 | 94 | impl QueryContent { 95 | pub fn resolve(self) -> syn::Result { 96 | match self { 97 | QueryContent::Query(query) => Ok(query), 98 | QueryContent::File(relative_path, span) => { 99 | let path = resolve_path(relative_path, span)?; 100 | 101 | std::fs::read_to_string(&path) 102 | .map_err(|error| { 103 | syn::Error::new( 104 | span, 105 | format!("failed to read query file at {}: {}", path.display(), error), 106 | ) 107 | }) 108 | .map(|value| value.trim().to_string()) 109 | } 110 | } 111 | } 112 | } 113 | -------------------------------------------------------------------------------- /dbschema/additional.gel: -------------------------------------------------------------------------------- 1 | module additional { 2 | scalar type Awesomeness extending enum; 3 | scalar type smartness extending enum; 4 | } -------------------------------------------------------------------------------- /dbschema/default.gel: -------------------------------------------------------------------------------- 1 | using extension postgis; 2 | 3 | module default { 4 | global current_user_id: uuid; 5 | 6 | type Location extending CreatedAt, UpdatedAt { 7 | required point: ext::postgis::geometry; 8 | required area: ext::postgis::geography; 9 | } 10 | 11 | type Account extending CreatedAt, UpdatedAt { 12 | required provider: AccountProvider; 13 | required provider_account_id: str; 14 | username: str; 15 | access_token: str; 16 | access_token_expires_at: datetime; 17 | refresh_token: str; 18 | refresh_token_expires_at: datetime; 19 | scope: str; 20 | required user: User { 21 | on target delete delete source; 22 | }; 23 | } 24 | 25 | type Email extending VerifiedAt, CreatedAt, UpdatedAt { 26 | required email: str { 27 | constraint exclusive; 28 | readonly := true; 29 | rewrite insert using (str_trim(str_lower(.email))) 30 | } 31 | required primary: bool { 32 | default := false; 33 | } 34 | required user: User { 35 | on target delete delete source; 36 | } 37 | constraint exclusive on ((.user, .primary)) except (not .primary); 38 | } 39 | 40 | type Project extending CreatedAt, RelationshipTarget, UpdatedAt { 41 | required name: str; 42 | required slug: str { 43 | constraint regexp(r'^(?=.{3,39}$)(?![_.-])(?!.*[_.-]{2})[a-zA-Z0-9._-]+(?; 130 | scalar type RelationshipType extending enum; 131 | scalar type Role extending enum; 132 | } 133 | -------------------------------------------------------------------------------- /dbschema/migrations/00002-m15h5hl.edgeql: -------------------------------------------------------------------------------- 1 | CREATE MIGRATION m15h5hlf7dhzkpyocyiqflw3lhhq6zadpunsbr3iihqurwsxxvqw7q 2 | ONTO m1k7o3tcbkvar3vkfeigwnorqbwahoxfrxrcfmqbte2tg7dhkd3zea 3 | { 4 | CREATE MODULE additional IF NOT EXISTS; 5 | CREATE SCALAR TYPE additional::Awesomeness EXTENDING enum; 6 | CREATE SCALAR TYPE additional::smartness EXTENDING enum; 7 | }; 8 | -------------------------------------------------------------------------------- /dbschema/migrations/00003-m1umlyt.edgeql: -------------------------------------------------------------------------------- 1 | CREATE MIGRATION m1umlytq2fg6arigkzjynrhtn5buuspjl4by7vznvvyyf7uw2hfofq 2 | ONTO m15h5hlf7dhzkpyocyiqflw3lhhq6zadpunsbr3iihqurwsxxvqw7q 3 | { 4 | CREATE EXTENSION postgis VERSION '3.5'; 5 | }; 6 | -------------------------------------------------------------------------------- /dbschema/migrations/00004-m14fgr2.edgeql: -------------------------------------------------------------------------------- 1 | CREATE MIGRATION m14fgr2cnwdlfq6rejide5ryxfa2y6dn2jlou47s4geadl5powkfma 2 | ONTO m1umlytq2fg6arigkzjynrhtn5buuspjl4by7vznvvyyf7uw2hfofq 3 | { 4 | CREATE TYPE default::Location EXTENDING default::CreatedAt, default::UpdatedAt { 5 | CREATE REQUIRED PROPERTY area: ext::postgis::geography; 6 | CREATE REQUIRED PROPERTY point: ext::postgis::geometry; 7 | }; 8 | }; 9 | -------------------------------------------------------------------------------- /devenv.lock: -------------------------------------------------------------------------------- 1 | { 2 | "nodes": { 3 | "devenv": { 4 | "locked": { 5 | "dir": "src/modules", 6 | "lastModified": 1747717470, 7 | "owner": "cachix", 8 | "repo": "devenv", 9 | "rev": "c7f2256ee4a4a4ee9cbf1e82a6e49b253c374995", 10 | "type": "github" 11 | }, 12 | "original": { 13 | "dir": "src/modules", 14 | "owner": "cachix", 15 | "repo": "devenv", 16 | "type": "github" 17 | } 18 | }, 19 | "flake-compat": { 20 | "flake": false, 21 | "locked": { 22 | "lastModified": 1747046372, 23 | "owner": "edolstra", 24 | "repo": "flake-compat", 25 | "rev": "9100a0f413b0c601e0533d1d94ffd501ce2e7885", 26 | "type": "github" 27 | }, 28 | "original": { 29 | "owner": "edolstra", 30 | "repo": "flake-compat", 31 | "type": "github" 32 | } 33 | }, 34 | "git-hooks": { 35 | "inputs": { 36 | "flake-compat": "flake-compat", 37 | "gitignore": "gitignore", 38 | "nixpkgs": [ 39 | "nixpkgs" 40 | ] 41 | }, 42 | "locked": { 43 | "lastModified": 1747372754, 44 | "owner": "cachix", 45 | "repo": "git-hooks.nix", 46 | "rev": "80479b6ec16fefd9c1db3ea13aeb038c60530f46", 47 | "type": "github" 48 | }, 49 | "original": { 50 | "owner": "cachix", 51 | "repo": "git-hooks.nix", 52 | "type": "github" 53 | } 54 | }, 55 | "gitignore": { 56 | "inputs": { 57 | "nixpkgs": [ 58 | "git-hooks", 59 | "nixpkgs" 60 | ] 61 | }, 62 | "locked": { 63 | "lastModified": 1709087332, 64 | "owner": "hercules-ci", 65 | "repo": "gitignore.nix", 66 | "rev": "637db329424fd7e46cf4185293b9cc8c88c95394", 67 | "type": "github" 68 | }, 69 | "original": { 70 | "owner": "hercules-ci", 71 | "repo": "gitignore.nix", 72 | "type": "github" 73 | } 74 | }, 75 | "nixpkgs": { 76 | "locked": { 77 | "lastModified": 1748221897, 78 | "owner": "NixOS", 79 | "repo": "nixpkgs", 80 | "rev": "9f3875761628112140c969c0e7c59295158e09bd", 81 | "type": "github" 82 | }, 83 | "original": { 84 | "owner": "NixOS", 85 | "ref": "master", 86 | "repo": "nixpkgs", 87 | "type": "github" 88 | } 89 | }, 90 | "nixpkgs_2": { 91 | "locked": { 92 | "lastModified": 1748186667, 93 | "owner": "NixOS", 94 | "repo": "nixpkgs", 95 | "rev": "bdac72d387dca7f836f6ef1fe547755fb0e9df61", 96 | "type": "github" 97 | }, 98 | "original": { 99 | "owner": "NixOS", 100 | "ref": "nixpkgs-unstable", 101 | "repo": "nixpkgs", 102 | "type": "github" 103 | } 104 | }, 105 | "root": { 106 | "inputs": { 107 | "devenv": "devenv", 108 | "git-hooks": "git-hooks", 109 | "nixpkgs": "nixpkgs", 110 | "pre-commit-hooks": [ 111 | "git-hooks" 112 | ], 113 | "rust-overlay": "rust-overlay" 114 | } 115 | }, 116 | "rust-overlay": { 117 | "inputs": { 118 | "nixpkgs": "nixpkgs_2" 119 | }, 120 | "locked": { 121 | "lastModified": 1748140821, 122 | "owner": "oxalica", 123 | "repo": "rust-overlay", 124 | "rev": "476b2ba7dc99ddbf70b1f45357dbbdbdbdfb4422", 125 | "type": "github" 126 | }, 127 | "original": { 128 | "owner": "oxalica", 129 | "repo": "rust-overlay", 130 | "type": "github" 131 | } 132 | } 133 | }, 134 | "root": "root", 135 | "version": 7 136 | } 137 | -------------------------------------------------------------------------------- /devenv.yaml: -------------------------------------------------------------------------------- 1 | inputs: 2 | nixpkgs: 3 | url: github:NixOS/nixpkgs/master 4 | rust-overlay: 5 | url: github:oxalica/rust-overlay 6 | overlays: 7 | - default 8 | -------------------------------------------------------------------------------- /dprint.json: -------------------------------------------------------------------------------- 1 | { 2 | "useTabs": true, 3 | "indentWidth": 2, 4 | "lineWidth": 100, 5 | "exec": { 6 | "commands": [ 7 | { 8 | "command": "rustfmt --unstable-features --edition 2021", 9 | "exts": ["rs"] 10 | }, 11 | { 12 | "command": "nixfmt", 13 | "exts": ["nix"] 14 | }, 15 | { 16 | "command": "shfmt --filename {{file_path}} -i 0", 17 | "exts": ["sh", "bash"] 18 | } 19 | ] 20 | }, 21 | "incremental": true, 22 | "json": { 23 | "deno": true, 24 | "useTabs": true 25 | }, 26 | "yaml": {}, 27 | "toml": { 28 | "useTabs": true, 29 | "indentWidth": 2, 30 | "cargo.applyConventions": true 31 | }, 32 | "markdown": { 33 | "deno": true, 34 | "textWrap": "never" 35 | }, 36 | "includes": [ 37 | "**/*.{json,jsonc,md,toml,rs,yml,yaml,sh,bash,nix}" 38 | ], 39 | "excludes": [ 40 | "crates/gelx/tests/compile", 41 | "pnpm-lock.yaml", 42 | "**/dist", 43 | ".devenv/**", 44 | "**/fixtures", 45 | "**/snapshots", 46 | "**/target", 47 | "**/changelog.md", 48 | ".bin/", 49 | "**/dist/**", 50 | "**/pkg/" 51 | ], 52 | "plugins": [ 53 | "https://plugins.dprint.dev/json-0.19.3.wasm", 54 | "https://plugins.dprint.dev/markdown-0.17.8.wasm", 55 | "https://plugins.dprint.dev/exec-0.5.0.json@8d9972eee71fa1590e04873540421f3eda7674d0f1aae3d7c788615e7b7413d0", 56 | "https://plugins.dprint.dev/g-plane/pretty_yaml-v0.5.0.wasm", 57 | "https://plugins.dprint.dev/toml-0.6.2.wasm" 58 | ] 59 | } 60 | -------------------------------------------------------------------------------- /examples/gelx_example/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "gelx_example" 3 | version = { workspace = true } 4 | authors = { workspace = true } 5 | edition = { workspace = true } 6 | homepage = { workspace = true } 7 | license = { workspace = true } 8 | repository = { workspace = true } 9 | rust-version = { workspace = true } 10 | 11 | [dependencies] 12 | anyhow = "1" 13 | gel-protocol = { workspace = true } 14 | gelx = { workspace = true, features = ["with_all", "serde", "strum", "query", "builder"] } 15 | serde = { workspace = true, features = ["derive"] } 16 | strum = { workspace = true, features = ["derive"] } 17 | tokio = { workspace = true, features = ["full"] } 18 | 19 | [lints] 20 | workspace = true 21 | 22 | [features] 23 | default = ["ssr"] 24 | ssr = ["gelx/query", "gelx/serde", "gelx/strum", "gelx/builder"] 25 | 26 | [package.metadata.gelx] 27 | queries_path = "./queries" 28 | features = { query = "ssr", strum = "ssr", builder = "ssr" } 29 | output_path = "./src/db" 30 | input_struct_name = "Input" 31 | output_struct_name = "Output" 32 | query_function_name = "query" 33 | transaction_function_name = "transaction" 34 | # gel_config_path = "./gel.toml" 35 | # gel_instance = "$GEL_INSTANCE" 36 | # gel_branch = "$GEL_BRANCH" 37 | -------------------------------------------------------------------------------- /examples/gelx_example/queries/insert_location.edgeql: -------------------------------------------------------------------------------- 1 | with NewLocation := (insert Location { 2 | point := $point, 3 | area := $area, 4 | }) 5 | select NewLocation { 6 | point, 7 | area, 8 | }; -------------------------------------------------------------------------------- /examples/gelx_example/queries/insert_user.edgeql: -------------------------------------------------------------------------------- 1 | with NewUser := (insert User { 2 | name := $name, 3 | bio := $bio, 4 | slug := $slug, 5 | }) 6 | select NewUser { 7 | id, 8 | name, 9 | bio, 10 | slug, 11 | }; 12 | -------------------------------------------------------------------------------- /examples/gelx_example/queries/remove_user.edgeql: -------------------------------------------------------------------------------- 1 | delete User filter .id = $id; 2 | -------------------------------------------------------------------------------- /examples/gelx_example/queries/select_accounts.edgeql: -------------------------------------------------------------------------------- 1 | select Account {**} filter .provider = $provider; -------------------------------------------------------------------------------- /examples/gelx_example/queries/select_user.edgeql: -------------------------------------------------------------------------------- 1 | select User { 2 | id, 3 | name, 4 | bio, 5 | slug, 6 | } filter .slug = $slug; -------------------------------------------------------------------------------- /examples/gelx_example/src/db/additional.rs: -------------------------------------------------------------------------------- 1 | //! This file is generated by `gelx generate`. 2 | //! It is not intended for manual editing. 3 | //! To update it, run `gelx generate`. 4 | #![cfg_attr(rustfmt, rustfmt_skip)] 5 | #![allow(unused)] 6 | #![allow(unused_qualifications)] 7 | #![allow(clippy::all)] 8 | use super::*; 9 | #[derive(Debug, Clone, Copy, __g::serde::Serialize, __g::serde::Deserialize)] 10 | #[cfg_attr( 11 | feature = "ssr", 12 | derive( 13 | __g::gel_derive::Queryable, 14 | __g::strum::AsRefStr, 15 | __g::strum::Display, 16 | __g::strum::EnumString, 17 | __g::strum::EnumIs, 18 | __g::strum::FromRepr, 19 | __g::strum::IntoStaticStr 20 | ) 21 | )] 22 | pub enum Awesomeness { 23 | Very, 24 | Somewhat, 25 | NotReally, 26 | } 27 | #[cfg(feature = "ssr")] 28 | impl From for __g::gel_protocol::value::Value { 29 | fn from(value: Awesomeness) -> Self { 30 | __g::gel_protocol::value::Value::Enum(value.as_ref().into()) 31 | } 32 | } 33 | #[derive(Debug, Clone, Copy, __g::serde::Serialize, __g::serde::Deserialize)] 34 | #[cfg_attr( 35 | feature = "ssr", 36 | derive( 37 | __g::gel_derive::Queryable, 38 | __g::strum::AsRefStr, 39 | __g::strum::Display, 40 | __g::strum::EnumString, 41 | __g::strum::EnumIs, 42 | __g::strum::FromRepr, 43 | __g::strum::IntoStaticStr 44 | ) 45 | )] 46 | pub enum Smartness { 47 | #[serde(rename = "low")] 48 | #[cfg_attr(feature = "ssr", strum(serialize = "low"))] 49 | Low, 50 | #[serde(rename = "mid")] 51 | #[cfg_attr(feature = "ssr", strum(serialize = "mid"))] 52 | Mid, 53 | #[serde(rename = "genius")] 54 | #[cfg_attr(feature = "ssr", strum(serialize = "genius"))] 55 | Genius, 56 | } 57 | #[cfg(feature = "ssr")] 58 | impl From for __g::gel_protocol::value::Value { 59 | fn from(value: Smartness) -> Self { 60 | __g::gel_protocol::value::Value::Enum(value.as_ref().into()) 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /examples/gelx_example/src/db/default.rs: -------------------------------------------------------------------------------- 1 | //! This file is generated by `gelx generate`. 2 | //! It is not intended for manual editing. 3 | //! To update it, run `gelx generate`. 4 | #![cfg_attr(rustfmt, rustfmt_skip)] 5 | #![allow(unused)] 6 | #![allow(unused_qualifications)] 7 | #![allow(clippy::all)] 8 | use super::*; 9 | #[derive(Debug, Clone, Copy, __g::serde::Serialize, __g::serde::Deserialize)] 10 | #[cfg_attr( 11 | feature = "ssr", 12 | derive( 13 | __g::gel_derive::Queryable, 14 | __g::strum::AsRefStr, 15 | __g::strum::Display, 16 | __g::strum::EnumString, 17 | __g::strum::EnumIs, 18 | __g::strum::FromRepr, 19 | __g::strum::IntoStaticStr 20 | ) 21 | )] 22 | pub enum AccountProvider { 23 | Github, 24 | } 25 | #[cfg(feature = "ssr")] 26 | impl From for __g::gel_protocol::value::Value { 27 | fn from(value: AccountProvider) -> Self { 28 | __g::gel_protocol::value::Value::Enum(value.as_ref().into()) 29 | } 30 | } 31 | #[derive(Debug, Clone, Copy, __g::serde::Serialize, __g::serde::Deserialize)] 32 | #[cfg_attr( 33 | feature = "ssr", 34 | derive( 35 | __g::gel_derive::Queryable, 36 | __g::strum::AsRefStr, 37 | __g::strum::Display, 38 | __g::strum::EnumString, 39 | __g::strum::EnumIs, 40 | __g::strum::FromRepr, 41 | __g::strum::IntoStaticStr 42 | ) 43 | )] 44 | pub enum RelationshipType { 45 | Follow, 46 | Block, 47 | Mute, 48 | } 49 | #[cfg(feature = "ssr")] 50 | impl From for __g::gel_protocol::value::Value { 51 | fn from(value: RelationshipType) -> Self { 52 | __g::gel_protocol::value::Value::Enum(value.as_ref().into()) 53 | } 54 | } 55 | #[derive(Debug, Clone, Copy, __g::serde::Serialize, __g::serde::Deserialize)] 56 | #[cfg_attr( 57 | feature = "ssr", 58 | derive( 59 | __g::gel_derive::Queryable, 60 | __g::strum::AsRefStr, 61 | __g::strum::Display, 62 | __g::strum::EnumString, 63 | __g::strum::EnumIs, 64 | __g::strum::FromRepr, 65 | __g::strum::IntoStaticStr 66 | ) 67 | )] 68 | pub enum Role { 69 | None, 70 | Editor, 71 | Moderator, 72 | Admin, 73 | Owner, 74 | } 75 | #[cfg(feature = "ssr")] 76 | impl From for __g::gel_protocol::value::Value { 77 | fn from(value: Role) -> Self { 78 | __g::gel_protocol::value::Value::Enum(value.as_ref().into()) 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /examples/gelx_example/src/main.rs: -------------------------------------------------------------------------------- 1 | mod db; 2 | 3 | use db::*; 4 | use gelx::create_client; 5 | 6 | #[tokio::main] 7 | async fn main() -> anyhow::Result<()> { 8 | let client = create_client().await?; 9 | let props = select_user::Input::builder().slug("test").build(); 10 | let query = select_user::query(&client, &props).await?; 11 | println!("{query:?}"); 12 | 13 | let props = select_accounts::Input::builder() 14 | .provider(AccountProvider::Github) 15 | .build(); 16 | let query = select_accounts::query(&client, &props).await?; 17 | println!("{query:?}"); 18 | 19 | Ok(()) 20 | } 21 | -------------------------------------------------------------------------------- /gel.toml: -------------------------------------------------------------------------------- 1 | [instance] 2 | server-version = "6.7" 3 | -------------------------------------------------------------------------------- /license: -------------------------------------------------------------------------------- 1 | This is free and unencumbered software released into the public domain. 2 | 3 | Anyone is free to copy, modify, publish, use, compile, sell, or 4 | distribute this software, either in source code form or as a compiled 5 | binary, for any purpose, commercial or non-commercial, and by any 6 | means. 7 | 8 | In jurisdictions that recognize copyright laws, the author or authors 9 | of this software dedicate any and all copyright interest in the 10 | software to the public domain. We make this dedication for the benefit 11 | of the public at large and to the detriment of our heirs and 12 | successors. We intend this dedication to be an overt act of 13 | relinquishment in perpetuity of all present and future rights to this 14 | software under copyright law. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19 | IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 20 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | OTHER DEALINGS IN THE SOFTWARE. 23 | 24 | For more information, please refer to 25 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | crates/gelx/readme.md -------------------------------------------------------------------------------- /rust-toolchain.toml: -------------------------------------------------------------------------------- 1 | [toolchain] 2 | # https://rust-lang.github.io/rustup-components-history/ 3 | channel = "nightly-2025-05-14" 4 | components = ["rustfmt", "cargo", "clippy", "rust-analyzer", "llvm-tools-preview"] 5 | profile = "default" 6 | -------------------------------------------------------------------------------- /rustfmt.toml: -------------------------------------------------------------------------------- 1 | edition = "2021" 2 | version = "Two" 3 | unstable_features = true 4 | condense_wildcard_suffixes = true 5 | force_multiline_blocks = true 6 | format_code_in_doc_comments = true 7 | format_macro_matchers = true 8 | format_strings = true 9 | group_imports = "StdExternalCrate" 10 | hard_tabs = true 11 | imports_granularity = "Item" 12 | imports_layout = "HorizontalVertical" 13 | indent_style = "Block" 14 | max_width = 100 15 | newline_style = "Unix" 16 | normalize_comments = true 17 | reorder_impl_items = true 18 | reorder_imports = true 19 | reorder_modules = true 20 | use_field_init_shorthand = true 21 | wrap_comments = true 22 | -------------------------------------------------------------------------------- /setup/assets/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ifiokjr/gelx/5e69e2e0b0afab90854c4ba2f9f8b4d9c5bb2714/setup/assets/logo.png -------------------------------------------------------------------------------- /setup/assets/logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /setup/editors/helix/languages.toml: -------------------------------------------------------------------------------- 1 | [language-server.nil] 2 | command = "nil" 3 | 4 | [language-server.nil.config] 5 | formatting = { command = "nixpkgs-fmt" } 6 | 7 | [language-server.rust-analyzer.config.check] 8 | command = "clippy" 9 | features = "all" 10 | 11 | [language-server.rust-analyzer.config.cargo] 12 | features = "all" 13 | 14 | [[language]] 15 | name = "markdown" 16 | indent = { tab-width = 2, unit = "\t" } 17 | formatter = { command = "dprint", args = ["fmt", "--stdin", "file.md"] } 18 | auto-format = true 19 | 20 | [[language]] 21 | name = "rust" 22 | language-servers = ["rust-analyzer"] 23 | indent = { tab-width = 2, unit = "\t" } 24 | formatter = { command = "dprint", args = ["fmt", "--stdin", "file.rs"] } 25 | auto-format = true 26 | 27 | [[language]] 28 | name = "yaml" 29 | indent = { tab-width = 2, unit = "\t" } 30 | formatter = { command = "dprint", args = ["fmt", "--stdin", "file.yaml"] } 31 | auto-format = true 32 | 33 | [[language]] 34 | name = "toml" 35 | indent = { tab-width = 2, unit = "\t" } 36 | language-servers = ["taplo"] 37 | formatter = { command = "dprint", args = ["fmt", "--stdin", "Cargo.toml"] } 38 | auto-format = true 39 | 40 | [[language]] 41 | name = "nix" 42 | language-servers = ["nil"] 43 | indent = { tab-width = 2, unit = "\t" } 44 | formatter = { command = "dprint", args = ["fmt", "--stdin", "file.nix"] } 45 | auto-format = true 46 | -------------------------------------------------------------------------------- /setup/editors/vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": [ 3 | "dprint.dprint", 4 | "mkhl.direnv", 5 | "ms-playwright.playwright", 6 | "rust-lang.rust-analyzer", 7 | "vadimcn.vscode-lldb" 8 | ] 9 | } 10 | -------------------------------------------------------------------------------- /setup/editors/vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "editor.detectIndentation": false, 3 | "editor.insertSpaces": false, 4 | "editor.tabSize": 2, 5 | "dprint.path": ".devenv/profile/bin/dprint", 6 | "rust-analyzer.cargo.features": "all", 7 | "rust-analyzer.check.command": "clippy", 8 | "[json]": { 9 | "editor.defaultFormatter": "dprint.dprint" 10 | }, 11 | "[jsonc]": { 12 | "editor.defaultFormatter": "dprint.dprint" 13 | }, 14 | "[markdown]": { 15 | "editor.defaultFormatter": "dprint.dprint" 16 | }, 17 | "[nix]": { 18 | "editor.defaultFormatter": "dprint.dprint" 19 | }, 20 | "[rust]": { 21 | "editor.defaultFormatter": "dprint.dprint" 22 | }, 23 | "[toml]": { 24 | "editor.defaultFormatter": "dprint.dprint" 25 | }, 26 | "[yaml]": { 27 | "editor.defaultFormatter": "dprint.dprint" 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /setup/scripts/nextest_setup.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Exit with 1 if NEXTEST_ENV isn't defined. 4 | if [ -z "$NEXTEST_ENV" ]; then 5 | exit 1 6 | fi 7 | 8 | # Set the default logging to `debug` for tests 9 | echo "RUST_LOG=trace,tarpc=off,solana_metrics=off,solana_program_test=off,solana_accounts_db=off,solana_runtime=off" >>"$NEXTEST_ENV" 10 | echo "RUST_LOG_SPAN_EVENTS=full" >>"$NEXTEST_ENV" 11 | --------------------------------------------------------------------------------