generated from phundrak/rust-poem-openapi-template
	feat: add new crud macro for easier entity manipulation in DB
	
		
			
	
		
	
	
		
	
		
			All checks were successful
		
		
	
	
		
			
				
	
				CI / tests (push) Successful in 7m52s
				
			
		
		
	
	
				
					
				
			
		
			All checks were successful
		
		
	
	CI / tests (push) Successful in 7m52s
				
			This commit is contained in:
		
							parent
							
								
									e2a5758e53
								
							
						
					
					
						commit
						642d7bae0d
					
				@ -1,6 +1,6 @@
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
  "db_name": "PostgreSQL",
 | 
					  "db_name": "PostgreSQL",
 | 
				
			||||||
  "query": "\nUPDATE users\nSET username = $1, email = $2, avatar = $3, name = $4, last_updated = $5\nWHERE id = $6\nRETURNING *\n",
 | 
					  "query": "UPDATE users SET username = $1, email = $2, avatar = $3, name = $4, created_at = $5, last_updated = $6 WHERE id = $7 RETURNING *",
 | 
				
			||||||
  "describe": {
 | 
					  "describe": {
 | 
				
			||||||
    "columns": [
 | 
					    "columns": [
 | 
				
			||||||
      {
 | 
					      {
 | 
				
			||||||
@ -46,6 +46,7 @@
 | 
				
			|||||||
        "Varchar",
 | 
					        "Varchar",
 | 
				
			||||||
        "Varchar",
 | 
					        "Varchar",
 | 
				
			||||||
        "Timestamptz",
 | 
					        "Timestamptz",
 | 
				
			||||||
 | 
					        "Timestamptz",
 | 
				
			||||||
        "Text"
 | 
					        "Text"
 | 
				
			||||||
      ]
 | 
					      ]
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
@ -59,5 +60,5 @@
 | 
				
			|||||||
      false
 | 
					      false
 | 
				
			||||||
    ]
 | 
					    ]
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
  "hash": "c36467a81bad236a0c1a8d3fc1b5f8efda9b9cf9eaab140c10246218f0240600"
 | 
					  "hash": "752d93e987bb126c321656bb3977ea3ae61ec20d641e6c9adc72d580b2fcc538"
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -1,6 +1,6 @@
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
  "db_name": "PostgreSQL",
 | 
					  "db_name": "PostgreSQL",
 | 
				
			||||||
  "query": "\nINSERT INTO users (id, username, email, avatar, name, created_at, last_updated)\nVALUES ($1, $2, $3, $4, $5, $6, $7)\nRETURNING *\n",
 | 
					  "query": "INSERT INTO users (id, username, email, avatar, name, created_at, last_updated) VALUES ($1, $2, $3, $4, $5, $6, $7) RETURNING *",
 | 
				
			||||||
  "describe": {
 | 
					  "describe": {
 | 
				
			||||||
    "columns": [
 | 
					    "columns": [
 | 
				
			||||||
      {
 | 
					      {
 | 
				
			||||||
@ -60,5 +60,5 @@
 | 
				
			|||||||
      false
 | 
					      false
 | 
				
			||||||
    ]
 | 
					    ]
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
  "hash": "24bbd63a324e36f4a0c559c44909621cc21b493b4c9ae4c14e30c99a6d8072bd"
 | 
					  "hash": "fe91cc30858aaf2f0d328a64d7da3a5dee255f85c130c1d6d7ee3e41b647bbf5"
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
							
								
								
									
										270
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										270
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
								
							@ -135,6 +135,12 @@ version = "0.5.1"
 | 
				
			|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
checksum = "7d902e3d592a523def97af8f317b08ce16b7ab854c1985a0c671e6f15cebc236"
 | 
					checksum = "7d902e3d592a523def97af8f317b08ce16b7ab854c1985a0c671e6f15cebc236"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[[package]]
 | 
				
			||||||
 | 
					name = "arrayvec"
 | 
				
			||||||
 | 
					version = "0.7.6"
 | 
				
			||||||
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
 | 
					checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
name = "async-trait"
 | 
					name = "async-trait"
 | 
				
			||||||
version = "0.1.83"
 | 
					version = "0.1.83"
 | 
				
			||||||
@ -143,7 +149,7 @@ checksum = "721cae7de5c34fbb2acd27e21e6d2cf7b886dce0c27388d46c4e6c47ea4318dd"
 | 
				
			|||||||
dependencies = [
 | 
					dependencies = [
 | 
				
			||||||
 "proc-macro2",
 | 
					 "proc-macro2",
 | 
				
			||||||
 "quote",
 | 
					 "quote",
 | 
				
			||||||
 "syn 2.0.89",
 | 
					 "syn 2.0.96",
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
@ -572,8 +578,8 @@ dependencies = [
 | 
				
			|||||||
 "ident_case",
 | 
					 "ident_case",
 | 
				
			||||||
 "proc-macro2",
 | 
					 "proc-macro2",
 | 
				
			||||||
 "quote",
 | 
					 "quote",
 | 
				
			||||||
 "strsim",
 | 
					 "strsim 0.11.1",
 | 
				
			||||||
 "syn 2.0.89",
 | 
					 "syn 2.0.96",
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
@ -584,7 +590,7 @@ checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806"
 | 
				
			|||||||
dependencies = [
 | 
					dependencies = [
 | 
				
			||||||
 "darling_core",
 | 
					 "darling_core",
 | 
				
			||||||
 "quote",
 | 
					 "quote",
 | 
				
			||||||
 "syn 2.0.89",
 | 
					 "syn 2.0.96",
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
@ -593,6 +599,47 @@ version = "2.6.0"
 | 
				
			|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
checksum = "e8566979429cf69b49a5c740c60791108e86440e8be149bbea4fe54d2c32d6e2"
 | 
					checksum = "e8566979429cf69b49a5c740c60791108e86440e8be149bbea4fe54d2c32d6e2"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[[package]]
 | 
				
			||||||
 | 
					name = "deluxe"
 | 
				
			||||||
 | 
					version = "0.5.0"
 | 
				
			||||||
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
 | 
					checksum = "8ed332aaf752b459088acf3dd4eca323e3ef4b83c70a84ca48fb0ec5305f1488"
 | 
				
			||||||
 | 
					dependencies = [
 | 
				
			||||||
 | 
					 "deluxe-core",
 | 
				
			||||||
 | 
					 "deluxe-macros",
 | 
				
			||||||
 | 
					 "once_cell",
 | 
				
			||||||
 | 
					 "proc-macro2",
 | 
				
			||||||
 | 
					 "syn 2.0.96",
 | 
				
			||||||
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[[package]]
 | 
				
			||||||
 | 
					name = "deluxe-core"
 | 
				
			||||||
 | 
					version = "0.5.0"
 | 
				
			||||||
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
 | 
					checksum = "eddada51c8576df9d6a8450c351ff63042b092c9458b8ac7d20f89cbd0ffd313"
 | 
				
			||||||
 | 
					dependencies = [
 | 
				
			||||||
 | 
					 "arrayvec",
 | 
				
			||||||
 | 
					 "proc-macro2",
 | 
				
			||||||
 | 
					 "quote",
 | 
				
			||||||
 | 
					 "strsim 0.10.0",
 | 
				
			||||||
 | 
					 "syn 2.0.96",
 | 
				
			||||||
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[[package]]
 | 
				
			||||||
 | 
					name = "deluxe-macros"
 | 
				
			||||||
 | 
					version = "0.5.0"
 | 
				
			||||||
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
 | 
					checksum = "f87546d9c837f0b7557e47b8bd6eae52c3c223141b76aa233c345c9ab41d9117"
 | 
				
			||||||
 | 
					dependencies = [
 | 
				
			||||||
 | 
					 "deluxe-core",
 | 
				
			||||||
 | 
					 "heck 0.4.1",
 | 
				
			||||||
 | 
					 "if_chain",
 | 
				
			||||||
 | 
					 "proc-macro-crate 1.3.1",
 | 
				
			||||||
 | 
					 "proc-macro2",
 | 
				
			||||||
 | 
					 "quote",
 | 
				
			||||||
 | 
					 "syn 2.0.96",
 | 
				
			||||||
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
name = "der"
 | 
					name = "der"
 | 
				
			||||||
version = "0.7.9"
 | 
					version = "0.7.9"
 | 
				
			||||||
@ -630,7 +677,7 @@ checksum = "cb7330aeadfbe296029522e6c40f315320aba36fc43a5b3632f3795348f3bd22"
 | 
				
			|||||||
dependencies = [
 | 
					dependencies = [
 | 
				
			||||||
 "proc-macro2",
 | 
					 "proc-macro2",
 | 
				
			||||||
 "quote",
 | 
					 "quote",
 | 
				
			||||||
 "syn 2.0.89",
 | 
					 "syn 2.0.96",
 | 
				
			||||||
 "unicode-xid",
 | 
					 "unicode-xid",
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -663,7 +710,7 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0"
 | 
				
			|||||||
dependencies = [
 | 
					dependencies = [
 | 
				
			||||||
 "proc-macro2",
 | 
					 "proc-macro2",
 | 
				
			||||||
 "quote",
 | 
					 "quote",
 | 
				
			||||||
 "syn 2.0.89",
 | 
					 "syn 2.0.96",
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
@ -760,6 +807,12 @@ version = "1.0.7"
 | 
				
			|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
 | 
					checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[[package]]
 | 
				
			||||||
 | 
					name = "foldhash"
 | 
				
			||||||
 | 
					version = "0.1.4"
 | 
				
			||||||
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
 | 
					checksum = "a0d2fde1f7b3d48b8395d5f2de76c18a528bd6a9cdde438df747bfcba3e05d6f"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
name = "form_urlencoded"
 | 
					name = "form_urlencoded"
 | 
				
			||||||
version = "1.2.1"
 | 
					version = "1.2.1"
 | 
				
			||||||
@ -836,7 +889,7 @@ checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650"
 | 
				
			|||||||
dependencies = [
 | 
					dependencies = [
 | 
				
			||||||
 "proc-macro2",
 | 
					 "proc-macro2",
 | 
				
			||||||
 "quote",
 | 
					 "quote",
 | 
				
			||||||
 "syn 2.0.89",
 | 
					 "syn 2.0.96",
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
@ -912,6 +965,7 @@ name = "gejdr-core"
 | 
				
			|||||||
version = "0.1.0"
 | 
					version = "0.1.0"
 | 
				
			||||||
dependencies = [
 | 
					dependencies = [
 | 
				
			||||||
 "chrono",
 | 
					 "chrono",
 | 
				
			||||||
 | 
					 "gejdr-macros",
 | 
				
			||||||
 "serde",
 | 
					 "serde",
 | 
				
			||||||
 "sqlx",
 | 
					 "sqlx",
 | 
				
			||||||
 "tracing",
 | 
					 "tracing",
 | 
				
			||||||
@ -919,6 +973,17 @@ dependencies = [
 | 
				
			|||||||
 "uuid",
 | 
					 "uuid",
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[[package]]
 | 
				
			||||||
 | 
					name = "gejdr-macros"
 | 
				
			||||||
 | 
					version = "0.1.0"
 | 
				
			||||||
 | 
					dependencies = [
 | 
				
			||||||
 | 
					 "deluxe",
 | 
				
			||||||
 | 
					 "proc-macro2",
 | 
				
			||||||
 | 
					 "quote",
 | 
				
			||||||
 | 
					 "sqlx",
 | 
				
			||||||
 | 
					 "syn 2.0.96",
 | 
				
			||||||
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
name = "generic-array"
 | 
					name = "generic-array"
 | 
				
			||||||
version = "0.14.7"
 | 
					version = "0.14.7"
 | 
				
			||||||
@ -1021,6 +1086,11 @@ name = "hashbrown"
 | 
				
			|||||||
version = "0.15.1"
 | 
					version = "0.15.1"
 | 
				
			||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
checksum = "3a9bfc1af68b1726ea47d3d5109de126281def866b33970e10fbab11b5dafab3"
 | 
					checksum = "3a9bfc1af68b1726ea47d3d5109de126281def866b33970e10fbab11b5dafab3"
 | 
				
			||||||
 | 
					dependencies = [
 | 
				
			||||||
 | 
					 "allocator-api2",
 | 
				
			||||||
 | 
					 "equivalent",
 | 
				
			||||||
 | 
					 "foldhash",
 | 
				
			||||||
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
name = "hashlink"
 | 
					name = "hashlink"
 | 
				
			||||||
@ -1033,11 +1103,11 @@ dependencies = [
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
name = "hashlink"
 | 
					name = "hashlink"
 | 
				
			||||||
version = "0.9.1"
 | 
					version = "0.10.0"
 | 
				
			||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
checksum = "6ba4ff7128dee98c7dc9794b6a411377e1404dba1c97deb8d1a55297bd25d8af"
 | 
					checksum = "7382cf6263419f2d8df38c55d7da83da5c18aef87fc7a7fc1fb1e344edfe14c1"
 | 
				
			||||||
dependencies = [
 | 
					dependencies = [
 | 
				
			||||||
 "hashbrown 0.14.5",
 | 
					 "hashbrown 0.15.1",
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
@ -1064,6 +1134,12 @@ dependencies = [
 | 
				
			|||||||
 "http 1.1.0",
 | 
					 "http 1.1.0",
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[[package]]
 | 
				
			||||||
 | 
					name = "heck"
 | 
				
			||||||
 | 
					version = "0.4.1"
 | 
				
			||||||
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
 | 
					checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
name = "heck"
 | 
					name = "heck"
 | 
				
			||||||
version = "0.5.0"
 | 
					version = "0.5.0"
 | 
				
			||||||
@ -1421,7 +1497,7 @@ checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6"
 | 
				
			|||||||
dependencies = [
 | 
					dependencies = [
 | 
				
			||||||
 "proc-macro2",
 | 
					 "proc-macro2",
 | 
				
			||||||
 "quote",
 | 
					 "quote",
 | 
				
			||||||
 "syn 2.0.89",
 | 
					 "syn 2.0.96",
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
@ -1451,6 +1527,12 @@ dependencies = [
 | 
				
			|||||||
 "icu_properties",
 | 
					 "icu_properties",
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[[package]]
 | 
				
			||||||
 | 
					name = "if_chain"
 | 
				
			||||||
 | 
					version = "1.0.2"
 | 
				
			||||||
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
 | 
					checksum = "cb56e1aa765b4b4f3aadfab769793b7087bb03a4ea4920644a6d238e2df5b9ed"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
name = "indexmap"
 | 
					name = "indexmap"
 | 
				
			||||||
version = "2.6.0"
 | 
					version = "2.6.0"
 | 
				
			||||||
@ -1529,7 +1611,6 @@ version = "0.30.1"
 | 
				
			|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
checksum = "2e99fb7a497b1e3339bc746195567ed8d3e24945ecd636e3619d20b9de9e9149"
 | 
					checksum = "2e99fb7a497b1e3339bc746195567ed8d3e24945ecd636e3619d20b9de9e9149"
 | 
				
			||||||
dependencies = [
 | 
					dependencies = [
 | 
				
			||||||
 "cc",
 | 
					 | 
				
			||||||
 "pkg-config",
 | 
					 "pkg-config",
 | 
				
			||||||
 "vcpkg",
 | 
					 "vcpkg",
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
@ -1809,12 +1890,6 @@ dependencies = [
 | 
				
			|||||||
 "windows-targets 0.52.6",
 | 
					 "windows-targets 0.52.6",
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					 | 
				
			||||||
name = "paste"
 | 
					 | 
				
			||||||
version = "1.0.15"
 | 
					 | 
				
			||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
					 | 
				
			||||||
checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
name = "pathdiff"
 | 
					name = "pathdiff"
 | 
				
			||||||
version = "0.2.2"
 | 
					version = "0.2.2"
 | 
				
			||||||
@ -1867,7 +1942,7 @@ dependencies = [
 | 
				
			|||||||
 "pest_meta",
 | 
					 "pest_meta",
 | 
				
			||||||
 "proc-macro2",
 | 
					 "proc-macro2",
 | 
				
			||||||
 "quote",
 | 
					 "quote",
 | 
				
			||||||
 "syn 2.0.89",
 | 
					 "syn 2.0.96",
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
@ -1994,10 +2069,10 @@ version = "3.1.4"
 | 
				
			|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
checksum = "7f2553c04acbd3887e2ad1959ff007fb9ec05d15d67931b6fdd6eb47de138649"
 | 
					checksum = "7f2553c04acbd3887e2ad1959ff007fb9ec05d15d67931b6fdd6eb47de138649"
 | 
				
			||||||
dependencies = [
 | 
					dependencies = [
 | 
				
			||||||
 "proc-macro-crate",
 | 
					 "proc-macro-crate 3.2.0",
 | 
				
			||||||
 "proc-macro2",
 | 
					 "proc-macro2",
 | 
				
			||||||
 "quote",
 | 
					 "quote",
 | 
				
			||||||
 "syn 2.0.89",
 | 
					 "syn 2.0.96",
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
@ -2037,11 +2112,11 @@ dependencies = [
 | 
				
			|||||||
 "http 1.1.0",
 | 
					 "http 1.1.0",
 | 
				
			||||||
 "indexmap",
 | 
					 "indexmap",
 | 
				
			||||||
 "mime",
 | 
					 "mime",
 | 
				
			||||||
 "proc-macro-crate",
 | 
					 "proc-macro-crate 3.2.0",
 | 
				
			||||||
 "proc-macro2",
 | 
					 "proc-macro2",
 | 
				
			||||||
 "quote",
 | 
					 "quote",
 | 
				
			||||||
 "regex",
 | 
					 "regex",
 | 
				
			||||||
 "syn 2.0.89",
 | 
					 "syn 2.0.96",
 | 
				
			||||||
 "thiserror 1.0.69",
 | 
					 "thiserror 1.0.69",
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -2106,20 +2181,30 @@ dependencies = [
 | 
				
			|||||||
 "indexmap",
 | 
					 "indexmap",
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[[package]]
 | 
				
			||||||
 | 
					name = "proc-macro-crate"
 | 
				
			||||||
 | 
					version = "1.3.1"
 | 
				
			||||||
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
 | 
					checksum = "7f4c021e1093a56626774e81216a4ce732a735e5bad4868a03f3ed65ca0c3919"
 | 
				
			||||||
 | 
					dependencies = [
 | 
				
			||||||
 | 
					 "once_cell",
 | 
				
			||||||
 | 
					 "toml_edit 0.19.15",
 | 
				
			||||||
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
name = "proc-macro-crate"
 | 
					name = "proc-macro-crate"
 | 
				
			||||||
version = "3.2.0"
 | 
					version = "3.2.0"
 | 
				
			||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
checksum = "8ecf48c7ca261d60b74ab1a7b20da18bede46776b2e55535cb958eb595c5fa7b"
 | 
					checksum = "8ecf48c7ca261d60b74ab1a7b20da18bede46776b2e55535cb958eb595c5fa7b"
 | 
				
			||||||
dependencies = [
 | 
					dependencies = [
 | 
				
			||||||
 "toml_edit",
 | 
					 "toml_edit 0.22.22",
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
name = "proc-macro2"
 | 
					name = "proc-macro2"
 | 
				
			||||||
version = "1.0.92"
 | 
					version = "1.0.93"
 | 
				
			||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0"
 | 
					checksum = "60946a68e5f9d28b0dc1c21bb8a97ee7d018a8b322fa57838ba31cc878e22d99"
 | 
				
			||||||
dependencies = [
 | 
					dependencies = [
 | 
				
			||||||
 "unicode-ident",
 | 
					 "unicode-ident",
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
@ -2188,9 +2273,9 @@ dependencies = [
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
name = "quote"
 | 
					name = "quote"
 | 
				
			||||||
version = "1.0.37"
 | 
					version = "1.0.38"
 | 
				
			||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af"
 | 
					checksum = "0e4dccaaaf89514f546c693ddc140f729f958c247918a13380cccc6078391acc"
 | 
				
			||||||
dependencies = [
 | 
					dependencies = [
 | 
				
			||||||
 "proc-macro2",
 | 
					 "proc-macro2",
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
@ -2581,7 +2666,7 @@ checksum = "ad1e866f866923f252f05c889987993144fb74e722403468a4ebd70c3cd756c0"
 | 
				
			|||||||
dependencies = [
 | 
					dependencies = [
 | 
				
			||||||
 "proc-macro2",
 | 
					 "proc-macro2",
 | 
				
			||||||
 "quote",
 | 
					 "quote",
 | 
				
			||||||
 "syn 2.0.89",
 | 
					 "syn 2.0.96",
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
@ -2747,21 +2832,11 @@ dependencies = [
 | 
				
			|||||||
 "der",
 | 
					 "der",
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					 | 
				
			||||||
name = "sqlformat"
 | 
					 | 
				
			||||||
version = "0.2.6"
 | 
					 | 
				
			||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
					 | 
				
			||||||
checksum = "7bba3a93db0cc4f7bdece8bb09e77e2e785c20bfebf79eb8340ed80708048790"
 | 
					 | 
				
			||||||
dependencies = [
 | 
					 | 
				
			||||||
 "nom",
 | 
					 | 
				
			||||||
 "unicode_categories",
 | 
					 | 
				
			||||||
]
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
name = "sqlx"
 | 
					name = "sqlx"
 | 
				
			||||||
version = "0.8.2"
 | 
					version = "0.8.3"
 | 
				
			||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
checksum = "93334716a037193fac19df402f8571269c84a00852f6a7066b5d2616dcd64d3e"
 | 
					checksum = "4410e73b3c0d8442c5f99b425d7a435b5ee0ae4167b3196771dd3f7a01be745f"
 | 
				
			||||||
dependencies = [
 | 
					dependencies = [
 | 
				
			||||||
 "sqlx-core",
 | 
					 "sqlx-core",
 | 
				
			||||||
 "sqlx-macros",
 | 
					 "sqlx-macros",
 | 
				
			||||||
@ -2772,38 +2847,32 @@ dependencies = [
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
name = "sqlx-core"
 | 
					name = "sqlx-core"
 | 
				
			||||||
version = "0.8.2"
 | 
					version = "0.8.3"
 | 
				
			||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
checksum = "d4d8060b456358185f7d50c55d9b5066ad956956fddec42ee2e8567134a8936e"
 | 
					checksum = "6a007b6936676aa9ab40207cde35daab0a04b823be8ae004368c0793b96a61e0"
 | 
				
			||||||
dependencies = [
 | 
					dependencies = [
 | 
				
			||||||
 "atoi",
 | 
					 | 
				
			||||||
 "byteorder",
 | 
					 | 
				
			||||||
 "bytes 1.8.0",
 | 
					 "bytes 1.8.0",
 | 
				
			||||||
 "chrono",
 | 
					 "chrono",
 | 
				
			||||||
 "crc",
 | 
					 "crc",
 | 
				
			||||||
 "crossbeam-queue",
 | 
					 "crossbeam-queue",
 | 
				
			||||||
 "either",
 | 
					 "either",
 | 
				
			||||||
 "event-listener",
 | 
					 "event-listener",
 | 
				
			||||||
 "futures-channel",
 | 
					 | 
				
			||||||
 "futures-core",
 | 
					 "futures-core",
 | 
				
			||||||
 "futures-intrusive",
 | 
					 "futures-intrusive",
 | 
				
			||||||
 "futures-io",
 | 
					 "futures-io",
 | 
				
			||||||
 "futures-util",
 | 
					 "futures-util",
 | 
				
			||||||
 "hashbrown 0.14.5",
 | 
					 "hashbrown 0.15.1",
 | 
				
			||||||
 "hashlink 0.9.1",
 | 
					 "hashlink 0.10.0",
 | 
				
			||||||
 "hex",
 | 
					 | 
				
			||||||
 "indexmap",
 | 
					 "indexmap",
 | 
				
			||||||
 "log",
 | 
					 "log",
 | 
				
			||||||
 "memchr",
 | 
					 "memchr",
 | 
				
			||||||
 "once_cell",
 | 
					 "once_cell",
 | 
				
			||||||
 "paste",
 | 
					 | 
				
			||||||
 "percent-encoding",
 | 
					 "percent-encoding",
 | 
				
			||||||
 "serde",
 | 
					 "serde",
 | 
				
			||||||
 "serde_json",
 | 
					 "serde_json",
 | 
				
			||||||
 "sha2 0.10.8",
 | 
					 "sha2 0.10.8",
 | 
				
			||||||
 "smallvec",
 | 
					 "smallvec",
 | 
				
			||||||
 "sqlformat",
 | 
					 "thiserror 2.0.3",
 | 
				
			||||||
 "thiserror 1.0.69",
 | 
					 | 
				
			||||||
 "tokio",
 | 
					 "tokio",
 | 
				
			||||||
 "tokio-stream",
 | 
					 "tokio-stream",
 | 
				
			||||||
 "tracing",
 | 
					 "tracing",
 | 
				
			||||||
@ -2813,26 +2882,26 @@ dependencies = [
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
name = "sqlx-macros"
 | 
					name = "sqlx-macros"
 | 
				
			||||||
version = "0.8.2"
 | 
					version = "0.8.3"
 | 
				
			||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
checksum = "cac0692bcc9de3b073e8d747391827297e075c7710ff6276d9f7a1f3d58c6657"
 | 
					checksum = "3112e2ad78643fef903618d78cf0aec1cb3134b019730edb039b69eaf531f310"
 | 
				
			||||||
dependencies = [
 | 
					dependencies = [
 | 
				
			||||||
 "proc-macro2",
 | 
					 "proc-macro2",
 | 
				
			||||||
 "quote",
 | 
					 "quote",
 | 
				
			||||||
 "sqlx-core",
 | 
					 "sqlx-core",
 | 
				
			||||||
 "sqlx-macros-core",
 | 
					 "sqlx-macros-core",
 | 
				
			||||||
 "syn 2.0.89",
 | 
					 "syn 2.0.96",
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
name = "sqlx-macros-core"
 | 
					name = "sqlx-macros-core"
 | 
				
			||||||
version = "0.8.2"
 | 
					version = "0.8.3"
 | 
				
			||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
checksum = "1804e8a7c7865599c9c79be146dc8a9fd8cc86935fa641d3ea58e5f0688abaa5"
 | 
					checksum = "4e9f90acc5ab146a99bf5061a7eb4976b573f560bc898ef3bf8435448dd5e7ad"
 | 
				
			||||||
dependencies = [
 | 
					dependencies = [
 | 
				
			||||||
 "dotenvy",
 | 
					 "dotenvy",
 | 
				
			||||||
 "either",
 | 
					 "either",
 | 
				
			||||||
 "heck",
 | 
					 "heck 0.5.0",
 | 
				
			||||||
 "hex",
 | 
					 "hex",
 | 
				
			||||||
 "once_cell",
 | 
					 "once_cell",
 | 
				
			||||||
 "proc-macro2",
 | 
					 "proc-macro2",
 | 
				
			||||||
@ -2844,7 +2913,7 @@ dependencies = [
 | 
				
			|||||||
 "sqlx-mysql",
 | 
					 "sqlx-mysql",
 | 
				
			||||||
 "sqlx-postgres",
 | 
					 "sqlx-postgres",
 | 
				
			||||||
 "sqlx-sqlite",
 | 
					 "sqlx-sqlite",
 | 
				
			||||||
 "syn 2.0.89",
 | 
					 "syn 2.0.96",
 | 
				
			||||||
 "tempfile",
 | 
					 "tempfile",
 | 
				
			||||||
 "tokio",
 | 
					 "tokio",
 | 
				
			||||||
 "url",
 | 
					 "url",
 | 
				
			||||||
@ -2852,9 +2921,9 @@ dependencies = [
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
name = "sqlx-mysql"
 | 
					name = "sqlx-mysql"
 | 
				
			||||||
version = "0.8.2"
 | 
					version = "0.8.3"
 | 
				
			||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
checksum = "64bb4714269afa44aef2755150a0fc19d756fb580a67db8885608cf02f47d06a"
 | 
					checksum = "4560278f0e00ce64938540546f59f590d60beee33fffbd3b9cd47851e5fff233"
 | 
				
			||||||
dependencies = [
 | 
					dependencies = [
 | 
				
			||||||
 "atoi",
 | 
					 "atoi",
 | 
				
			||||||
 "base64 0.22.1",
 | 
					 "base64 0.22.1",
 | 
				
			||||||
@ -2888,7 +2957,7 @@ dependencies = [
 | 
				
			|||||||
 "smallvec",
 | 
					 "smallvec",
 | 
				
			||||||
 "sqlx-core",
 | 
					 "sqlx-core",
 | 
				
			||||||
 "stringprep",
 | 
					 "stringprep",
 | 
				
			||||||
 "thiserror 1.0.69",
 | 
					 "thiserror 2.0.3",
 | 
				
			||||||
 "tracing",
 | 
					 "tracing",
 | 
				
			||||||
 "uuid",
 | 
					 "uuid",
 | 
				
			||||||
 "whoami",
 | 
					 "whoami",
 | 
				
			||||||
@ -2896,9 +2965,9 @@ dependencies = [
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
name = "sqlx-postgres"
 | 
					name = "sqlx-postgres"
 | 
				
			||||||
version = "0.8.2"
 | 
					version = "0.8.3"
 | 
				
			||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
checksum = "6fa91a732d854c5d7726349bb4bb879bb9478993ceb764247660aee25f67c2f8"
 | 
					checksum = "c5b98a57f363ed6764d5b3a12bfedf62f07aa16e1856a7ddc2a0bb190a959613"
 | 
				
			||||||
dependencies = [
 | 
					dependencies = [
 | 
				
			||||||
 "atoi",
 | 
					 "atoi",
 | 
				
			||||||
 "base64 0.22.1",
 | 
					 "base64 0.22.1",
 | 
				
			||||||
@ -2910,7 +2979,6 @@ dependencies = [
 | 
				
			|||||||
 "etcetera",
 | 
					 "etcetera",
 | 
				
			||||||
 "futures-channel",
 | 
					 "futures-channel",
 | 
				
			||||||
 "futures-core",
 | 
					 "futures-core",
 | 
				
			||||||
 "futures-io",
 | 
					 | 
				
			||||||
 "futures-util",
 | 
					 "futures-util",
 | 
				
			||||||
 "hex",
 | 
					 "hex",
 | 
				
			||||||
 "hkdf",
 | 
					 "hkdf",
 | 
				
			||||||
@ -2928,7 +2996,7 @@ dependencies = [
 | 
				
			|||||||
 "smallvec",
 | 
					 "smallvec",
 | 
				
			||||||
 "sqlx-core",
 | 
					 "sqlx-core",
 | 
				
			||||||
 "stringprep",
 | 
					 "stringprep",
 | 
				
			||||||
 "thiserror 1.0.69",
 | 
					 "thiserror 2.0.3",
 | 
				
			||||||
 "tracing",
 | 
					 "tracing",
 | 
				
			||||||
 "uuid",
 | 
					 "uuid",
 | 
				
			||||||
 "whoami",
 | 
					 "whoami",
 | 
				
			||||||
@ -2936,9 +3004,9 @@ dependencies = [
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
name = "sqlx-sqlite"
 | 
					name = "sqlx-sqlite"
 | 
				
			||||||
version = "0.8.2"
 | 
					version = "0.8.3"
 | 
				
			||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
checksum = "d5b2cf34a45953bfd3daaf3db0f7a7878ab9b7a6b91b422d24a7a9e4c857b680"
 | 
					checksum = "f85ca71d3a5b24e64e1d08dd8fe36c6c95c339a896cc33068148906784620540"
 | 
				
			||||||
dependencies = [
 | 
					dependencies = [
 | 
				
			||||||
 "atoi",
 | 
					 "atoi",
 | 
				
			||||||
 "chrono",
 | 
					 "chrono",
 | 
				
			||||||
@ -2988,6 +3056,12 @@ dependencies = [
 | 
				
			|||||||
 "unicode-properties",
 | 
					 "unicode-properties",
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[[package]]
 | 
				
			||||||
 | 
					name = "strsim"
 | 
				
			||||||
 | 
					version = "0.10.0"
 | 
				
			||||||
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
 | 
					checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
name = "strsim"
 | 
					name = "strsim"
 | 
				
			||||||
version = "0.11.1"
 | 
					version = "0.11.1"
 | 
				
			||||||
@ -3013,9 +3087,9 @@ dependencies = [
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
name = "syn"
 | 
					name = "syn"
 | 
				
			||||||
version = "2.0.89"
 | 
					version = "2.0.96"
 | 
				
			||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
checksum = "44d46482f1c1c87acd84dea20c1bf5ebff4c757009ed6bf19cfd36fb10e92c4e"
 | 
					checksum = "d5d0adab1ae378d7f53bdebc67a39f1f151407ef230f0ce2883572f5d8985c80"
 | 
				
			||||||
dependencies = [
 | 
					dependencies = [
 | 
				
			||||||
 "proc-macro2",
 | 
					 "proc-macro2",
 | 
				
			||||||
 "quote",
 | 
					 "quote",
 | 
				
			||||||
@ -3045,7 +3119,7 @@ checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971"
 | 
				
			|||||||
dependencies = [
 | 
					dependencies = [
 | 
				
			||||||
 "proc-macro2",
 | 
					 "proc-macro2",
 | 
				
			||||||
 "quote",
 | 
					 "quote",
 | 
				
			||||||
 "syn 2.0.89",
 | 
					 "syn 2.0.96",
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
@ -3108,7 +3182,7 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1"
 | 
				
			|||||||
dependencies = [
 | 
					dependencies = [
 | 
				
			||||||
 "proc-macro2",
 | 
					 "proc-macro2",
 | 
				
			||||||
 "quote",
 | 
					 "quote",
 | 
				
			||||||
 "syn 2.0.89",
 | 
					 "syn 2.0.96",
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
@ -3119,7 +3193,7 @@ checksum = "f077553d607adc1caf65430528a576c757a71ed73944b66ebb58ef2bbd243568"
 | 
				
			|||||||
dependencies = [
 | 
					dependencies = [
 | 
				
			||||||
 "proc-macro2",
 | 
					 "proc-macro2",
 | 
				
			||||||
 "quote",
 | 
					 "quote",
 | 
				
			||||||
 "syn 2.0.89",
 | 
					 "syn 2.0.96",
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
@ -3221,7 +3295,7 @@ checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752"
 | 
				
			|||||||
dependencies = [
 | 
					dependencies = [
 | 
				
			||||||
 "proc-macro2",
 | 
					 "proc-macro2",
 | 
				
			||||||
 "quote",
 | 
					 "quote",
 | 
				
			||||||
 "syn 2.0.89",
 | 
					 "syn 2.0.96",
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
@ -3290,7 +3364,7 @@ dependencies = [
 | 
				
			|||||||
 "serde",
 | 
					 "serde",
 | 
				
			||||||
 "serde_spanned",
 | 
					 "serde_spanned",
 | 
				
			||||||
 "toml_datetime",
 | 
					 "toml_datetime",
 | 
				
			||||||
 "toml_edit",
 | 
					 "toml_edit 0.22.22",
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
@ -3302,6 +3376,17 @@ dependencies = [
 | 
				
			|||||||
 "serde",
 | 
					 "serde",
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[[package]]
 | 
				
			||||||
 | 
					name = "toml_edit"
 | 
				
			||||||
 | 
					version = "0.19.15"
 | 
				
			||||||
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
 | 
					checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421"
 | 
				
			||||||
 | 
					dependencies = [
 | 
				
			||||||
 | 
					 "indexmap",
 | 
				
			||||||
 | 
					 "toml_datetime",
 | 
				
			||||||
 | 
					 "winnow 0.5.40",
 | 
				
			||||||
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
name = "toml_edit"
 | 
					name = "toml_edit"
 | 
				
			||||||
version = "0.22.22"
 | 
					version = "0.22.22"
 | 
				
			||||||
@ -3312,7 +3397,7 @@ dependencies = [
 | 
				
			|||||||
 "serde",
 | 
					 "serde",
 | 
				
			||||||
 "serde_spanned",
 | 
					 "serde_spanned",
 | 
				
			||||||
 "toml_datetime",
 | 
					 "toml_datetime",
 | 
				
			||||||
 "winnow",
 | 
					 "winnow 0.6.20",
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
@ -3341,7 +3426,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7"
 | 
				
			|||||||
dependencies = [
 | 
					dependencies = [
 | 
				
			||||||
 "proc-macro2",
 | 
					 "proc-macro2",
 | 
				
			||||||
 "quote",
 | 
					 "quote",
 | 
				
			||||||
 "syn 2.0.89",
 | 
					 "syn 2.0.96",
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
@ -3462,12 +3547,6 @@ version = "0.2.6"
 | 
				
			|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853"
 | 
					checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					 | 
				
			||||||
name = "unicode_categories"
 | 
					 | 
				
			||||||
version = "0.1.1"
 | 
					 | 
				
			||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
					 | 
				
			||||||
checksum = "39ec24b3121d976906ece63c9daad25b85969647682eee313cb5779fdd69e14e"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
name = "universal-hash"
 | 
					name = "universal-hash"
 | 
				
			||||||
version = "0.4.0"
 | 
					version = "0.4.0"
 | 
				
			||||||
@ -3526,9 +3605,9 @@ checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be"
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
name = "uuid"
 | 
					name = "uuid"
 | 
				
			||||||
version = "1.11.0"
 | 
					version = "1.12.0"
 | 
				
			||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
checksum = "f8c5f0a0af699448548ad1a2fbf920fb4bee257eae39953ba95cb84891a0446a"
 | 
					checksum = "744018581f9a3454a9e15beb8a33b017183f1e7c0cd170232a2d1453b23a51c4"
 | 
				
			||||||
dependencies = [
 | 
					dependencies = [
 | 
				
			||||||
 "getrandom",
 | 
					 "getrandom",
 | 
				
			||||||
 "serde",
 | 
					 "serde",
 | 
				
			||||||
@ -3595,7 +3674,7 @@ dependencies = [
 | 
				
			|||||||
 "once_cell",
 | 
					 "once_cell",
 | 
				
			||||||
 "proc-macro2",
 | 
					 "proc-macro2",
 | 
				
			||||||
 "quote",
 | 
					 "quote",
 | 
				
			||||||
 "syn 2.0.89",
 | 
					 "syn 2.0.96",
 | 
				
			||||||
 "wasm-bindgen-shared",
 | 
					 "wasm-bindgen-shared",
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -3629,7 +3708,7 @@ checksum = "26c6ab57572f7a24a4985830b120de1594465e5d500f24afe89e16b4e833ef68"
 | 
				
			|||||||
dependencies = [
 | 
					dependencies = [
 | 
				
			||||||
 "proc-macro2",
 | 
					 "proc-macro2",
 | 
				
			||||||
 "quote",
 | 
					 "quote",
 | 
				
			||||||
 "syn 2.0.89",
 | 
					 "syn 2.0.96",
 | 
				
			||||||
 "wasm-bindgen-backend",
 | 
					 "wasm-bindgen-backend",
 | 
				
			||||||
 "wasm-bindgen-shared",
 | 
					 "wasm-bindgen-shared",
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
@ -3900,6 +3979,15 @@ version = "0.52.6"
 | 
				
			|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
 | 
					checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[[package]]
 | 
				
			||||||
 | 
					name = "winnow"
 | 
				
			||||||
 | 
					version = "0.5.40"
 | 
				
			||||||
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
 | 
					checksum = "f593a95398737aeed53e489c785df13f3618e41dbcd6718c6addbf1395aa6876"
 | 
				
			||||||
 | 
					dependencies = [
 | 
				
			||||||
 | 
					 "memchr",
 | 
				
			||||||
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
name = "winnow"
 | 
					name = "winnow"
 | 
				
			||||||
version = "0.6.20"
 | 
					version = "0.6.20"
 | 
				
			||||||
@ -3962,7 +4050,7 @@ checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154"
 | 
				
			|||||||
dependencies = [
 | 
					dependencies = [
 | 
				
			||||||
 "proc-macro2",
 | 
					 "proc-macro2",
 | 
				
			||||||
 "quote",
 | 
					 "quote",
 | 
				
			||||||
 "syn 2.0.89",
 | 
					 "syn 2.0.96",
 | 
				
			||||||
 "synstructure",
 | 
					 "synstructure",
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -3984,7 +4072,7 @@ checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e"
 | 
				
			|||||||
dependencies = [
 | 
					dependencies = [
 | 
				
			||||||
 "proc-macro2",
 | 
					 "proc-macro2",
 | 
				
			||||||
 "quote",
 | 
					 "quote",
 | 
				
			||||||
 "syn 2.0.89",
 | 
					 "syn 2.0.96",
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
@ -4004,7 +4092,7 @@ checksum = "595eed982f7d355beb85837f651fa22e90b3c044842dc7f2c2842c086f295808"
 | 
				
			|||||||
dependencies = [
 | 
					dependencies = [
 | 
				
			||||||
 "proc-macro2",
 | 
					 "proc-macro2",
 | 
				
			||||||
 "quote",
 | 
					 "quote",
 | 
				
			||||||
 "syn 2.0.89",
 | 
					 "syn 2.0.96",
 | 
				
			||||||
 "synstructure",
 | 
					 "synstructure",
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -4033,5 +4121,5 @@ checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6"
 | 
				
			|||||||
dependencies = [
 | 
					dependencies = [
 | 
				
			||||||
 "proc-macro2",
 | 
					 "proc-macro2",
 | 
				
			||||||
 "quote",
 | 
					 "quote",
 | 
				
			||||||
 "syn 2.0.89",
 | 
					 "syn 2.0.96",
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
 | 
				
			|||||||
@ -4,5 +4,6 @@ members = [
 | 
				
			|||||||
  "gejdr-core",
 | 
					  "gejdr-core",
 | 
				
			||||||
  "gejdr-bot",
 | 
					  "gejdr-bot",
 | 
				
			||||||
  "gejdr-backend",
 | 
					  "gejdr-backend",
 | 
				
			||||||
 | 
					  "gejdr-macros"
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
resolver = "2"
 | 
					resolver = "2"
 | 
				
			||||||
 | 
				
			|||||||
@ -9,8 +9,9 @@ serde = "1.0.215"
 | 
				
			|||||||
tracing = "0.1.40"
 | 
					tracing = "0.1.40"
 | 
				
			||||||
tracing-subscriber = { version = "0.3.18", features = ["fmt", "std", "env-filter", "registry", "json", "tracing-log"] }
 | 
					tracing-subscriber = { version = "0.3.18", features = ["fmt", "std", "env-filter", "registry", "json", "tracing-log"] }
 | 
				
			||||||
uuid = { version = "1.11.0", features = ["v4", "serde"] }
 | 
					uuid = { version = "1.11.0", features = ["v4", "serde"] }
 | 
				
			||||||
 | 
					gejdr-macros = { path = "../gejdr-macros" }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[dependencies.sqlx]
 | 
					[dependencies.sqlx]
 | 
				
			||||||
version = "0.8.2"
 | 
					version = "0.8.3"
 | 
				
			||||||
default-features = false
 | 
					default-features = false
 | 
				
			||||||
features = ["postgres", "uuid", "chrono", "migrate", "runtime-tokio", "macros"]
 | 
					features = ["postgres", "uuid", "chrono", "migrate", "runtime-tokio", "macros"]
 | 
				
			||||||
 | 
				
			|||||||
@ -1,3 +1,4 @@
 | 
				
			|||||||
 | 
					use super::Crud;
 | 
				
			||||||
use sqlx::PgPool;
 | 
					use sqlx::PgPool;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type Timestampz = chrono::DateTime<chrono::Utc>;
 | 
					type Timestampz = chrono::DateTime<chrono::Utc>;
 | 
				
			||||||
@ -17,13 +18,15 @@ impl RemoteUser {
 | 
				
			|||||||
    pub async fn refresh_in_database(self, pool: &PgPool) -> Result<User, sqlx::Error> {
 | 
					    pub async fn refresh_in_database(self, pool: &PgPool) -> Result<User, sqlx::Error> {
 | 
				
			||||||
        match User::find(pool, &self.id).await? {
 | 
					        match User::find(pool, &self.id).await? {
 | 
				
			||||||
            Some(local_user) => local_user.update_from_remote(self).update(pool).await,
 | 
					            Some(local_user) => local_user.update_from_remote(self).update(pool).await,
 | 
				
			||||||
            None => User::from(self).save(pool).await,
 | 
					            None => User::from(self).create(pool).await,
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[derive(serde::Deserialize, serde::Serialize, Debug, PartialEq, Eq, Default, Clone)]
 | 
					#[derive(serde::Deserialize, serde::Serialize, Debug, PartialEq, Eq, Default, Clone, Crud)]
 | 
				
			||||||
 | 
					#[crud(table = "users")]
 | 
				
			||||||
pub struct User {
 | 
					pub struct User {
 | 
				
			||||||
 | 
					    #[crud(id)]
 | 
				
			||||||
    pub id: String,
 | 
					    pub id: String,
 | 
				
			||||||
    pub username: String,
 | 
					    pub username: String,
 | 
				
			||||||
    pub email: Option<String>,
 | 
					    pub email: Option<String>,
 | 
				
			||||||
@ -79,68 +82,6 @@ impl User {
 | 
				
			|||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					 | 
				
			||||||
    pub async fn find(pool: &PgPool, id: &String) -> Result<Option<Self>, sqlx::Error> {
 | 
					 | 
				
			||||||
        sqlx::query_as!(Self, r#"SELECT * FROM users WHERE id = $1"#, id)
 | 
					 | 
				
			||||||
            .fetch_optional(pool)
 | 
					 | 
				
			||||||
            .await
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    pub async fn save(&self, pool: &PgPool) -> Result<Self, sqlx::Error> {
 | 
					 | 
				
			||||||
        sqlx::query_as!(
 | 
					 | 
				
			||||||
            Self,
 | 
					 | 
				
			||||||
            r#"
 | 
					 | 
				
			||||||
INSERT INTO users (id, username, email, avatar, name, created_at, last_updated)
 | 
					 | 
				
			||||||
VALUES ($1, $2, $3, $4, $5, $6, $7)
 | 
					 | 
				
			||||||
RETURNING *
 | 
					 | 
				
			||||||
"#,
 | 
					 | 
				
			||||||
            self.id,
 | 
					 | 
				
			||||||
            self.username,
 | 
					 | 
				
			||||||
            self.email,
 | 
					 | 
				
			||||||
            self.avatar,
 | 
					 | 
				
			||||||
            self.name,
 | 
					 | 
				
			||||||
            self.created_at,
 | 
					 | 
				
			||||||
            self.last_updated
 | 
					 | 
				
			||||||
        )
 | 
					 | 
				
			||||||
        .fetch_one(pool)
 | 
					 | 
				
			||||||
        .await
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    pub async fn update(&self, pool: &PgPool) -> Result<Self, sqlx::Error> {
 | 
					 | 
				
			||||||
        sqlx::query_as!(
 | 
					 | 
				
			||||||
            Self,
 | 
					 | 
				
			||||||
            r#"
 | 
					 | 
				
			||||||
UPDATE users
 | 
					 | 
				
			||||||
SET username = $1, email = $2, avatar = $3, name = $4, last_updated = $5
 | 
					 | 
				
			||||||
WHERE id = $6
 | 
					 | 
				
			||||||
RETURNING *
 | 
					 | 
				
			||||||
"#,
 | 
					 | 
				
			||||||
            self.username,
 | 
					 | 
				
			||||||
            self.email,
 | 
					 | 
				
			||||||
            self.avatar,
 | 
					 | 
				
			||||||
            self.name,
 | 
					 | 
				
			||||||
            self.last_updated,
 | 
					 | 
				
			||||||
            self.id
 | 
					 | 
				
			||||||
        )
 | 
					 | 
				
			||||||
        .fetch_one(pool)
 | 
					 | 
				
			||||||
        .await
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    pub async fn save_or_update(&self, pool: &PgPool) -> Result<Self, sqlx::Error> {
 | 
					 | 
				
			||||||
        if Self::find(pool, &self.id).await?.is_some() {
 | 
					 | 
				
			||||||
            self.update(pool).await
 | 
					 | 
				
			||||||
        } else {
 | 
					 | 
				
			||||||
            self.save(pool).await
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    pub async fn delete(pool: &PgPool, id: &String) -> Result<u64, sqlx::Error> {
 | 
					 | 
				
			||||||
        let rows_affected = sqlx::query!("DELETE FROM users WHERE id = $1", id)
 | 
					 | 
				
			||||||
            .execute(pool)
 | 
					 | 
				
			||||||
            .await?
 | 
					 | 
				
			||||||
            .rows_affected();
 | 
					 | 
				
			||||||
        Ok(rows_affected)
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[cfg(test)]
 | 
					#[cfg(test)]
 | 
				
			||||||
@ -287,7 +228,7 @@ mod tests {
 | 
				
			|||||||
            username: "user1".into(),
 | 
					            username: "user1".into(),
 | 
				
			||||||
            ..Default::default()
 | 
					            ..Default::default()
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
        user.save(&pool).await?;
 | 
					        user.create(&pool).await?;
 | 
				
			||||||
        let users = sqlx::query_as!(User, "SELECT * FROM users")
 | 
					        let users = sqlx::query_as!(User, "SELECT * FROM users")
 | 
				
			||||||
            .fetch_all(&pool)
 | 
					            .fetch_all(&pool)
 | 
				
			||||||
            .await?;
 | 
					            .await?;
 | 
				
			||||||
@ -328,7 +269,7 @@ mod tests {
 | 
				
			|||||||
            username: "user1".into(),
 | 
					            username: "user1".into(),
 | 
				
			||||||
            ..Default::default()
 | 
					            ..Default::default()
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
        user.save_or_update(&pool).await?;
 | 
					        user.create_or_update(&pool).await?;
 | 
				
			||||||
        let rows = sqlx::query_as!(User, "SELECT * FROM users")
 | 
					        let rows = sqlx::query_as!(User, "SELECT * FROM users")
 | 
				
			||||||
            .fetch_all(&pool)
 | 
					            .fetch_all(&pool)
 | 
				
			||||||
            .await?;
 | 
					            .await?;
 | 
				
			||||||
@ -350,7 +291,7 @@ mod tests {
 | 
				
			|||||||
            name: Some("Cool Nam".into()),
 | 
					            name: Some("Cool Nam".into()),
 | 
				
			||||||
            ..Default::default()
 | 
					            ..Default::default()
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
        user.save_or_update(&pool).await?;
 | 
					        user.create_or_update(&pool).await?;
 | 
				
			||||||
        let rows = sqlx::query_as!(User, "SELECT * FROM users")
 | 
					        let rows = sqlx::query_as!(User, "SELECT * FROM users")
 | 
				
			||||||
            .fetch_all(&pool)
 | 
					            .fetch_all(&pool)
 | 
				
			||||||
            .await?;
 | 
					            .await?;
 | 
				
			||||||
@ -369,7 +310,7 @@ mod tests {
 | 
				
			|||||||
            .await?;
 | 
					            .await?;
 | 
				
			||||||
        assert_eq!(2, rows.len());
 | 
					        assert_eq!(2, rows.len());
 | 
				
			||||||
        let id = "id1".to_string();
 | 
					        let id = "id1".to_string();
 | 
				
			||||||
        let deletions = User::delete(&pool, &id).await?;
 | 
					        let deletions = User::delete_by_id(&pool, &id).await?;
 | 
				
			||||||
        assert_eq!(1, deletions);
 | 
					        assert_eq!(1, deletions);
 | 
				
			||||||
        let rows = sqlx::query_as!(User, "SELECT * FROM users")
 | 
					        let rows = sqlx::query_as!(User, "SELECT * FROM users")
 | 
				
			||||||
            .fetch_all(&pool)
 | 
					            .fetch_all(&pool)
 | 
				
			||||||
@ -385,7 +326,7 @@ mod tests {
 | 
				
			|||||||
            .await?;
 | 
					            .await?;
 | 
				
			||||||
        assert_eq!(2, rows.len());
 | 
					        assert_eq!(2, rows.len());
 | 
				
			||||||
        let id = "invalid".to_string();
 | 
					        let id = "invalid".to_string();
 | 
				
			||||||
        let deletions = User::delete(&pool, &id).await?;
 | 
					        let deletions = User::delete_by_id(&pool, &id).await?;
 | 
				
			||||||
        assert_eq!(0, deletions);
 | 
					        assert_eq!(0, deletions);
 | 
				
			||||||
        let rows = sqlx::query_as!(User, "SELECT * FROM users")
 | 
					        let rows = sqlx::query_as!(User, "SELECT * FROM users")
 | 
				
			||||||
            .fetch_all(&pool)
 | 
					            .fetch_all(&pool)
 | 
				
			||||||
 | 
				
			|||||||
@ -1 +1,73 @@
 | 
				
			|||||||
pub mod accounts;
 | 
					pub mod accounts;
 | 
				
			||||||
 | 
					pub use gejdr_macros::Crud;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pub trait Crud<Id> {
 | 
				
			||||||
 | 
					    /// Find the entiy in the database based on its identifier.
 | 
				
			||||||
 | 
					    ///
 | 
				
			||||||
 | 
					    /// # Errors
 | 
				
			||||||
 | 
					    /// Returns any error Postgres may have encountered
 | 
				
			||||||
 | 
					    fn find(
 | 
				
			||||||
 | 
					        pool: &sqlx::PgPool,
 | 
				
			||||||
 | 
					        id: &Id,
 | 
				
			||||||
 | 
					    ) -> impl std::future::Future<Output = sqlx::Result<Option<Self>>> + Send
 | 
				
			||||||
 | 
					    where
 | 
				
			||||||
 | 
					        Self: Sized;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// Create the entity in the database.
 | 
				
			||||||
 | 
					    ///
 | 
				
			||||||
 | 
					    /// # Errors
 | 
				
			||||||
 | 
					    /// Returns any error Postgres may have encountered
 | 
				
			||||||
 | 
					    fn create(
 | 
				
			||||||
 | 
					        &self,
 | 
				
			||||||
 | 
					        pool: &sqlx::PgPool,
 | 
				
			||||||
 | 
					    ) -> impl std::future::Future<Output = sqlx::Result<Self>> + Send
 | 
				
			||||||
 | 
					    where
 | 
				
			||||||
 | 
					        Self: Sized;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// Update an entity with a matching identifier in the database.
 | 
				
			||||||
 | 
					    ///
 | 
				
			||||||
 | 
					    /// # Errors
 | 
				
			||||||
 | 
					    /// Returns any error Postgres may have encountered
 | 
				
			||||||
 | 
					    fn update(
 | 
				
			||||||
 | 
					        &self,
 | 
				
			||||||
 | 
					        pool: &sqlx::PgPool,
 | 
				
			||||||
 | 
					    ) -> impl std::future::Future<Output = sqlx::Result<Self>> + Send
 | 
				
			||||||
 | 
					    where
 | 
				
			||||||
 | 
					        Self: Sized;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// Update an entity with a matching identifier in the database if
 | 
				
			||||||
 | 
					    /// it exists, create it otherwise.
 | 
				
			||||||
 | 
					    ///
 | 
				
			||||||
 | 
					    /// # Errors
 | 
				
			||||||
 | 
					    /// Returns any error Postgres may have encountered
 | 
				
			||||||
 | 
					    fn create_or_update(
 | 
				
			||||||
 | 
					        &self,
 | 
				
			||||||
 | 
					        pool: &sqlx::PgPool,
 | 
				
			||||||
 | 
					    ) -> impl std::future::Future<Output = sqlx::Result<Self>> + Send
 | 
				
			||||||
 | 
					    where
 | 
				
			||||||
 | 
					        Self: Sized;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// Delete the entity from the database if it exists.
 | 
				
			||||||
 | 
					    ///
 | 
				
			||||||
 | 
					    /// # Returns
 | 
				
			||||||
 | 
					    /// Returns the amount of rows affected by the deletion.
 | 
				
			||||||
 | 
					    ///
 | 
				
			||||||
 | 
					    /// # Errors
 | 
				
			||||||
 | 
					    /// Returns any error Postgres may have encountered
 | 
				
			||||||
 | 
					    fn delete(
 | 
				
			||||||
 | 
					        &self,
 | 
				
			||||||
 | 
					        pool: &sqlx::PgPool,
 | 
				
			||||||
 | 
					    ) -> impl std::future::Future<Output = sqlx::Result<u64>> + Send;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// Delete any entity with the identifier `id`.
 | 
				
			||||||
 | 
					    ///
 | 
				
			||||||
 | 
					    /// # Returns
 | 
				
			||||||
 | 
					    /// Returns the amount of rows affected by the deletion.
 | 
				
			||||||
 | 
					    ///
 | 
				
			||||||
 | 
					    /// # Errors
 | 
				
			||||||
 | 
					    /// Returns any error Postgres may have encountered
 | 
				
			||||||
 | 
					    fn delete_by_id(
 | 
				
			||||||
 | 
					        pool: &sqlx::PgPool,
 | 
				
			||||||
 | 
					        id: &Id,
 | 
				
			||||||
 | 
					    ) -> impl std::future::Future<Output = sqlx::Result<u64>> + Send;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										18
									
								
								gejdr-macros/Cargo.toml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								gejdr-macros/Cargo.toml
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,18 @@
 | 
				
			|||||||
 | 
					[package]
 | 
				
			||||||
 | 
					name = "gejdr-macros"
 | 
				
			||||||
 | 
					version = "0.1.0"
 | 
				
			||||||
 | 
					edition = "2021"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[lib]
 | 
				
			||||||
 | 
					proc-macro = true
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[dependencies]
 | 
				
			||||||
 | 
					deluxe = "0.5.0"
 | 
				
			||||||
 | 
					proc-macro2 = "1.0.93"
 | 
				
			||||||
 | 
					quote = "1.0.38"
 | 
				
			||||||
 | 
					syn = "2.0.96"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[dependencies.sqlx]
 | 
				
			||||||
 | 
					version = "0.8.3"
 | 
				
			||||||
 | 
					default-features = false
 | 
				
			||||||
 | 
					features = ["postgres", "uuid", "chrono", "migrate", "runtime-tokio", "macros"]
 | 
				
			||||||
							
								
								
									
										23
									
								
								gejdr-macros/src/crud/ir.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								gejdr-macros/src/crud/ir.rs
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,23 @@
 | 
				
			|||||||
 | 
					#[derive(deluxe::ExtractAttributes)]
 | 
				
			||||||
 | 
					#[deluxe(attributes(crud))]
 | 
				
			||||||
 | 
					pub struct CrudStructAttributes {
 | 
				
			||||||
 | 
					    pub table: String,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[derive(deluxe::ExtractAttributes, Clone)]
 | 
				
			||||||
 | 
					#[deluxe(attributes(crud))]
 | 
				
			||||||
 | 
					pub struct CrudFieldAttributes {
 | 
				
			||||||
 | 
					    #[deluxe(default = false)]
 | 
				
			||||||
 | 
					    pub id: bool,
 | 
				
			||||||
 | 
					    #[deluxe(default = None)]
 | 
				
			||||||
 | 
					    pub column: Option<String>,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[derive(Clone)]
 | 
				
			||||||
 | 
					pub struct CrudField {
 | 
				
			||||||
 | 
					    pub ident: syn::Ident,
 | 
				
			||||||
 | 
					    pub field: syn::Field,
 | 
				
			||||||
 | 
					    pub column: String,
 | 
				
			||||||
 | 
					    pub id: bool,
 | 
				
			||||||
 | 
					    pub ty: syn::Type,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										188
									
								
								gejdr-macros/src/crud/mod.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										188
									
								
								gejdr-macros/src/crud/mod.rs
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,188 @@
 | 
				
			|||||||
 | 
					use ir::{CrudField, CrudFieldAttributes, CrudStructAttributes};
 | 
				
			||||||
 | 
					use quote::quote;
 | 
				
			||||||
 | 
					use syn::DeriveInput;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					mod ir;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					fn extract_crud_field_attrs(ast: &mut DeriveInput) -> deluxe::Result<(Vec<CrudField>, CrudField)> {
 | 
				
			||||||
 | 
					    let mut field_attrs: Vec<CrudField> = Vec::new();
 | 
				
			||||||
 | 
					    // let mut identifier: Option<CrudIdentifier> = None;
 | 
				
			||||||
 | 
					    let mut identifier: Option<CrudField> = None;
 | 
				
			||||||
 | 
					    let mut identifier_counter = 0;
 | 
				
			||||||
 | 
					    if let syn::Data::Struct(s) = &mut ast.data {
 | 
				
			||||||
 | 
					        for field in &mut s.fields {
 | 
				
			||||||
 | 
					            let ident = field.clone().ident.unwrap();
 | 
				
			||||||
 | 
					            let ty = field.clone().ty;
 | 
				
			||||||
 | 
					            let attrs: CrudFieldAttributes =
 | 
				
			||||||
 | 
					                deluxe::extract_attributes(field).expect("Could not extract attributes from field");
 | 
				
			||||||
 | 
					            let field = CrudField {
 | 
				
			||||||
 | 
					                ident: ident.clone(),
 | 
				
			||||||
 | 
					                field: field.to_owned(),
 | 
				
			||||||
 | 
					                column: attrs.column.unwrap_or_else(|| ident.to_string()),
 | 
				
			||||||
 | 
					                id: attrs.id,
 | 
				
			||||||
 | 
					                ty,
 | 
				
			||||||
 | 
					            };
 | 
				
			||||||
 | 
					            if attrs.id {
 | 
				
			||||||
 | 
					                identifier_counter += 1;
 | 
				
			||||||
 | 
					                identifier = Some(field.clone());
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            if identifier_counter > 1 {
 | 
				
			||||||
 | 
					                return Err(syn::Error::new_spanned(
 | 
				
			||||||
 | 
					                    field.field,
 | 
				
			||||||
 | 
					                    "Struct {name} can only have one identifier",
 | 
				
			||||||
 | 
					                ));
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            field_attrs.push(field);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if identifier_counter < 1 {
 | 
				
			||||||
 | 
					        Err(syn::Error::new_spanned(
 | 
				
			||||||
 | 
					            ast,
 | 
				
			||||||
 | 
					            "Struct {name} must have one identifier",
 | 
				
			||||||
 | 
					        ))
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					        Ok((field_attrs, identifier.unwrap()))
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					fn generate_find_query(table: &str, id: &CrudField) -> proc_macro2::TokenStream {
 | 
				
			||||||
 | 
					    let find_string = format!("SELECT * FROM {} WHERE {} = $1", table, id.column);
 | 
				
			||||||
 | 
					    let ty = &id.ty;
 | 
				
			||||||
 | 
					    quote! {
 | 
				
			||||||
 | 
					        async fn find(pool: &::sqlx::PgPool, id: &#ty) -> ::sqlx::Result<Option<Self>> {
 | 
				
			||||||
 | 
					            ::sqlx::query_as!(Self, #find_string, id)
 | 
				
			||||||
 | 
					                .fetch_optional(pool)
 | 
				
			||||||
 | 
					                .await
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					fn generate_create_query(table: &str, fields: &[CrudField]) -> proc_macro2::TokenStream {
 | 
				
			||||||
 | 
					    let inputs: Vec<String> = (1..=fields.len()).map(|num| format!("${num}")).collect();
 | 
				
			||||||
 | 
					    let create_string = format!(
 | 
				
			||||||
 | 
					        "INSERT INTO {} ({}) VALUES ({}) RETURNING *",
 | 
				
			||||||
 | 
					        table,
 | 
				
			||||||
 | 
					        fields
 | 
				
			||||||
 | 
					            .iter()
 | 
				
			||||||
 | 
					            .map(|v| v.column.clone())
 | 
				
			||||||
 | 
					            .collect::<Vec<String>>()
 | 
				
			||||||
 | 
					            .join(", "),
 | 
				
			||||||
 | 
					        inputs.join(", ")
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					    let field_idents: Vec<syn::Ident> = fields.iter().map(|f| f.ident.clone()).collect();
 | 
				
			||||||
 | 
					    quote! {
 | 
				
			||||||
 | 
					        async fn create(&self, pool: &::sqlx::PgPool) -> ::sqlx::Result<Self> {
 | 
				
			||||||
 | 
					            ::sqlx::query_as!(
 | 
				
			||||||
 | 
					                Self,
 | 
				
			||||||
 | 
					                #create_string,
 | 
				
			||||||
 | 
					                #(self.#field_idents),*
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					            .fetch_one(pool)
 | 
				
			||||||
 | 
					            .await
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					fn generate_update_query(
 | 
				
			||||||
 | 
					    table: &str,
 | 
				
			||||||
 | 
					    fields: &[CrudField],
 | 
				
			||||||
 | 
					    id: &CrudField,
 | 
				
			||||||
 | 
					) -> proc_macro2::TokenStream {
 | 
				
			||||||
 | 
					    let mut fields: Vec<&CrudField> = fields.iter().filter(|f| !f.id).collect();
 | 
				
			||||||
 | 
					    let update_columns = fields
 | 
				
			||||||
 | 
					        .iter()
 | 
				
			||||||
 | 
					        .enumerate()
 | 
				
			||||||
 | 
					        .map(|(i, &field)| format!("{} = ${}", field.column, i + 1))
 | 
				
			||||||
 | 
					        .collect::<Vec<String>>()
 | 
				
			||||||
 | 
					        .join(", ");
 | 
				
			||||||
 | 
					    let update_string = format!(
 | 
				
			||||||
 | 
					        "UPDATE {} SET {} WHERE {} = ${} RETURNING *",
 | 
				
			||||||
 | 
					        table,
 | 
				
			||||||
 | 
					        update_columns,
 | 
				
			||||||
 | 
					        id.column,
 | 
				
			||||||
 | 
					        fields.len() + 1
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					    fields.push(id);
 | 
				
			||||||
 | 
					    let field_idents: Vec<_> = fields.iter().map(|f| f.ident.clone()).collect();
 | 
				
			||||||
 | 
					    quote! {
 | 
				
			||||||
 | 
					        async fn update(&self, pool: &::sqlx::PgPool) -> ::sqlx::Result<Self> {
 | 
				
			||||||
 | 
					            ::sqlx::query_as!(
 | 
				
			||||||
 | 
					                Self,
 | 
				
			||||||
 | 
					                #update_string,
 | 
				
			||||||
 | 
					                #(self.#field_idents),*
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					            .fetch_one(pool)
 | 
				
			||||||
 | 
					            .await
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					fn generate_delete_query(table: &str, id: &CrudField) -> proc_macro2::TokenStream {
 | 
				
			||||||
 | 
					    let delete_string = format!("DELETE FROM {} WHERE {} = $1", table, id.column);
 | 
				
			||||||
 | 
					    let ty = &id.ty;
 | 
				
			||||||
 | 
					    let ident = &id.ident;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    quote! {
 | 
				
			||||||
 | 
					        async fn delete_by_id(pool: &::sqlx::PgPool, id: &#ty) -> ::sqlx::Result<u64> {
 | 
				
			||||||
 | 
					            let rows_affected = ::sqlx::query!(#delete_string, id)
 | 
				
			||||||
 | 
					                .execute(pool)
 | 
				
			||||||
 | 
					                .await?
 | 
				
			||||||
 | 
					                .rows_affected();
 | 
				
			||||||
 | 
					            Ok(rows_affected)
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        async fn delete(&self, pool: &::sqlx::PgPool) -> ::sqlx::Result<u64> {
 | 
				
			||||||
 | 
					            let rows_affected = ::sqlx::query!(#delete_string, self.#ident)
 | 
				
			||||||
 | 
					                .execute(pool)
 | 
				
			||||||
 | 
					                .await?
 | 
				
			||||||
 | 
					                .rows_affected();
 | 
				
			||||||
 | 
					            Ok(rows_affected)
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pub fn crud_derive_macro2(
 | 
				
			||||||
 | 
					    item: proc_macro2::TokenStream,
 | 
				
			||||||
 | 
					) -> deluxe::Result<proc_macro2::TokenStream> {
 | 
				
			||||||
 | 
					    // parse
 | 
				
			||||||
 | 
					    let mut ast: DeriveInput = syn::parse2(item).expect("Failed to parse input");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // extract struct attributes
 | 
				
			||||||
 | 
					    let CrudStructAttributes { table } =
 | 
				
			||||||
 | 
					        deluxe::extract_attributes(&mut ast).expect("Could not extract attributes from struct");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // extract field attributes
 | 
				
			||||||
 | 
					    let (fields, id) = extract_crud_field_attrs(&mut ast)?;
 | 
				
			||||||
 | 
					    let ty = &id.ty;
 | 
				
			||||||
 | 
					    let id_ident = &id.ident;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // define impl variables
 | 
				
			||||||
 | 
					    let ident = &ast.ident;
 | 
				
			||||||
 | 
					    let (impl_generics, type_generics, where_clause) = ast.generics.split_for_impl();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // generate
 | 
				
			||||||
 | 
					    let find_query = generate_find_query(&table, &id);
 | 
				
			||||||
 | 
					    let create_query = generate_create_query(&table, &fields);
 | 
				
			||||||
 | 
					    let update_query = generate_update_query(&table, &fields, &id);
 | 
				
			||||||
 | 
					    let delete_query = generate_delete_query(&table, &id);
 | 
				
			||||||
 | 
					    let code = quote! {
 | 
				
			||||||
 | 
					        impl #impl_generics Crud<#ty> for #ident #type_generics #where_clause {
 | 
				
			||||||
 | 
					            #find_query
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            #create_query
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            #update_query
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            async fn create_or_update(&self, pool: &::sqlx::PgPool) -> ::sqlx::Result<Self> {
 | 
				
			||||||
 | 
					                if Self::find(pool, &self.#id_ident).await?.is_some() {
 | 
				
			||||||
 | 
					                    self.update(pool).await
 | 
				
			||||||
 | 
					                } else {
 | 
				
			||||||
 | 
					                    self.create(pool).await
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            #delete_query
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					    Ok(code)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										81
									
								
								gejdr-macros/src/lib.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										81
									
								
								gejdr-macros/src/lib.rs
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,81 @@
 | 
				
			|||||||
 | 
					#![deny(clippy::all)]
 | 
				
			||||||
 | 
					#![deny(clippy::pedantic)]
 | 
				
			||||||
 | 
					#![deny(clippy::nursery)]
 | 
				
			||||||
 | 
					#![allow(clippy::module_name_repetitions)]
 | 
				
			||||||
 | 
					#![allow(clippy::unused_async)]
 | 
				
			||||||
 | 
					#![allow(clippy::useless_let_if_seq)] // Reason: prevents some OpenApi structs from compiling
 | 
				
			||||||
 | 
					#![forbid(unsafe_code)]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//! Create ``SQLx`` CRUD code for a struct in Postgres.
 | 
				
			||||||
 | 
					//!
 | 
				
			||||||
 | 
					//! This crate provides the trait implementation `Crud` which
 | 
				
			||||||
 | 
					//! generates the following ``SQLx`` queries:
 | 
				
			||||||
 | 
					//! - find an entity by id
 | 
				
			||||||
 | 
					//!
 | 
				
			||||||
 | 
					//!   SQL query: `SELECT * FROM ... WHERE <id> = ...`
 | 
				
			||||||
 | 
					//! - insert an entity into the database
 | 
				
			||||||
 | 
					//!
 | 
				
			||||||
 | 
					//!   SQL query: `INSERT INTO ... (...) VALUES (...) RETURNING *`
 | 
				
			||||||
 | 
					//! - update an entity in the database
 | 
				
			||||||
 | 
					//!
 | 
				
			||||||
 | 
					//!   SQL query: `UPDATE ... SET ... WHERE <id> = ... RETURNING *`
 | 
				
			||||||
 | 
					//! - delete an entity from the database using its id
 | 
				
			||||||
 | 
					//!
 | 
				
			||||||
 | 
					//!   SQL query: `DELETE FROM ... WHERE <id> = ...`
 | 
				
			||||||
 | 
					//! - update an entity or create it if it does not already exist in
 | 
				
			||||||
 | 
					//! - the database
 | 
				
			||||||
 | 
					//!
 | 
				
			||||||
 | 
					//! This macro relies on the trait `Crud` found in the `gejdr-core`
 | 
				
			||||||
 | 
					//! crate.
 | 
				
			||||||
 | 
					//!
 | 
				
			||||||
 | 
					//! To use this macro, you need to add it to the derives of the
 | 
				
			||||||
 | 
					//! struct. You will also need to define its identifier
 | 
				
			||||||
 | 
					//!
 | 
				
			||||||
 | 
					//! # Usage
 | 
				
			||||||
 | 
					//!
 | 
				
			||||||
 | 
					//! Add `#[crud(table = "my_table_name")]` atop of the structure,
 | 
				
			||||||
 | 
					//! after the `Crud` derive. You will also need to add `#[crud(id)]`
 | 
				
			||||||
 | 
					//! atop of the field of your struct that will be used as the
 | 
				
			||||||
 | 
					//! identifier of your entity.
 | 
				
			||||||
 | 
					//!
 | 
				
			||||||
 | 
					//! ```ignore
 | 
				
			||||||
 | 
					//! #[derive(Crud)]
 | 
				
			||||||
 | 
					//! #[crud(table = "users")]
 | 
				
			||||||
 | 
					//! pub struct User {
 | 
				
			||||||
 | 
					//!     #[crud(id)]
 | 
				
			||||||
 | 
					//!     id: String,
 | 
				
			||||||
 | 
					//!     username: String,
 | 
				
			||||||
 | 
					//!     created_at: Timestampz,
 | 
				
			||||||
 | 
					//!     last_updated: Timestampz,
 | 
				
			||||||
 | 
					//! }
 | 
				
			||||||
 | 
					//! ```
 | 
				
			||||||
 | 
					//!
 | 
				
			||||||
 | 
					//! With the example of the `User` struct, this links it to the
 | 
				
			||||||
 | 
					//! `users` table of the connected database. It will use `Users.id` to
 | 
				
			||||||
 | 
					//! uniquely identify a user entity.
 | 
				
			||||||
 | 
					//!
 | 
				
			||||||
 | 
					//! # Limitations
 | 
				
			||||||
 | 
					//! ## ID
 | 
				
			||||||
 | 
					//! For now, only one identifier is supported. It does not have to be
 | 
				
			||||||
 | 
					//! a primary key, but it is strongly encouraged to use GeJDR’s Crud
 | 
				
			||||||
 | 
					//! ID on a unique and non-null column of your database schema.
 | 
				
			||||||
 | 
					//!
 | 
				
			||||||
 | 
					//! ## Database type
 | 
				
			||||||
 | 
					//!
 | 
				
			||||||
 | 
					//! For now, only the ``PostgreSQL`` syntax is supported. If you use
 | 
				
			||||||
 | 
					//! another database that uses the same syntax, you’re in luck!
 | 
				
			||||||
 | 
					//! Otherwise, pull requests to add additional syntaxes are most
 | 
				
			||||||
 | 
					//! welcome.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					mod crud;
 | 
				
			||||||
 | 
					use crud::crud_derive_macro2;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// Generates CRUD code for Sqlx for a struct.
 | 
				
			||||||
 | 
					///
 | 
				
			||||||
 | 
					/// # Panics
 | 
				
			||||||
 | 
					///
 | 
				
			||||||
 | 
					/// May panic if errors arise while parsing and generating code.
 | 
				
			||||||
 | 
					#[proc_macro_derive(Crud, attributes(crud))]
 | 
				
			||||||
 | 
					pub fn crud_derive_macro(item: proc_macro::TokenStream) -> proc_macro::TokenStream {
 | 
				
			||||||
 | 
					    crud_derive_macro2(item.into()).unwrap().into()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user