Skip to content

Commit

Permalink
Merge pull request #1106 from undb-xyz/release/0.5.0
Browse files Browse the repository at this point in the history
  • Loading branch information
nichenqin authored Jun 6, 2023
2 parents 63dbe5d + c9fce0c commit c5dce8d
Show file tree
Hide file tree
Showing 64 changed files with 1,392 additions and 95 deletions.
8 changes: 7 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,22 @@

Private first, unified, self-hosted no code database.

<a href="https://demo.undb.xyz/">Live Demo</a>
<a href="https://demo.undb.xyz?lng=en">Live Demo</a>
·
<a href="https://docs.undb.xyz/">Documentation</a>
·
<a href="https://www.undb.xyz/">Website</a>
·
<a href="https://github.com/orgs/undb-xyz/projects/1/views/2?query=is%3Aopen+sort%3Aupdated-desc">Roadmap</a>

> use email `test@example.com` and password `123456` to login
![undb](./docs/undb.png)

<p>
<a href="https://discord.gg/3rcNdU3y3U"><img alt="Discord" src="https://img.shields.io/badge/discord-chat-5865f2?logo=discord&logoColor=f5f5f5" /></a>
</p>

## Features

- :closed_lock_with_key: Private first
Expand Down
4 changes: 3 additions & 1 deletion apps/backend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@
"version": "0.0.0",
"dependencies": {
"@aws-sdk/client-s3": "^3.338.0",
"@json2csv/plainjs": "^7.0.0",
"@mikro-orm/better-sqlite": "^5.7.10",
"@mikro-orm/core": "^5.7.10",
"@mikro-orm/migrations": "^5.7.10",
"@mikro-orm/nestjs": "^5.1.8",
"@json2csv/plainjs": "^7.0.0",
"@nestjs/common": "^9.4.2",
"@nestjs/config": "^2.3.2",
"@nestjs/core": "^9.4.2",
Expand All @@ -22,6 +22,7 @@
"@undb/cqrs": "^0.0.0",
"@undb/domain": "^0.0.0",
"@undb/i18n": "^0.0.0",
"@undb/openapi": "workspace:^",
"@undb/sqlite": "^0.0.0",
"@undb/trpc": "^0.0.0",
"aws-sdk-v3-nest": "^0.2.0",
Expand Down Expand Up @@ -72,6 +73,7 @@
"jest": "^29.5.0",
"nodemon": "^2.0.22",
"npm-run-all": "^4.1.5",
"openapi3-ts": "^4.1.2",
"supertest": "^6.3.3",
"ts-jest": "^29.1.0",
"ts-loader": "^9.4.3",
Expand Down
2 changes: 2 additions & 0 deletions apps/backend/src/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import { HealthModule } from './health/health.module.js'
import { I18nModule } from './i18n/i18n.module.js'
import { modules } from './modules/index.js'
import { UserService } from './modules/user/user.service.js'
import { OpenAPIModule } from './openapi/openapi.module.js'
import { TrpcModule } from './trpc/trpc.module.js'

@Module({
Expand Down Expand Up @@ -53,6 +54,7 @@ import { TrpcModule } from './trpc/trpc.module.js'
}),
AuthModule,
I18nModule,
OpenAPIModule,
],
})
export class AppModule implements OnModuleInit {
Expand Down
1 change: 1 addition & 0 deletions apps/backend/src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ async function bootstrap() {

app.enableCors()
app.enableShutdownHooks()
app.enableVersioning()
app.setGlobalPrefix('/api', { exclude: ['health'] })

const httpAdapterHost = app.get(HttpAdapterHost)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ export class NestRecordSqliteQueryModel extends RecordSqliteQueryModel implement
}

@UseRequestContext()
async findOne(tableId: string, spec: IRecordSpec): Promise<Option<IQueryRecordSchema>> {
async findOne(tableId: string, spec: IRecordSpec | null): Promise<Option<IQueryRecordSchema>> {
return super.findOne(tableId, spec)
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,18 +1,20 @@
import type { ICommandHandler } from '@nestjs/cqrs'
import { CommandHandler } from '@nestjs/cqrs'
import { ClsStore, TableSpecHandler, type ITableRepository } from '@undb/core'
import { ClsStore, TableSpecHandler, type IRecordRepository, type ITableRepository } from '@undb/core'
import { CreateTableCommand, CreateTableCommandHandler as DomainHandler } from '@undb/cqrs'
import { ClsService } from 'nestjs-cls'
import { InjectTableReposiory } from '../adapters/index.js'
import { InjectRecordReposiory, InjectTableReposiory } from '../adapters/index.js'

@CommandHandler(CreateTableCommand)
export class CreateTableCommandHandler extends DomainHandler implements ICommandHandler<CreateTableCommand> {
constructor(
@InjectTableReposiory()
protected readonly repo: ITableRepository,
@InjectRecordReposiory()
protected readonly recordRepo: IRecordRepository,
protected readonly handler: TableSpecHandler,
protected readonly cls: ClsService<ClsStore>,
) {
super(repo, handler, cls)
super(repo, recordRepo, handler, cls)
}
}
1 change: 1 addition & 0 deletions apps/backend/src/modules/table/table.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,6 @@ import { tableSpecHandler } from './services/table-spec.handler.js'
controllers: [RecordController],
imports: [CqrsModule],
providers: [...commandHandlers, ...queryHandlers, ...dbAdapters, tableSpecHandler, ...exportors],
exports: [...dbAdapters],
})
export class TableModule {}
16 changes: 16 additions & 0 deletions apps/backend/src/openapi/openapi-doc.controller.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { Controller, Get, Param, Res } from '@nestjs/common'
import { type Response } from 'express'
import { OpenAPIDocService } from './openapi-doc.service.js'

@Controller('openapi')
export class OpenAPIDocController {
constructor(private readonly openAPIService: OpenAPIDocService) {}

@Get('docs/tables/:tableId')
public async doc(@Res() res: Response, @Param('tableId') tableId: string) {
const html = await this.openAPIService.generateDoc(tableId)

res.type('html')
res.send(html)
}
}
23 changes: 23 additions & 0 deletions apps/backend/src/openapi/openapi-doc.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { Injectable } from '@nestjs/common'
import { type IRecordQueryModel, type ITableRepository } from '@undb/core'
import { createRedocHTML, createTableSchema } from '@undb/openapi'
import { InjectRecordQueryModel, InjectTableReposiory } from '../modules/table/adapters/index.js'

@Injectable()
export class OpenAPIDocService {
constructor(
@InjectTableReposiory()
private readonly repo: ITableRepository,
@InjectRecordQueryModel()
private readonly recordRepo: IRecordQueryModel,
) {}
public async generateDoc(tableId: string): Promise<string> {
const table = (await this.repo.findOneById(tableId)).unwrap()
const record = await this.recordRepo.findOne(tableId, null)

const spec = createTableSchema(table, record.into())
const html = createRedocHTML(table, spec)

return html
}
}
46 changes: 46 additions & 0 deletions apps/backend/src/openapi/openapi.controller.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import { Body, Controller, Delete, Get, Param, Query, UseGuards, Version } from '@nestjs/common'
import { CommandBus, QueryBus } from '@nestjs/cqrs'
import { BulkDeleteRecordsCommand, DeleteRecordCommand, GetRecordQuery, GetRecordsQuery } from '@undb/cqrs'
import { JwtAuthGuard } from '../auth/jwt-auth.guard.js'
import { OpenAPIService } from './openapi.service.js'

@Controller({
path: 'openapi',
version: '1',
})
@UseGuards(JwtAuthGuard)
export class OpenAPIController {
constructor(
private queryBus: QueryBus,
private readonly commandBus: CommandBus,
private readonly service: OpenAPIService,
) {}

@Version('1')
@Get('tables/:tableId/records')
public async getRecords(@Param('tableId') tableId: string, @Query('viewId') viewId?: string) {
const result = await this.queryBus.execute(new GetRecordsQuery({ tableId, viewId }))
const records = await this.service.mapMany(tableId, result.records ?? [])
return { records }
}

@Version('1')
@Get('tables/:tableId/records/:id')
public async getRecordById(@Param('tableId') tableId: string, @Param('id') id: string) {
const result = await this.queryBus.execute(new GetRecordQuery({ tableId, id }))
const record = result ? await this.service.mapMany(tableId, result) : null
return { record }
}

@Version('1')
@Delete('tables/:tableId/records/:id')
public async deleteRecord(@Param('tableId') tableId: string, @Param('id') id: string) {
await this.commandBus.execute(new DeleteRecordCommand({ tableId, id }))
}

@Version('1')
@Delete('tables/:tableId/records')
public async deleteRecordsByIds(@Param('tableId') tableId: string, @Body('ids') ids: [string, ...string[]]) {
await this.commandBus.execute(new BulkDeleteRecordsCommand({ tableId, ids }))
}
}
11 changes: 11 additions & 0 deletions apps/backend/src/openapi/openapi.mapper.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { Inject, Provider } from '@nestjs/common'
import { openApiRecordMapper } from '@undb/openapi'

const OPEN_API_MAPPER = Symbol('OPEN_API_MAPPER')

export const InjectOpenAPIMapper = () => Inject(OPEN_API_MAPPER)

export const provider: Provider = {
provide: OPEN_API_MAPPER,
useValue: openApiRecordMapper,
}
15 changes: 15 additions & 0 deletions apps/backend/src/openapi/openapi.module.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { Module } from '@nestjs/common'
import { CqrsModule } from '@nestjs/cqrs'
import { TableModule } from '../modules/table/table.module.js'
import { OpenAPIDocController } from './openapi-doc.controller.js'
import { OpenAPIDocService } from './openapi-doc.service.js'
import { OpenAPIController } from './openapi.controller.js'
import { provider as mapper } from './openapi.mapper.js'
import { OpenAPIService } from './openapi.service.js'

@Module({
imports: [TableModule, CqrsModule],
controllers: [OpenAPIDocController, OpenAPIController],
providers: [OpenAPIDocService, OpenAPIService, mapper],
})
export class OpenAPIModule {}
29 changes: 29 additions & 0 deletions apps/backend/src/openapi/openapi.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { Injectable } from '@nestjs/common'
import type { IQueryRecordSchema, ITableRepository } from '@undb/core'
import type { IOpenApiRecordMapper } from '@undb/openapi'
import { InjectTableReposiory } from '../modules/table/adapters/index.js'
import { InjectOpenAPIMapper } from './openapi.mapper.js'

@Injectable()
export class OpenAPIService {
constructor(
@InjectOpenAPIMapper()
private readonly mapper: IOpenApiRecordMapper,
@InjectTableReposiory()
private readonly repo: ITableRepository,
) {}

public async mapMany(tableId: string, records: IQueryRecordSchema[]) {
const table = (await this.repo.findOneById(tableId)).unwrap()
const fields = table.schema.fields

return records.map((record) => this.mapper(fields, record))
}

public async map(tableId: string, record: IQueryRecordSchema) {
const table = (await this.repo.findOneById(tableId)).unwrap()
const fields = table.schema.fields

return this.mapper(fields, record)
}
}
3 changes: 3 additions & 0 deletions apps/frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
"@types/js-cookie": "^3.0.3",
"@types/lodash-es": "^4.17.7",
"@types/nprogress": "^0.2.0",
"@types/papaparse": "^5.3.7",
"@types/sortablejs": "^1.15.1",
"@typescript-eslint/eslint-plugin": "^5.59.7",
"@typescript-eslint/parser": "^5.59.7",
Expand All @@ -57,6 +58,7 @@
"keycode": "^2.2.1",
"lodash-es": "^4.17.21",
"nprogress": "^0.2.0",
"papaparse": "^5.4.1",
"plausible-tracker": "^0.3.8",
"postcss": "^8.4.23",
"postcss-load-config": "^4.0.1",
Expand All @@ -66,6 +68,7 @@
"svelte": "^3.59.1",
"svelte-chartjs": "^3.1.2",
"svelte-check": "^3.3.2",
"svelte-copy": "^1.3.2",
"svelte-dnd-action": "^0.9.22",
"svelte-grid": "^5.1.1",
"svelte-i18next": "^2.0.0",
Expand Down
Loading

0 comments on commit c5dce8d

Please sign in to comment.