feat: add database seed script

This commit is contained in:
2026-08-29 23:00:27 +03:30
parent dd9a31278e
commit 9ecc9647b5
6 changed files with 1406 additions and 10 deletions
+504
View File
@@ -59,6 +59,7 @@
"ts-loader": "^9.5.2", "ts-loader": "^9.5.2",
"ts-node": "^10.9.2", "ts-node": "^10.9.2",
"tsconfig-paths": "^4.2.0", "tsconfig-paths": "^4.2.0",
"tsx": "^4.23.12",
"typescript": "^5.7.3", "typescript": "^5.7.3",
"typescript-eslint": "^8.20.0" "typescript-eslint": "^8.20.0"
} }
@@ -775,6 +776,448 @@
"dev": true, "dev": true,
"license": "MIT" "license": "MIT"
}, },
"node_modules/@esbuild/aix-ppc64": {
"version": "0.28.2",
"resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.28.2.tgz",
"integrity": "sha512-XExcO+dvLKvVtNTibSTBej1NCAbaGhWn9Ww1ZPx80qsahhPFe/8jgWP0IchNe0F3HwkU7n8ejhH8bjonqht8mQ==",
"cpu": [
"ppc64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"aix"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/android-arm": {
"version": "0.28.2",
"resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.28.2.tgz",
"integrity": "sha512-kXXoiPVVGQcnIYGOeaovwOURpniDBpSq4A03qkQ+BMQqtGG6HYap3xne9C1O1yo4TR3qxlCX5IqqmX6fFo2Lqg==",
"cpu": [
"arm"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"android"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/android-arm64": {
"version": "0.28.2",
"resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.28.2.tgz",
"integrity": "sha512-5YfKeeI8qWfBZIX+u2xZC3Zlb3Os/gLS2sbEKM+I4ZOcsWmHS2WLysCcQZDAFRslDUU5Oiq44gf6PYN1vGwG5A==",
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"android"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/android-x64": {
"version": "0.28.2",
"resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.28.2.tgz",
"integrity": "sha512-O387ite7SzUyCcy3JQX4P4bLtEA7bLLkx+esve5JHnyYfNTxcVpXZo9jhdB0lTKN44gztELTdU7nS8Nr16Fs1Q==",
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"android"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/darwin-arm64": {
"version": "0.28.2",
"resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.28.2.tgz",
"integrity": "sha512-n4KqkOQrraxHJcgjM1RvwbigfQKIKJVpM7xp+KsxiyUSrRdIXnt73VhrPAx0fV44hgfmIVKjxMN9J1t5jySVkw==",
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"darwin"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/darwin-x64": {
"version": "0.28.2",
"resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.28.2.tgz",
"integrity": "sha512-uq6suIWYP37qzGddBKPw5QEQPi6HiLGsO7UmkpfyaYNQ3D+rN6w6WfwH+nuqcGXWvawGwxOEroO4YGnFh95azw==",
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"darwin"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/freebsd-arm64": {
"version": "0.28.2",
"resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.28.2.tgz",
"integrity": "sha512-n+I0BTSRIoy+d6RPKnEVwql5UwBJolytvY4mAOIEJorKlqgPII8ix6slVVrfZ5Tnj7glIZvloylbB/EJPMWEXw==",
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"freebsd"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/freebsd-x64": {
"version": "0.28.2",
"resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.28.2.tgz",
"integrity": "sha512-78XJTJkvPs0kz2w61301PJjXl4g7q3JqiYMZ/M/yVI73EHBrCRTgkhu9oqG7vPqq+a/yadEW8aD+agKlk5xrmg==",
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"freebsd"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/linux-arm": {
"version": "0.28.2",
"resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.28.2.tgz",
"integrity": "sha512-XlDnu2q5yoqems+xay6wSAcg9DDD7K9RLKZEBOMZm3ckNpJBvOX20tSfby8KfrrhINDyv9V2YVZKY/SpoGJI8w==",
"cpu": [
"arm"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/linux-arm64": {
"version": "0.28.2",
"resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.28.2.tgz",
"integrity": "sha512-pW4AC0P3it8c7do9MVM4p51FzHzdM/TZrerurgRcHJ2WTa1VQ1CIq18xncfpBJw4ojkiZZrKW2yIBWBP92j6Ug==",
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/linux-ia32": {
"version": "0.28.2",
"resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.28.2.tgz",
"integrity": "sha512-CYbnj78HsIeA+DhgUKgFCfvNsTHFhMMrinUrMZpDXJXKN8T3XViTZ/+wtHeVxEWY8ewSzTFN+nRmSwO2tZaLUQ==",
"cpu": [
"ia32"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/linux-loong64": {
"version": "0.28.2",
"resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.28.2.tgz",
"integrity": "sha512-buwkd8nsph4R+ajRvw0qM5Hja/TXQow3ptzWO2EbG/cqcIkHloRrdlBtQlshyYGTNFvfkfJ5tpPLVkY4DtsPfQ==",
"cpu": [
"loong64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/linux-mips64el": {
"version": "0.28.2",
"resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.28.2.tgz",
"integrity": "sha512-ZVykbDyk7519VwiNb9Lcj9m8XM6v5V9uKPvrEMkkEedVewf+0itkhahp4HDpgERXhwLRpWFypsGbG/J8s0QjJA==",
"cpu": [
"mips64el"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/linux-ppc64": {
"version": "0.28.2",
"resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.28.2.tgz",
"integrity": "sha512-CAXl+Dtd9UUuJd8pKKdwh6MLm3MUMiqMPmhZ3tTSXPqfyQ3vDl6R5hZdZ/kYojK4ofXtdfSv1tFq8XzWx3heNQ==",
"cpu": [
"ppc64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/linux-riscv64": {
"version": "0.28.2",
"resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.28.2.tgz",
"integrity": "sha512-GeXCej4IQtU1B+QlDV8W/RRvbzI3O/Stss+/bCXv4lZls5WGRtu2a+3JkA3i4qIUlMXpcHebWpF8AkJhATowuA==",
"cpu": [
"riscv64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/linux-s390x": {
"version": "0.28.2",
"resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.28.2.tgz",
"integrity": "sha512-3H1weTYZPxt/WOhByszQZybS9w5lKzUn1FDMsgEChbHWQwHYQQRfBxgCcZvPhjHfKyJjIievvMmEUawJrdY9Dg==",
"cpu": [
"s390x"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/linux-x64": {
"version": "0.28.2",
"resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.28.2.tgz",
"integrity": "sha512-4xTZr1FUmSoQW4XIWmit3tzQrUTZM+N3P0XV8xROKYF50XfI7xeO90+1bZvNwxIufQ9hDQVRJH5YhgPVF8A/HQ==",
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/netbsd-arm64": {
"version": "0.28.2",
"resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.28.2.tgz",
"integrity": "sha512-sSATRjPeDBg3pdgHoQfoYBob11Kk1FGa9lui5RIHZCoCkJa9QKlvl3/vKz2usCmYYjs7ymJR/2Nnsqe+Hjt5nw==",
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"netbsd"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/netbsd-x64": {
"version": "0.28.2",
"resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.28.2.tgz",
"integrity": "sha512-lqnzCV+mM0gIADaKihiCg6ifgfU2L3h5E33rNQBN1Y4MaVGnzryzmvvf7UHxprpQdE8hpqLolJ9Rl+SkIRDpyw==",
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"netbsd"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/openbsd-arm64": {
"version": "0.28.2",
"resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.28.2.tgz",
"integrity": "sha512-AL2qJILH7lNjrDmCQDvdxMfAUIv8KMNZOvrwAQ8i8//ntL9FflhOyMJ8OZSMBb8/AWXe3/5v5S20y3zCoZWKoQ==",
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"openbsd"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/openbsd-x64": {
"version": "0.28.2",
"resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.28.2.tgz",
"integrity": "sha512-QtiuPytchRyC4rwUKhexJdQKvDuZ6hWloi3igqPQNUJCS1/v9EiO3UTOXR6A3FoMo4fnAKbWJdqaIwhOzh8qEw==",
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"openbsd"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/openharmony-arm64": {
"version": "0.28.2",
"resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.28.2.tgz",
"integrity": "sha512-WkhYDmpTjLvGlScA1rwjRUmhl4k8oXR3cIbtqWmELgU/dFeHHlEllxDvdWcNJV9rbzCexB5vz8gtNewWLgCT7Q==",
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"openharmony"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/sunos-x64": {
"version": "0.28.2",
"resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.28.2.tgz",
"integrity": "sha512-GPMSkTOtMnv2U2F8gxe4Io6qmVs+YKyp832Etqqxr0hFngmXQ3rzwytelm3GIn7T4VviRUlf3sOgBOiTdvaf7g==",
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"sunos"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/win32-arm64": {
"version": "0.28.2",
"resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.28.2.tgz",
"integrity": "sha512-PIhhEkE9uPBleRBrQEJpUn7MBnibZzbGzYWPmY3x+YoVg/95zbjB4CxPPOQ8l5tYYM4mMaCthF8/1DIfBQQyWQ==",
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"win32"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/win32-ia32": {
"version": "0.28.2",
"resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.28.2.tgz",
"integrity": "sha512-YmJbfTlvU7Sdn9BB+4PRES4oB6pxgS37MAONj+hBr/cpXS1aBPKXxNnDbu+QCWPj0o9dgyxeq79g6c5P8KeuYA==",
"cpu": [
"ia32"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"win32"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/win32-x64": {
"version": "0.28.2",
"resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.28.2.tgz",
"integrity": "sha512-5ebpxr3nWMzrL/rnUI755Jkuee0bHL/Gq0WTF9lvcpv73wAp5eu8MfBUgWK9bhWvZjj7yX8etf/8tI8Ney695g==",
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"win32"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@eslint-community/eslint-utils": { "node_modules/@eslint-community/eslint-utils": {
"version": "4.10.1", "version": "4.10.1",
"resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.10.1.tgz", "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.10.1.tgz",
@@ -5151,6 +5594,48 @@
"node": ">= 0.4" "node": ">= 0.4"
} }
}, },
"node_modules/esbuild": {
"version": "0.28.2",
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.28.2.tgz",
"integrity": "sha512-HKVLS8dvII+xoKW9kmqxbRKrnWEXfJJr/FZhhJmiqIB0e053QNYFqOBouTMO/k5sID4MvCiUCvv8b9M4h32wIA==",
"dev": true,
"hasInstallScript": true,
"license": "MIT",
"bin": {
"esbuild": "bin/esbuild"
},
"engines": {
"node": ">=18"
},
"optionalDependencies": {
"@esbuild/aix-ppc64": "0.28.2",
"@esbuild/android-arm": "0.28.2",
"@esbuild/android-arm64": "0.28.2",
"@esbuild/android-x64": "0.28.2",
"@esbuild/darwin-arm64": "0.28.2",
"@esbuild/darwin-x64": "0.28.2",
"@esbuild/freebsd-arm64": "0.28.2",
"@esbuild/freebsd-x64": "0.28.2",
"@esbuild/linux-arm": "0.28.2",
"@esbuild/linux-arm64": "0.28.2",
"@esbuild/linux-ia32": "0.28.2",
"@esbuild/linux-loong64": "0.28.2",
"@esbuild/linux-mips64el": "0.28.2",
"@esbuild/linux-ppc64": "0.28.2",
"@esbuild/linux-riscv64": "0.28.2",
"@esbuild/linux-s390x": "0.28.2",
"@esbuild/linux-x64": "0.28.2",
"@esbuild/netbsd-arm64": "0.28.2",
"@esbuild/netbsd-x64": "0.28.2",
"@esbuild/openbsd-arm64": "0.28.2",
"@esbuild/openbsd-x64": "0.28.2",
"@esbuild/openharmony-arm64": "0.28.2",
"@esbuild/sunos-x64": "0.28.2",
"@esbuild/win32-arm64": "0.28.2",
"@esbuild/win32-ia32": "0.28.2",
"@esbuild/win32-x64": "0.28.2"
}
},
"node_modules/escalade": { "node_modules/escalade": {
"version": "3.2.0", "version": "3.2.0",
"resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz",
@@ -10377,6 +10862,25 @@
"integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==",
"license": "0BSD" "license": "0BSD"
}, },
"node_modules/tsx": {
"version": "4.23.12",
"resolved": "https://registry.npmjs.org/tsx/-/tsx-4.23.12.tgz",
"integrity": "sha512-FDf4L4sYzKtzWYhU/Xm0AQFdTjdIxNo9ElTf2mxXM6k8YMHXzYUe4yODVaXP4V9uMFbVg8c0qyBccK2OOxb45Q==",
"dev": true,
"license": "MIT",
"dependencies": {
"esbuild": "~0.28.0"
},
"bin": {
"tsx": "dist/cli.mjs"
},
"engines": {
"node": ">=18.0.0"
},
"optionalDependencies": {
"fsevents": "~2.3.3"
}
},
"node_modules/type-check": { "node_modules/type-check": {
"version": "0.4.0", "version": "0.4.0",
"resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
+4 -1
View File
@@ -25,7 +25,9 @@
"migration:run:dev": "npm run typeorm:dev -- migration:run", "migration:run:dev": "npm run typeorm:dev -- migration:run",
"migration:run:prod": "npm run typeorm:prod -- migration:run", "migration:run:prod": "npm run typeorm:prod -- migration:run",
"migration:revert:dev": "npm run typeorm:dev -- migration:revert", "migration:revert:dev": "npm run typeorm:dev -- migration:revert",
"migration:revert:prod": "npm run typeorm:prod -- migration:revert" "migration:revert:prod": "npm run typeorm:prod -- migration:revert",
"seed": "cross-env NODE_ENV=development tsx src/database/seeds/seed.ts",
"seed:prod": "cross-env NODE_ENV=production node dist/database/seeds/seed.js"
}, },
"dependencies": { "dependencies": {
"@nestjs/common": "^11.0.1", "@nestjs/common": "^11.0.1",
@@ -78,6 +80,7 @@
"ts-loader": "^9.5.2", "ts-loader": "^9.5.2",
"ts-node": "^10.9.2", "ts-node": "^10.9.2",
"tsconfig-paths": "^4.2.0", "tsconfig-paths": "^4.2.0",
"tsx": "^4.23.12",
"typescript": "^5.7.3", "typescript": "^5.7.3",
"typescript-eslint": "^8.20.0" "typescript-eslint": "^8.20.0"
}, },
+887
View File
@@ -0,0 +1,887 @@
import * as bcrypt from 'bcrypt';
import dataSource from '../data-source';
import { User } from '../../modules/users/entities/user.entity';
import { Test } from '../../modules/tests/entities/test.entity';
import { Question } from '../../modules/questions/entities/question.entity';
import { Choice } from '../../modules/questions/entities/choice.entity';
import { QuestionRangeRule } from '../../modules/questions/entities/question-range-rule.entity';
import { QuestionTransition } from '../../modules/questions/entities/question-transition.entity';
import { Role } from '@/common/enums/roles.enum';
import { QuestionType } from '../../modules/questions/enums/question-type.enum';
import { AccessType } from '@/modules/tests/enums/access-types.enum';
import { TestStatus } from '../../modules/tests/enums/test-status.enum';
import { QuestionTransitionType } from '../../modules/questions/enums/question-transition-type.enum';
const TEST_TITLE = 'تست ارزیابی خطر ابتلا به عفونت‌های منتقله از راه جنسی';
const SUPERUSER_PHONE = process.env.SUPERUSER_PHONE;
const SUPERUSER_PASSWORD = process.env.SUPERUSER_PASSWORD;
async function seedSuperuser() {
if (!SUPERUSER_PHONE || !SUPERUSER_PASSWORD) {
console.log(
'SUPERUSER_PHONE or SUPERUSER_PASSWORD is not defined. Skipping superuser seed.',
);
return;
}
const userRepository = dataSource.getRepository(User);
const existingUser = await userRepository.findOne({
where: {
phone: SUPERUSER_PHONE,
},
});
if (existingUser) {
if (existingUser.role !== Role.SUPERUSER) {
existingUser.role = Role.SUPERUSER;
await userRepository.save(existingUser);
console.log(`User ${SUPERUSER_PHONE} promoted to SUPERUSER.`);
} else {
console.log(`Superuser ${SUPERUSER_PHONE} already exists.`);
}
return;
}
const passwordHash = await bcrypt.hash(SUPERUSER_PASSWORD, 12);
const superuser = userRepository.create({
phone: SUPERUSER_PHONE,
password: passwordHash,
role: Role.SUPERUSER,
});
await userRepository.save(superuser);
console.log(`Superuser ${SUPERUSER_PHONE} created successfully.`);
}
async function seedTest() {
const result = await dataSource.transaction(async (manager) => {
const testRepository = manager.getRepository(Test);
const questionRepository = manager.getRepository(Question);
const choiceRepository = manager.getRepository(Choice);
const rangeRuleRepository = manager.getRepository(QuestionRangeRule);
const transitionRepository = manager.getRepository(QuestionTransition);
const existingTest = await testRepository.findOne({
where: {
title: TEST_TITLE,
},
});
if (existingTest) {
return {
created: false,
testId: existingTest.id,
};
}
/*
* ---------------------------------------------------------
* TEST
* ---------------------------------------------------------
*/
const test = testRepository.create({
title: TEST_TITLE,
description:
'این تست برای ارزیابی عوامل مرتبط با خطر ابتلا به عفونت‌های منتقله از راه جنسی طراحی شده است.',
status: TestStatus.PUBLISHED,
accessType: AccessType.FREE,
isActive: true,
questionsCount: 12,
});
const savedTest = await testRepository.save(test);
/*
* ---------------------------------------------------------
* QUESTIONS
* ---------------------------------------------------------
*/
const q1 = questionRepository.create({
test: savedTest,
type: QuestionType.SINGLE_CHOICE,
order: 1,
weight: 1,
required: true,
content:
'آیا اخیراً علائمی داشته‌اید که فکر می‌کنید ممکن است ناشی از عفونت‌های منتقله از راه جنسی باشند؟',
metadata: {},
});
const q2 = questionRepository.create({
test: savedTest,
type: QuestionType.SINGLE_CHOICE,
order: 2,
weight: 1,
required: true,
content:
'آیا تا به حال پزشک یا یکی از کادر درمان به شما گفته است که به یک یا چند بیماری مقاربتی مبتلا شده‌اید؟',
metadata: {},
});
const q3 = questionRepository.create({
test: savedTest,
type: QuestionType.MULTI_CHOICE,
order: 3,
weight: 1,
required: true,
content:
'تاکنون به کدام‌یک از بیماری‌های مقاربتی مبتلا بوده‌اید؟ (می‌توانید بیش از یک گزینه را انتخاب کنید.)',
metadata: {},
});
const q4 = questionRepository.create({
test: savedTest,
type: QuestionType.MULTI_CHOICE,
order: 4,
weight: 1,
required: true,
content:
'آیا اخیراً با فردی که به یکی از بیماری‌های زیر مبتلا بوده، رابطهٔ جنسی داشته‌اید؟',
metadata: {},
});
const q5 = questionRepository.create({
test: savedTest,
type: QuestionType.SINGLE_CHOICE,
order: 5,
weight: 1,
required: true,
content: 'آیا تاکنون ماده‌ای غیرقانونی را به صورت تزریقی مصرف کرده‌اید؟',
metadata: {},
});
const q6 = questionRepository.create({
test: savedTest,
type: QuestionType.SINGLE_CHOICE,
order: 6,
weight: 1,
required: true,
content:
'در ۱۲ ماه گذشته، آیا با فردی با تابعیت غیر ایرانی رابطهٔ جنسی داشته‌اید؟ (مثلاً هنگام سفر به خارج از کشور رابطهٔ جنسی داشته‌اید، یا در ایران با فردی از کشور دیگری رابطه داشته‌اید؟)',
metadata: {},
});
const q7 = questionRepository.create({
test: savedTest,
type: QuestionType.SINGLE_CHOICE,
order: 7,
weight: 1,
required: true,
content: 'آیا در حال حاضر به عنوان کارگر جنسی فعالیت می‌کنید؟',
metadata: {},
});
const q8 = questionRepository.create({
test: savedTest,
type: QuestionType.SINGLE_CHOICE,
order: 8,
weight: 1,
required: true,
content:
'در ۱۲ ماه گذشته، آیا با یک فرد همجنس رابطهٔ جنسی داشته‌اید؟ (مثلاً مرد با مرد)',
metadata: {},
});
const q9 = questionRepository.create({
test: savedTest,
type: QuestionType.NUMERIC,
order: 9,
weight: 1,
required: true,
content:
'در ۱۲ ماه گذشته، با چند فرد از همجنس خود رابطهٔ جنسی داشته‌اید؟',
metadata: {},
});
const q10 = questionRepository.create({
test: savedTest,
type: QuestionType.SINGLE_CHOICE,
order: 10,
weight: 1,
required: true,
content:
'در ۱۲ ماه گذشته، آیا با یک فرد از جنس مخالف رابطهٔ جنسی داشته‌اید؟',
metadata: {},
});
const q11 = questionRepository.create({
test: savedTest,
type: QuestionType.NUMERIC,
order: 11,
weight: 1,
required: true,
content:
'در ۱۲ ماه گذشته، با چند نفر از جنس مخالف رابطهٔ جنسی داشته‌اید؟',
metadata: {},
});
const q12 = questionRepository.create({
test: savedTest,
type: QuestionType.SINGLE_CHOICE,
order: 12,
weight: 1,
required: true,
content:
'در ۱۲ ماه گذشته، آیا هنگام رابطهٔ واژنی یا مقعدی از کاندوم استفاده کرده‌اید؟',
metadata: {},
});
await questionRepository.save([
q1,
q2,
q3,
q4,
q5,
q6,
q7,
q8,
q9,
q10,
q11,
q12,
]);
/*
* ---------------------------------------------------------
* QUESTION 1 CHOICES
* ---------------------------------------------------------
*/
const q1Yes = choiceRepository.create({
question: q1,
text: 'بله',
value: 1,
order: 1,
score: 1,
});
const q1No = choiceRepository.create({
question: q1,
text: 'خیر',
value: 0,
order: 2,
score: 0,
});
await choiceRepository.save([q1Yes, q1No]);
/*
* ---------------------------------------------------------
* QUESTION 2 CHOICES
* ---------------------------------------------------------
*/
const q2Yes = choiceRepository.create({
question: q2,
text: 'بله',
value: 1,
order: 1,
score: 1,
});
const q2No = choiceRepository.create({
question: q2,
text: 'خیر',
value: 0,
order: 2,
score: 0,
});
const q2NotSure = choiceRepository.create({
question: q2,
text: 'مطمئن نیستم',
value: 2,
order: 3,
score: 1,
});
await choiceRepository.save([q2Yes, q2No, q2NotSure]);
/*
* ---------------------------------------------------------
* QUESTION 3 CHOICES
* ---------------------------------------------------------
*/
const q3Texts = [
'اچ‌آی‌وی (HIV)',
'سیفلیس',
'سوزاک',
'عفونت غیراختصاصی مجرای ادرار',
'هپاتیت B',
'هپاتیت C',
'کلامیدیا',
'زگیل تناسلی',
// 'سایر',
// 'مطمئن نیستم',
// 'هیچ کدام',
];
const q3Choices = q3Texts.map((text, index) =>
choiceRepository.create({
question: q3,
text,
value: index + 1,
order: index + 1,
score: 2,
}),
);
await choiceRepository.save(q3Choices);
/*
* ---------------------------------------------------------
* QUESTION 4 CHOICES
* ---------------------------------------------------------
*/
const q4Texts = [
'سیفلیس',
'سوزاک',
'عفونت غیراختصاصی مجرای ادرار',
'هپاتیت B',
'هپاتیت C',
'کلامیدیا',
'زگیل تناسلی',
// 'سایر',
// 'مطمئن نیستم',
// 'هیچ کدام',
];
const q4Choices = q4Texts.map((text, index) =>
choiceRepository.create({
question: q4,
text,
value: index + 1,
order: index + 1,
score: 1,
}),
);
await choiceRepository.save(q4Choices);
/*
* ---------------------------------------------------------
* QUESTION 5 CHOICES
* ---------------------------------------------------------
*/
const q5Yes = choiceRepository.create({
question: q5,
text: 'بله',
value: 1,
order: 1,
score: 1,
});
const q5No = choiceRepository.create({
question: q5,
text: 'خیر',
value: 0,
order: 2,
score: 0,
});
const q5NotSure = choiceRepository.create({
question: q5,
text: 'مطمئن نیستم',
value: 2,
order: 3,
score: 1,
});
await choiceRepository.save([q5Yes, q5No, q5NotSure]);
/*
* ---------------------------------------------------------
* QUESTION 6 CHOICES
* ---------------------------------------------------------
*/
const q6Yes = choiceRepository.create({
question: q6,
text: 'بله',
value: 1,
order: 1,
score: 1,
});
const q6No = choiceRepository.create({
question: q6,
text: 'خیر',
value: 0,
order: 2,
score: 0,
});
const q6NotSure = choiceRepository.create({
question: q6,
text: 'مطمئن نیستم',
value: 2,
order: 3,
score: 1,
});
await choiceRepository.save([q6Yes, q6No, q6NotSure]);
/*
* ---------------------------------------------------------
* QUESTION 7 CHOICES
* ---------------------------------------------------------
*/
const q7Yes = choiceRepository.create({
question: q7,
text: 'بله',
value: 1,
order: 1,
score: 2,
});
const q7No = choiceRepository.create({
question: q7,
text: 'خیر',
value: 0,
order: 2,
score: 0,
});
await choiceRepository.save([q7Yes, q7No]);
/*
* ---------------------------------------------------------
* QUESTION 8 CHOICES
* ---------------------------------------------------------
*/
const q8Yes = choiceRepository.create({
question: q8,
text: 'بله',
value: 1,
order: 1,
score: 2,
});
const q8No = choiceRepository.create({
question: q8,
text: 'خیر',
value: 0,
order: 2,
score: 0,
});
await choiceRepository.save([q8Yes, q8No]);
/*
* ---------------------------------------------------------
* QUESTION 10 CHOICES
* ---------------------------------------------------------
*/
const q10Yes = choiceRepository.create({
question: q10,
text: 'بله',
value: 1,
order: 1,
score: 1,
});
const q10No = choiceRepository.create({
question: q10,
text: 'خیر',
value: 0,
order: 2,
score: 0,
});
await choiceRepository.save([q10Yes, q10No]);
/*
* ---------------------------------------------------------
* QUESTION 12 CHOICES
* ---------------------------------------------------------
*/
const q12Always = choiceRepository.create({
question: q12,
text: 'همیشه با همهٔ شرکای جنسی‌ام از کاندوم استفاده کرده‌ام.',
value: 1,
order: 1,
score: 0,
});
const q12Sometimes = choiceRepository.create({
question: q12,
text: 'گاهی با شرکای جنسی‌ام از کاندوم استفاده کرده‌ام.',
value: 2,
order: 2,
score: 2,
});
const q12Never = choiceRepository.create({
question: q12,
text: 'هیچ‌وقت با هیچ‌کدام از شرکای جنسی‌ام از کاندوم استفاده نکرده‌ام.',
value: 3,
order: 3,
score: 5,
});
const q12NotApplicable = choiceRepository.create({
question: q12,
text: 'سؤال در مورد من صحت ندارد؛ چون که رابطهٔ واژنی یا مقعدی نداشته‌ام.',
value: 4,
order: 4,
score: 1,
});
const q12NotSure = choiceRepository.create({
question: q12,
text: 'مطمئن نیستم.',
value: 5,
order: 5,
score: 2,
});
await choiceRepository.save([
q12Always,
q12Sometimes,
q12Never,
q12NotApplicable,
q12NotSure,
]);
/*
* ---------------------------------------------------------
* QUESTION 9 RANGE RULES
* ---------------------------------------------------------
*
* 1 person => 2
* 2 people => 3
* 3 or more => 5
*/
await rangeRuleRepository.save([
rangeRuleRepository.create({
question: q9,
min: 1,
max: 1,
score: 2,
}),
rangeRuleRepository.create({
question: q9,
min: 2,
max: 2,
score: 3,
}),
rangeRuleRepository.create({
question: q9,
min: 3,
max: 2147483647,
score: 5,
}),
]);
/*
* ---------------------------------------------------------
* QUESTION 11 RANGE RULES
* ---------------------------------------------------------
*
* 1 person => 1
* 2 people => 2
* 3 or more => 3
*/
await rangeRuleRepository.save([
rangeRuleRepository.create({
question: q11,
min: 1,
max: 1,
score: 1,
}),
rangeRuleRepository.create({
question: q11,
min: 2,
max: 2,
score: 2,
}),
rangeRuleRepository.create({
question: q11,
min: 3,
max: 2147483647,
score: 3,
}),
]);
/*
* ---------------------------------------------------------
* QUESTION TRANSITIONS
* ---------------------------------------------------------
*/
/*
* START -> Q1
*/
await transitionRepository.save(
transitionRepository.create({
test: savedTest,
fromQuestion: null,
toQuestion: q1,
type: QuestionTransitionType.START,
condition: null,
}),
);
/*
* Q1 -> Q2
*/
await transitionRepository.save(
transitionRepository.create({
test: savedTest,
fromQuestion: q1,
toQuestion: q2,
type: QuestionTransitionType.DEFAULT,
condition: null,
}),
);
/*
* Q2 -> Q3
*/
await transitionRepository.save(
transitionRepository.create({
test: savedTest,
fromQuestion: q2,
toQuestion: q3,
type: QuestionTransitionType.DEFAULT,
condition: null,
}),
);
/*
* Q3 -> Q4
*/
await transitionRepository.save(
transitionRepository.create({
test: savedTest,
fromQuestion: q3,
toQuestion: q4,
type: QuestionTransitionType.DEFAULT,
condition: null,
}),
);
/*
* Q4 -> Q5
*/
await transitionRepository.save(
transitionRepository.create({
test: savedTest,
fromQuestion: q4,
toQuestion: q5,
type: QuestionTransitionType.DEFAULT,
condition: null,
}),
);
/*
* Q5 -> Q6
*/
await transitionRepository.save(
transitionRepository.create({
test: savedTest,
fromQuestion: q5,
toQuestion: q6,
type: QuestionTransitionType.DEFAULT,
condition: null,
}),
);
/*
* Q6 -> Q7
*/
await transitionRepository.save(
transitionRepository.create({
test: savedTest,
fromQuestion: q6,
toQuestion: q7,
type: QuestionTransitionType.DEFAULT,
condition: null,
}),
);
/*
* Q7 -> Q8
*/
await transitionRepository.save(
transitionRepository.create({
test: savedTest,
fromQuestion: q7,
toQuestion: q8,
type: QuestionTransitionType.DEFAULT,
condition: null,
}),
);
/*
* ---------------------------------------------------------
* Q8 BRANCH
* ---------------------------------------------------------
*
* YES -> Q9
* NO -> Q10
*/
await transitionRepository.save(
transitionRepository.create({
test: savedTest,
fromQuestion: q8,
toQuestion: q9,
type: QuestionTransitionType.CHOICE,
condition: {
choiceId: q8Yes.id,
},
}),
);
await transitionRepository.save(
transitionRepository.create({
test: savedTest,
fromQuestion: q8,
toQuestion: q10,
type: QuestionTransitionType.DEFAULT,
condition: null,
}),
);
/*
* Q9 -> Q10
*/
await transitionRepository.save(
transitionRepository.create({
test: savedTest,
fromQuestion: q9,
toQuestion: q10,
type: QuestionTransitionType.DEFAULT,
condition: null,
}),
);
/*
* ---------------------------------------------------------
* Q10 BRANCH
* ---------------------------------------------------------
*
* YES -> Q11
* NO -> Q12
*/
await transitionRepository.save(
transitionRepository.create({
test: savedTest,
fromQuestion: q10,
toQuestion: q11,
type: QuestionTransitionType.CHOICE,
condition: {
choiceId: q10Yes.id,
},
}),
);
await transitionRepository.save(
transitionRepository.create({
test: savedTest,
fromQuestion: q10,
toQuestion: q12,
type: QuestionTransitionType.DEFAULT,
condition: null,
}),
);
/*
* Q11 -> Q12
*/
await transitionRepository.save(
transitionRepository.create({
test: savedTest,
fromQuestion: q11,
toQuestion: q12,
type: QuestionTransitionType.DEFAULT,
condition: null,
}),
);
/*
* Q12 -> END
*/
await transitionRepository.save(
transitionRepository.create({
test: savedTest,
fromQuestion: q12,
toQuestion: null,
type: QuestionTransitionType.END,
condition: null,
}),
);
return {
created: true,
testId: savedTest.id,
};
});
if (result.created) {
console.log(`Test created successfully. ID: ${result.testId}`);
} else {
console.log(
`Test already exists. ID: ${result.testId}. Nothing was created.`,
);
}
}
async function seed() {
try {
await dataSource.initialize();
console.log('Database connection initialized.');
await seedSuperuser();
await seedTest();
console.log('Seed completed successfully.');
} catch (error) {
console.error('Seed failed:', error);
process.exitCode = 1;
} finally {
if (dataSource.isInitialized) {
await dataSource.destroy();
}
}
}
void seed();
@@ -3,7 +3,7 @@ Authorization: Bearer {{$global.accessToken}}
Content-Type: application/json Content-Type: application/json
{ {
// "accessType": "login", "accessType": "free"
// "isActive": false // "isActive": false
"status": "published" // "status": "published"
} }
@@ -0,0 +1,2 @@
GET {{baseUrl}}/submissions/6183e332-d28d-45ba-90a7-942f9d15100f/history
Authorization: Bearer {{$global.accessToken}}
@@ -1,17 +1,17 @@
POST {{baseUrl}}/submissions/start POST {{baseUrl}}/submissions/start
Authorization: Bearer {{$global.accessToken}}
Content-Type: application/json Content-Type: application/json
# Authorization: Bearer {{$global.accessToken}}
{ {
"testId": 2 "testId": 3
} }
POST {{baseUrl}}/submissions/1/answer POST {{baseUrl}}/submissions/6183e332-d28d-45ba-90a7-942f9d15100f/answer
Authorization: Bearer {{$global.accessToken}}
Content-Type: application/json Content-Type: application/json
# Authorization: Bearer {{$global.accessToken}}
{ {
// "choiceId": 17 "choiceId": 57
// "numericValue": 12 // "numericValue": 10
"choiceIds": [19,21] // "choiceIds": [45]
} }