{"id":20084438,"url":"https://github.com/eicrud/eicrud-tutorial","last_synced_at":"2025-05-06T01:31:55.973Z","repository":{"id":246641643,"uuid":"821726871","full_name":"eicrud/eicrud-tutorial","owner":"eicrud","description":"A simple tutorial for the Eicrud framework","archived":false,"fork":false,"pushed_at":"2024-06-29T16:05:20.000Z","size":135,"stargazers_count":16,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-04-09T06:50:28.453Z","etag":null,"topics":["api","backend","crud","eicrud","framework","nodejs","tutorial"],"latest_commit_sha":null,"homepage":"https://github.com/eicrud/eicrud","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/eicrud.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-06-29T09:05:42.000Z","updated_at":"2025-02-21T04:45:15.000Z","dependencies_parsed_at":"2024-06-29T10:34:09.007Z","dependency_job_id":"5381b1b6-4ea8-4395-afd4-d8fc8c1cbbe2","html_url":"https://github.com/eicrud/eicrud-tutorial","commit_stats":null,"previous_names":["eicrud/eicrud-tutorial"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eicrud%2Feicrud-tutorial","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eicrud%2Feicrud-tutorial/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eicrud%2Feicrud-tutorial/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eicrud%2Feicrud-tutorial/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/eicrud","download_url":"https://codeload.github.com/eicrud/eicrud-tutorial/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":252604358,"owners_count":21775088,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["api","backend","crud","eicrud","framework","nodejs","tutorial"],"created_at":"2024-11-13T15:52:02.347Z","updated_at":"2025-05-06T01:31:55.641Z","avatar_url":"https://github.com/eicrud.png","language":"TypeScript","readme":"# Build your CRUD backend in 20min with Eicrud + MongoDB\n\nIn this tutorial, I'm going to demonstrate how [Eicrud](eicrud.com) can save you tons of time when building your Node.js backend.\n\nWe're going to make a simple blogging platform where users can read, publish and comment on articles. \n\n## Prerequisites\n\n- [Node.js](https://nodejs.org/en/download/package-manager) \u003e= v18\n- [MongoDB](https://www.mongodb.com/docs/manual/installation/) listening on localhost:27017\n- [ts-node](https://www.npmjs.com/package/ts-node) or your favorite frontend framework\n\n---\n\n## Installation\n\nFirst, let's set up our app by following [Eicrud's documentation](https://docs.eicrud.com/installation/).\n\nWe create a new [NestJS](https://nestjs.com/) application.\n\n```bash\n npm i -g @nestjs/cli\n nest new myblog\n cd myblog\n```\nThen install [Eicrud](eicrud.com) on top of it.\n```bash\nnpm i -g @eicrud/cli\neicrud setup mongo myblog\n```\nFinally, we generate a secret key and store it in a `.env` file at the root of our project.\n\n```bash\necho \"JWT_SECRET=$(node -e \"console.log(require('crypto').randomBytes(256).toString('base64'));\")\" \u003e .env\n```\nNow we already have a well-structured project! You can check that everything is working.\n```bash\nnpm run start\n```\n\n## Services\n\nThe [CLI](https://www.npmjs.com/package/@eicrud/cli) already generated a `User` service for us in `src\\services\\user`. All we need to add to our application is an `Article` service and a `Comment` service.\n\n\n```bash\neicrud generate service Article\neicrud generate service Comment\n```\n\n\n## Model definition\n\nLet's edit our entities to our liking.\n\nUpdate the file `src\\services\\article\\article.entity.ts` with the following.\n\n```typescript\nimport { Entity, PrimaryKey, Property, \n    ManyToOne } from \"@mikro-orm/core\";\nimport { IsString, IsOptional } from \"class-validator\";\nimport { CrudEntity } from \"@eicrud/core/crud\";\nimport { User } from \"../user/user.entity\";\nimport { $MaxSize } from \"@eicrud/core/validation\";\n\n\n@Entity()\nexport class Article implements CrudEntity {\n\n    @PrimaryKey({ name: '_id' })\n    @IsString()\n    @IsOptional()\n    id: string;\n\n    @ManyToOne(() =\u003e User)\n    @IsString()\n    author: User | string;\n\n    @Property()\n    @IsString()\n    title: string;\n\n    @Property()\n    @IsString()\n    @$MaxSize(1000)\n    content: string;\n\n    @Property()\n    createdAt: Date;\n\n    @Property()\n    updatedAt: Date;\n\n}\n```\n\nAnd don't forget our `Comment` entity in `src\\services\\comment\\comment.entity.ts`.\n\n```typescript\nimport { Entity, PrimaryKey, Property, ManyToOne } from \"@mikro-orm/core\";\nimport { IsString, IsOptional } from \"class-validator\";\nimport { CrudEntity } from \"@eicrud/core/crud\";\nimport { Article } from \"../article/article.entity\";\nimport { User } from \"../user/user.entity\";\nimport { $MaxSize } from \"@eicrud/core/validation\";\n\n\n@Entity()\nexport class Comment implements CrudEntity {\n\n    @PrimaryKey({ name: '_id' })\n    @IsString()\n    @IsOptional()\n    id: string;\n\n    @ManyToOne(() =\u003e Article)\n    @IsString()\n    article: Article | string;\n\n    @ManyToOne(() =\u003e User)\n    @IsString()\n    author: User | string;\n\n    @Property()\n    @IsString()\n    @$MaxSize(200)\n    content: string;\n\n    @Property()\n    createdAt: Date;\n\n    @Property()\n    updatedAt: Date;\n\n}\n```\n\n## Access rules\nNow that we have our model, let's update the access rules in `src\\services\\article\\article.security.ts`. We want everyone to read our articles, but only their author should be able to modify them.\n\n```typescript\nguest: {\n    async defineCRUDAbility(can, cannot, ctx) {\n        // guests can read all articles\n        can('read', article)\n    }\n},\nuser: {\n    async defineCRUDAbility(can, cannot, ctx) {\n        // user can manage their own articles\n        can('crud', article, { author: ctx.userId })\n    }\n}\n```\nIt's the same idea for comments, except this time we don't want users to modify their comments after creation. Let's change the rules in `src\\services\\comment\\comment.security.ts`.\n\n```typescript\nguest: {\n    async defineCRUDAbility(can, cannot, ctx) {\n        // guests can read all comments\n        can('read', comment)\n    }\n},\nuser: {\n    async defineCRUDAbility(can, cannot, ctx) {\n        // user create and delete their own comments\n        can('cd', comment, {author: ctx.userId})\n    }\n}\n```\n## Commands\nEicrud has [prebuilt commands](https://docs.eicrud.com/user/service/#account-creation) for account creation and login. We just need to allow their usage in `src\\services\\user\\cmds\\create_account\\create_account.security.ts`.\n\n```typescript\nguest: {\n    async defineCMDAbility(can, cannot, ctx) {\n        // can create an account with the role 'user'\n        can(create_account, user, {role: 'user'})\n    }\n}\n```\n\nAnd in `src\\services\\user\\cmds\\login\\login.security.ts`.\n```typescript\nguest: {\n    async defineCMDAbility(can, cannot, ctx) {\n        // Define abilities for user\n        can(login, user)\n    }\n}\n```\nNow our backend is ready for action! Let's start the server and switch to another terminal.\n```bash\nnpm run start\n```\n\n## Calling the API\nTo simulate our frontend we're going to use [ts-node](https://www.npmjs.com/package/ts-node), but you can use your favorite framework or tools like [esbuild](https://esbuild.github.io/) if you prefer.\n\n```bash\nnpm i -g ts-node # make sur to install it globally\n```\n\nLet's install [Eicrud's client](https://docs.eicrud.com/client/setup).\n```bash\nnpm i @eicrud/client\n```\nCreate a file `front.ts` and start with a helper class to make Eicrud's client dynamic.\n\n```typescript\nimport { ClientConfig, CrudClient } from \"@eicrud/client\";\n\nexport class DynamicClient {\n    crudClient: CrudClient\u003cany\u003e;\n\n    constructor() {\n        const initalConfig: ClientConfig = {\n            url: 'http://localhost:3000',\n            serviceName: 'user',\n        }\n        this.crudClient = new CrudClient(initalConfig);\n    }\n\n    get(serviceName){\n        this.crudClient.config.serviceName = serviceName;\n        return this.crudClient;\n    }\n}\n```\nNow we can create our first account and publish an article.\n\n```typescript\n// ... following in front.ts\n\nimport { ICreateAccountDto } from '@eicrud/shared/interfaces';\nimport { ILoginDto } from '@eicrud/shared/interfaces';\nimport { Article } from \"./src/services/article/article.entity\";\n\nasync function main() {\n    const client = new DynamicClient();\n\n    // Create account and publish article\n    const dto: ICreateAccountDto = {\n        email: 'new.user@mail.com',\n        password: 'p4ssw0rd',\n        role: 'user',\n    };\n    const { userId } = await client.get('user').cmdS('create_account', dto);\n\n    console.log('User created!', userId);\n\n    const loginDto: ILoginDto = {\n        email: 'new.user@mail.com',\n        password: 'p4ssw0rd',\n    };\n    \n    await client.get('user').login(loginDto);\n\n    const newArticle: Partial\u003cArticle\u003e = {\n        title: 'New article',\n        content: 'This is a new article',\n        author: userId,\n    };\n\n    await client.get('article').create(newArticle);\n\n    // Let's check that our article was created\n    const userArticles = await client.get('article').find({ author: userId });\n    console.log('User articles:', userArticles);\n}\n\nmain();\n```\nAnd let's run our frontend to test our API.\n```bash\nts-node front.ts\n```\nThat's all for the basics! \n\nTake note of all the [CRUD operations](https://docs.eicrud.com/client/operations) available to the client. You can use any of them to query the `'article'` or `'comment'` service.\n\n## Going further\n\nEicrud is in active development and has many features to make your life easier. You can learn all about it in the [documentation](https://docs.eicrud.com). If you find any issue don't hesitate to [create one](https://github.com/eicrud/eicrud/issues) and I'll look into it.\n\nHappy coding!\n\n---\n\nOriginal article: https://dev.to/acrosett/build-your-crud-backend-in-20min-with-eicrud-mongodb-4n3p\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Feicrud%2Feicrud-tutorial","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Feicrud%2Feicrud-tutorial","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Feicrud%2Feicrud-tutorial/lists"}