Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
# main

- Add automatic parsing of PostgreSQL check constraints to generate ReScript polyvariant types for enumeration-style constraints. Supports both `column IN (value1, value2, ...)` and `column = ANY (ARRAY[value1, value2, ...])` patterns with string and integer values.
- Remove dependency on `@rescript/core` since it's not really used.

# 2.6.0

- Improve `pg` bindings.
Expand Down
63 changes: 63 additions & 0 deletions RESCRIPT.md
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,69 @@ In order for this mode to work, you need one more thing - configure the `rescrip

With that, you should be able to write queries directly in your ReScript source, and with the `watch` mode enabled have a seamless experience with types autogenerated and wired up for you.

## Check Constraint Support

`pgtyped-rescript` automatically analyzes PostgreSQL check constraints and generates ReScript polyvariant types for enumeration-style constraints. This provides compile-time safety for constrained database fields.

### Supported Constraint Patterns

The following constraint patterns are automatically detected and converted to polyvariant types:

```sql
-- Pattern 1: IN clause
status TEXT CHECK (status IN ('published', 'draft', 'archived')),

-- Pattern 2: ANY with ARRAY
format TEXT CHECK (format = ANY (ARRAY['hardcover'::text, 'paperback'::text, 'ebook'::text])),

-- Both string and integer values are supported
priority INTEGER CHECK (priority IN (1, 2, 3, 4, 5))
```

### Generated Types

For a table with these constraints:

```sql
CREATE TABLE books (
id SERIAL PRIMARY KEY,
status TEXT CHECK (status IN ('published', 'draft', 'archived')),
priority INTEGER CHECK (priority IN (1, 2, 3, 4, 5))
);
```

The generated ReScript types will include:

```rescript
type result = {
id: int,
status: option<[#"published" | #"draft" | #"archived"]>,
priority: option<[#1 | #2 | #3 | #4 | #5]>,
}
```

### Limitations

- **Float constraints**: Not supported since ReScript polyvariants cannot represent float literals
- **Complex constraints**: Only simple enumeration patterns are supported (no `BETWEEN`, `OR` logic, function calls, etc.)
- **Mixed types**: Constraints mixing different data types in the same clause are not supported

### Example

```sql
/* @name getBooksByStatus */
SELECT * FROM books WHERE status = :status;
```

```rescript
// The generated function will accept a polyvariant for status
let books = await client->GetBooksByStatus.many({
status: #published // Compile-time checked against the database constraint!
})
```

This feature works seamlessly with both separate SQL files and SQL-in-ReScript modes.

## API

### `PgTyped`
Expand Down
131 changes: 128 additions & 3 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 0 additions & 2 deletions packages/cli/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,6 @@
"@pgtyped/parser": "^2.1.0",
"@pgtyped/wire": "^2.2.0",
"@rescript/tools": "0.6.4",
"@rescript/core": "1.6.0",
"camel-case": "^4.1.1",
"chalk": "^4.0.0",
"chokidar": "^3.3.1",
Expand All @@ -66,7 +65,6 @@
"rescript": "11.1.0"
},
"peerDependencies": {
"@rescript/core": ">= 1.3.0",
"rescript": ">= 11.1.0"
}
}
4 changes: 1 addition & 3 deletions packages/cli/rescript.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,5 @@
"module": "commonjs",
"in-source": true
},
"suffix": ".js",
"bs-dependencies": ["@rescript/core"],
"bsc-flags": ["-open RescriptCore"]
"suffix": ".js"
}
Loading