convex-schema-parser 0.1.5.0 → 0.1.6.0
raw patch · 6 files changed
+78/−10 lines, 6 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
+ Convex.Schema.Parser: sanitizeUnionValues :: String -> String
Files
- CHANGELOG.md +5/−0
- README.md +1/−1
- convex-schema-parser.cabal +1/−1
- src/Backend/Rust.hs +5/−5
- src/Convex/Schema/Parser.hs +14/−1
- test/SchemaParserTest.hs +52/−2
CHANGELOG.md view
@@ -1,5 +1,10 @@ # Revision history for convex-schema-parser +## 0.1.6.0 -- 2025-07-21++* **Codegen Improvements Rust:**+ * `convex-schema-parser` now properly handles union types with special chars.+ ## 0.1.5.0 -- 2025-07-12 * **Backend Improvements:**
README.md view
@@ -9,7 +9,7 @@ 2. A persistent `dev` mode that watches your Convex project for changes and automatically regenerates your clients, providing a seamless development experience. > [!IMPORTANT]-> At the bottom you will find a USAGE section+> At the bottom you will find a USAGE section and in `examples` a complete simple example configuration with multiple projects. ## Installation
convex-schema-parser.cabal view
@@ -1,6 +1,6 @@ cabal-version: 3.0 name: convex-schema-parser-version: 0.1.5.0+version: 0.1.6.0 license: MIT author: Norbert Dzikowski maintainer: lambdax.one@icloud.com
src/Backend/Rust.hs view
@@ -487,11 +487,11 @@ | all Schema.isLiteral literals = let enumName = toPascalCase name enumFromConvexValueImpl = generateFromConvexValueImplEnum ("types::" ++ enumName) literals- variantNames = map Schema.getLiteralString literals+ variantNames = map (\l -> let n = Schema.getLiteralString l in (Schema.sanitizeUnionValues n, n)) literals buildVariantLines [] = []- buildVariantLines (first : rest) =- (indent 2 "#[default]\n" ++ indent 2 ("#[serde(rename = \"" ++ first ++ "\")]\n") ++ indent 2 (toPascalCase first ++ ","))- : map (\v -> indent 2 ("#[serde(rename = \"" ++ v ++ "\")]\n") ++ indent 2 (toPascalCase v ++ ",")) rest+ buildVariantLines ((sanitizedFirst, originalFirst) : rest) =+ (indent 2 "#[default]\n" ++ indent 2 ("#[serde(rename = \"" ++ originalFirst ++ "\")]\n") ++ indent 2 ((toPascalCase sanitizedFirst) ++ ","))+ : map (\(sanitizedV, originalV) -> indent 2 ("#[serde(rename = \"" ++ originalV ++ "\")]\n") ++ indent 2 (toPascalCase sanitizedV ++ ",")) rest code = unlines [ indent 1 "#[derive(Default, Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq)]",@@ -649,7 +649,7 @@ let cases = map ( \case- (Schema.VLiteral s) -> "\"" ++ s ++ "\" => Ok(" ++ structName ++ "::" ++ toPascalCase s ++ "),"+ (Schema.VLiteral s) -> "\"" ++ s ++ "\" => Ok(" ++ structName ++ "::" ++ (toPascalCase . Schema.sanitizeUnionValues $ s) ++ ")," _ -> error "Expected a literal for enum field" ) fields
src/Convex/Schema/Parser.hs view
@@ -13,6 +13,7 @@ initialState, getLiteralString, isLiteral,+ sanitizeUnionValues, ) where @@ -228,10 +229,22 @@ "array" -> VArray <$> parens convexTypeParser "object" -> parens structParser "optional" -> VOptional <$> parens convexTypeParser- "union" -> VUnion <$> parens (sepBy convexTypeParser (lexeme $ char ','))+ "union" -> VUnion <$> parens (sepEndBy convexTypeParser (lexeme $ char ',')) "literal" -> VLiteral <$> parens stringLiteral _ -> fail $ "Unknown v-dot type: " ++ typeName referenceParser = VReference <$> identifier++-- | Sanitizes union literals. It might be that a union like this is defined:+-- export const instruction_mime_type = v.union(+-- v.literal("application/pdf"),+-- v.literal("text/html"),+-- v.literal("text/plain")+-- );+--+-- And `application/pdf` would be translated into a type `Application/pdf`, which+-- is invalid in most languages. After sanitization, it would become `application_pdf`.+sanitizeUnionValues :: String -> String+sanitizeUnionValues = concatMap (\c -> if c `elem` ['/', '@', '\\'] then ['_'] else [c]) topLevelConstParser :: SchemaParser () topLevelConstParser = lexeme $ do
test/SchemaParserTest.hs view
@@ -105,7 +105,6 @@ " exchange_code: v.string(),", " tenant_id: v.id(\"tenants\"),", "};",- "", "// A type alias, which should be parsed and stored.", "export type MyId = typeof v.id(\"tenants\");", "",@@ -288,6 +287,56 @@ } } +-- Test Case for sanitizing union literals+sampleSchemaWithUnionsToSanitize :: String+sampleSchemaWithUnionsToSanitize =+ unlines+ [ "import { defineSchema, defineTable, v } from \"convex/server\";",+ "",+ "export const instruction_mime_type = v.union(",+ " v.literal(\"application/pdf\"),",+ " v.literal(\"text/html\"),",+ " v.literal(\"text/plain\"),",+ " v.literal(\"user@example.com\")",+ ");",+ "",+ "export default defineSchema({",+ " documents: defineTable({",+ " name: v.string(),",+ " mime_type: instruction_mime_type",+ " })",+ "});"+ ]++expectedSchemaWithSanitizedUnions :: Schema.ParsedFile+expectedSchemaWithSanitizedUnions =+ Schema.ParsedFile+ { Schema.parsedConstants =+ Map.fromList+ [ ( "instruction_mime_type",+ Schema.VUnion+ [ Schema.VLiteral "application/pdf",+ Schema.VLiteral "text/html",+ Schema.VLiteral "text/plain",+ Schema.VLiteral "user@example.com"+ ]+ )+ ],+ Schema.parsedSchema =+ Schema.Schema+ { Schema.getTables =+ [ Schema.Table+ { Schema.tableName = "documents",+ Schema.tableFields =+ [ Schema.Field "name" Schema.VString,+ Schema.Field "mime_type" (Schema.VReference "instruction_mime_type")+ ],+ Schema.tableIndexes = []+ }+ ]+ }+ }+ -- Main test suite combining all cases. tests :: Test tests =@@ -298,5 +347,6 @@ runSchemaTest "parses table defined with an object reference" sampleSchemaWithObjectRef expectedSchemaWithObjectRef, runSchemaTest "parses complex schema without semicolons" sampleComplexNoSemicolons expectedComplexNoSemicolons, runSchemaTest "parses optional array of objects" sampleOptionalArrayOfObjects expectedOptionalArrayOfObjects,- runSchemaTest "parses array of primitives" sampleArrayOfPrimitives expectedArrayOfPrimitives+ runSchemaTest "parses array of primitives" sampleArrayOfPrimitives expectedArrayOfPrimitives,+ runSchemaTest "sanitizes union literals with special characters" sampleSchemaWithUnionsToSanitize expectedSchemaWithSanitizedUnions ]