diff --git a/api/.gitignore b/api/.gitignore
new file mode 100644
index 00000000..5add9449
--- /dev/null
+++ b/api/.gitignore
@@ -0,0 +1,2 @@
+/node_modules
+/yarn.lock
diff --git a/api/.prettierrc b/api/.prettierrc
new file mode 100644
index 00000000..dcb72794
--- /dev/null
+++ b/api/.prettierrc
@@ -0,0 +1,4 @@
+{
+ "singleQuote": true,
+ "trailingComma": "all"
+}
\ No newline at end of file
diff --git a/api/README.md b/api/README.md
new file mode 100644
index 00000000..6f6c6037
--- /dev/null
+++ b/api/README.md
@@ -0,0 +1,55 @@
+
+
+
+
+## Description
+
+[OhMyForm](https://github.com/ohmyforn) api backend
+
+## Installation
+
+```bash
+$ yarn install
+```
+
+## Running the app
+
+```bash
+# development
+$ npm run start
+
+# watch mode
+$ npm run start:dev
+
+# incremental rebuild (webpack)
+$ npm run webpack
+$ npm run start:hmr
+
+# production mode
+$ npm run start:prod
+```
+
+## Test
+
+```bash
+# unit tests
+$ npm run test
+
+# e2e tests
+$ npm run test:e2e
+
+# test coverage
+$ npm run test:cov
+```
+
+## Support
+
+TODO
+
+## Stay in touch
+
+- Website - [https://ohmyform.com](https://ohmyform.com/)
+
+## License
+
+TODO
diff --git a/api/nest-cli.json b/api/nest-cli.json
new file mode 100644
index 00000000..0dde5f8c
--- /dev/null
+++ b/api/nest-cli.json
@@ -0,0 +1,5 @@
+{
+ "language": "ts",
+ "collection": "@nestjs/schematics",
+ "sourceRoot": "src"
+}
diff --git a/api/nodemon-debug.json b/api/nodemon-debug.json
new file mode 100644
index 00000000..7caf94b0
--- /dev/null
+++ b/api/nodemon-debug.json
@@ -0,0 +1,6 @@
+{
+ "watch": ["src"],
+ "ext": "ts",
+ "ignore": ["src/**/*.spec.ts"],
+ "exec": "node --inspect-brk -r ts-node/register src/main.ts"
+}
\ No newline at end of file
diff --git a/api/nodemon.json b/api/nodemon.json
new file mode 100644
index 00000000..583bb426
--- /dev/null
+++ b/api/nodemon.json
@@ -0,0 +1,6 @@
+{
+ "watch": ["src"],
+ "ext": "ts",
+ "ignore": ["src/**/*.spec.ts"],
+ "exec": "ts-node -r tsconfig-paths/register src/main.ts"
+}
diff --git a/api/package.json b/api/package.json
new file mode 100644
index 00000000..c76a2102
--- /dev/null
+++ b/api/package.json
@@ -0,0 +1,66 @@
+{
+ "name": "ohmyform",
+ "version": "0.1.0",
+ "description": "Opensource alternative to TypeForm",
+ "author": "multiple",
+ "license": "MIT",
+ "scripts": {
+ "build": "rimraf dist && tsc -p tsconfig.build.json",
+ "format": "prettier --write \"src/**/*.ts\"",
+ "start": "ts-node -r tsconfig-paths/register src/main.ts",
+ "start:dev": "tsc-watch -p tsconfig.build.json --onSuccess \"node dist/main.js\"",
+ "start:debug": "tsc-watch -p tsconfig.build.json --onSuccess \"node --inspect-brk dist/main.js\"",
+ "start:prod": "node dist/main.js",
+ "lint": "tslint -p tsconfig.json -c tslint.json",
+ "test": "jest",
+ "test:watch": "jest --watch",
+ "test:cov": "jest --coverage",
+ "test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand",
+ "test:e2e": "jest --config ./test/jest-e2e.json"
+ },
+ "dependencies": {
+ "@godaddy/terminus": "^4.1.2",
+ "@nestjs/common": "^6.0.0",
+ "@nestjs/core": "^6.0.0",
+ "@nestjs/mongoose": "^6.1.2",
+ "@nestjs/platform-express": "^6.0.0",
+ "@nestjs/swagger": "^3.1.0",
+ "@nestjs/terminus": "^6.5.0",
+ "@types/mongoose": "^5.5.11",
+ "mongoose": "^5.6.7",
+ "reflect-metadata": "^0.1.12",
+ "rimraf": "^2.6.2",
+ "rxjs": "^6.3.3",
+ "swagger-ui-express": "^4.0.7"
+ },
+ "devDependencies": {
+ "@nestjs/testing": "6.1.1",
+ "@types/express": "4.16.1",
+ "@types/jest": "24.0.11",
+ "@types/node": "11.13.4",
+ "@types/supertest": "2.0.7",
+ "jest": "24.7.1",
+ "prettier": "1.17.0",
+ "supertest": "4.0.2",
+ "ts-jest": "24.0.2",
+ "ts-node": "8.1.0",
+ "tsc-watch": "2.2.1",
+ "tsconfig-paths": "3.8.0",
+ "tslint": "5.16.0",
+ "typescript": "3.4.3"
+ },
+ "jest": {
+ "moduleFileExtensions": [
+ "js",
+ "json",
+ "ts"
+ ],
+ "rootDir": "src",
+ "testRegex": ".spec.ts$",
+ "transform": {
+ "^.+\\.(t|j)s$": "ts-jest"
+ },
+ "coverageDirectory": "../coverage",
+ "testEnvironment": "node"
+ }
+}
diff --git a/api/src/app.controller.spec.ts b/api/src/app.controller.spec.ts
new file mode 100644
index 00000000..d22f3890
--- /dev/null
+++ b/api/src/app.controller.spec.ts
@@ -0,0 +1,22 @@
+import { Test, TestingModule } from '@nestjs/testing';
+import { AppController } from './app.controller';
+import { AppService } from './app.service';
+
+describe('AppController', () => {
+ let appController: AppController;
+
+ beforeEach(async () => {
+ const app: TestingModule = await Test.createTestingModule({
+ controllers: [AppController],
+ providers: [AppService],
+ }).compile();
+
+ appController = app.get(AppController);
+ });
+
+ describe('root', () => {
+ it('should return "Hello World!"', () => {
+ expect(appController.getHello()).toBe('Hello World!');
+ });
+ });
+});
diff --git a/api/src/app.controller.ts b/api/src/app.controller.ts
new file mode 100644
index 00000000..cce879ee
--- /dev/null
+++ b/api/src/app.controller.ts
@@ -0,0 +1,12 @@
+import { Controller, Get } from '@nestjs/common';
+import { AppService } from './app.service';
+
+@Controller()
+export class AppController {
+ constructor(private readonly appService: AppService) {}
+
+ @Get()
+ getHello(): string {
+ return this.appService.getHello();
+ }
+}
diff --git a/api/src/app.module.ts b/api/src/app.module.ts
new file mode 100644
index 00000000..26a16ed0
--- /dev/null
+++ b/api/src/app.module.ts
@@ -0,0 +1,22 @@
+import { Module } from '@nestjs/common';
+import { TerminusModule } from '@nestjs/terminus';
+import { MongooseModule } from '@nestjs/mongoose';
+import { TerminusOptionsService } from './terminus-options.service';
+import { AppController } from './app.controller';
+import { AppService } from './app.service';
+import {UsersModule} from "./users/users.module"
+import {FormsModule} from "./forms/forms.module"
+
+@Module({
+ imports: [
+ MongooseModule.forRoot('mongodb://localhost/nest'),
+ TerminusModule.forRootAsync({
+ useClass: TerminusOptionsService,
+ }),
+ UsersModule,
+ FormsModule,
+ ],
+ controllers: [AppController],
+ providers: [AppService],
+})
+export class AppModule {}
diff --git a/api/src/app.service.ts b/api/src/app.service.ts
new file mode 100644
index 00000000..927d7cca
--- /dev/null
+++ b/api/src/app.service.ts
@@ -0,0 +1,8 @@
+import { Injectable } from '@nestjs/common';
+
+@Injectable()
+export class AppService {
+ getHello(): string {
+ return 'Hello World!';
+ }
+}
diff --git a/api/src/forms/forms.module.ts b/api/src/forms/forms.module.ts
new file mode 100644
index 00000000..ad6d579c
--- /dev/null
+++ b/api/src/forms/forms.module.ts
@@ -0,0 +1,7 @@
+import { Module } from '@nestjs/common';
+
+@Module({
+ providers: [],
+ exports: [],
+})
+export class FormsModule {}
diff --git a/api/src/main.ts b/api/src/main.ts
new file mode 100644
index 00000000..1e7989a5
--- /dev/null
+++ b/api/src/main.ts
@@ -0,0 +1,22 @@
+import { NestFactory } from '@nestjs/core';
+import { SwaggerModule, DocumentBuilder } from '@nestjs/swagger';
+import { AppModule } from './app.module';
+
+const pkg = require('../package.json')
+
+async function bootstrap() {
+ const app = await NestFactory.create(AppModule);
+
+ const options = new DocumentBuilder()
+ .setTitle('OhMyForm')
+ .setDescription('API documentation')
+ .setVersion(pkg.version)
+ .build();
+
+ const document = SwaggerModule.createDocument(app, options);
+ SwaggerModule.setup('doc', app, document);
+
+ await app.listen(3000);
+}
+
+bootstrap();
diff --git a/api/src/terminus-options.service.ts b/api/src/terminus-options.service.ts
new file mode 100644
index 00000000..5346b416
--- /dev/null
+++ b/api/src/terminus-options.service.ts
@@ -0,0 +1,29 @@
+import {
+ TerminusEndpoint,
+ TerminusOptionsFactory,
+ DNSHealthIndicator,
+ MongooseHealthIndicator,
+ TerminusModuleOptions
+} from '@nestjs/terminus';
+import { Injectable } from '@nestjs/common';
+
+@Injectable()
+export class TerminusOptionsService implements TerminusOptionsFactory {
+ constructor(
+ private readonly dns: DNSHealthIndicator,
+ private readonly mongoose: MongooseHealthIndicator
+ ) {}
+
+ createTerminusOptions(): TerminusModuleOptions {
+ const healthEndpoint: TerminusEndpoint = {
+ url: '/health',
+ healthIndicators: [
+ async () => this.dns.pingCheck('mail', 'https://google.com'),
+ async () => this.mongoose.pingCheck('mongo')
+ ],
+ };
+ return {
+ endpoints: [healthEndpoint],
+ };
+ }
+}
diff --git a/api/src/users/users.module.ts b/api/src/users/users.module.ts
new file mode 100644
index 00000000..fa1c4450
--- /dev/null
+++ b/api/src/users/users.module.ts
@@ -0,0 +1,7 @@
+import { Module } from '@nestjs/common';
+
+@Module({
+ providers: [],
+ exports: [],
+})
+export class UsersModule {}
diff --git a/api/tsconfig.build.json b/api/tsconfig.build.json
new file mode 100644
index 00000000..64f86c6b
--- /dev/null
+++ b/api/tsconfig.build.json
@@ -0,0 +1,4 @@
+{
+ "extends": "./tsconfig.json",
+ "exclude": ["node_modules", "test", "dist", "**/*spec.ts"]
+}
diff --git a/api/tsconfig.json b/api/tsconfig.json
new file mode 100644
index 00000000..69f185fd
--- /dev/null
+++ b/api/tsconfig.json
@@ -0,0 +1,15 @@
+{
+ "compilerOptions": {
+ "module": "commonjs",
+ "declaration": true,
+ "removeComments": true,
+ "emitDecoratorMetadata": true,
+ "experimentalDecorators": true,
+ "target": "es2017",
+ "sourceMap": true,
+ "outDir": "./dist",
+ "baseUrl": "./",
+ "incremental": true
+ },
+ "exclude": ["node_modules", "dist"]
+}
diff --git a/api/tslint.json b/api/tslint.json
new file mode 100644
index 00000000..e66f0a4a
--- /dev/null
+++ b/api/tslint.json
@@ -0,0 +1,55 @@
+{
+ "defaultSeverity": "error",
+ "extends": [
+ "tslint:recommended"
+ ],
+ "jsRules": {
+ "no-unused-expression": true
+ },
+ "rules": {
+ "eofline": false,
+ "quotemark": [
+ true,
+ "single"
+ ],
+ "indent": false,
+ "member-access": [
+ false
+ ],
+ "ordered-imports": [
+ false
+ ],
+ "max-line-length": [
+ true,
+ 150
+ ],
+ "member-ordering": [
+ false
+ ],
+ "curly": false,
+ "interface-name": [
+ false
+ ],
+ "array-type": [
+ false
+ ],
+ "no-empty-interface": false,
+ "no-empty": false,
+ "arrow-parens": false,
+ "object-literal-sort-keys": false,
+ "no-unused-expression": false,
+ "max-classes-per-file": [
+ false
+ ],
+ "variable-name": [
+ false
+ ],
+ "one-line": [
+ false
+ ],
+ "one-variable-per-declaration": [
+ false
+ ]
+ },
+ "rulesDirectory": []
+}