schematic-pg 0.1.4 → 0.1.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +10 -0
- package/dist/api-generator/utils/filter-operators.d.ts +1 -0
- package/dist/api-generator/utils/filter-operators.js +7 -1
- package/dist/api-generator/zod-schema-generator.js +1 -2
- package/dist/cli/init.js +5 -1
- package/dist/cli/templates.d.ts +2 -1
- package/dist/cli/templates.js +17 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -203,6 +203,14 @@ cd my-app
|
|
|
203
203
|
|
|
204
204
|
Edit `app.schema`, then generate code and start the API:
|
|
205
205
|
|
|
206
|
+
```bash
|
|
207
|
+
make dev
|
|
208
|
+
# → starts PostgreSQL, generates code, bootstraps the DB, and runs the dev server
|
|
209
|
+
# → http://localhost:3000
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
Or run each step individually:
|
|
213
|
+
|
|
206
214
|
```bash
|
|
207
215
|
# Start PostgreSQL (PostGIS-enabled, matches .env defaults)
|
|
208
216
|
docker compose up -d
|
|
@@ -225,6 +233,7 @@ The `init` command creates everything you need to get running:
|
|
|
225
233
|
| `app.schema` | Starter schema (one `User` model) — edit this |
|
|
226
234
|
| `.env` | `DATABASE_URL`, JWT settings |
|
|
227
235
|
| `docker-compose.yml` | Local PostGIS PostgreSQL on `:5432` |
|
|
236
|
+
| `Makefile` | `make dev` — docker compose + generate + db:bootstrap + dev |
|
|
228
237
|
| `tsconfig.json` | TypeScript config for `generated/` and `src/routes/` |
|
|
229
238
|
| `package.json` | `schematic-pg` + runtime deps (`hono`, `pg`, `zod`, …) |
|
|
230
239
|
| `src/routes/health.ts` | Example custom route mounted at `/health` |
|
|
@@ -286,6 +295,7 @@ schematic-pg dev [schema] # generate:client + generate:api, then start generat
|
|
|
286
295
|
Equivalent npm scripts in a project created by `init`:
|
|
287
296
|
|
|
288
297
|
```bash
|
|
298
|
+
make dev # docker compose up -d + generate + db:bootstrap + dev
|
|
289
299
|
npm run dev # schematic-pg dev
|
|
290
300
|
npm run generate # schematic-pg generate
|
|
291
301
|
```
|
|
@@ -11,4 +11,5 @@ export declare function getFilterFieldKind(field: Field, schema: Schema): Filter
|
|
|
11
11
|
export declare function getFilterOperators(kind: FilterFieldKind): FilterOperator[];
|
|
12
12
|
export declare function buildFilterFieldMeta(field: Field, schema: Schema): FilterFieldMeta;
|
|
13
13
|
export declare function queryParamKey(fieldName: string, operator: FilterOperator): string;
|
|
14
|
+
export declare function toQueryBooleanZodType(): string;
|
|
14
15
|
export declare function toFilterZodType(type: TypeExpr, field: Field, schema: Schema, operator: FilterOperator, coerce?: boolean): string;
|
|
@@ -54,6 +54,12 @@ export function queryParamKey(fieldName, operator) {
|
|
|
54
54
|
}
|
|
55
55
|
return `${fieldName}_${operator}`;
|
|
56
56
|
}
|
|
57
|
+
export function toQueryBooleanZodType() {
|
|
58
|
+
return `z.preprocess(
|
|
59
|
+
(value) => (typeof value === 'string' ? value.toLowerCase() : value),
|
|
60
|
+
z.union([z.boolean(), z.enum(['true', 'false'])]).transform((value) => value === true || value === 'true'),
|
|
61
|
+
)`;
|
|
62
|
+
}
|
|
57
63
|
export function toFilterZodType(type, field, schema, operator, coerce = false) {
|
|
58
64
|
const prefix = coerce ? 'z.coerce.' : 'z.';
|
|
59
65
|
const enumType = schema.enums.find((enumDef) => enumDef.name === type.name);
|
|
@@ -77,7 +83,7 @@ export function toFilterZodType(type, field, schema, operator, coerce = false) {
|
|
|
77
83
|
case 'SMALLINT':
|
|
78
84
|
return `${prefix}number().int()`;
|
|
79
85
|
case 'BOOLEAN':
|
|
80
|
-
return
|
|
86
|
+
return toQueryBooleanZodType();
|
|
81
87
|
case 'TIMESTAMP':
|
|
82
88
|
return 'z.coerce.date()';
|
|
83
89
|
case 'DECIMAL':
|
|
@@ -86,8 +86,7 @@ export class ZodSchemaGenerator {
|
|
|
86
86
|
const lines = [];
|
|
87
87
|
for (const operator of meta.operators) {
|
|
88
88
|
const key = queryParamKey(field.name, operator);
|
|
89
|
-
const
|
|
90
|
-
const zodType = toFilterZodType(field.type, field, this.schema, operator, useCoerce);
|
|
89
|
+
const zodType = toFilterZodType(field.type, field, this.schema, operator, true);
|
|
91
90
|
lines.push(`${key}: ${zodType}.optional(),`);
|
|
92
91
|
}
|
|
93
92
|
return lines;
|
package/dist/cli/init.js
CHANGED
|
@@ -3,12 +3,13 @@ import { PACKAGE_NAME } from '../constants.js';
|
|
|
3
3
|
import { existsSync } from 'node:fs';
|
|
4
4
|
import { mkdir, readdir, writeFile } from 'node:fs/promises';
|
|
5
5
|
import path from 'node:path';
|
|
6
|
-
import { APP_SCHEMA_TEMPLATE, createPackageJsonTemplate, DOCKER_COMPOSE_TEMPLATE, ENV_TEMPLATE, GITIGNORE_TEMPLATE, HEALTH_ROUTE_TEMPLATE, TSCONFIG_TEMPLATE, } from './templates.js';
|
|
6
|
+
import { APP_SCHEMA_TEMPLATE, createPackageJsonTemplate, DOCKER_COMPOSE_TEMPLATE, ENV_TEMPLATE, GITIGNORE_TEMPLATE, HEALTH_ROUTE_TEMPLATE, MAKEFILE_TEMPLATE, TSCONFIG_TEMPLATE, } from './templates.js';
|
|
7
7
|
const INIT_FILES = [
|
|
8
8
|
{ relativePath: 'app.schema', content: APP_SCHEMA_TEMPLATE },
|
|
9
9
|
{ relativePath: '.env', content: ENV_TEMPLATE },
|
|
10
10
|
{ relativePath: '.gitignore', content: GITIGNORE_TEMPLATE },
|
|
11
11
|
{ relativePath: 'docker-compose.yml', content: DOCKER_COMPOSE_TEMPLATE },
|
|
12
|
+
{ relativePath: 'Makefile', content: MAKEFILE_TEMPLATE },
|
|
12
13
|
{ relativePath: 'tsconfig.json', content: TSCONFIG_TEMPLATE },
|
|
13
14
|
{ relativePath: 'src/routes/health.ts', content: HEALTH_ROUTE_TEMPLATE },
|
|
14
15
|
];
|
|
@@ -101,6 +102,9 @@ export async function runInit(args) {
|
|
|
101
102
|
if (skipInstall) {
|
|
102
103
|
console.log(' npm install');
|
|
103
104
|
}
|
|
105
|
+
console.log(' make dev');
|
|
106
|
+
console.log('');
|
|
107
|
+
console.log(' # or run individually:');
|
|
104
108
|
console.log(' docker compose up -d');
|
|
105
109
|
console.log(` npx ${PACKAGE_NAME} generate`);
|
|
106
110
|
console.log(` npx ${PACKAGE_NAME} db:bootstrap`);
|
package/dist/cli/templates.d.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
export declare const APP_SCHEMA_TEMPLATE = "
|
|
1
|
+
export declare const APP_SCHEMA_TEMPLATE = "extensions {\n\n}\n\nenums {\n\n}\n\nmodels {\n model User {\n id: UUID @id @default(gen_random_uuid())\n email: VARCHAR(255) @unique\n name: VARCHAR(150)\n createdAt: TIMESTAMP @default(now())\n }\n}\n";
|
|
2
2
|
export declare const ENV_TEMPLATE = "DATABASE_URL=postgresql://postgrest:postgrest@localhost:5432/postgrest\nJWT_SECRET=\nJWT_ROLE_CLAIM=role\nJWT_USER_ID_CLAIM=sub\n";
|
|
3
3
|
export declare const GITIGNORE_TEMPLATE = "node_modules/\ndist/\n.env\ndocker_data/\n.DS_Store\n*.log\nnpm-debug.log*\n";
|
|
4
4
|
export declare const DOCKER_COMPOSE_TEMPLATE = "services:\n postgres:\n image: postgis/postgis:16-3.4\n container_name: schematic-pg-postgres\n restart: unless-stopped\n ports:\n - \"5432:5432\"\n environment:\n POSTGRES_USER: postgrest\n POSTGRES_PASSWORD: postgrest\n POSTGRES_DB: postgrest\n volumes:\n - ./docker_data/postgres:/var/lib/postgresql/data\n healthcheck:\n test: [\"CMD-SHELL\", \"pg_isready -U postgrest -d postgrest\"]\n interval: 5s\n timeout: 5s\n retries: 5\n";
|
|
5
5
|
export declare const TSCONFIG_TEMPLATE = "{\n \"compilerOptions\": {\n \"target\": \"ES2022\",\n \"module\": \"NodeNext\",\n \"moduleResolution\": \"NodeNext\",\n \"strict\": true,\n \"esModuleInterop\": true,\n \"skipLibCheck\": true,\n \"outDir\": \"dist\",\n \"rootDir\": \".\"\n },\n \"include\": [\"generated/**/*\", \"src/**/*\"]\n}\n";
|
|
6
|
+
export declare const MAKEFILE_TEMPLATE = ".PHONY: dev\n\ndev:\n\tdocker compose up -d\n\tnpx schematic-pg generate\n\tnpx schematic-pg db:bootstrap\n\tnpx schematic-pg dev\n";
|
|
6
7
|
export declare const HEALTH_ROUTE_TEMPLATE = "import { Hono } from 'hono';\nimport type { AppEnv } from 'schematic-pg/api/types';\n\nconst router = new Hono<AppEnv>();\nrouter.get('/', (c) => c.json({ ok: true }));\nexport default router;\n";
|
|
7
8
|
export declare function createPackageJsonTemplate(projectName: string): string;
|
package/dist/cli/templates.js
CHANGED
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
import { PACKAGE_NAME, PACKAGE_VERSION } from '../constants.js';
|
|
2
|
-
export const APP_SCHEMA_TEMPLATE = `
|
|
2
|
+
export const APP_SCHEMA_TEMPLATE = `extensions {
|
|
3
|
+
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
enums {
|
|
7
|
+
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
models {
|
|
3
11
|
model User {
|
|
4
12
|
id: UUID @id @default(gen_random_uuid())
|
|
5
13
|
email: VARCHAR(255) @unique
|
|
@@ -54,6 +62,14 @@ export const TSCONFIG_TEMPLATE = `{
|
|
|
54
62
|
"include": ["generated/**/*", "src/**/*"]
|
|
55
63
|
}
|
|
56
64
|
`;
|
|
65
|
+
export const MAKEFILE_TEMPLATE = `.PHONY: dev
|
|
66
|
+
|
|
67
|
+
dev:
|
|
68
|
+
\tdocker compose up -d
|
|
69
|
+
\tnpx ${PACKAGE_NAME} generate
|
|
70
|
+
\tnpx ${PACKAGE_NAME} db:bootstrap
|
|
71
|
+
\tnpx ${PACKAGE_NAME} dev
|
|
72
|
+
`;
|
|
57
73
|
export const HEALTH_ROUTE_TEMPLATE = `import { Hono } from 'hono';
|
|
58
74
|
import type { AppEnv } from '${PACKAGE_NAME}/api/types';
|
|
59
75
|
|