Skip to content

Commit 1f20252

Browse files
committed
Update package readmes, add init command
1 parent 57f15f5 commit 1f20252

12 files changed

Lines changed: 565 additions & 131 deletions

File tree

README.md

Lines changed: 72 additions & 107 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,65 @@
11
# effql
22

33
[![CI](https://github.com/gloomweaver/effql/actions/workflows/ci.yml/badge.svg)](https://github.com/gloomweaver/effql/actions/workflows/ci.yml)
4+
[![npm: @effql/cli](https://img.shields.io/npm/v/%40effql%2Fcli?label=%40effql%2Fcli)](https://www.npmjs.com/package/@effql/cli)
5+
[![npm: @effql/core](https://img.shields.io/npm/v/%40effql%2Fcore?label=%40effql%2Fcore)](https://www.npmjs.com/package/@effql/core)
46

57
`effql` is a `sqlc`-style TypeScript code generator for `effect` / `@effect/sql`.
68

79
It keeps a SQL-first workflow, uses Postgres introspection to infer types, and emits Effect-native code built around `Schema` and `SqlSchema.*`.
810

9-
## Why effql
11+
## Packages
1012

11-
- write raw SQL in `.sql` files
12-
- keep familiar query annotations like `-- name: GetUser :one`
13-
- use TypeScript / JavaScript config via `defineConfig()` instead of YAML
14-
- infer result shapes from a real Postgres database
15-
- generate executable Effect wrappers instead of plain DTOs
13+
- [`@effql/cli`](https://www.npmjs.com/package/@effql/cli) — CLI package providing the `effql` command
14+
- [`@effql/core`](https://www.npmjs.com/package/@effql/core) — config loading, SQL parsing, Postgres analysis, and code generation
1615

17-
## Status
16+
## Installation
1817

19-
This is an early **Postgres-only MVP**.
18+
```bash
19+
npm install -D @effql/cli @effql/core
20+
```
2021

21-
What works today:
22+
```bash
23+
pnpm add -D @effql/cli @effql/core
24+
```
2225

23-
- TS / JS config via `defineConfig()`
24-
- query annotations: `:one`, `:maybeOne`, `:many`, `:exec`
25-
- named params via `@param`
26-
- Postgres-backed type inference
27-
- generated `Schema` exports and `SqlSchema.single/findOne/findAll/void` wrappers
28-
- self-contained CRUD example with Docker Compose and an Effect HTTP API
26+
## CLI usage
27+
28+
Bootstrap a project:
29+
30+
```bash
31+
npx @effql/cli init
32+
npx @effql/cli init --config ./effql.config.ts
33+
```
34+
35+
This creates:
36+
37+
- `effql.config.ts`
38+
- `sql/queries.sql`
39+
- `package.json` if one does not already exist
40+
41+
Installed locally:
42+
43+
```bash
44+
npx effql init
45+
npx effql generate
46+
npx effql generate --config ./effql.config.ts
47+
```
48+
49+
One-off without installing:
50+
51+
```bash
52+
npx @effql/cli generate
53+
npx @effql/cli generate --config ./effql.config.ts
54+
```
55+
56+
Also works with pnpm:
57+
58+
```bash
59+
pnpm dlx @effql/cli generate
60+
```
61+
62+
Yes — `npx` works because `@effql/cli` publishes the `effql` bin.
2963

3064
## Quick start
3165

@@ -48,19 +82,6 @@ Or run the full smoke test used by CI:
4882
pnpm run example:smoke
4983
```
5084

51-
## Workspace
52-
53-
- `packages/core` — config loading, SQL parsing, Postgres analysis, code generation
54-
- `packages/cli``effql generate`
55-
- `examples/basic` — self-contained Postgres + generated CRUD module + Effect HTTP API
56-
57-
## CLI
58-
59-
```bash
60-
effql --help
61-
effql generate --config ./effql.config.ts
62-
```
63-
6485
## Config
6586

6687
`effql` uses code-based config:
@@ -99,15 +120,12 @@ RETURNING id, email, created_at;
99120
SELECT id, email, created_at
100121
FROM users
101122
WHERE id = @id::uuid;
102-
103-
-- name: ListUsers :many
104-
SELECT id, email, created_at
105-
FROM users
106-
ORDER BY created_at DESC;
107123
```
108124

109125
## Generated output shape
110126

127+
Starter `sql/queries.sql` contains a simple `Healthcheck` query you can edit right away.
128+
111129
Generated modules export:
112130

113131
- `*ParamsSchema`
@@ -116,8 +134,6 @@ Generated modules export:
116134
- raw `*Sql` strings
117135
- executable `SqlSchema.*` wrappers
118136

119-
Example:
120-
121137
```ts
122138
export const CreateUserResultSchema = Schema.Struct({
123139
id: Schema.UUID,
@@ -135,58 +151,28 @@ export const createUser = SqlSchema.single({
135151
});
136152
```
137153

138-
## Direct usage example
139-
140-
You can call generated functions by providing a SQL client layer:
141-
142-
```ts
143-
import { PgClient } from "@effect/sql-pg";
144-
import { Effect, Redacted } from "effect";
145-
import { createUser, listUsers } from "./generated/index.ts";
146-
147-
const program = Effect.gen(function* () {
148-
const created = yield* createUser({
149-
id: "33333333-3333-3333-3333-333333333333",
150-
email: "grace@example.com",
151-
});
152-
153-
const users = yield* listUsers({});
154-
155-
return { created, users };
156-
});
157-
158-
const runnable = program.pipe(
159-
Effect.provide(
160-
PgClient.layer({
161-
url: Redacted.make("postgres://postgres:postgres@127.0.0.1:54329/postgres"),
162-
}),
163-
),
164-
);
165-
```
166-
167-
## Effect HTTP API example
168-
169-
`examples/basic/src/httpApi.ts` wires generated CRUD queries into an Effect `HttpApi`.
154+
## Example project
170155

171-
Routes:
156+
See `examples/basic` for the easiest end-to-end demo:
172157

173-
- `POST /users`
174-
- `GET /users`
175-
- `GET /users/:id`
176-
- `PUT /users/:id`
177-
- `DELETE /users/:id`
158+
- `compose.yaml` starts Postgres on `127.0.0.1:54329`
159+
- `schema.sql` creates and seeds `users`
160+
- `sql/queries.sql` defines CRUD queries
161+
- `generated/index.ts` is committed generated output
162+
- `src/httpApi.ts` and `src/server.ts` show runtime usage
178163

179-
Try it:
164+
## Status
180165

181-
```bash
182-
curl http://127.0.0.1:3000/users
166+
This is an early **Postgres-only MVP**.
183167

184-
curl http://127.0.0.1:3000/users/11111111-1111-1111-1111-111111111111
168+
What works today:
185169

186-
curl -X POST http://127.0.0.1:3000/users \
187-
-H 'content-type: application/json' \
188-
-d '{"email":"grace@example.com"}'
189-
```
170+
- TS / JS config via `defineConfig()`
171+
- query annotations: `:one`, `:maybeOne`, `:many`, `:exec`
172+
- named params via `@param`
173+
- Postgres-backed type inference
174+
- generated `Schema` exports and `SqlSchema.single/findOne/findAll/void` wrappers
175+
- self-contained CRUD example with Docker Compose and an Effect HTTP API
190176

191177
## Known limitations
192178

@@ -199,26 +185,15 @@ Current MVP limitations:
199185
- output is currently a single generated module per target
200186
- API / config shape may still evolve before a stable release
201187

202-
## Validation and CI
203-
204-
Current checks cover:
205-
206-
- formatting and linting
207-
- workspace typechecking
208-
- unit tests
209-
- Postgres integration tests
210-
- example generation smoke test in GitHub Actions
211-
- example API smoke test via `pnpm run example:smoke`
212-
213188
## Publishing
214189

215190
A GitHub Actions release workflow publishes the npm packages when a GitHub release is marked as `published`.
216191

217192
Before using it:
218193

219-
- add an `NPM_TOKEN` repository secret
194+
- add an `NPM_TOKEN` repository secret if you keep token-based publishing
220195
- make sure you own/publish to both `@effql/cli` and `@effql/core` on npm
221-
- create releases with tags that match the package versions, for example `v0.1.0`
196+
- create releases with tags that match the package versions, for example `v0.1.1`
222197

223198
The release workflow:
224199

@@ -228,23 +203,13 @@ The release workflow:
228203
- publishes `@effql/core`
229204
- publishes `@effql/cli`
230205

231-
## Example project
232-
233-
See `examples/basic` for the easiest end-to-end demo:
234-
235-
- `compose.yaml` starts Postgres on `127.0.0.1:54329`
236-
- `schema.sql` creates and seeds `users`
237-
- `sql/queries.sql` defines CRUD queries
238-
- `generated/index.ts` is committed generated output
239-
- `src/httpApi.ts` and `src/server.ts` show runtime usage
240-
241-
## Development commands
206+
## Development
242207

243208
```bash
244209
vp install
245210
vp lint
246-
vp run -r check
247-
vp run -r test
211+
vp fmt
212+
vp test
248213
vp run -r build
249214
pnpm run example:smoke
250215
```

examples/basic/generated/index.ts

Lines changed: 13 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,10 @@ RETURNING id, email, created_at`;
3030
export const createUser = SqlSchema.single({
3131
Request: CreateUserParamsSchema,
3232
Result: CreateUserResultSchema,
33-
execute: (request) => Effect.flatMap(SqlClient.SqlClient, (sql) =>
34-
sql.unsafe(createUserSql, [request.id, request.email])
35-
),
33+
execute: (request) =>
34+
Effect.flatMap(SqlClient.SqlClient, (sql) =>
35+
sql.unsafe(createUserSql, [request.id, request.email]),
36+
),
3637
});
3738

3839
/**
@@ -61,9 +62,8 @@ WHERE id = $1::uuid`;
6162
export const getUser = SqlSchema.single({
6263
Request: GetUserParamsSchema,
6364
Result: GetUserResultSchema,
64-
execute: (request) => Effect.flatMap(SqlClient.SqlClient, (sql) =>
65-
sql.unsafe(getUserSql, [request.id])
66-
),
65+
execute: (request) =>
66+
Effect.flatMap(SqlClient.SqlClient, (sql) => sql.unsafe(getUserSql, [request.id])),
6767
});
6868

6969
/**
@@ -90,9 +90,7 @@ ORDER BY created_at DESC`;
9090
export const listUsers = SqlSchema.findAll({
9191
Request: ListUsersParamsSchema,
9292
Result: ListUsersResultSchema,
93-
execute: (request) => Effect.flatMap(SqlClient.SqlClient, (sql) =>
94-
sql.unsafe(listUsersSql)
95-
),
93+
execute: (request) => Effect.flatMap(SqlClient.SqlClient, (sql) => sql.unsafe(listUsersSql)),
9694
});
9795

9896
/**
@@ -124,9 +122,10 @@ RETURNING id, email, created_at`;
124122
export const updateUser = SqlSchema.single({
125123
Request: UpdateUserParamsSchema,
126124
Result: UpdateUserResultSchema,
127-
execute: (request) => Effect.flatMap(SqlClient.SqlClient, (sql) =>
128-
sql.unsafe(updateUserSql, [request.email, request.id])
129-
),
125+
execute: (request) =>
126+
Effect.flatMap(SqlClient.SqlClient, (sql) =>
127+
sql.unsafe(updateUserSql, [request.email, request.id]),
128+
),
130129
});
131130

132131
/**
@@ -146,7 +145,6 @@ export const deleteUserSql = String.raw`DELETE FROM users
146145
WHERE id = $1::uuid`;
147146
export const deleteUser = SqlSchema.void({
148147
Request: DeleteUserParamsSchema,
149-
execute: (request) => Effect.flatMap(SqlClient.SqlClient, (sql) =>
150-
sql.unsafe(deleteUserSql, [request.id])
151-
),
148+
execute: (request) =>
149+
Effect.flatMap(SqlClient.SqlClient, (sql) => sql.unsafe(deleteUserSql, [request.id])),
152150
});

package.json

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "effql-workspace",
3-
"version": "0.1.0",
3+
"version": "0.1.1",
44
"private": true,
55
"description": "sqlc-style TypeScript code generation for Effect SQL using Postgres introspection",
66
"keywords": [
@@ -9,7 +9,6 @@
99
"effect-ts",
1010
"postgres",
1111
"sql",
12-
"sqlc",
1312
"typescript"
1413
],
1514
"homepage": "https://github.com/gloomweaver/effql#readme",

packages/cli/README.md

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
# @effql/cli
2+
3+
[![npm: @effql/cli](https://img.shields.io/npm/v/%40effql%2Fcli?label=%40effql%2Fcli)](https://www.npmjs.com/package/@effql/cli)
4+
5+
CLI package for `effql`.
6+
7+
It publishes the `effql` command.
8+
9+
## Install
10+
11+
```bash
12+
npm install -D @effql/cli @effql/core
13+
```
14+
15+
```bash
16+
pnpm add -D @effql/cli @effql/core
17+
```
18+
19+
## Usage
20+
21+
Bootstrap a project:
22+
23+
```bash
24+
npx @effql/cli init
25+
npx @effql/cli init --config ./effql.config.ts
26+
```
27+
28+
This writes:
29+
30+
- `effql.config.ts`
31+
- `sql/queries.sql`
32+
- `package.json` if missing
33+
34+
Installed locally:
35+
36+
```bash
37+
npx effql init
38+
npx effql generate
39+
npx effql generate --config ./effql.config.ts
40+
```
41+
42+
One-off usage:
43+
44+
```bash
45+
npx @effql/cli generate
46+
pnpm dlx @effql/cli generate
47+
```
48+
49+
## Help
50+
51+
```bash
52+
effql --help
53+
```
54+
55+
See the main repo README for config details and the end-to-end example.

0 commit comments

Comments
 (0)