elysia-crud-plugin 0.1.0

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 ADDED
@@ -0,0 +1,204 @@
1
+ # Elysia CRUD Plugin
2
+
3
+ Generate REST endpoints for your Drizzle tables without writing boilerplate. Inspired by Django Rest Framework's simplicity, this plugin creates full CRUD operations from your table definitions.
4
+
5
+ ## What it does
6
+
7
+ Pass a Drizzle table to the `crud` function, and you get five REST endpoints:
8
+
9
+ - `GET /{tableName}` - List all records
10
+ - `GET /{tableName}/:id` - Get one record
11
+ - `POST /{tableName}` - Create a record
12
+ - `PUT /{tableName}/:id` - Update a record
13
+ - `DELETE /{tableName}/:id` - Delete a record
14
+
15
+ The plugin automatically detects your primary key, handles errors, and returns appropriate HTTP status codes.
16
+
17
+ ## Installation
18
+
19
+ ```bash
20
+ bun add elysia-crud-plugin
21
+ ```
22
+
23
+ You also need Elysia and Drizzle ORM:
24
+
25
+ ```bash
26
+ bun add elysia drizzle-orm
27
+ ```
28
+
29
+ ## Quick start
30
+
31
+ ```typescript
32
+ import { Elysia } from "elysia";
33
+ import { drizzle } from "drizzle-orm/bun-sqlite";
34
+ import { sqliteTable, integer, text } from "drizzle-orm/sqlite-core";
35
+ import { Database } from "bun:sqlite";
36
+ import { crud } from "elysia-crud-plugin";
37
+
38
+ // Define your table
39
+ const users = sqliteTable("users", {
40
+ id: integer("id").primaryKey({ autoIncrement: true }),
41
+ name: text("name").notNull(),
42
+ email: text("email").notNull(),
43
+ });
44
+
45
+ // Set up database
46
+ const sqlite = new Database("example.db");
47
+ const db = drizzle(sqlite);
48
+
49
+ // Create your app
50
+ const app = new Elysia().decorate("db", db).use(crud(users)).listen(3000);
51
+ ```
52
+
53
+ That's it. You now have working CRUD endpoints for users.
54
+
55
+ ## How it works
56
+
57
+ The plugin reads your Drizzle table definition to:
58
+
59
+ 1. Extract the table name for route generation
60
+ 2. Find the primary key column automatically
61
+ 3. Generate type-safe endpoints based on your table schema
62
+
63
+ You don't write route handlers, validation logic, or error handling. The plugin handles it.
64
+
65
+ ## Field selection
66
+
67
+ Control which fields appear in responses using the `fields` option:
68
+
69
+ ```typescript
70
+ app.use(crud(users, { fields: ["id", "name", "email"] }));
71
+ ```
72
+
73
+ This returns only the specified fields in all responses. Useful for hiding sensitive data like passwords or internal fields.
74
+
75
+ Field selection affects responses only. All fields are still validated on create and update operations.
76
+
77
+ ## Database setup
78
+
79
+ The plugin expects a database instance decorated on your Elysia app. Use Elysia's `decorate` method:
80
+
81
+ ```typescript
82
+ const app = new Elysia().decorate("db", db).use(crud(users));
83
+ ```
84
+
85
+ The plugin works with any database Drizzle supports: SQLite, PostgreSQL, MySQL, and others.
86
+
87
+ ## Error handling
88
+
89
+ The plugin handles common errors:
90
+
91
+ - `404 Not Found` - Record doesn't exist (GET, PUT, DELETE by ID)
92
+ - `500 Internal Server Error` - Database not configured or other server errors
93
+
94
+ Error responses include a JSON body with an `error` field:
95
+
96
+ ```json
97
+ {
98
+ "error": "Resource not found"
99
+ }
100
+ ```
101
+
102
+ ## Limitations
103
+
104
+ The current version focuses on core CRUD operations. It doesn't include:
105
+
106
+ - Pagination for list endpoints
107
+ - Filtering or sorting
108
+ - Query parameter field selection
109
+ - Lifecycle hooks
110
+ - Custom validation beyond Drizzle schema
111
+
112
+ These may be added in future versions. For now, the plugin keeps things simple and focused.
113
+
114
+ ## Publishing to npm
115
+
116
+ Para publicar este pacote no npm, siga estes passos:
117
+
118
+ ### 1. Preparação
119
+
120
+ Certifique-se de que o `package.json` está configurado corretamente:
121
+
122
+ - Verifique o nome do pacote (deve ser único no npm)
123
+ - Atualize a versão seguindo [Semantic Versioning](https://semver.org/)
124
+ - Preencha os campos `repository`, `bugs` e `homepage` com a URL do seu repositório
125
+ - Adicione informações do autor
126
+
127
+ ### 2. Build
128
+
129
+ Compile o código TypeScript:
130
+
131
+ ```bash
132
+ bun run build
133
+ ```
134
+
135
+ Isso irá:
136
+
137
+ - Compilar o código para `dist/index.js`
138
+ - Gerar os arquivos de tipos TypeScript em `dist/index.d.ts`
139
+
140
+ ### 3. Teste local (opcional)
141
+
142
+ Antes de publicar, você pode testar o pacote localmente:
143
+
144
+ ```bash
145
+ npm pack
146
+ ```
147
+
148
+ Isso cria um arquivo `.tgz` que você pode instalar em outro projeto para testar.
149
+
150
+ ### 4. Login no npm
151
+
152
+ Se ainda não estiver logado:
153
+
154
+ ```bash
155
+ npm login
156
+ ```
157
+
158
+ Você precisará de:
159
+
160
+ - Nome de usuário do npm
161
+ - Senha
162
+ - Email (para verificação de dois fatores, se habilitado)
163
+
164
+ ### 5. Publicar
165
+
166
+ Para publicar o pacote:
167
+
168
+ ```bash
169
+ npm publish
170
+ ```
171
+
172
+ Se o nome do pacote for scoped (começa com `@`), você precisará torná-lo público:
173
+
174
+ ```bash
175
+ npm publish --access public
176
+ ```
177
+
178
+ ### 6. Verificar publicação
179
+
180
+ Após publicar, verifique se o pacote está disponível:
181
+
182
+ ```bash
183
+ npm view elysia-crud-plugin
184
+ ```
185
+
186
+ Ou visite: `https://www.npmjs.com/package/elysia-crud-plugin`
187
+
188
+ ### Atualizando versões
189
+
190
+ Para atualizar o pacote:
191
+
192
+ 1. Atualize a versão no `package.json` (ex: `0.1.0` → `0.1.1`)
193
+ 2. Execute `bun run build`
194
+ 3. Execute `npm publish`
195
+
196
+ Você também pode usar `npm version` para atualizar a versão automaticamente:
197
+
198
+ ```bash
199
+ npm version patch # 0.1.0 → 0.1.1
200
+ npm version minor # 0.1.0 → 0.2.0
201
+ npm version major # 0.1.0 → 1.0.0
202
+ ```
203
+
204
+ Isso atualiza o `package.json` e cria uma tag git automaticamente.
@@ -0,0 +1,40 @@
1
+ import { Elysia } from 'elysia';
2
+ import { Table } from 'drizzle-orm';
3
+ type ColumnNames<TTable extends Table> = keyof TTable['_']['columns'] & string;
4
+ interface CrudOptions<TTable extends Table> {
5
+ fields?: ColumnNames<TTable>[];
6
+ }
7
+ export declare function crud<TTable extends Table>(table: TTable, options?: CrudOptions<TTable>): Elysia<"", {
8
+ decorator: {};
9
+ store: {};
10
+ derive: {};
11
+ resolve: {};
12
+ }, {
13
+ typebox: {};
14
+ error: {};
15
+ }, {
16
+ schema: {};
17
+ standaloneSchema: {};
18
+ macro: {};
19
+ macroFn: {};
20
+ parser: {};
21
+ response: {};
22
+ }, {}, {
23
+ derive: {};
24
+ resolve: {};
25
+ schema: {};
26
+ standaloneSchema: {};
27
+ response: {};
28
+ }, {
29
+ derive: {};
30
+ resolve: {};
31
+ schema: {};
32
+ standaloneSchema: {};
33
+ response: {
34
+ [x: number]: number;
35
+ 200: Readonly<Error> | {
36
+ error: string;
37
+ };
38
+ };
39
+ }>;
40
+ export {};
package/dist/index.js ADDED
@@ -0,0 +1,136 @@
1
+ // @bun
2
+ // src/index.ts
3
+ import { Elysia, NotFoundError, InternalServerError } from "elysia";
4
+ import { getTableColumns, getTableName } from "drizzle-orm";
5
+ import { eq } from "drizzle-orm";
6
+ function getPrimaryKeyColumn(table) {
7
+ const columns = getTableColumns(table);
8
+ for (const [name, column] of Object.entries(columns)) {
9
+ if (column.primary) {
10
+ return { name, column };
11
+ }
12
+ }
13
+ throw new Error(`Table "${getTableName(table)}" must have a primary key column. ` + `Use .primaryKey() on a column or define a composite primary key.`);
14
+ }
15
+ function crud(table, options) {
16
+ const tableName = getTableName(table);
17
+ const { name: primaryKeyField, column: primaryKeyColumn } = getPrimaryKeyColumn(table);
18
+ const columns = getTableColumns(table);
19
+ const app = new Elysia().onError(({ code, error, set }) => {
20
+ if (code === "NOT_FOUND") {
21
+ set.status = 404;
22
+ return { error: error.message };
23
+ }
24
+ if (code === "INTERNAL_SERVER_ERROR") {
25
+ set.status = 500;
26
+ return { error: error.message };
27
+ }
28
+ return error;
29
+ });
30
+ app.get(`/${tableName}`, async ({ db }) => {
31
+ if (!db) {
32
+ throw new InternalServerError("Database not configured");
33
+ }
34
+ if (options?.fields) {
35
+ const selectedColumns = {};
36
+ for (const fieldName of options.fields) {
37
+ selectedColumns[fieldName] = columns[fieldName];
38
+ }
39
+ return await db.select(selectedColumns).from(table);
40
+ }
41
+ return await db.select().from(table);
42
+ });
43
+ app.get(`/${tableName}/:id`, async ({ db, params }) => {
44
+ if (!db) {
45
+ throw new InternalServerError("Database not configured");
46
+ }
47
+ let resources;
48
+ if (options?.fields) {
49
+ const selectedColumns = {};
50
+ for (const fieldName of options.fields) {
51
+ selectedColumns[fieldName] = columns[fieldName];
52
+ }
53
+ resources = await db.select(selectedColumns).from(table).where(eq(primaryKeyColumn, params.id)).limit(1);
54
+ } else {
55
+ resources = await db.select().from(table).where(eq(primaryKeyColumn, params.id)).limit(1);
56
+ }
57
+ if (resources.length === 0) {
58
+ throw new NotFoundError("Resource not found");
59
+ }
60
+ return resources[0];
61
+ });
62
+ app.post(`/${tableName}`, async ({ db, body, set }) => {
63
+ if (!db) {
64
+ throw new InternalServerError("Database not configured");
65
+ }
66
+ const { [primaryKeyField]: _ignoredId, ...dataWithoutId } = body;
67
+ let dataToInsert = dataWithoutId;
68
+ if (options?.fields) {
69
+ dataToInsert = {};
70
+ for (const fieldName of options.fields) {
71
+ if (fieldName !== primaryKeyField && fieldName in dataWithoutId) {
72
+ dataToInsert[fieldName] = dataWithoutId[fieldName];
73
+ }
74
+ }
75
+ }
76
+ const result = await db.insert(table).values(dataToInsert).returning();
77
+ set.status = 201;
78
+ return result[0];
79
+ });
80
+ app.put(`/${tableName}/:id`, async ({ db, params, body }) => {
81
+ if (!db) {
82
+ throw new InternalServerError("Database not configured");
83
+ }
84
+ let existing;
85
+ if (options?.fields) {
86
+ const selectedColumns = {};
87
+ for (const fieldName of options.fields) {
88
+ selectedColumns[fieldName] = columns[fieldName];
89
+ }
90
+ existing = await db.select(selectedColumns).from(table).where(eq(primaryKeyColumn, params.id)).limit(1);
91
+ } else {
92
+ existing = await db.select().from(table).where(eq(primaryKeyColumn, params.id)).limit(1);
93
+ }
94
+ if (existing.length === 0) {
95
+ throw new NotFoundError("Resource not found");
96
+ }
97
+ const { [primaryKeyField]: _ignoredId, ...dataWithoutId } = body;
98
+ let dataToUpdate = dataWithoutId;
99
+ if (options?.fields) {
100
+ dataToUpdate = {};
101
+ for (const fieldName of options.fields) {
102
+ if (fieldName !== primaryKeyField && fieldName in dataWithoutId) {
103
+ dataToUpdate[fieldName] = dataWithoutId[fieldName];
104
+ }
105
+ }
106
+ }
107
+ const result = await db.update(table).set(dataToUpdate).where(eq(primaryKeyColumn, params.id)).returning();
108
+ return result[0];
109
+ });
110
+ app.delete(`/${tableName}/:id`, async ({ db, params, set }) => {
111
+ if (!db) {
112
+ throw new InternalServerError("Database not configured");
113
+ }
114
+ let existing;
115
+ if (options?.fields) {
116
+ const selectedColumns = {};
117
+ for (const fieldName of options.fields) {
118
+ selectedColumns[fieldName] = columns[fieldName];
119
+ }
120
+ existing = await db.select(selectedColumns).from(table).where(eq(primaryKeyColumn, params.id)).limit(1);
121
+ } else {
122
+ existing = await db.select().from(table).where(eq(primaryKeyColumn, params.id)).limit(1);
123
+ }
124
+ if (existing.length === 0) {
125
+ throw new NotFoundError("Resource not found");
126
+ }
127
+ await db.delete(table).where(eq(primaryKeyColumn, params.id));
128
+ set.status = 204;
129
+ });
130
+ return app;
131
+ }
132
+ export {
133
+ crud
134
+ };
135
+
136
+ //# debugId=92D49CB7EB779F4A64756E2164756E21
@@ -0,0 +1,10 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["..\\src\\index.ts"],
4
+ "sourcesContent": [
5
+ "import { Elysia, NotFoundError, InternalServerError } from 'elysia'\nimport { getTableColumns, getTableName, Table } from 'drizzle-orm'\nimport { eq } from 'drizzle-orm'\n\ntype ColumnNames<TTable extends Table> = keyof TTable['_']['columns'] & string\n\ninterface CrudOptions<TTable extends Table> {\n fields?: ColumnNames<TTable>[]\n}\n\nfunction getPrimaryKeyColumn(table: Table) {\n const columns = getTableColumns(table)\n\n for (const [name, column] of Object.entries(columns)) {\n if (column.primary) {\n return { name, column }\n }\n }\n\n throw new Error(\n `Table \"${getTableName(table)}\" must have a primary key column. ` +\n `Use .primaryKey() on a column or define a composite primary key.`\n )\n}\n\nexport function crud<TTable extends Table>(\n table: TTable,\n options?: CrudOptions<TTable>\n) {\n const tableName = getTableName(table)\n const { name: primaryKeyField, column: primaryKeyColumn } = getPrimaryKeyColumn(table)\n const columns = getTableColumns(table)\n\n const app = new Elysia()\n .onError(({ code, error, set }) => {\n if (code === 'NOT_FOUND') {\n set.status = 404\n return { error: error.message }\n }\n\n if (code === 'INTERNAL_SERVER_ERROR') {\n set.status = 500\n return { error: error.message }\n }\n\n return error\n })\n\n app.get(`/${tableName}`, async ({ db }: any) => {\n if (!db) {\n throw new InternalServerError('Database not configured')\n }\n\n if (options?.fields) {\n const selectedColumns: Record<string, any> = {}\n for (const fieldName of options.fields) {\n selectedColumns[fieldName] = columns[fieldName]\n }\n return await db.select(selectedColumns).from(table)\n }\n\n return await db.select().from(table)\n })\n\n app.get(`/${tableName}/:id`, async ({ db, params }: any) => {\n if (!db) {\n throw new InternalServerError('Database not configured')\n }\n\n let resources\n if (options?.fields) {\n const selectedColumns: Record<string, any> = {}\n for (const fieldName of options.fields) {\n selectedColumns[fieldName] = columns[fieldName]\n }\n resources = await db\n .select(selectedColumns)\n .from(table)\n .where(eq(primaryKeyColumn, params.id))\n .limit(1)\n } else {\n resources = await db\n .select()\n .from(table)\n .where(eq(primaryKeyColumn, params.id))\n .limit(1)\n }\n\n if (resources.length === 0) {\n throw new NotFoundError('Resource not found')\n }\n\n return resources[0]\n })\n\n app.post(`/${tableName}`, async ({ db, body, set }: any) => {\n if (!db) {\n throw new InternalServerError('Database not configured')\n }\n\n const { [primaryKeyField]: _ignoredId, ...dataWithoutId } = body\n\n let dataToInsert = dataWithoutId\n if (options?.fields) {\n dataToInsert = {}\n for (const fieldName of options.fields) {\n if (fieldName !== primaryKeyField && fieldName in dataWithoutId) {\n dataToInsert[fieldName] = dataWithoutId[fieldName]\n }\n }\n }\n\n const result = await db.insert(table).values(dataToInsert).returning()\n\n set.status = 201\n return result[0]\n })\n\n app.put(`/${tableName}/:id`, async ({ db, params, body }: any) => {\n if (!db) {\n throw new InternalServerError('Database not configured')\n }\n\n let existing\n if (options?.fields) {\n const selectedColumns: Record<string, any> = {}\n for (const fieldName of options.fields) {\n selectedColumns[fieldName] = columns[fieldName]\n }\n existing = await db\n .select(selectedColumns)\n .from(table)\n .where(eq(primaryKeyColumn, params.id))\n .limit(1)\n } else {\n existing = await db\n .select()\n .from(table)\n .where(eq(primaryKeyColumn, params.id))\n .limit(1)\n }\n\n if (existing.length === 0) {\n throw new NotFoundError('Resource not found')\n }\n\n const { [primaryKeyField]: _ignoredId, ...dataWithoutId } = body\n\n let dataToUpdate = dataWithoutId\n if (options?.fields) {\n dataToUpdate = {}\n for (const fieldName of options.fields) {\n if (fieldName !== primaryKeyField && fieldName in dataWithoutId) {\n dataToUpdate[fieldName] = dataWithoutId[fieldName]\n }\n }\n }\n\n const result = await db\n .update(table)\n .set(dataToUpdate)\n .where(eq(primaryKeyColumn, params.id))\n .returning()\n\n return result[0]\n })\n\n app.delete(`/${tableName}/:id`, async ({ db, params, set }: any) => {\n if (!db) {\n throw new InternalServerError('Database not configured')\n }\n\n let existing\n if (options?.fields) {\n const selectedColumns: Record<string, any> = {}\n for (const fieldName of options.fields) {\n selectedColumns[fieldName] = columns[fieldName]\n }\n existing = await db\n .select(selectedColumns)\n .from(table)\n .where(eq(primaryKeyColumn, params.id))\n .limit(1)\n } else {\n existing = await db\n .select()\n .from(table)\n .where(eq(primaryKeyColumn, params.id))\n .limit(1)\n }\n\n if (existing.length === 0) {\n throw new NotFoundError('Resource not found')\n }\n\n await db.delete(table).where(eq(primaryKeyColumn, params.id))\n\n set.status = 204\n })\n\n return app\n}\n"
6
+ ],
7
+ "mappings": "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",
8
+ "debugId": "92D49CB7EB779F4A64756E2164756E21",
9
+ "names": []
10
+ }
package/package.json ADDED
@@ -0,0 +1,58 @@
1
+ {
2
+ "name": "elysia-crud-plugin",
3
+ "version": "0.1.0",
4
+ "description": "Generate REST endpoints for your Drizzle tables without writing boilerplate. Inspired by Django Rest Framework's simplicity.",
5
+ "type": "module",
6
+ "main": "./dist/index.js",
7
+ "module": "./dist/index.js",
8
+ "types": "./dist/index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "types": "./dist/index.d.ts",
12
+ "import": "./dist/index.js",
13
+ "default": "./dist/index.js"
14
+ }
15
+ },
16
+ "files": [
17
+ "dist",
18
+ "README.md"
19
+ ],
20
+ "scripts": {
21
+ "build": "bun run build.ts",
22
+ "prepublishOnly": "bun run build",
23
+ "test": "bun test"
24
+ },
25
+ "keywords": [
26
+ "elysia",
27
+ "drizzle",
28
+ "drizzle-orm",
29
+ "crud",
30
+ "rest",
31
+ "api",
32
+ "plugin",
33
+ "typescript",
34
+ "bun"
35
+ ],
36
+ "author": "Ruan Gustavo",
37
+ "license": "MIT",
38
+ "repository": {
39
+ "type": "git",
40
+ "url": "https://github.com/ruangustavo/elysia-crud-plugin.git"
41
+ },
42
+ "bugs": {
43
+ "url": "https://github.com/ruangustavo/elysia-crud-plugin/issues"
44
+ },
45
+ "homepage": "https://github.com/ruangustavo/elysia-crud-plugin#readme",
46
+ "devDependencies": {
47
+ "@types/bun": "latest",
48
+ "postgres": "^3.4.8",
49
+ "typescript": "^5.0.0"
50
+ },
51
+ "peerDependencies": {
52
+ "typescript": "^5"
53
+ },
54
+ "dependencies": {
55
+ "drizzle-orm": "^0.45.1",
56
+ "elysia": "^1.4.21"
57
+ }
58
+ }