Compare commits
1 Commits
master
...
dependabot
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
63fa55e410 |
140
.github/workflows/test.yml
vendored
140
.github/workflows/test.yml
vendored
@ -8,13 +8,6 @@ on:
|
||||
branches:
|
||||
- master
|
||||
|
||||
env:
|
||||
CREATE_ADMIN: true
|
||||
ADMIN_EMAIL: admin@localhost
|
||||
ADMIN_USERNAME: admin
|
||||
ADMIN_PASSWORD: admin
|
||||
MAILER_URI: smtp://localhost:1025
|
||||
|
||||
jobs:
|
||||
run-linters:
|
||||
name: Run linters
|
||||
@ -42,136 +35,3 @@ jobs:
|
||||
- name: Typecheck
|
||||
uses: andoshin11/typescript-error-reporter-action@v1.0.2
|
||||
|
||||
run-postgres:
|
||||
name: Run Postgres
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
services:
|
||||
postgres:
|
||||
image: postgres:10-alpine
|
||||
env:
|
||||
POSTGRES_USER: root
|
||||
POSTGRES_PASSWORD: root
|
||||
POSTGRES_DB: ohmyform
|
||||
ports:
|
||||
- 5432:5432
|
||||
options: >-
|
||||
--health-cmd pg_isready
|
||||
--health-interval 10s
|
||||
--health-timeout 5s
|
||||
--health-retries 5
|
||||
|
||||
steps:
|
||||
- name: Check out Git repository
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Set up Node.js
|
||||
uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: 16
|
||||
|
||||
- name: Install Node.js dependencies
|
||||
run: yarn install --frozen-lockfile --silent
|
||||
|
||||
- name: PostgreSQL Migrations
|
||||
run: yarn typeorm migration:run
|
||||
env:
|
||||
DATABASE_DRIVER: postgres
|
||||
|
||||
TYPEORM_CONNECTION: postgres
|
||||
TYPEORM_HOST: localhost
|
||||
TYPEORM_PORT: 5432
|
||||
TYPEORM_USERNAME: root
|
||||
TYPEORM_PASSWORD: root
|
||||
TYPEORM_DATABASE: ohmyform
|
||||
TYPEORM_AUTO_SCHEMA_SYNC: false
|
||||
TYPEORM_ENTITIES: src/entity/**/*.ts
|
||||
TYPEORM_SUBSCRIBERS: src/subscriber/**/*.ts
|
||||
TYPEORM_MIGRATIONS: src/migrations/postgres/**/*.ts
|
||||
TYPEORM_MIGRATIONS_TRANSACTION_MODE: 'each'
|
||||
TYPEORM_ENTITIES_DIR: src/entity
|
||||
TYPEORM_MIGRATIONS_DIR: src/migrations/postgres
|
||||
TYPEORM_SUBSCRIBERS_DIR: src/subscriber
|
||||
|
||||
run-mariadb:
|
||||
name: Run MariaDB
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
services:
|
||||
mariadb:
|
||||
image: mariadb
|
||||
env:
|
||||
MYSQL_ROOT_PASSWORD: root
|
||||
MYSQL_DATABASE: ohmyform
|
||||
ports:
|
||||
- 3306:3306
|
||||
options: >-
|
||||
--health-cmd "mysqladmin ping"
|
||||
--health-interval 10s
|
||||
--health-timeout 5s
|
||||
--health-retries 5
|
||||
|
||||
steps:
|
||||
- name: Check out Git repository
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Set up Node.js
|
||||
uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: 16
|
||||
|
||||
- name: Install Node.js dependencies
|
||||
run: yarn install --frozen-lockfile --silent
|
||||
|
||||
- name: MariaDB Migrations
|
||||
run: yarn typeorm migration:run
|
||||
env:
|
||||
DATABASE_DRIVER: mariadb
|
||||
|
||||
TYPEORM_CONNECTION: mariadb
|
||||
TYPEORM_HOST: localhost
|
||||
TYPEORM_PORT: 3306
|
||||
TYPEORM_USERNAME: root
|
||||
TYPEORM_PASSWORD: root
|
||||
TYPEORM_DATABASE: ohmyform
|
||||
TYPEORM_AUTO_SCHEMA_SYNC: false
|
||||
TYPEORM_ENTITIES: src/entity/**/*.ts
|
||||
TYPEORM_SUBSCRIBERS: src/subscriber/**/*.ts
|
||||
TYPEORM_MIGRATIONS: src/migrations/mariadb/**/*.ts
|
||||
TYPEORM_MIGRATIONS_TRANSACTION_MODE: 'each'
|
||||
TYPEORM_ENTITIES_DIR: src/entity
|
||||
TYPEORM_MIGRATIONS_DIR: src/migrations/mariadb
|
||||
TYPEORM_SUBSCRIBERS_DIR: src/subscriber
|
||||
|
||||
run-sqlite:
|
||||
name: Run SQLite
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Check out Git repository
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Set up Node.js
|
||||
uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: 16
|
||||
|
||||
- name: Install Node.js dependencies
|
||||
run: yarn install --frozen-lockfile --silent
|
||||
|
||||
- name: SQLite Migrations
|
||||
run: yarn typeorm migration:run --transaction none
|
||||
env:
|
||||
DATABASE_DRIVER: sqlite
|
||||
|
||||
TYPEORM_CONNECTION: sqlite
|
||||
TYPEORM_USERNAME: root
|
||||
TYPEORM_DATABASE: data.sqlite
|
||||
TYPEORM_AUTO_SCHEMA_SYNC: false
|
||||
TYPEORM_ENTITIES: src/entity/**/*.ts
|
||||
TYPEORM_SUBSCRIBERS: src/subscriber/**/*.ts
|
||||
TYPEORM_MIGRATIONS: src/migrations/sqlite/**/*.ts
|
||||
TYPEORM_MIGRATIONS_TRANSACTION_MODE: 'none'
|
||||
TYPEORM_ENTITIES_DIR: src/entity
|
||||
TYPEORM_MIGRATIONS_DIR: src/migrations/sqlite
|
||||
TYPEORM_SUBSCRIBERS_DIR: src/subscriber
|
||||
|
||||
11
.travis.yml
Normal file
11
.travis.yml
Normal file
@ -0,0 +1,11 @@
|
||||
language: node_js
|
||||
|
||||
node_js:
|
||||
- 16
|
||||
cache:
|
||||
directories:
|
||||
- node_modules
|
||||
|
||||
script:
|
||||
- yarn
|
||||
- yarn lint
|
||||
70
CHANGELOG.md
70
CHANGELOG.md
@ -5,79 +5,10 @@ All notable changes to this project will be documented in this file.
|
||||
The format is based on [Keep a Changelog](http://keepachangelog.com/)
|
||||
and this project adheres to [Semantic Versioning](http://semver.org/).
|
||||
|
||||
<!--
|
||||
Template for next version
|
||||
## [Unreleased]
|
||||
|
||||
### Added
|
||||
|
||||
### Changed
|
||||
|
||||
### Fixed
|
||||
|
||||
### Security
|
||||
-->
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
### Added
|
||||
|
||||
### Changed
|
||||
|
||||
### Fixed
|
||||
|
||||
- creation of new logic elements
|
||||
- node prune location (https://github.com/ohmyform/ohmyform/issues/184)
|
||||
|
||||
### Security
|
||||
|
||||
## [1.0.3] - 2022-03-27
|
||||
|
||||
### Added
|
||||
|
||||
- add start and end page to form create call
|
||||
|
||||
### Changed
|
||||
|
||||
- notifications / hooks / pages and buttons encode and decode their ids
|
||||
|
||||
### Fixed
|
||||
|
||||
- missing encode / decode for form fields within submissions (https://github.com/ohmyform/ui/commit/30ff2c96bca20c1641d9cbb96c34cce934e1afea#r68602651)
|
||||
- form field resolvers were missing
|
||||
- node-gyp update to enable build on osx 12.3
|
||||
- creating of new fields
|
||||
|
||||
### Security
|
||||
|
||||
- form hooks should only be queryable for form admins
|
||||
|
||||
## [1.0.2] - 2022-03-13
|
||||
|
||||
### Fixed
|
||||
|
||||
- error sending notification when field is not defined (https://github.com/ohmyform/ohmyform/issues/161)
|
||||
|
||||
## [1.0.1] - 2022-03-01
|
||||
|
||||
### Added
|
||||
|
||||
- allow one field nested data to be submitted
|
||||
|
||||
### Fixed
|
||||
|
||||
- only update user fields in update mutation if they changed
|
||||
- form delete
|
||||
- field submission without value field
|
||||
|
||||
### Security
|
||||
|
||||
- start using hashids to prevent insights into form ids (https://hashids.org/javascript/)
|
||||
|
||||
## [1.0.0] - 2022-02-28
|
||||
|
||||
### Added
|
||||
|
||||
- logic backend components
|
||||
- forms now have multiple notification
|
||||
- layout for forms
|
||||
@ -88,7 +19,6 @@ Template for next version
|
||||
- ability to load submission by id if token is present
|
||||
- anonymous form submissions (fixes https://github.com/ohmyform/ohmyform/issues/108)
|
||||
- ability to filter for partial / completed or empty submissions
|
||||
- migration tests for all commits
|
||||
|
||||
### Changed
|
||||
|
||||
|
||||
@ -6,7 +6,7 @@ WORKDIR /usr/src/app
|
||||
RUN apk update && apk add curl bash && rm -rf /var/cache/apk/*
|
||||
|
||||
# install node-prune (https://github.com/tj/node-prune)
|
||||
RUN curl -sf https://gobinaries.com/tj/node-prune | sh
|
||||
RUN curl -sfL https://install.goreleaser.com/github.com/tj/node-prune.sh | bash -s -- -b /usr/local/bin
|
||||
|
||||
# just copy everhing
|
||||
COPY . .
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "ohmyform-api",
|
||||
"version": "1.0.3",
|
||||
"version": "1.0.0",
|
||||
"description": "",
|
||||
"author": "",
|
||||
"license": "AGPL-3.0-or-later",
|
||||
@ -22,8 +22,7 @@
|
||||
"test:e2e": "jest --config ./test/jest-e2e.json",
|
||||
"typeorm:sqlite": "cross-env TS_NODE_TRANSPILE_ONLY=true ts-node -r tsconfig-paths/register ./node_modules/typeorm/cli.js -f ormconfig_sqlite.json",
|
||||
"typeorm:postgres": "cross-env TS_NODE_TRANSPILE_ONLY=true ts-node -r tsconfig-paths/register ./node_modules/typeorm/cli.js -f ormconfig_postgres.json",
|
||||
"typeorm:mariadb": "cross-env TS_NODE_TRANSPILE_ONLY=true ts-node -r tsconfig-paths/register ./node_modules/typeorm/cli.js -f ormconfig_mariadb.json",
|
||||
"typeorm": "cross-env TS_NODE_TRANSPILE_ONLY=true ts-node -r tsconfig-paths/register ./node_modules/typeorm/cli.js"
|
||||
"typeorm:mariadb": "cross-env TS_NODE_TRANSPILE_ONLY=true ts-node -r tsconfig-paths/register ./node_modules/typeorm/cli.js -f ormconfig_mariadb.json"
|
||||
},
|
||||
"dependencies": {
|
||||
"@ardatan/aggregate-error": "^0.0.6",
|
||||
@ -51,7 +50,6 @@
|
||||
"graphql-subscriptions": "^2.0.0",
|
||||
"graphql-tools": "^8.2.0",
|
||||
"handlebars": "^4.7.7",
|
||||
"hashids": "^2.2.10",
|
||||
"html-to-text": "^8.1.0",
|
||||
"inquirer": "^8.2.0",
|
||||
"ioredis": "^4.28.5",
|
||||
@ -85,7 +83,7 @@
|
||||
"@types/handlebars": "^4.1.0",
|
||||
"@types/html-to-text": "^8.0.1",
|
||||
"@types/inquirer": "^8.2.0",
|
||||
"@types/jest": "^27.4.1",
|
||||
"@types/jest": "27.4.1",
|
||||
"@types/mjml": "^4.7.0",
|
||||
"@types/node": "^17.0.21",
|
||||
"@types/passport-jwt": "^3.0.6",
|
||||
@ -100,7 +98,6 @@
|
||||
"eslint-plugin-nestjs": "^1.2.3",
|
||||
"eslint-plugin-unused-imports": "^2.0.0",
|
||||
"jest": "^27.5.1",
|
||||
"node-gyp": "^9.0.0",
|
||||
"prettier": "^2.5.1",
|
||||
"supertest": "^6.2.2",
|
||||
"ts-jest": "27.1.3",
|
||||
|
||||
@ -1,13 +1,11 @@
|
||||
import { commands } from './command'
|
||||
import { guards } from './guard'
|
||||
import { pipes } from './pipe'
|
||||
import { resolvers } from './resolver'
|
||||
import { services } from './service'
|
||||
|
||||
export const providers = [
|
||||
...commands,
|
||||
...guards,
|
||||
...pipes,
|
||||
...resolvers,
|
||||
...commands,
|
||||
...services,
|
||||
...guards,
|
||||
]
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
import { Field, ID, ObjectType } from '@nestjs/graphql'
|
||||
import { Field, ObjectType } from '@nestjs/graphql'
|
||||
|
||||
@ObjectType('Deleted')
|
||||
export class DeletedModel {
|
||||
@Field(() => ID)
|
||||
@Field()
|
||||
id: string
|
||||
|
||||
constructor(id: string) {
|
||||
|
||||
@ -3,8 +3,6 @@ import { PageButtonEntity } from '../../entity/page.button.entity'
|
||||
|
||||
@ObjectType('Button')
|
||||
export class ButtonModel {
|
||||
readonly _id: number
|
||||
|
||||
@Field(() => ID)
|
||||
readonly id: string
|
||||
|
||||
@ -26,9 +24,8 @@ export class ButtonModel {
|
||||
@Field({ nullable: true })
|
||||
readonly color?: string
|
||||
|
||||
constructor(id: string, button: Partial<PageButtonEntity>) {
|
||||
this._id = button.id
|
||||
this.id = id
|
||||
constructor(button: Partial<PageButtonEntity>) {
|
||||
this.id = button.id.toString()
|
||||
this.url = button.url
|
||||
this.action = button.action
|
||||
this.text = button.text
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
import { Field, InputType } from '@nestjs/graphql'
|
||||
import { PageInput } from './page.input'
|
||||
|
||||
@InputType('FormCreateInput')
|
||||
export class FormCreateInput {
|
||||
@ -20,10 +19,4 @@ export class FormCreateInput {
|
||||
|
||||
@Field({ nullable: true })
|
||||
readonly layout: string
|
||||
|
||||
@Field({ nullable: true })
|
||||
readonly startPage: PageInput
|
||||
|
||||
@Field({ nullable: true })
|
||||
readonly endPage: PageInput
|
||||
}
|
||||
|
||||
@ -3,8 +3,6 @@ import { FormFieldLogicEntity } from '../../entity/form.field.logic.entity'
|
||||
|
||||
@ObjectType('FormFieldLogic')
|
||||
export class FormFieldLogicModel {
|
||||
readonly _id: number
|
||||
|
||||
@Field(() => ID)
|
||||
readonly id: string
|
||||
|
||||
@ -32,9 +30,8 @@ export class FormFieldLogicModel {
|
||||
@Field()
|
||||
readonly enabled: boolean
|
||||
|
||||
constructor(id: string, document: FormFieldLogicEntity) {
|
||||
this._id = document.id
|
||||
this.id = id
|
||||
constructor(document: FormFieldLogicEntity) {
|
||||
this.id = document.id.toString()
|
||||
this.enabled = document.enabled
|
||||
|
||||
this.formula = document.formula
|
||||
|
||||
@ -1,10 +1,11 @@
|
||||
import { Field, ID, ObjectType } from '@nestjs/graphql'
|
||||
import { FormFieldEntity } from '../../entity/form.field.entity'
|
||||
import { FormFieldLogicModel } from './form.field.logic.model'
|
||||
import { FormFieldOptionModel } from './form.field.option.model'
|
||||
import { FormFieldRatingModel } from './form.field.rating.model'
|
||||
|
||||
@ObjectType('FormField')
|
||||
export class FormFieldModel {
|
||||
readonly _id: number
|
||||
|
||||
@Field(() => ID)
|
||||
readonly id: string
|
||||
|
||||
@ -29,9 +30,17 @@ export class FormFieldModel {
|
||||
@Field({ nullable: true })
|
||||
readonly defaultValue: string
|
||||
|
||||
constructor(id: string, document: FormFieldEntity) {
|
||||
this._id = document.id
|
||||
this.id = id
|
||||
@Field(() => [FormFieldOptionModel])
|
||||
readonly options: FormFieldOptionModel[]
|
||||
|
||||
@Field(() => [FormFieldLogicModel])
|
||||
readonly logic: FormFieldLogicModel[]
|
||||
|
||||
@Field(() => FormFieldRatingModel, { nullable: true })
|
||||
readonly rating: FormFieldRatingModel
|
||||
|
||||
constructor(document: FormFieldEntity) {
|
||||
this.id = document.id.toString()
|
||||
this.idx = document.idx
|
||||
this.title = document.title
|
||||
this.slug = document.slug
|
||||
@ -39,5 +48,8 @@ export class FormFieldModel {
|
||||
this.description = document.description
|
||||
this.required = document.required
|
||||
this.defaultValue = document.defaultValue
|
||||
this.options = document.options?.map(option => new FormFieldOptionModel(option)) || []
|
||||
this.logic = document.logic?.map(logic => new FormFieldLogicModel(logic)) || []
|
||||
this.rating = document.rating ? new FormFieldRatingModel(document.rating) : null
|
||||
}
|
||||
}
|
||||
|
||||
@ -3,8 +3,6 @@ import { FormFieldOptionEntity } from '../../entity/form.field.option.entity'
|
||||
|
||||
@ObjectType('FormFieldOption')
|
||||
export class FormFieldOptionModel {
|
||||
readonly _id: number
|
||||
|
||||
@Field(() => ID)
|
||||
readonly id: string
|
||||
|
||||
@ -17,9 +15,8 @@ export class FormFieldOptionModel {
|
||||
@Field()
|
||||
readonly value: string
|
||||
|
||||
constructor(id: string, option: FormFieldOptionEntity) {
|
||||
this._id = option.id
|
||||
this.id = id
|
||||
constructor(option: FormFieldOptionEntity) {
|
||||
this.id = option.id.toString()
|
||||
this.key = option.key
|
||||
this.title = option.title
|
||||
this.value = option.value
|
||||
|
||||
@ -3,8 +3,6 @@ import { FormHookEntity } from '../../entity/form.hook.entity'
|
||||
|
||||
@ObjectType('FormHook')
|
||||
export class FormHookModel {
|
||||
readonly _id: number
|
||||
|
||||
@Field(() => ID)
|
||||
readonly id: string
|
||||
|
||||
@ -17,9 +15,8 @@ export class FormHookModel {
|
||||
@Field({ nullable: true })
|
||||
readonly format?: string
|
||||
|
||||
constructor(id, hook: FormHookEntity) {
|
||||
this._id = hook.id
|
||||
this.id = id
|
||||
constructor(hook: FormHookEntity) {
|
||||
this.id = hook.id.toString()
|
||||
this.enabled = hook.enabled
|
||||
this.url = hook.url
|
||||
this.format = hook.format
|
||||
|
||||
@ -3,8 +3,6 @@ import { FormEntity } from '../../entity/form.entity'
|
||||
|
||||
@ObjectType('Form')
|
||||
export class FormModel {
|
||||
readonly _id: number
|
||||
|
||||
@Field(() => ID)
|
||||
readonly id: string
|
||||
|
||||
@ -26,9 +24,8 @@ export class FormModel {
|
||||
@Field()
|
||||
readonly anonymousSubmission: boolean
|
||||
|
||||
constructor(id: string, form: FormEntity) {
|
||||
this._id = form.id
|
||||
this.id = id
|
||||
constructor(form: FormEntity) {
|
||||
this.id = form.id.toString()
|
||||
this.title = form.title
|
||||
this.created = form.created
|
||||
this.lastModified = form.lastModified
|
||||
|
||||
@ -3,8 +3,6 @@ import { FormNotificationEntity } from '../../entity/form.notification.entity'
|
||||
|
||||
@ObjectType('FormNotification')
|
||||
export class FormNotificationModel {
|
||||
readonly _id: number
|
||||
|
||||
@Field(() => ID)
|
||||
readonly id: string
|
||||
|
||||
@ -29,9 +27,8 @@ export class FormNotificationModel {
|
||||
@Field()
|
||||
readonly enabled: boolean
|
||||
|
||||
constructor(id: string, partial: Partial<FormNotificationEntity>) {
|
||||
this._id = partial.id
|
||||
this.id = id
|
||||
constructor(partial: Partial<FormNotificationEntity>) {
|
||||
this.id = partial.id.toString()
|
||||
this.subject = partial.subject
|
||||
this.htmlTemplate = partial.htmlTemplate
|
||||
this.enabled = partial.enabled
|
||||
|
||||
@ -18,6 +18,6 @@ export class PageInput {
|
||||
@Field({ nullable: true })
|
||||
readonly buttonText?: string
|
||||
|
||||
@Field(() => [ButtonInput], { nullable: true })
|
||||
@Field(() => [ButtonInput])
|
||||
readonly buttons: ButtonInput[]
|
||||
}
|
||||
|
||||
@ -1,10 +1,9 @@
|
||||
import { Field, ID, ObjectType } from '@nestjs/graphql'
|
||||
import { PageEntity } from '../../entity/page.entity'
|
||||
import { ButtonModel } from './button.model'
|
||||
|
||||
@ObjectType('Page')
|
||||
export class PageModel {
|
||||
readonly _id: number
|
||||
|
||||
@Field(() => ID)
|
||||
readonly id: string
|
||||
|
||||
@ -20,18 +19,22 @@ export class PageModel {
|
||||
@Field({ nullable: true })
|
||||
readonly buttonText?: string
|
||||
|
||||
constructor(id: string, page?: Partial<PageEntity>) {
|
||||
@Field(() => [ButtonModel])
|
||||
readonly buttons: ButtonModel[]
|
||||
|
||||
constructor(page: Partial<PageEntity>) {
|
||||
if (!page) {
|
||||
this.id = id
|
||||
this.id = Math.random().toString()
|
||||
this.show = false
|
||||
this.buttons = []
|
||||
return
|
||||
}
|
||||
|
||||
this._id = page.id
|
||||
this.id = id
|
||||
this.id = page.id.toString()
|
||||
this.show = page.show
|
||||
this.title = page.title
|
||||
this.paragraph = page.paragraph
|
||||
this.buttonText = page.buttonText
|
||||
this.buttons = (page.buttons || []).map(button => new ButtonModel(button))
|
||||
}
|
||||
}
|
||||
|
||||
@ -7,8 +7,8 @@ export class ProfileModel extends UserModel {
|
||||
@Field(() => [String])
|
||||
readonly roles: string[]
|
||||
|
||||
constructor(id: string, user: UserEntity) {
|
||||
super(id, user)
|
||||
constructor(user: UserEntity) {
|
||||
super(user)
|
||||
|
||||
this.roles = user.roles
|
||||
}
|
||||
|
||||
@ -3,8 +3,6 @@ import { SubmissionFieldEntity } from '../../entity/submission.field.entity'
|
||||
|
||||
@ObjectType('SubmissionField')
|
||||
export class SubmissionFieldModel {
|
||||
readonly _id: number
|
||||
|
||||
@Field(() => ID)
|
||||
readonly id: string
|
||||
|
||||
@ -14,9 +12,8 @@ export class SubmissionFieldModel {
|
||||
@Field()
|
||||
readonly type: string
|
||||
|
||||
constructor(id: string, field: SubmissionFieldEntity) {
|
||||
this._id = field.id
|
||||
this.id = id
|
||||
constructor(field: SubmissionFieldEntity) {
|
||||
this.id = field.id.toString()
|
||||
this.value = JSON.stringify(field.content)
|
||||
this.type = field.type
|
||||
}
|
||||
|
||||
@ -5,10 +5,8 @@ import { GeoLocationModel } from './geo.location.model'
|
||||
|
||||
@ObjectType('Submission')
|
||||
export class SubmissionModel {
|
||||
readonly _id: number
|
||||
|
||||
@Field(() => ID)
|
||||
readonly id: string
|
||||
readonly id: number
|
||||
|
||||
@Field()
|
||||
readonly ipAddr: string
|
||||
@ -31,9 +29,8 @@ export class SubmissionModel {
|
||||
@Field({ nullable: true })
|
||||
readonly lastModified?: Date
|
||||
|
||||
constructor(id: string, submission: SubmissionEntity) {
|
||||
this._id = submission.id
|
||||
this.id = id
|
||||
constructor(submission: SubmissionEntity) {
|
||||
this.id = submission.id
|
||||
|
||||
this.ipAddr = submission.ipAddr
|
||||
this.geoLocation = new GeoLocationModel(submission.geoLocation)
|
||||
|
||||
@ -3,8 +3,6 @@ import { SubmissionEntity } from '../../entity/submission.entity'
|
||||
|
||||
@ObjectType('SubmissionProgress')
|
||||
export class SubmissionProgressModel {
|
||||
readonly _id: number
|
||||
|
||||
@Field(() => ID)
|
||||
readonly id: string
|
||||
|
||||
@ -20,9 +18,8 @@ export class SubmissionProgressModel {
|
||||
@Field({ nullable: true })
|
||||
readonly lastModified?: Date
|
||||
|
||||
constructor(id: string, submission: Partial<SubmissionEntity>) {
|
||||
this._id = submission.id
|
||||
this.id = id
|
||||
constructor(submission: Partial<SubmissionEntity>) {
|
||||
this.id = submission.id.toString()
|
||||
|
||||
this.timeElapsed = submission.timeElapsed
|
||||
this.percentageComplete = submission.percentageComplete
|
||||
|
||||
@ -3,8 +3,6 @@ import { UserEntity } from '../../entity/user.entity'
|
||||
|
||||
@ObjectType('User')
|
||||
export class UserModel {
|
||||
readonly _id: number
|
||||
|
||||
@Field(() => ID)
|
||||
readonly id: string
|
||||
|
||||
@ -38,9 +36,8 @@ export class UserModel {
|
||||
@Field({ nullable: true })
|
||||
readonly lastModified: Date
|
||||
|
||||
constructor(id: string, user: UserEntity) {
|
||||
this._id = user.id
|
||||
this.id = id
|
||||
constructor(user: UserEntity) {
|
||||
this.id = user.id.toString()
|
||||
this.username = user.username
|
||||
this.email = user.email
|
||||
|
||||
|
||||
@ -72,10 +72,4 @@ export class FormEntity {
|
||||
|
||||
@UpdateDateColumn()
|
||||
public lastModified: Date
|
||||
|
||||
constructor(partial?: Partial<FormEntity>) {
|
||||
if (partial) {
|
||||
Object.assign(this, partial)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -2,12 +2,8 @@ import { Column, Entity, ManyToOne, PrimaryGeneratedColumn, RelationId } from 't
|
||||
import { FormFieldEntity } from './form.field.entity'
|
||||
import { SubmissionEntity } from './submission.entity'
|
||||
|
||||
type Simple = string | number | boolean
|
||||
|
||||
export type SubmissionFieldContent = Simple | Simple[] | {
|
||||
[key: string]: Simple | Simple[] | {
|
||||
[key: string]: Simple | Simple[]
|
||||
}
|
||||
export interface SubmissionFieldContent {
|
||||
[key: string]: string | string[] | number | number[] | boolean | boolean[]
|
||||
}
|
||||
|
||||
@Entity({ name: 'submission_field' })
|
||||
|
||||
@ -1,10 +1,9 @@
|
||||
import { QueryRunner } from 'typeorm'
|
||||
import { SqliteMigration } from '../sqlite.migration'
|
||||
import { MigrationInterface, QueryRunner } from 'typeorm'
|
||||
|
||||
export class initial1619723437787 extends SqliteMigration {
|
||||
export class initial1619723437787 implements MigrationInterface {
|
||||
name = 'initial1619723437787'
|
||||
|
||||
public async realUp(queryRunner: QueryRunner): Promise<void> {
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query('CREATE TABLE "page" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "show" boolean NOT NULL, "title" varchar, "paragraph" text, "buttonText" varchar)');
|
||||
await queryRunner.query('CREATE TABLE "user" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "firstName" varchar, "lastName" varchar, "email" varchar(255) NOT NULL, "username" varchar(255) NOT NULL, "passwordHash" varchar NOT NULL, "salt" varchar, "provider" varchar NOT NULL, "roles" text NOT NULL, "language" varchar NOT NULL, "resetPasswordToken" varchar, "resetPasswordExpires" datetime, "token" varchar, "apiKey" varchar, "created" datetime NOT NULL DEFAULT (datetime(\'now\')), "lastModified" datetime NOT NULL DEFAULT (datetime(\'now\')), CONSTRAINT "UQ_e12875dfb3b1d92d7d7c5377e22" UNIQUE ("email"), CONSTRAINT "UQ_78a916df40e02a9deb1c4b75edb" UNIQUE ("username"))');
|
||||
await queryRunner.query('CREATE TABLE "form_field_logic" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "formula" varchar NOT NULL, "action" varchar(10) NOT NULL, "visible" boolean, "require" boolean, "disable" boolean, "enabled" boolean NOT NULL, "fieldId" integer, "jumpToId" integer, CONSTRAINT "FK_6098b83f6759445d8cfdd03d545" FOREIGN KEY ("fieldId") REFERENCES "form_field" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION, CONSTRAINT "FK_4a8019f2b753cfb3216dc3001a6" FOREIGN KEY ("jumpToId") REFERENCES "form_field" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION)');
|
||||
@ -17,10 +16,13 @@ export class initial1619723437787 extends SqliteMigration {
|
||||
await queryRunner.query('CREATE TABLE "form_visitor" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "referrer" varchar, "ipAddr" varchar NOT NULL, "created" datetime NOT NULL DEFAULT (datetime(\'now\')), "updated" datetime NOT NULL DEFAULT (datetime(\'now\')), "formId" integer, "geoLocationCountry" varchar, "geoLocationCity" varchar, "deviceLanguage" varchar, "deviceType" varchar, "deviceName" varchar, CONSTRAINT "FK_72ade6c3a3e55d1fce94300f8b6" FOREIGN KEY ("formId") REFERENCES "form" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION)');
|
||||
await queryRunner.query('CREATE TABLE "submission" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "ipAddr" varchar NOT NULL, "tokenHash" varchar NOT NULL, "timeElapsed" numeric NOT NULL, "percentageComplete" numeric NOT NULL, "created" datetime NOT NULL DEFAULT (datetime(\'now\')), "lastModified" datetime NOT NULL DEFAULT (datetime(\'now\')), "formId" integer, "visitorId" integer, "userId" integer, "geoLocationCountry" varchar, "geoLocationCity" varchar, "deviceLanguage" varchar, "deviceType" varchar, "deviceName" varchar, CONSTRAINT "FK_6090e1d5cbf3433ffd14e3b53e7" FOREIGN KEY ("formId") REFERENCES "form" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION, CONSTRAINT "FK_95b73c7faf2c199f005fda5e8c8" FOREIGN KEY ("visitorId") REFERENCES "form_visitor" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION, CONSTRAINT "FK_7bd626272858ef6464aa2579094" FOREIGN KEY ("userId") REFERENCES "user" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION)');
|
||||
|
||||
|
||||
|
||||
|
||||
await queryRunner.query('CREATE TABLE "form" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "title" varchar NOT NULL, "language" varchar(10) NOT NULL, "showFooter" boolean NOT NULL, "isLive" boolean NOT NULL, "created" datetime NOT NULL DEFAULT (datetime(\'now\')), "lastModified" datetime NOT NULL DEFAULT (datetime(\'now\')), "adminId" integer, "startPageId" integer, "endPageId" integer, "analyticsGacode" varchar, "designFont" varchar, "designColorsBackground" varchar, "designColorsQuestion" varchar, "designColorsAnswer" varchar, "designColorsButton" varchar, "designColorsButtonactive" varchar, "designColorsButtontext" varchar, CONSTRAINT "FK_a7cb33580bca2b362e5e34fdfcd" FOREIGN KEY ("adminId") REFERENCES "user" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION, CONSTRAINT "FK_023d9cf1d97e93facc96c86ca70" FOREIGN KEY ("startPageId") REFERENCES "page" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION, CONSTRAINT "FK_e5d158932e43cfbf9958931ee01" FOREIGN KEY ("endPageId") REFERENCES "page" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION)');
|
||||
}
|
||||
|
||||
public async realDown(queryRunner: QueryRunner): Promise<void> {
|
||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query('DROP TABLE "form"');
|
||||
await queryRunner.query('DROP TABLE "submission"');
|
||||
await queryRunner.query('DROP TABLE "form_visitor"');
|
||||
|
||||
@ -1,14 +1,13 @@
|
||||
import { QueryRunner } from 'typeorm'
|
||||
import { SqliteMigration } from '../sqlite.migration'
|
||||
import { MigrationInterface, QueryRunner } from 'typeorm'
|
||||
|
||||
export class defaultValue1645952169100 extends SqliteMigration {
|
||||
export class defaultValue1645952169100 implements MigrationInterface {
|
||||
name = 'defaultValue1645952169100'
|
||||
|
||||
public async realUp(queryRunner: QueryRunner): Promise<void> {
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query('ALTER TABLE "form_field" RENAME COLUMN "value" TO "defaultValue"');
|
||||
}
|
||||
|
||||
public async realDown(queryRunner: QueryRunner): Promise<void> {
|
||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query('ALTER TABLE "form_field" RENAME COLUMN "defaultValue" TO "value"');
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,19 +0,0 @@
|
||||
import { ArgumentMetadata, Injectable, PipeTransform } from '@nestjs/common'
|
||||
import { FormEntity } from '../../entity/form.entity'
|
||||
import { FormService } from '../../service/form/form.service'
|
||||
import { IdService } from '../../service/id.service'
|
||||
|
||||
@Injectable()
|
||||
export class FormByIdPipe implements PipeTransform<string, Promise<FormEntity>> {
|
||||
constructor(
|
||||
private readonly formService: FormService,
|
||||
private readonly idService: IdService,
|
||||
) {
|
||||
}
|
||||
|
||||
async transform(value: string, metadata: ArgumentMetadata): Promise<FormEntity> {
|
||||
const id = this.idService.decode(value)
|
||||
|
||||
return await this.formService.findById(id)
|
||||
}
|
||||
}
|
||||
@ -1,3 +0,0 @@
|
||||
import { FormByIdPipe } from './form.by.id.pipe'
|
||||
|
||||
export const formPipes = [FormByIdPipe]
|
||||
@ -1,9 +0,0 @@
|
||||
import { formPipes } from './form'
|
||||
import { submissionPipes } from './submission'
|
||||
import { userPipes } from './user'
|
||||
|
||||
export const pipes = [
|
||||
...formPipes,
|
||||
...submissionPipes,
|
||||
...userPipes,
|
||||
]
|
||||
@ -1,3 +0,0 @@
|
||||
import { SubmissionByIdPipe } from './submission.by.id.pipe'
|
||||
|
||||
export const submissionPipes = [SubmissionByIdPipe]
|
||||
@ -1,19 +0,0 @@
|
||||
import { ArgumentMetadata, Injectable, PipeTransform } from '@nestjs/common'
|
||||
import { SubmissionEntity } from '../../entity/submission.entity'
|
||||
import { IdService } from '../../service/id.service'
|
||||
import { SubmissionService } from '../../service/submission/submission.service'
|
||||
|
||||
@Injectable()
|
||||
export class SubmissionByIdPipe implements PipeTransform<string, Promise<SubmissionEntity>> {
|
||||
constructor(
|
||||
private readonly submissionService: SubmissionService,
|
||||
private readonly idService: IdService,
|
||||
) {
|
||||
}
|
||||
|
||||
async transform(value: string, metadata: ArgumentMetadata): Promise<SubmissionEntity> {
|
||||
const id = this.idService.decode(value)
|
||||
|
||||
return await this.submissionService.findById(id)
|
||||
}
|
||||
}
|
||||
@ -1,3 +0,0 @@
|
||||
import { UserByIdPipe } from './user.by.id.pipe'
|
||||
|
||||
export const userPipes = [UserByIdPipe]
|
||||
@ -1,19 +0,0 @@
|
||||
import { ArgumentMetadata, Injectable, PipeTransform } from '@nestjs/common'
|
||||
import { UserEntity } from '../../entity/user.entity'
|
||||
import { IdService } from '../../service/id.service'
|
||||
import { UserService } from '../../service/user/user.service'
|
||||
|
||||
@Injectable()
|
||||
export class UserByIdPipe implements PipeTransform<string, Promise<UserEntity>> {
|
||||
constructor(
|
||||
private readonly userService: UserService,
|
||||
private readonly idService: IdService,
|
||||
) {
|
||||
}
|
||||
|
||||
async transform(value: string, metadata: ArgumentMetadata): Promise<UserEntity> {
|
||||
const id = this.idService.decode(value)
|
||||
|
||||
return await this.userService.findById(id)
|
||||
}
|
||||
}
|
||||
@ -1,10 +1,12 @@
|
||||
|
||||
type ID = string | number
|
||||
|
||||
export class ContextCache<A = any> {
|
||||
private cache: {
|
||||
[key: string]: any
|
||||
} = {}
|
||||
|
||||
public getCacheKey(type: string, id: number): string {
|
||||
public getCacheKey(type: string, id: ID): string {
|
||||
return `${type}:${id}`
|
||||
}
|
||||
|
||||
|
||||
@ -7,14 +7,12 @@ import { FormModel } from '../../dto/form/form.model'
|
||||
import { FormEntity } from '../../entity/form.entity'
|
||||
import { UserEntity } from '../../entity/user.entity'
|
||||
import { FormCreateService } from '../../service/form/form.create.service'
|
||||
import { IdService } from '../../service/id.service'
|
||||
import { ContextCache } from '../context.cache'
|
||||
|
||||
@Injectable()
|
||||
export class FormCreateMutation {
|
||||
constructor(
|
||||
private readonly createService: FormCreateService,
|
||||
private readonly idService: IdService,
|
||||
private readonly createService: FormCreateService
|
||||
) {
|
||||
}
|
||||
|
||||
@ -29,6 +27,6 @@ export class FormCreateMutation {
|
||||
|
||||
cache.add(cache.getCacheKey(FormEntity.name, form.id), form)
|
||||
|
||||
return new FormModel(this.idService.encode(form.id), form)
|
||||
return new FormModel(form)
|
||||
}
|
||||
}
|
||||
|
||||
@ -3,19 +3,15 @@ import { Args, ID, Mutation } from '@nestjs/graphql'
|
||||
import { Roles } from '../../decorator/roles.decorator'
|
||||
import { User } from '../../decorator/user.decorator'
|
||||
import { DeletedModel } from '../../dto/deleted.model'
|
||||
import { FormEntity } from '../../entity/form.entity'
|
||||
import { UserEntity } from '../../entity/user.entity'
|
||||
import { FormByIdPipe } from '../../pipe/form/form.by.id.pipe'
|
||||
import { FormDeleteService } from '../../service/form/form.delete.service'
|
||||
import { FormService } from '../../service/form/form.service'
|
||||
import { IdService } from '../../service/id.service'
|
||||
|
||||
@Injectable()
|
||||
export class FormDeleteMutation {
|
||||
constructor(
|
||||
private readonly deleteService: FormDeleteService,
|
||||
private readonly formService: FormService,
|
||||
private readonly idService: IdService,
|
||||
) {
|
||||
}
|
||||
|
||||
@ -23,14 +19,16 @@ export class FormDeleteMutation {
|
||||
@Roles('admin')
|
||||
async deleteForm(
|
||||
@User() user: UserEntity,
|
||||
@Args('id', {type: () => ID}, FormByIdPipe) form: FormEntity,
|
||||
@Args({ name: 'id', type: () => ID}) id: string,
|
||||
): Promise<DeletedModel> {
|
||||
const form = await this.formService.findById(id)
|
||||
|
||||
if (!form.isLive && !this.formService.isAdmin(form, user)) {
|
||||
throw new Error('invalid form')
|
||||
}
|
||||
|
||||
await this.deleteService.delete(form.id)
|
||||
await this.deleteService.delete(id)
|
||||
|
||||
return new DeletedModel(this.idService.encode(form.id))
|
||||
return new DeletedModel(id)
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,73 +0,0 @@
|
||||
import { Context, Parent, ResolveField, Resolver } from '@nestjs/graphql'
|
||||
import { FormFieldLogicModel } from '../../dto/form/form.field.logic.model'
|
||||
import { FormFieldModel } from '../../dto/form/form.field.model'
|
||||
import { FormFieldOptionModel } from '../../dto/form/form.field.option.model'
|
||||
import { FormFieldRatingModel } from '../../dto/form/form.field.rating.model'
|
||||
import { FormFieldEntity } from '../../entity/form.field.entity'
|
||||
import { IdService } from '../../service/id.service'
|
||||
import { ContextCache } from '../context.cache'
|
||||
|
||||
@Resolver(FormFieldModel)
|
||||
export class FormFieldResolver {
|
||||
constructor(
|
||||
private readonly idService: IdService,
|
||||
) {
|
||||
}
|
||||
|
||||
@ResolveField(() => [FormFieldOptionModel])
|
||||
async options(
|
||||
@Parent() parent: FormFieldModel,
|
||||
@Context('cache') cache: ContextCache,
|
||||
): Promise<FormFieldOptionModel[]> {
|
||||
const field = await cache.get<FormFieldEntity>(cache.getCacheKey(
|
||||
FormFieldEntity.name,
|
||||
parent._id
|
||||
))
|
||||
|
||||
if (!field.options) {
|
||||
return []
|
||||
}
|
||||
|
||||
return field.options.map(option => new FormFieldOptionModel(
|
||||
this.idService.encode(option.id),
|
||||
option,
|
||||
))
|
||||
}
|
||||
|
||||
@ResolveField(() => [FormFieldLogicModel])
|
||||
async logic(
|
||||
@Parent() parent: FormFieldModel,
|
||||
@Context('cache') cache: ContextCache,
|
||||
): Promise<FormFieldLogicModel[]> {
|
||||
const field = await cache.get<FormFieldEntity>(cache.getCacheKey(
|
||||
FormFieldEntity.name,
|
||||
parent._id
|
||||
))
|
||||
|
||||
if (!field.logic) {
|
||||
return []
|
||||
}
|
||||
|
||||
return field.logic.map(logic => new FormFieldLogicModel(
|
||||
this.idService.encode(logic.id),
|
||||
logic,
|
||||
))
|
||||
}
|
||||
|
||||
@ResolveField(() => FormFieldRatingModel, { nullable: true })
|
||||
async rating(
|
||||
@Parent() parent: FormFieldModel,
|
||||
@Context('cache') cache: ContextCache,
|
||||
): Promise<FormFieldRatingModel> {
|
||||
const field = await cache.get<FormFieldEntity>(cache.getCacheKey(
|
||||
FormFieldEntity.name,
|
||||
parent._id
|
||||
))
|
||||
|
||||
if (!field.rating) {
|
||||
return null
|
||||
}
|
||||
|
||||
return new FormFieldRatingModel(field.rating)
|
||||
}
|
||||
}
|
||||
@ -7,14 +7,12 @@ import { FormPagerModel } from '../../dto/form/form.pager.model'
|
||||
import { FormEntity } from '../../entity/form.entity'
|
||||
import { UserEntity } from '../../entity/user.entity'
|
||||
import { FormService } from '../../service/form/form.service'
|
||||
import { IdService } from '../../service/id.service'
|
||||
import { ContextCache } from '../context.cache'
|
||||
|
||||
@Injectable()
|
||||
export class FormListQuery {
|
||||
constructor(
|
||||
private readonly formService: FormService,
|
||||
private readonly idService: IdService,
|
||||
) {
|
||||
}
|
||||
|
||||
@ -36,7 +34,7 @@ export class FormListQuery {
|
||||
forms.forEach(form => cache.add(cache.getCacheKey(FormEntity.name, form.id), form))
|
||||
|
||||
return new FormPagerModel(
|
||||
forms.map(form => new FormModel(this.idService.encode(form.id), form)),
|
||||
forms.map(form => new FormModel(form)),
|
||||
total,
|
||||
limit,
|
||||
start,
|
||||
|
||||
@ -4,31 +4,30 @@ import { User } from '../../decorator/user.decorator'
|
||||
import { FormModel } from '../../dto/form/form.model'
|
||||
import { FormEntity } from '../../entity/form.entity'
|
||||
import { UserEntity } from '../../entity/user.entity'
|
||||
import { FormByIdPipe } from '../../pipe/form/form.by.id.pipe'
|
||||
import { FormService } from '../../service/form/form.service'
|
||||
import { IdService } from '../../service/id.service'
|
||||
import { ContextCache } from '../context.cache'
|
||||
|
||||
@Injectable()
|
||||
export class FormQuery {
|
||||
constructor(
|
||||
private readonly formService: FormService,
|
||||
private readonly idService: IdService,
|
||||
) {
|
||||
}
|
||||
|
||||
@Query(() => FormModel)
|
||||
getFormById(
|
||||
async getFormById(
|
||||
@User() user: UserEntity,
|
||||
@Args('id', {type: () => ID}, FormByIdPipe) form: FormEntity,
|
||||
@Args('id', {type: () => ID}) id,
|
||||
@Context('cache') cache: ContextCache,
|
||||
): FormModel {
|
||||
): Promise<FormModel> {
|
||||
const form = await this.formService.findById(id)
|
||||
|
||||
if (!form.isLive && !this.formService.isAdmin(form, user)) {
|
||||
throw new Error('invalid form')
|
||||
}
|
||||
|
||||
cache.add(cache.getCacheKey(FormEntity.name, form.id), form)
|
||||
|
||||
return new FormModel(this.idService.encode(form.id), form)
|
||||
return new FormModel(form)
|
||||
}
|
||||
}
|
||||
|
||||
@ -9,18 +9,14 @@ import { FormNotificationModel } from '../../dto/form/form.notification.model'
|
||||
import { PageModel } from '../../dto/form/page.model'
|
||||
import { UserModel } from '../../dto/user/user.model'
|
||||
import { FormEntity } from '../../entity/form.entity'
|
||||
import { FormFieldEntity } from '../../entity/form.field.entity'
|
||||
import { PageEntity } from '../../entity/page.entity'
|
||||
import { UserEntity } from '../../entity/user.entity'
|
||||
import { FormService } from '../../service/form/form.service'
|
||||
import { IdService } from '../../service/id.service'
|
||||
import { ContextCache } from '../context.cache'
|
||||
|
||||
@Resolver(() => FormModel)
|
||||
export class FormResolver {
|
||||
constructor(
|
||||
private readonly formService: FormService,
|
||||
private readonly idService: IdService,
|
||||
) {
|
||||
}
|
||||
|
||||
@ -30,45 +26,20 @@ export class FormResolver {
|
||||
@Parent() parent: FormModel,
|
||||
@Context('cache') cache: ContextCache,
|
||||
): Promise<FormFieldModel[]> {
|
||||
const form = await cache.get<FormEntity>(cache.getCacheKey(FormEntity.name, parent._id))
|
||||
const form = await cache.get<FormEntity>(cache.getCacheKey(FormEntity.name, parent.id))
|
||||
|
||||
if (!form.fields) {
|
||||
return []
|
||||
}
|
||||
|
||||
return form.fields
|
||||
.sort((a,b) => a.idx - b.idx)
|
||||
.map(field => {
|
||||
cache.add(cache.getCacheKey(FormFieldEntity.name, field.id), field)
|
||||
|
||||
return new FormFieldModel(
|
||||
this.idService.encode(field.id),
|
||||
field,
|
||||
)
|
||||
})
|
||||
return form.fields?.map(field => new FormFieldModel(field)).sort((a,b) => a.idx - b.idx) || []
|
||||
}
|
||||
|
||||
@ResolveField(() => [FormHookModel])
|
||||
@Roles('admin')
|
||||
async hooks(
|
||||
@User() user: UserEntity,
|
||||
@Parent() parent: FormModel,
|
||||
@Context('cache') cache: ContextCache,
|
||||
): Promise<FormHookModel[]> {
|
||||
const form = await cache.get<FormEntity>(cache.getCacheKey(FormEntity.name, parent._id))
|
||||
const form = await cache.get<FormEntity>(cache.getCacheKey(FormEntity.name, parent.id))
|
||||
|
||||
if (!this.formService.isAdmin(form, user)) {
|
||||
throw new Error('no access to field')
|
||||
}
|
||||
|
||||
if (!form.hooks) {
|
||||
return []
|
||||
}
|
||||
|
||||
return form.hooks.map(hook => new FormHookModel(
|
||||
this.idService.encode(hook.id),
|
||||
hook
|
||||
))
|
||||
return form.hooks?.map(hook => new FormHookModel(hook)) || []
|
||||
}
|
||||
|
||||
@ResolveField(() => Boolean)
|
||||
@ -78,7 +49,7 @@ export class FormResolver {
|
||||
@Parent() parent: FormModel,
|
||||
@Context('cache') cache: ContextCache,
|
||||
): Promise<boolean> {
|
||||
const form = await cache.get<FormEntity>(cache.getCacheKey(FormEntity.name, parent._id))
|
||||
const form = await cache.get<FormEntity>(cache.getCacheKey(FormEntity.name, parent.id))
|
||||
|
||||
if (!this.formService.isAdmin(form, user)) {
|
||||
throw new Error('no access to field')
|
||||
@ -94,20 +65,13 @@ export class FormResolver {
|
||||
@Parent() parent: FormModel,
|
||||
@Context('cache') cache: ContextCache,
|
||||
): Promise<FormNotificationModel[]> {
|
||||
const form = await cache.get<FormEntity>(cache.getCacheKey(FormEntity.name, parent._id))
|
||||
const form = await cache.get<FormEntity>(cache.getCacheKey(FormEntity.name, parent.id))
|
||||
|
||||
if (!this.formService.isAdmin(form, user)) {
|
||||
throw new Error('no access to field')
|
||||
}
|
||||
|
||||
if (!form.notifications) {
|
||||
return []
|
||||
}
|
||||
|
||||
return form.notifications.map(notification => new FormNotificationModel(
|
||||
this.idService.encode(notification.id),
|
||||
notification
|
||||
))
|
||||
return form.notifications?.map(notification => new FormNotificationModel(notification)) || []
|
||||
}
|
||||
|
||||
@ResolveField(() => DesignModel)
|
||||
@ -116,7 +80,7 @@ export class FormResolver {
|
||||
@Parent() parent: FormModel,
|
||||
@Context('cache') cache: ContextCache,
|
||||
): Promise<DesignModel> {
|
||||
const form = await cache.get<FormEntity>(cache.getCacheKey(FormEntity.name, parent._id))
|
||||
const form = await cache.get<FormEntity>(cache.getCacheKey(FormEntity.name, parent.id))
|
||||
|
||||
return new DesignModel(form.design)
|
||||
}
|
||||
@ -126,21 +90,9 @@ export class FormResolver {
|
||||
@Parent() parent: FormModel,
|
||||
@Context('cache') cache: ContextCache,
|
||||
): Promise<PageModel> {
|
||||
const { startPage } = await cache.get<FormEntity>(cache.getCacheKey(
|
||||
FormEntity.name,
|
||||
parent._id
|
||||
))
|
||||
const form = await cache.get<FormEntity>(cache.getCacheKey(FormEntity.name, parent.id))
|
||||
|
||||
if (startPage) {
|
||||
cache.add(cache.getCacheKey(PageEntity.name, startPage.id), startPage)
|
||||
|
||||
return new PageModel(
|
||||
this.idService.encode(startPage.id),
|
||||
startPage
|
||||
)
|
||||
}
|
||||
|
||||
return new PageModel(Math.random().toString())
|
||||
return new PageModel(form.startPage)
|
||||
}
|
||||
|
||||
@ResolveField(() => PageModel)
|
||||
@ -148,18 +100,9 @@ export class FormResolver {
|
||||
@Parent() parent: FormModel,
|
||||
@Context('cache') cache: ContextCache,
|
||||
): Promise<PageModel> {
|
||||
const { endPage } = await cache.get<FormEntity>(cache.getCacheKey(FormEntity.name, parent._id))
|
||||
const form = await cache.get<FormEntity>(cache.getCacheKey(FormEntity.name, parent.id))
|
||||
|
||||
if (endPage) {
|
||||
cache.add(cache.getCacheKey(PageEntity.name, endPage.id), endPage)
|
||||
|
||||
return new PageModel(
|
||||
this.idService.encode(endPage.id),
|
||||
endPage
|
||||
)
|
||||
}
|
||||
|
||||
return new PageModel(Math.random().toString())
|
||||
return new PageModel(form.endPage)
|
||||
}
|
||||
|
||||
@ResolveField(() => UserModel, { nullable: true })
|
||||
@ -168,12 +111,12 @@ export class FormResolver {
|
||||
@Parent() parent: FormModel,
|
||||
@Context('cache') cache: ContextCache,
|
||||
): Promise<UserModel> {
|
||||
const form = await cache.get<FormEntity>(cache.getCacheKey(FormEntity.name, parent._id))
|
||||
const form = await cache.get<FormEntity>(cache.getCacheKey(FormEntity.name, parent.id))
|
||||
|
||||
if (!form.admin) {
|
||||
return null
|
||||
}
|
||||
|
||||
return new UserModel(this.idService.encode(form.admin.id), form.admin)
|
||||
return new UserModel(form.admin)
|
||||
}
|
||||
}
|
||||
|
||||
@ -8,7 +8,6 @@ import { FormEntity } from '../../entity/form.entity'
|
||||
import { UserEntity } from '../../entity/user.entity'
|
||||
import { FormService } from '../../service/form/form.service'
|
||||
import { FormUpdateService } from '../../service/form/form.update.service'
|
||||
import { IdService } from '../../service/id.service'
|
||||
import { ContextCache } from '../context.cache'
|
||||
|
||||
@Injectable()
|
||||
@ -16,7 +15,6 @@ export class FormUpdateMutation {
|
||||
constructor(
|
||||
private readonly updateService: FormUpdateService,
|
||||
private readonly formService: FormService,
|
||||
private readonly idService: IdService,
|
||||
) {
|
||||
}
|
||||
|
||||
@ -27,7 +25,7 @@ export class FormUpdateMutation {
|
||||
@Args({ name: 'form', type: () => FormUpdateInput }) input: FormUpdateInput,
|
||||
@Context('cache') cache: ContextCache,
|
||||
): Promise<FormModel> {
|
||||
const form = await this.formService.findById(this.idService.decode(input.id))
|
||||
const form = await this.formService.findById(input.id)
|
||||
|
||||
if (!form.isLive && !this.formService.isAdmin(form, user)) {
|
||||
throw new Error('invalid form')
|
||||
@ -37,6 +35,6 @@ export class FormUpdateMutation {
|
||||
|
||||
cache.add(cache.getCacheKey(FormEntity.name, form.id), form)
|
||||
|
||||
return new FormModel(this.idService.encode(form.id), form)
|
||||
return new FormModel(form)
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,23 +1,19 @@
|
||||
import { FormCreateMutation } from './form.create.mutation'
|
||||
import { FormDeleteMutation } from './form.delete.mutation'
|
||||
import { FormFieldResolver } from './form.field.resolver'
|
||||
import { FormListQuery } from './form.list.query'
|
||||
import { FormQuery } from './form.query'
|
||||
import { FormResolver } from './form.resolver'
|
||||
import { FormStatisticQuery } from './form.statistic.query'
|
||||
import { FormStatisticResolver } from './form.statistic.resolver'
|
||||
import { FormUpdateMutation } from './form.update.mutation'
|
||||
import { PageResolver } from './page.resolver'
|
||||
|
||||
export const formResolvers = [
|
||||
FormCreateMutation,
|
||||
FormDeleteMutation,
|
||||
FormFieldResolver,
|
||||
FormQuery,
|
||||
FormResolver,
|
||||
FormListQuery,
|
||||
FormStatisticQuery,
|
||||
FormStatisticResolver,
|
||||
FormUpdateMutation,
|
||||
PageResolver,
|
||||
]
|
||||
|
||||
@ -1,32 +0,0 @@
|
||||
import { Context, Parent, ResolveField, Resolver } from '@nestjs/graphql'
|
||||
import { ButtonModel } from '../../dto/form/button.model'
|
||||
import { FormModel } from '../../dto/form/form.model'
|
||||
import { PageModel } from '../../dto/form/page.model'
|
||||
import { PageEntity } from '../../entity/page.entity'
|
||||
import { IdService } from '../../service/id.service'
|
||||
import { ContextCache } from '../context.cache'
|
||||
|
||||
@Resolver(() => PageModel)
|
||||
export class PageResolver {
|
||||
constructor(
|
||||
private readonly idService: IdService,
|
||||
) {
|
||||
}
|
||||
|
||||
@ResolveField(() => [ButtonModel])
|
||||
async buttons(
|
||||
@Parent() parent: FormModel,
|
||||
@Context('cache') cache: ContextCache,
|
||||
): Promise<ButtonModel[]> {
|
||||
if (!parent._id) {
|
||||
return []
|
||||
}
|
||||
|
||||
const page = await cache.get<PageEntity>(cache.getCacheKey(PageEntity.name, parent._id))
|
||||
|
||||
return page.buttons.map(button => new ButtonModel(
|
||||
this.idService.encode(button.id),
|
||||
button
|
||||
))
|
||||
}
|
||||
}
|
||||
@ -4,16 +4,10 @@ import { Roles } from '../../decorator/roles.decorator'
|
||||
import { User } from '../../decorator/user.decorator'
|
||||
import { ProfileModel } from '../../dto/profile/profile.model'
|
||||
import { UserEntity } from '../../entity/user.entity'
|
||||
import { IdService } from '../../service/id.service'
|
||||
import { ContextCache } from '../context.cache'
|
||||
|
||||
@Injectable()
|
||||
export class ProfileQuery {
|
||||
constructor(
|
||||
private readonly idService: IdService,
|
||||
) {
|
||||
}
|
||||
|
||||
@Query(() => ProfileModel)
|
||||
@Roles('user')
|
||||
public me(
|
||||
@ -22,6 +16,6 @@ export class ProfileQuery {
|
||||
): ProfileModel {
|
||||
cache.add(cache.getCacheKey(UserEntity.name, user.id), user)
|
||||
|
||||
return new ProfileModel(this.idService.encode(user.id), user)
|
||||
return new ProfileModel(user)
|
||||
}
|
||||
}
|
||||
|
||||
@ -5,7 +5,6 @@ import { User } from '../../decorator/user.decorator'
|
||||
import { ProfileModel } from '../../dto/profile/profile.model'
|
||||
import { ProfileUpdateInput } from '../../dto/profile/profile.update.input'
|
||||
import { UserEntity } from '../../entity/user.entity'
|
||||
import { IdService } from '../../service/id.service'
|
||||
import { ProfileUpdateService } from '../../service/profile/profile.update.service'
|
||||
import { ContextCache } from '../context.cache'
|
||||
|
||||
@ -13,7 +12,6 @@ import { ContextCache } from '../context.cache'
|
||||
export class ProfileUpdateMutation {
|
||||
constructor(
|
||||
private readonly updateService: ProfileUpdateService,
|
||||
private readonly idService: IdService,
|
||||
) {
|
||||
}
|
||||
|
||||
@ -28,7 +26,7 @@ export class ProfileUpdateMutation {
|
||||
|
||||
cache.add(cache.getCacheKey(UserEntity.name, user.id), user)
|
||||
|
||||
return new ProfileModel(this.idService.encode(user.id), user)
|
||||
return new ProfileModel(user)
|
||||
}
|
||||
|
||||
@Mutation(() => ProfileModel)
|
||||
@ -42,6 +40,6 @@ export class ProfileUpdateMutation {
|
||||
|
||||
cache.add(cache.getCacheKey(UserEntity.name, user.id), user)
|
||||
|
||||
return new ProfileModel(this.idService.encode(user.id), user)
|
||||
return new ProfileModel(user)
|
||||
}
|
||||
}
|
||||
|
||||
@ -4,14 +4,12 @@ import { SubmissionFieldModel } from '../../dto/submission/submission.field.mode
|
||||
import { FormFieldEntity } from '../../entity/form.field.entity'
|
||||
import { SubmissionFieldEntity } from '../../entity/submission.field.entity'
|
||||
import { FormFieldService } from '../../service/form/form.field.service'
|
||||
import { IdService } from '../../service/id.service'
|
||||
import { ContextCache } from '../context.cache'
|
||||
|
||||
@Resolver(() => SubmissionFieldModel)
|
||||
export class SubmissionFieldResolver {
|
||||
constructor(
|
||||
private readonly formFieldService: FormFieldService,
|
||||
private readonly idService: IdService,
|
||||
) {
|
||||
}
|
||||
|
||||
@ -21,7 +19,7 @@ export class SubmissionFieldResolver {
|
||||
@Context('cache') cache: ContextCache,
|
||||
): Promise<FormFieldModel> {
|
||||
const submissionField = await cache.get<SubmissionFieldEntity>(
|
||||
cache.getCacheKey(SubmissionFieldEntity.name, parent._id)
|
||||
cache.getCacheKey(SubmissionFieldEntity.name, parent.id)
|
||||
)
|
||||
|
||||
const field = await cache.get<FormFieldEntity>(
|
||||
@ -35,9 +33,6 @@ export class SubmissionFieldResolver {
|
||||
return null
|
||||
}
|
||||
|
||||
return new FormFieldModel(
|
||||
this.idService.encode(field.id),
|
||||
field,
|
||||
)
|
||||
return new FormFieldModel(field)
|
||||
}
|
||||
}
|
||||
|
||||
@ -2,31 +2,33 @@ import { Injectable } from '@nestjs/common'
|
||||
import { Args, Context, ID, Mutation } from '@nestjs/graphql'
|
||||
import { User } from '../../decorator/user.decorator'
|
||||
import { SubmissionProgressModel } from '../../dto/submission/submission.progress.model'
|
||||
import { SubmissionSetFieldInput } from '../../dto/submission/submission.set.field.input'
|
||||
import { SubmissionEntity } from '../../entity/submission.entity'
|
||||
import { UserEntity } from '../../entity/user.entity'
|
||||
import { SubmissionByIdPipe } from '../../pipe/submission/submission.by.id.pipe'
|
||||
import { IdService } from '../../service/id.service'
|
||||
import { SubmissionService } from '../../service/submission/submission.service'
|
||||
import { SubmissionSetFieldService } from '../../service/submission/submission.set.field.service'
|
||||
import { ContextCache } from '../context.cache'
|
||||
|
||||
@Injectable()
|
||||
export class SubmissionFinishMutation {
|
||||
constructor(
|
||||
private readonly submissionService: SubmissionService,
|
||||
private readonly setFieldService: SubmissionSetFieldService,
|
||||
private readonly idService: IdService,
|
||||
) {
|
||||
}
|
||||
|
||||
@Mutation(() => SubmissionProgressModel)
|
||||
async submissionFinish(
|
||||
@User() user: UserEntity,
|
||||
@Args({ name: 'submission', type: () => ID }, SubmissionByIdPipe) submission: SubmissionEntity,
|
||||
@Args({ name: 'submission', type: () => ID }) id: string,
|
||||
@Context('cache') cache: ContextCache,
|
||||
): Promise<SubmissionProgressModel> {
|
||||
const submission = await this.submissionService.findById(id)
|
||||
|
||||
await this.setFieldService.finishSubmission(submission)
|
||||
|
||||
cache.add(cache.getCacheKey(SubmissionEntity.name, submission.id), submission)
|
||||
|
||||
return new SubmissionProgressModel(this.idService.encode(submission.id), submission)
|
||||
return new SubmissionProgressModel(submission)
|
||||
}
|
||||
}
|
||||
|
||||
@ -4,31 +4,31 @@ import { User } from '../../decorator/user.decorator'
|
||||
import { SubmissionModel } from '../../dto/submission/submission.model'
|
||||
import { SubmissionPagerFilterInput } from '../../dto/submission/submission.pager.filter.input'
|
||||
import { SubmissionPagerModel } from '../../dto/submission/submission.pager.model'
|
||||
import { FormEntity } from '../../entity/form.entity'
|
||||
import { SubmissionEntity } from '../../entity/submission.entity'
|
||||
import { UserEntity } from '../../entity/user.entity'
|
||||
import { FormByIdPipe } from '../../pipe/form/form.by.id.pipe'
|
||||
import { IdService } from '../../service/id.service'
|
||||
import { FormService } from '../../service/form/form.service'
|
||||
import { SubmissionService } from '../../service/submission/submission.service'
|
||||
import { ContextCache } from '../context.cache'
|
||||
|
||||
@Injectable()
|
||||
export class SubmissionListQuery {
|
||||
constructor(
|
||||
private readonly formService: FormService,
|
||||
private readonly submissionService: SubmissionService,
|
||||
private readonly idService: IdService,
|
||||
) {
|
||||
}
|
||||
|
||||
@Query(() => SubmissionPagerModel)
|
||||
async listSubmissions(
|
||||
@User() user: UserEntity,
|
||||
@Args('form', {type: () => ID}, FormByIdPipe) form: FormEntity,
|
||||
@Args('form', {type: () => ID}) id: string,
|
||||
@Args('start', {type: () => Int, defaultValue: 0, nullable: true}) start: number,
|
||||
@Args('limit', {type: () => Int, defaultValue: 50, nullable: true}) limit: number,
|
||||
@Args('filter', {type: () => SubmissionPagerFilterInput, defaultValue: new SubmissionPagerFilterInput()}) filter: SubmissionPagerFilterInput,
|
||||
@Context('cache') cache: ContextCache,
|
||||
): Promise<SubmissionPagerModel> {
|
||||
const form = await this.formService.findById(id)
|
||||
|
||||
const [submissions, total] = await this.submissionService.find(
|
||||
form,
|
||||
start,
|
||||
@ -42,10 +42,7 @@ export class SubmissionListQuery {
|
||||
})
|
||||
|
||||
return new SubmissionPagerModel(
|
||||
submissions.map(submission => new SubmissionModel(
|
||||
this.idService.encode(submission.id),
|
||||
submission
|
||||
)),
|
||||
submissions.map(submission => new SubmissionModel(submission)),
|
||||
total,
|
||||
limit,
|
||||
start,
|
||||
|
||||
@ -4,9 +4,8 @@ import { User } from '../../decorator/user.decorator'
|
||||
import { SubmissionModel } from '../../dto/submission/submission.model'
|
||||
import { SubmissionEntity } from '../../entity/submission.entity'
|
||||
import { UserEntity } from '../../entity/user.entity'
|
||||
import { SubmissionByIdPipe } from '../../pipe/submission/submission.by.id.pipe'
|
||||
import { FormService } from '../../service/form/form.service'
|
||||
import { IdService } from '../../service/id.service'
|
||||
import { SubmissionService } from '../../service/submission/submission.service'
|
||||
import { SubmissionTokenService } from '../../service/submission/submission.token.service'
|
||||
import { ContextCache } from '../context.cache'
|
||||
|
||||
@ -14,18 +13,20 @@ import { ContextCache } from '../context.cache'
|
||||
export class SubmissionQuery {
|
||||
constructor(
|
||||
private readonly formService: FormService,
|
||||
private readonly submissionService: SubmissionService,
|
||||
private readonly tokenService: SubmissionTokenService,
|
||||
private readonly idService: IdService,
|
||||
) {
|
||||
}
|
||||
|
||||
@Query(() => SubmissionModel)
|
||||
async getSubmissionById(
|
||||
@User() user: UserEntity,
|
||||
@Args('id', {type: () => ID}, SubmissionByIdPipe) submission: SubmissionEntity,
|
||||
@Args('id', {type: () => ID}) id: string,
|
||||
@Args('token', {nullable: true}) token: string,
|
||||
@Context('cache') cache: ContextCache,
|
||||
): Promise<SubmissionModel> {
|
||||
const submission = await this.submissionService.findById(id)
|
||||
|
||||
if (
|
||||
!await this.tokenService.verify(token, submission.tokenHash)
|
||||
&& !this.formService.isAdmin(submission.form, user)
|
||||
@ -35,6 +36,6 @@ export class SubmissionQuery {
|
||||
|
||||
cache.add(cache.getCacheKey(SubmissionEntity.name, submission.id), submission)
|
||||
|
||||
return new SubmissionModel(this.idService.encode(submission.id), submission)
|
||||
return new SubmissionModel(submission)
|
||||
}
|
||||
}
|
||||
|
||||
@ -5,16 +5,10 @@ import { SubmissionModel } from '../../dto/submission/submission.model'
|
||||
import { SubmissionEntity } from '../../entity/submission.entity'
|
||||
import { SubmissionFieldEntity } from '../../entity/submission.field.entity'
|
||||
import { UserEntity } from '../../entity/user.entity'
|
||||
import { IdService } from '../../service/id.service'
|
||||
import { ContextCache } from '../context.cache'
|
||||
|
||||
@Resolver(() => SubmissionModel)
|
||||
export class SubmissionResolver {
|
||||
constructor(
|
||||
private readonly idService: IdService,
|
||||
) {
|
||||
}
|
||||
|
||||
@ResolveField(() => [SubmissionFieldModel])
|
||||
async fields(
|
||||
@User() user: UserEntity,
|
||||
@ -22,12 +16,12 @@ export class SubmissionResolver {
|
||||
@Context('cache') cache: ContextCache,
|
||||
): Promise<SubmissionFieldModel[]> {
|
||||
const submission = await cache.get<SubmissionEntity>(
|
||||
cache.getCacheKey(SubmissionEntity.name, parent._id)
|
||||
cache.getCacheKey(SubmissionEntity.name, parent.id)
|
||||
)
|
||||
|
||||
return submission.fields.map(field => {
|
||||
cache.add(cache.getCacheKey(SubmissionFieldEntity.name, field.id), field)
|
||||
return new SubmissionFieldModel(this.idService.encode(field.id), field)
|
||||
return new SubmissionFieldModel(field)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@ -5,8 +5,6 @@ import { SubmissionProgressModel } from '../../dto/submission/submission.progres
|
||||
import { SubmissionSetFieldInput } from '../../dto/submission/submission.set.field.input'
|
||||
import { SubmissionEntity } from '../../entity/submission.entity'
|
||||
import { UserEntity } from '../../entity/user.entity'
|
||||
import { SubmissionByIdPipe } from '../../pipe/submission/submission.by.id.pipe'
|
||||
import { IdService } from '../../service/id.service'
|
||||
import { SubmissionService } from '../../service/submission/submission.service'
|
||||
import { SubmissionSetFieldService } from '../../service/submission/submission.set.field.service'
|
||||
import { ContextCache } from '../context.cache'
|
||||
@ -16,17 +14,18 @@ export class SubmissionSetFieldMutation {
|
||||
constructor(
|
||||
private readonly submissionService: SubmissionService,
|
||||
private readonly setFieldService: SubmissionSetFieldService,
|
||||
private readonly idService: IdService,
|
||||
) {
|
||||
}
|
||||
|
||||
@Mutation(() => SubmissionProgressModel)
|
||||
async submissionSetField(
|
||||
@User() user: UserEntity,
|
||||
@Args({ name: 'submission', type: () => ID }, SubmissionByIdPipe) submission: SubmissionEntity,
|
||||
@Args({ name: 'submission', type: () => ID }) id: string,
|
||||
@Args({ name: 'field', type: () => SubmissionSetFieldInput }) input: SubmissionSetFieldInput,
|
||||
@Context('cache') cache: ContextCache,
|
||||
): Promise<SubmissionProgressModel> {
|
||||
const submission = await this.submissionService.findById(id)
|
||||
|
||||
if (!await this.submissionService.isOwner(submission, input.token)) {
|
||||
throw new Error('no access to submission')
|
||||
}
|
||||
@ -35,6 +34,6 @@ export class SubmissionSetFieldMutation {
|
||||
|
||||
cache.add(cache.getCacheKey(SubmissionEntity.name, submission.id), submission)
|
||||
|
||||
return new SubmissionProgressModel(this.idService.encode(submission.id), submission)
|
||||
return new SubmissionProgressModel(submission)
|
||||
}
|
||||
}
|
||||
|
||||
@ -4,12 +4,9 @@ import { IpAddress } from '../../decorator/ip.address.decorator'
|
||||
import { User } from '../../decorator/user.decorator'
|
||||
import { SubmissionProgressModel } from '../../dto/submission/submission.progress.model'
|
||||
import { SubmissionStartInput } from '../../dto/submission/submission.start.input'
|
||||
import { FormEntity } from '../../entity/form.entity'
|
||||
import { SubmissionEntity } from '../../entity/submission.entity'
|
||||
import { UserEntity } from '../../entity/user.entity'
|
||||
import { FormByIdPipe } from '../../pipe/form/form.by.id.pipe'
|
||||
import { FormService } from '../../service/form/form.service'
|
||||
import { IdService } from '../../service/id.service'
|
||||
import { SubmissionStartService } from '../../service/submission/submission.start.service'
|
||||
import { ContextCache } from '../context.cache'
|
||||
|
||||
@ -18,18 +15,19 @@ export class SubmissionStartMutation {
|
||||
constructor(
|
||||
private readonly startService: SubmissionStartService,
|
||||
private readonly formService: FormService,
|
||||
private readonly idService: IdService,
|
||||
) {
|
||||
}
|
||||
|
||||
@Mutation(() => SubmissionProgressModel)
|
||||
async submissionStart(
|
||||
@User() user: UserEntity,
|
||||
@Args({ name: 'form', type: () => ID }, FormByIdPipe) form: FormEntity,
|
||||
@Args({ name: 'form', type: () => ID }) id: string,
|
||||
@Args({ name: 'submission', type: () => SubmissionStartInput }) input: SubmissionStartInput,
|
||||
@IpAddress() ipAddr: string,
|
||||
@Context('cache') cache: ContextCache,
|
||||
): Promise<SubmissionProgressModel> {
|
||||
const form = await this.formService.findById(id)
|
||||
|
||||
if (!form.isLive && !this.formService.isAdmin(form, user)) {
|
||||
throw new Error('invalid form')
|
||||
}
|
||||
@ -38,6 +36,6 @@ export class SubmissionStartMutation {
|
||||
|
||||
cache.add(cache.getCacheKey(SubmissionEntity.name, submission.id), submission)
|
||||
|
||||
return new SubmissionProgressModel(this.idService.encode(submission.id), submission)
|
||||
return new SubmissionProgressModel(submission)
|
||||
}
|
||||
}
|
||||
|
||||
@ -4,15 +4,12 @@ import { Roles } from '../../decorator/roles.decorator'
|
||||
import { User } from '../../decorator/user.decorator'
|
||||
import { DeletedModel } from '../../dto/deleted.model'
|
||||
import { UserEntity } from '../../entity/user.entity'
|
||||
import { UserByIdPipe } from '../../pipe/user/user.by.id.pipe'
|
||||
import { IdService } from '../../service/id.service'
|
||||
import { UserDeleteService } from '../../service/user/user.delete.service'
|
||||
|
||||
@Injectable()
|
||||
export class UserDeleteMutation {
|
||||
constructor(
|
||||
private readonly deleteService: UserDeleteService,
|
||||
private readonly idService: IdService,
|
||||
) {
|
||||
}
|
||||
|
||||
@ -20,14 +17,14 @@ export class UserDeleteMutation {
|
||||
@Roles('admin')
|
||||
async deleteUser(
|
||||
@User() auth: UserEntity,
|
||||
@Args({ name: 'id', type: () => ID}, UserByIdPipe) user: UserEntity,
|
||||
@Args({ name: 'id', type: () => ID}) id: string,
|
||||
): Promise<DeletedModel> {
|
||||
if (auth.id === user.id) {
|
||||
if (auth.id.toString() === id) {
|
||||
throw new Error('cannot delete your own user')
|
||||
}
|
||||
|
||||
await this.deleteService.delete(user.id)
|
||||
await this.deleteService.delete(id)
|
||||
|
||||
return new DeletedModel(this.idService.encode(user.id))
|
||||
return new DeletedModel(id)
|
||||
}
|
||||
}
|
||||
|
||||
@ -3,7 +3,6 @@ import { Roles } from '../../decorator/roles.decorator'
|
||||
import { UserModel } from '../../dto/user/user.model'
|
||||
import { UserPagerModel } from '../../dto/user/user.pager.model'
|
||||
import { UserEntity } from '../../entity/user.entity'
|
||||
import { IdService } from '../../service/id.service'
|
||||
import { UserService } from '../../service/user/user.service'
|
||||
import { ContextCache } from '../context.cache'
|
||||
|
||||
@ -11,7 +10,6 @@ import { ContextCache } from '../context.cache'
|
||||
export class UserListQuery {
|
||||
constructor(
|
||||
private readonly userService: UserService,
|
||||
private readonly idService: IdService,
|
||||
) {
|
||||
}
|
||||
|
||||
@ -27,7 +25,7 @@ export class UserListQuery {
|
||||
return new UserPagerModel(
|
||||
entities.map(entity => {
|
||||
cache.add(cache.getCacheKey(UserEntity.name, entity.id), entity)
|
||||
return new UserModel(this.idService.encode(entity.id), entity)
|
||||
return new UserModel(entity)
|
||||
}),
|
||||
total,
|
||||
limit,
|
||||
|
||||
@ -3,25 +3,26 @@ import { Args, Context, ID, Query } from '@nestjs/graphql'
|
||||
import { Roles } from '../../decorator/roles.decorator'
|
||||
import { UserModel } from '../../dto/user/user.model'
|
||||
import { UserEntity } from '../../entity/user.entity'
|
||||
import { UserByIdPipe } from '../../pipe/user/user.by.id.pipe'
|
||||
import { IdService } from '../../service/id.service'
|
||||
import { UserService } from '../../service/user/user.service'
|
||||
import { ContextCache } from '../context.cache'
|
||||
|
||||
@Injectable()
|
||||
export class UserQuery {
|
||||
constructor(
|
||||
private readonly idService: IdService,
|
||||
private readonly userService: UserService,
|
||||
) {
|
||||
}
|
||||
|
||||
@Query(() => UserModel)
|
||||
@Roles('admin')
|
||||
public getUserById(
|
||||
@Args('id', {type: () => ID}, UserByIdPipe) user: UserEntity,
|
||||
public async getUserById(
|
||||
@Args('id', {type: () => ID}) id: string,
|
||||
@Context('cache') cache: ContextCache,
|
||||
): UserModel {
|
||||
): Promise<UserModel> {
|
||||
const user = await this.userService.findById(id)
|
||||
|
||||
cache.add(cache.getCacheKey(UserEntity.name, user.id), user)
|
||||
|
||||
return new UserModel(this.idService.encode(user.id), user)
|
||||
return new UserModel(user)
|
||||
}
|
||||
}
|
||||
|
||||
@ -21,7 +21,7 @@ export class UserResolver {
|
||||
@Context('cache') cache: ContextCache,
|
||||
): Promise<string[]> {
|
||||
return this.returnFieldForSuperuser(
|
||||
await cache.get<UserEntity>(cache.getCacheKey(UserEntity.name, parent._id)),
|
||||
await cache.get<UserEntity>(cache.getCacheKey(UserEntity.name, parent.id)),
|
||||
user,
|
||||
c => c.roles
|
||||
)
|
||||
|
||||
@ -5,7 +5,6 @@ import { User } from '../../decorator/user.decorator'
|
||||
import { UserModel } from '../../dto/user/user.model'
|
||||
import { UserUpdateInput } from '../../dto/user/user.update.input'
|
||||
import { UserEntity } from '../../entity/user.entity'
|
||||
import { IdService } from '../../service/id.service'
|
||||
import { UserService } from '../../service/user/user.service'
|
||||
import { UserUpdateService } from '../../service/user/user.update.service'
|
||||
import { ContextCache } from '../context.cache'
|
||||
@ -15,7 +14,6 @@ export class UserUpdateMutation {
|
||||
constructor(
|
||||
private readonly updateService: UserUpdateService,
|
||||
private readonly userService: UserService,
|
||||
private readonly idService: IdService,
|
||||
) {
|
||||
}
|
||||
|
||||
@ -30,12 +28,12 @@ export class UserUpdateMutation {
|
||||
throw new Error('cannot update your own user')
|
||||
}
|
||||
|
||||
const user = await this.userService.findById(this.idService.decode(input.id))
|
||||
const user = await this.userService.findById(input.id)
|
||||
|
||||
await this.updateService.update(user, input)
|
||||
|
||||
cache.add(cache.getCacheKey(UserEntity.name, user.id), user)
|
||||
|
||||
return new UserModel(this.idService.encode(user.id), user)
|
||||
return new UserModel(user)
|
||||
}
|
||||
}
|
||||
|
||||
@ -3,16 +3,13 @@ import { InjectRepository } from '@nestjs/typeorm'
|
||||
import { Repository } from 'typeorm'
|
||||
import { FormCreateInput } from '../../dto/form/form.create.input'
|
||||
import { FormEntity } from '../../entity/form.entity'
|
||||
import { PageEntity } from '../../entity/page.entity'
|
||||
import { UserEntity } from '../../entity/user.entity'
|
||||
import { FormPageCreateService } from './form.page.create.service'
|
||||
|
||||
@Injectable()
|
||||
export class FormCreateService {
|
||||
constructor(
|
||||
@InjectRepository(FormEntity)
|
||||
private readonly formRepository: Repository<FormEntity>,
|
||||
private readonly formPageCreateService: FormPageCreateService,
|
||||
private readonly formRepository: Repository<FormEntity>
|
||||
) {
|
||||
}
|
||||
|
||||
@ -26,14 +23,9 @@ export class FormCreateService {
|
||||
form.language = input.language || 'en'
|
||||
form.design.layout = input.layout
|
||||
|
||||
|
||||
form.endPage = this.formPageCreateService.create(input.endPage)
|
||||
form.startPage = this.formPageCreateService.create(input.startPage)
|
||||
|
||||
form.admin = admin
|
||||
|
||||
return await this.formRepository.save(form)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -14,13 +14,15 @@ export class FormDeleteService {
|
||||
) {
|
||||
}
|
||||
|
||||
async delete(id: number): Promise<void> {
|
||||
await this.submissionRepository.delete({
|
||||
form: new FormEntity({ id }),
|
||||
})
|
||||
async delete(id: string): Promise<void> {
|
||||
await this.submissionRepository.createQueryBuilder('s')
|
||||
.delete()
|
||||
.where('s.form = :form', { form: id })
|
||||
.execute()
|
||||
|
||||
await this.formRepository.delete({
|
||||
id,
|
||||
})
|
||||
await this.formRepository.createQueryBuilder('f')
|
||||
.delete()
|
||||
.where('f.id = :form', { form: id })
|
||||
.execute()
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,44 +0,0 @@
|
||||
import { Injectable } from '@nestjs/common'
|
||||
import { PageInput } from '../../dto/form/page.input'
|
||||
import { PageButtonEntity } from '../../entity/page.button.entity'
|
||||
import { PageEntity } from '../../entity/page.entity'
|
||||
import { IdService } from '../id.service'
|
||||
|
||||
@Injectable()
|
||||
export class FormPageCreateService {
|
||||
constructor(
|
||||
private readonly idService: IdService,
|
||||
) {
|
||||
}
|
||||
|
||||
public create(input: PageInput): PageEntity {
|
||||
const page = new PageEntity()
|
||||
page.show = Boolean(input?.show)
|
||||
page.buttons = []
|
||||
|
||||
if (!input) {
|
||||
return page
|
||||
}
|
||||
|
||||
page.title = input.title
|
||||
page.buttonText = input.buttonText
|
||||
page.paragraph = input.paragraph
|
||||
|
||||
if (input.buttons !== undefined) {
|
||||
page.buttons = input.buttons.map(buttonInput => {
|
||||
const button = new PageButtonEntity()
|
||||
button.page = page
|
||||
button.url = buttonInput.url
|
||||
button.action = buttonInput.action
|
||||
button.text = buttonInput.text
|
||||
button.color = buttonInput.color
|
||||
button.bgColor = buttonInput.bgColor
|
||||
button.activeColor = buttonInput.activeColor
|
||||
|
||||
return button
|
||||
})
|
||||
}
|
||||
|
||||
return page
|
||||
}
|
||||
}
|
||||
@ -1,73 +0,0 @@
|
||||
import { Injectable } from '@nestjs/common'
|
||||
import { PageInput } from '../../dto/form/page.input'
|
||||
import { PageButtonEntity } from '../../entity/page.button.entity'
|
||||
import { PageEntity } from '../../entity/page.entity'
|
||||
import { IdService } from '../id.service'
|
||||
|
||||
@Injectable()
|
||||
export class FormPageUpdateService {
|
||||
constructor(
|
||||
private readonly idService: IdService,
|
||||
) {
|
||||
}
|
||||
|
||||
public update(page: PageEntity, input: PageInput): PageEntity {
|
||||
if (!page) {
|
||||
page = new PageEntity()
|
||||
page.show = false
|
||||
}
|
||||
|
||||
if (input.show !== undefined) {
|
||||
page.show = input.show
|
||||
}
|
||||
|
||||
if (input.title !== undefined) {
|
||||
page.title = input.title
|
||||
}
|
||||
|
||||
if (input.paragraph !== undefined) {
|
||||
page.paragraph = input.paragraph
|
||||
}
|
||||
|
||||
if (input.buttonText !== undefined) {
|
||||
page.buttonText = input.buttonText
|
||||
}
|
||||
|
||||
if (input.buttons !== undefined) {
|
||||
page.buttons = input.buttons.map(buttonInput => {
|
||||
const entity = this.findByIdInList(
|
||||
page?.buttons,
|
||||
buttonInput.id,
|
||||
new PageButtonEntity()
|
||||
)
|
||||
|
||||
entity.page = page
|
||||
entity.url = buttonInput.url
|
||||
entity.action = buttonInput.action
|
||||
entity.text = buttonInput.text
|
||||
entity.color = buttonInput.color
|
||||
entity.bgColor = buttonInput.bgColor
|
||||
entity.activeColor = buttonInput.activeColor
|
||||
|
||||
return entity
|
||||
})
|
||||
}
|
||||
|
||||
return page
|
||||
}
|
||||
|
||||
|
||||
private findByIdInList<T extends { id: number }>(list: T[], id: string, fallback: T): T {
|
||||
if (!list || /^NEW-/.test(id)) {
|
||||
return fallback
|
||||
}
|
||||
|
||||
const found = list.find((value) => value.id === this.idService.decode(id))
|
||||
|
||||
if (found) {
|
||||
return found
|
||||
}
|
||||
|
||||
return fallback
|
||||
}
|
||||
}
|
||||
@ -10,8 +10,6 @@ import { FormHookEntity } from '../../entity/form.hook.entity'
|
||||
import { FormNotificationEntity } from '../../entity/form.notification.entity'
|
||||
import { PageButtonEntity } from '../../entity/page.button.entity'
|
||||
import { PageEntity } from '../../entity/page.entity'
|
||||
import { IdService } from '../id.service'
|
||||
import { FormPageUpdateService } from './form.page.update.service'
|
||||
|
||||
@Injectable()
|
||||
export class FormUpdateService {
|
||||
@ -22,8 +20,6 @@ export class FormUpdateService {
|
||||
private readonly formFieldRepository: Repository<FormFieldEntity>,
|
||||
@InjectRepository(FormHookEntity)
|
||||
private readonly formHookRepository: Repository<FormHookEntity>,
|
||||
private readonly idService: IdService,
|
||||
private readonly pageService: FormPageUpdateService,
|
||||
) {
|
||||
}
|
||||
|
||||
@ -263,11 +259,87 @@ export class FormUpdateService {
|
||||
*/
|
||||
|
||||
if (input.startPage !== undefined) {
|
||||
form.startPage = this.pageService.update(form.startPage, input.startPage)
|
||||
if (!form.startPage) {
|
||||
form.startPage = new PageEntity()
|
||||
form.startPage.show = false
|
||||
}
|
||||
|
||||
if (input.startPage.show !== undefined) {
|
||||
form.startPage.show = input.startPage.show
|
||||
}
|
||||
|
||||
if (input.startPage.title !== undefined) {
|
||||
form.startPage.title = input.startPage.title
|
||||
}
|
||||
|
||||
if (input.startPage.paragraph !== undefined) {
|
||||
form.startPage.paragraph = input.startPage.paragraph
|
||||
}
|
||||
|
||||
if (input.startPage.buttonText !== undefined) {
|
||||
form.startPage.buttonText = input.startPage.buttonText
|
||||
}
|
||||
|
||||
if (input.startPage.buttons !== undefined) {
|
||||
form.startPage.buttons = input.startPage.buttons.map(buttonInput => {
|
||||
const entity = this.findByIdInList(
|
||||
form.startPage?.buttons,
|
||||
buttonInput.id,
|
||||
new PageButtonEntity()
|
||||
)
|
||||
entity.page = form.startPage
|
||||
entity.url = buttonInput.url
|
||||
entity.action = buttonInput.action
|
||||
entity.text = buttonInput.text
|
||||
entity.color = buttonInput.color
|
||||
entity.bgColor = buttonInput.bgColor
|
||||
entity.activeColor = buttonInput.activeColor
|
||||
|
||||
return entity
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
if (input.endPage !== undefined) {
|
||||
form.endPage = this.pageService.update(form.endPage, input.endPage)
|
||||
if (!form.endPage) {
|
||||
form.endPage = new PageEntity()
|
||||
form.endPage.show = false
|
||||
}
|
||||
|
||||
if (input.endPage.show !== undefined) {
|
||||
form.endPage.show = input.endPage.show
|
||||
}
|
||||
|
||||
if (input.endPage.title !== undefined) {
|
||||
form.endPage.title = input.endPage.title
|
||||
}
|
||||
|
||||
if (input.endPage.paragraph !== undefined) {
|
||||
form.endPage.paragraph = input.endPage.paragraph
|
||||
}
|
||||
|
||||
if (input.endPage.buttonText !== undefined) {
|
||||
form.endPage.buttonText = input.endPage.buttonText
|
||||
}
|
||||
|
||||
if (input.endPage.buttons !== undefined) {
|
||||
form.endPage.buttons = input.endPage.buttons.map(buttonInput => {
|
||||
const entity = this.findByIdInList(
|
||||
form.endPage?.buttons,
|
||||
buttonInput.id,
|
||||
new PageButtonEntity()
|
||||
)
|
||||
entity.page = form.endPage
|
||||
entity.url = buttonInput.url
|
||||
entity.action = buttonInput.action
|
||||
entity.text = buttonInput.text
|
||||
entity.color = buttonInput.color
|
||||
entity.bgColor = buttonInput.bgColor
|
||||
entity.activeColor = buttonInput.activeColor
|
||||
|
||||
return entity
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
await this.formRepository.save(form)
|
||||
@ -275,12 +347,12 @@ export class FormUpdateService {
|
||||
return form
|
||||
}
|
||||
|
||||
private findByIdInList<T extends { id: number }>(list: T[], id: string, fallback: T): T {
|
||||
if (!list || /^NEW-/.test(id) || !id) {
|
||||
private findByIdInList<T>(list: T[], id: string, fallback: T): T {
|
||||
if (!list) {
|
||||
return fallback
|
||||
}
|
||||
|
||||
const found = list.find((value) => value.id === this.idService.decode(id))
|
||||
const found = list.find((value: any) => String(value.id) === String(id))
|
||||
|
||||
if (found) {
|
||||
return found
|
||||
|
||||
@ -1,8 +1,6 @@
|
||||
import { FormCreateService } from './form.create.service'
|
||||
import { FormDeleteService } from './form.delete.service'
|
||||
import { FormFieldService } from './form.field.service'
|
||||
import { FormPageCreateService } from './form.page.create.service'
|
||||
import { FormPageUpdateService } from './form.page.update.service'
|
||||
import { FormService } from './form.service'
|
||||
import { FormStatisticService } from './form.statistic.service'
|
||||
import { FormUpdateService } from './form.update.service'
|
||||
@ -11,8 +9,6 @@ export const formServices = [
|
||||
FormCreateService,
|
||||
FormDeleteService,
|
||||
FormFieldService,
|
||||
FormPageCreateService,
|
||||
FormPageUpdateService,
|
||||
FormService,
|
||||
FormStatisticService,
|
||||
FormUpdateService,
|
||||
|
||||
@ -1,32 +0,0 @@
|
||||
import { Injectable } from '@nestjs/common'
|
||||
import { ConfigService } from '@nestjs/config'
|
||||
import Hashids from 'hashids'
|
||||
|
||||
@Injectable()
|
||||
export class IdService {
|
||||
private readonly hashids: Hashids
|
||||
|
||||
constructor(
|
||||
readonly config: ConfigService
|
||||
) {
|
||||
this.hashids = new Hashids(config.get('SECRET_KEY'), 6)
|
||||
}
|
||||
|
||||
public encode(id: number): string {
|
||||
return this.hashids.encode([ id ])
|
||||
}
|
||||
|
||||
public decode(raw: string): number {
|
||||
if (!this.hashids.isValidId(raw)) {
|
||||
throw new Error('invalid id passed')
|
||||
}
|
||||
|
||||
const results: number[] = this.hashids.decode(raw) as number[]
|
||||
|
||||
if (results[0] === undefined) {
|
||||
throw new Error('invalid id passed')
|
||||
}
|
||||
|
||||
return results[0]
|
||||
}
|
||||
}
|
||||
@ -5,7 +5,6 @@ import Redis from 'ioredis'
|
||||
import { PinoLogger } from 'nestjs-pino'
|
||||
import { authServices } from './auth'
|
||||
import { formServices } from './form'
|
||||
import { IdService } from './id.service'
|
||||
import { InstallationMetricsService } from './installation.metrics.service'
|
||||
import { MailService } from './mail.service'
|
||||
import { profileServices } from './profile'
|
||||
@ -45,5 +44,4 @@ export const services = [
|
||||
})
|
||||
},
|
||||
},
|
||||
IdService,
|
||||
]
|
||||
|
||||
@ -25,12 +25,12 @@ export class SubmissionNotificationService {
|
||||
try {
|
||||
const to = this.getEmail(
|
||||
submission,
|
||||
notification.toField?.id,
|
||||
notification.toField.id,
|
||||
notification.toEmail
|
||||
)
|
||||
const from = this.getEmail(
|
||||
submission,
|
||||
notification.fromField?.id,
|
||||
notification.fromField.id,
|
||||
notification.fromEmail
|
||||
)
|
||||
|
||||
@ -73,18 +73,14 @@ export class SubmissionNotificationService {
|
||||
}
|
||||
|
||||
private getEmail(submission: SubmissionEntity, fieldId: number, fallback: string): string {
|
||||
if (!fieldId) {
|
||||
return fallback
|
||||
}
|
||||
|
||||
const data = submission.fields.find(field => field.fieldId === fieldId)?.content
|
||||
|
||||
if (!data) {
|
||||
return fallback
|
||||
}
|
||||
|
||||
if (typeof data === 'string') {
|
||||
return data
|
||||
if (typeof data.value === 'string') {
|
||||
return data.value
|
||||
}
|
||||
|
||||
return fallback
|
||||
|
||||
@ -58,7 +58,7 @@ export class SubmissionService {
|
||||
return await qb.getManyAndCount()
|
||||
}
|
||||
|
||||
async findById(id: number): Promise<SubmissionEntity> {
|
||||
async findById(id: string): Promise<SubmissionEntity> {
|
||||
const submission = await this.submissionRepository.findOne(id);
|
||||
|
||||
if (!submission) {
|
||||
|
||||
@ -7,7 +7,6 @@ import { Repository } from 'typeorm'
|
||||
import { SubmissionSetFieldInput } from '../../dto/submission/submission.set.field.input'
|
||||
import { SubmissionEntity } from '../../entity/submission.entity'
|
||||
import { SubmissionFieldContent, SubmissionFieldEntity } from '../../entity/submission.field.entity'
|
||||
import { IdService } from '../id.service'
|
||||
import { SubmissionHookService } from './submission.hook.service'
|
||||
import { SubmissionNotificationService } from './submission.notification.service'
|
||||
|
||||
@ -20,16 +19,13 @@ export class SubmissionSetFieldService {
|
||||
private readonly submissionFieldRepository: Repository<SubmissionFieldEntity>,
|
||||
private readonly webHook: SubmissionHookService,
|
||||
private readonly notifications: SubmissionNotificationService,
|
||||
private readonly idService: IdService,
|
||||
private readonly logger: PinoLogger,
|
||||
) {
|
||||
logger.setContext(this.constructor.name)
|
||||
}
|
||||
|
||||
async saveField(submission: SubmissionEntity, input: SubmissionSetFieldInput): Promise<void> {
|
||||
const formFieldId = this.idService.decode(input.field)
|
||||
|
||||
let field = submission.fields.find(field => field.field.id === formFieldId)
|
||||
let field = submission.fields.find(field => field.field.id.toString() === input.field)
|
||||
|
||||
submission.timeElapsed = dayjs().diff(dayjs(submission.created), 'second')
|
||||
|
||||
@ -42,7 +38,7 @@ export class SubmissionSetFieldService {
|
||||
field = new SubmissionFieldEntity()
|
||||
|
||||
field.submission = submission
|
||||
field.field = submission.form.fields.find(field => field.id === formFieldId)
|
||||
field.field = submission.form.fields.find(field => field.id.toString() === input.field)
|
||||
field.type = field.field.type
|
||||
field.content = this.parseData(field, input.data)
|
||||
|
||||
@ -88,7 +84,7 @@ export class SubmissionSetFieldService {
|
||||
field: SubmissionFieldEntity,
|
||||
data: string
|
||||
): SubmissionFieldContent {
|
||||
let raw: SubmissionFieldContent
|
||||
let raw: { [key: string]: unknown }
|
||||
|
||||
const context = {
|
||||
field: field.fieldId,
|
||||
@ -96,49 +92,21 @@ export class SubmissionSetFieldService {
|
||||
}
|
||||
|
||||
try {
|
||||
raw = JSON.parse(data) as SubmissionFieldContent
|
||||
raw = JSON.parse(data) as { [key: string]: unknown }
|
||||
} catch (e) {
|
||||
this.logger.warn(context, 'received invalid data for field')
|
||||
return { value: null }
|
||||
}
|
||||
|
||||
if (Array.isArray(raw)) {
|
||||
return raw.map((row: unknown, index) => {
|
||||
switch (typeof row) {
|
||||
case 'number':
|
||||
case 'string':
|
||||
case 'boolean':
|
||||
case 'undefined':
|
||||
return row
|
||||
}
|
||||
|
||||
if (row === null) {
|
||||
return row
|
||||
}
|
||||
|
||||
this.logger.warn({
|
||||
...context,
|
||||
path: `${index}`,
|
||||
}, 'invalid data in array')
|
||||
valid = false
|
||||
|
||||
return null
|
||||
})
|
||||
}
|
||||
|
||||
if (
|
||||
[
|
||||
'number',
|
||||
'string',
|
||||
'boolean',
|
||||
'undefined',
|
||||
].includes(typeof raw)
|
||||
) {
|
||||
return raw
|
||||
if (typeof raw !== 'object' || Array.isArray(raw)) {
|
||||
this.logger.warn(context, 'only object supported for data')
|
||||
return { value: null }
|
||||
}
|
||||
|
||||
// now ensure data structure
|
||||
const result = {}
|
||||
const result = {
|
||||
value: null,
|
||||
}
|
||||
|
||||
let valid = true
|
||||
|
||||
@ -179,48 +147,6 @@ export class SubmissionSetFieldService {
|
||||
return
|
||||
}
|
||||
|
||||
if (typeof value === 'object') {
|
||||
result[String(key)] = {}
|
||||
|
||||
for (const subKey of Object.keys(value)) {
|
||||
const subValue = raw[String(key)][String(subKey)]
|
||||
|
||||
switch (typeof subValue) {
|
||||
case 'number':
|
||||
case 'string':
|
||||
case 'boolean':
|
||||
result[String(key)][String(subKey)] = subValue
|
||||
return
|
||||
}
|
||||
|
||||
if (Array.isArray(subValue)) {
|
||||
result[String(key)][String(subKey)] = subValue.map((row: unknown, index) => {
|
||||
switch (typeof row) {
|
||||
case 'number':
|
||||
case 'string':
|
||||
case 'boolean':
|
||||
case 'undefined':
|
||||
return row
|
||||
}
|
||||
|
||||
if (row === null) {
|
||||
return row
|
||||
}
|
||||
|
||||
this.logger.warn({
|
||||
...context,
|
||||
path: `${key}/${subKey}/${index}`,
|
||||
}, 'invalid data in array')
|
||||
valid = false
|
||||
|
||||
return null
|
||||
})
|
||||
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.logger.warn({
|
||||
...context,
|
||||
path: String(key),
|
||||
|
||||
@ -11,7 +11,7 @@ export class UserDeleteService {
|
||||
) {
|
||||
}
|
||||
|
||||
async delete(id: number): Promise<void> {
|
||||
async delete(id: string): Promise<void> {
|
||||
await this.userRepository.delete(id)
|
||||
}
|
||||
}
|
||||
|
||||
@ -26,7 +26,7 @@ export class UserService {
|
||||
return await qb.getManyAndCount()
|
||||
}
|
||||
|
||||
async findById(id: number): Promise<UserEntity> {
|
||||
async findById(id: string): Promise<UserEntity> {
|
||||
const user = await this.userRepository.findOne(id);
|
||||
|
||||
if (!user) {
|
||||
|
||||
@ -16,15 +16,15 @@ export class UserUpdateService {
|
||||
}
|
||||
|
||||
async update(user: UserEntity, input: UserUpdateInput): Promise<UserEntity> {
|
||||
if (this.shouldUpdate(input, user, 'firstName')) {
|
||||
if (input.firstName !== undefined) {
|
||||
user.firstName = input.firstName
|
||||
}
|
||||
|
||||
if (this.shouldUpdate(input, user, 'lastName')) {
|
||||
if (input.lastName !== undefined) {
|
||||
user.lastName = input.lastName
|
||||
}
|
||||
|
||||
if (this.shouldUpdate(input, user, 'email')) {
|
||||
if (input.email !== undefined) {
|
||||
user.email = input.email
|
||||
user.emailVerified = false
|
||||
// TODO request email verification
|
||||
@ -34,15 +34,15 @@ export class UserUpdateService {
|
||||
}
|
||||
}
|
||||
|
||||
if (this.shouldUpdate(input, user, 'username')) {
|
||||
if (input.username !== undefined) {
|
||||
user.username = input.username
|
||||
}
|
||||
|
||||
if (this.shouldUpdate(input, user, 'roles')) {
|
||||
if (input.roles !== undefined) {
|
||||
user.roles = input.roles as rolesType
|
||||
}
|
||||
|
||||
if (this.shouldUpdate(input, user, 'language')) {
|
||||
if (input.language !== undefined) {
|
||||
user.language = input.language
|
||||
}
|
||||
|
||||
@ -54,16 +54,4 @@ export class UserUpdateService {
|
||||
|
||||
return user
|
||||
}
|
||||
|
||||
private shouldUpdate(
|
||||
input: UserUpdateInput,
|
||||
user: UserEntity,
|
||||
property: keyof UserUpdateInput
|
||||
): boolean {
|
||||
if (input[property] === undefined) {
|
||||
return false
|
||||
}
|
||||
|
||||
return input[property] == user[property]
|
||||
}
|
||||
}
|
||||
|
||||
354
yarn.lock
354
yarn.lock
@ -532,11 +532,6 @@
|
||||
minimatch "^3.0.4"
|
||||
strip-json-comments "^3.1.1"
|
||||
|
||||
"@gar/promisify@^1.1.3":
|
||||
version "1.1.3"
|
||||
resolved "https://registry.yarnpkg.com/@gar/promisify/-/promisify-1.1.3.tgz#555193ab2e3bb3b6adc3d551c9c030d9e860daf6"
|
||||
integrity sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==
|
||||
|
||||
"@graphql-tools/merge@8.2.2":
|
||||
version "8.2.2"
|
||||
resolved "https://registry.yarnpkg.com/@graphql-tools/merge/-/merge-8.2.2.tgz#433566c662a33f5a9c3cc5f3ce3753fb0019477a"
|
||||
@ -1075,22 +1070,6 @@
|
||||
"@nodelib/fs.scandir" "2.1.5"
|
||||
fastq "^1.6.0"
|
||||
|
||||
"@npmcli/fs@^2.1.0":
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/@npmcli/fs/-/fs-2.1.0.tgz#f2a21c28386e299d1a9fae8051d35ad180e33109"
|
||||
integrity sha512-DmfBvNXGaetMxj9LTp8NAN9vEidXURrf5ZTslQzEAi/6GbW+4yjaLFQc6Tue5cpZ9Frlk4OBo/Snf1Bh/S7qTQ==
|
||||
dependencies:
|
||||
"@gar/promisify" "^1.1.3"
|
||||
semver "^7.3.5"
|
||||
|
||||
"@npmcli/move-file@^1.1.2":
|
||||
version "1.1.2"
|
||||
resolved "https://registry.yarnpkg.com/@npmcli/move-file/-/move-file-1.1.2.tgz#1a82c3e372f7cae9253eb66d72543d6b8685c674"
|
||||
integrity sha512-1SUf/Cg2GzGDyaf15aR9St9TWlb+XvbZXWpDx8YKs7MLzMH/BCeopv+y9vzrzgkfykCGuWOlSu3mZhj2+FQcrg==
|
||||
dependencies:
|
||||
mkdirp "^1.0.4"
|
||||
rimraf "^3.0.2"
|
||||
|
||||
"@nuxtjs/opencollective@0.3.2":
|
||||
version "0.3.2"
|
||||
resolved "https://registry.yarnpkg.com/@nuxtjs/opencollective/-/opencollective-0.3.2.tgz#620ce1044f7ac77185e825e1936115bb38e2681c"
|
||||
@ -1185,11 +1164,6 @@
|
||||
resolved "https://registry.yarnpkg.com/@tootallnate/once/-/once-1.1.2.tgz#ccb91445360179a04e7fe6aff78c00ffc1eeaf82"
|
||||
integrity sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==
|
||||
|
||||
"@tootallnate/once@2":
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/@tootallnate/once/-/once-2.0.0.tgz#f544a148d3ab35801c1f633a7441fd87c2e484bf"
|
||||
integrity sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==
|
||||
|
||||
"@tsconfig/node10@^1.0.7":
|
||||
version "1.0.8"
|
||||
resolved "https://registry.yarnpkg.com/@tsconfig/node10/-/node10-1.0.8.tgz#c1e4e80d6f964fbecb3359c43bd48b40f7cadad9"
|
||||
@ -1382,7 +1356,7 @@
|
||||
dependencies:
|
||||
"@types/istanbul-lib-report" "*"
|
||||
|
||||
"@types/jest@^27.4.1":
|
||||
"@types/jest@27.4.1":
|
||||
version "27.4.1"
|
||||
resolved "https://registry.yarnpkg.com/@types/jest/-/jest-27.4.1.tgz#185cbe2926eaaf9662d340cc02e548ce9e11ab6d"
|
||||
integrity sha512-23iPJADSmicDVrWk+HT58LMJtzLAnB2AgIzplQuq/bSrGaxCrlvRFjGbXmamnnk/mAmCdLStiGqggu28ocUyiw==
|
||||
@ -1863,23 +1837,6 @@ agent-base@6, agent-base@^6.0.0, agent-base@^6.0.2:
|
||||
dependencies:
|
||||
debug "4"
|
||||
|
||||
agentkeepalive@^4.2.1:
|
||||
version "4.2.1"
|
||||
resolved "https://registry.yarnpkg.com/agentkeepalive/-/agentkeepalive-4.2.1.tgz#a7975cbb9f83b367f06c90cc51ff28fe7d499717"
|
||||
integrity sha512-Zn4cw2NEqd+9fiSVWMscnjyQ1a8Yfoc5oBajLeo5w+YBHgDUcEBY2hS4YpTz6iN5f/2zQiktcuM6tS8x1p9dpA==
|
||||
dependencies:
|
||||
debug "^4.1.0"
|
||||
depd "^1.1.2"
|
||||
humanize-ms "^1.2.1"
|
||||
|
||||
aggregate-error@^3.0.0:
|
||||
version "3.1.0"
|
||||
resolved "https://registry.yarnpkg.com/aggregate-error/-/aggregate-error-3.1.0.tgz#92670ff50f5359bdb7a3e0d40d0ec30c5737687a"
|
||||
integrity sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==
|
||||
dependencies:
|
||||
clean-stack "^2.0.0"
|
||||
indent-string "^4.0.0"
|
||||
|
||||
ajv-formats@2.1.1:
|
||||
version "2.1.1"
|
||||
resolved "https://registry.yarnpkg.com/ajv-formats/-/ajv-formats-2.1.1.tgz#6e669400659eb74973bbf2e33327180a0996b520"
|
||||
@ -2107,14 +2064,6 @@ are-we-there-yet@^2.0.0:
|
||||
delegates "^1.0.0"
|
||||
readable-stream "^3.6.0"
|
||||
|
||||
are-we-there-yet@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-3.0.0.tgz#ba20bd6b553e31d62fc8c31bd23d22b95734390d"
|
||||
integrity sha512-0GWpv50YSOcLXaN6/FAKY3vfRbllXWV2xvfA/oKJF8pzFhWXPV+yjhJXDBbjscDYowv7Yw1A3uigpzn5iEGTyw==
|
||||
dependencies:
|
||||
delegates "^1.0.0"
|
||||
readable-stream "^3.6.0"
|
||||
|
||||
are-we-there-yet@~1.1.2:
|
||||
version "1.1.7"
|
||||
resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-1.1.7.tgz#b15474a932adab4ff8a50d9adfa7e4e926f21146"
|
||||
@ -2487,30 +2436,6 @@ bytes@3.1.1:
|
||||
resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.1.tgz#3f018291cb4cbad9accb6e6970bca9c8889e879a"
|
||||
integrity sha512-dWe4nWO/ruEOY7HkUJ5gFt1DCFV9zPRoJr8pV0/ASQermOZjtq8jMjOprC0Kd10GLN+l7xaUPvxzJFWtxGu8Fg==
|
||||
|
||||
cacache@^16.0.2:
|
||||
version "16.0.3"
|
||||
resolved "https://registry.yarnpkg.com/cacache/-/cacache-16.0.3.tgz#0b6314bde969bd4098b03a5f90a351e8a1483f48"
|
||||
integrity sha512-eC7wYodNCVb97kuHGk5P+xZsvUJHkhSEOyNwkenqQPAsOtrTjvWOE5vSPNBpz9d8X3acIf6w2Ub5s4rvOCTs4g==
|
||||
dependencies:
|
||||
"@npmcli/fs" "^2.1.0"
|
||||
"@npmcli/move-file" "^1.1.2"
|
||||
chownr "^2.0.0"
|
||||
fs-minipass "^2.1.0"
|
||||
glob "^7.2.0"
|
||||
infer-owner "^1.0.4"
|
||||
lru-cache "^7.7.1"
|
||||
minipass "^3.1.6"
|
||||
minipass-collect "^1.0.2"
|
||||
minipass-flush "^1.0.5"
|
||||
minipass-pipeline "^1.2.4"
|
||||
mkdirp "^1.0.4"
|
||||
p-map "^4.0.0"
|
||||
promise-inflight "^1.0.1"
|
||||
rimraf "^3.0.2"
|
||||
ssri "^8.0.1"
|
||||
tar "^6.1.11"
|
||||
unique-filename "^1.1.1"
|
||||
|
||||
call-bind@^1.0.0, call-bind@^1.0.2:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c"
|
||||
@ -2720,11 +2645,6 @@ clean-css@^4.2.1:
|
||||
dependencies:
|
||||
source-map "~0.6.0"
|
||||
|
||||
clean-stack@^2.0.0:
|
||||
version "2.2.0"
|
||||
resolved "https://registry.yarnpkg.com/clean-stack/-/clean-stack-2.2.0.tgz#ee8472dbb129e727b31e8a10a427dee9dfe4008b"
|
||||
integrity sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==
|
||||
|
||||
cli-cursor@^3.1.0:
|
||||
version "3.1.0"
|
||||
resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-3.1.0.tgz#264305a7ae490d1d03bf0c9ba7c925d1753af307"
|
||||
@ -2821,7 +2741,7 @@ color-name@~1.1.4:
|
||||
resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2"
|
||||
integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==
|
||||
|
||||
color-support@^1.1.2, color-support@^1.1.3:
|
||||
color-support@^1.1.2:
|
||||
version "1.1.3"
|
||||
resolved "https://registry.yarnpkg.com/color-support/-/color-support-1.1.3.tgz#93834379a1cc9a0c61f82f52f0d04322251bd5a2"
|
||||
integrity sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==
|
||||
@ -3173,7 +3093,7 @@ denque@^2.0.1:
|
||||
resolved "https://registry.yarnpkg.com/denque/-/denque-2.0.1.tgz#bcef4c1b80dc32efe97515744f21a4229ab8934a"
|
||||
integrity sha512-tfiWc6BQLXNLpNiR5iGd0Ocu3P3VpxfzFiqubLgMfhfOw9WyvgJBd46CClNn9k3qfbjvT//0cf7AlYRX/OslMQ==
|
||||
|
||||
depd@^1.1.2, depd@~1.1.2:
|
||||
depd@~1.1.2:
|
||||
version "1.1.2"
|
||||
resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9"
|
||||
integrity sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=
|
||||
@ -3430,13 +3350,6 @@ encoding-japanese@1.0.30:
|
||||
resolved "https://registry.yarnpkg.com/encoding-japanese/-/encoding-japanese-1.0.30.tgz#537c4d62881767925d601acb4c79fb14db81703a"
|
||||
integrity sha512-bd/DFLAoJetvv7ar/KIpE3CNO8wEuyrt9Xuw6nSMiZ+Vrz/Q21BPsMHvARL2Wz6IKHKXgb+DWZqtRg1vql9cBg==
|
||||
|
||||
encoding@^0.1.13:
|
||||
version "0.1.13"
|
||||
resolved "https://registry.yarnpkg.com/encoding/-/encoding-0.1.13.tgz#56574afdd791f54a8e9b2785c0582a2d26210fa9"
|
||||
integrity sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==
|
||||
dependencies:
|
||||
iconv-lite "^0.6.2"
|
||||
|
||||
end-of-stream@^1.1.0, end-of-stream@^1.4.1:
|
||||
version "1.4.4"
|
||||
resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0"
|
||||
@ -3462,16 +3375,6 @@ entities@^2.0.0:
|
||||
resolved "https://registry.yarnpkg.com/entities/-/entities-2.2.0.tgz#098dc90ebb83d8dffa089d55256b351d34c4da55"
|
||||
integrity sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==
|
||||
|
||||
env-paths@^2.2.0:
|
||||
version "2.2.1"
|
||||
resolved "https://registry.yarnpkg.com/env-paths/-/env-paths-2.2.1.tgz#420399d416ce1fbe9bc0a07c62fa68d67fd0f8f2"
|
||||
integrity sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==
|
||||
|
||||
err-code@^2.0.2:
|
||||
version "2.0.3"
|
||||
resolved "https://registry.yarnpkg.com/err-code/-/err-code-2.0.3.tgz#23c2f3b756ffdfc608d30e27c9a941024807e7f9"
|
||||
integrity sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==
|
||||
|
||||
error-ex@^1.3.1:
|
||||
version "1.3.2"
|
||||
resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf"
|
||||
@ -4156,7 +4059,7 @@ fs-minipass@^1.2.7:
|
||||
dependencies:
|
||||
minipass "^2.6.0"
|
||||
|
||||
fs-minipass@^2.0.0, fs-minipass@^2.1.0:
|
||||
fs-minipass@^2.0.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-2.1.0.tgz#7f5036fdbf12c63c169190cbe4199c852271f9fb"
|
||||
integrity sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==
|
||||
@ -4221,20 +4124,6 @@ gauge@^3.0.0:
|
||||
strip-ansi "^6.0.1"
|
||||
wide-align "^1.1.2"
|
||||
|
||||
gauge@^4.0.0:
|
||||
version "4.0.3"
|
||||
resolved "https://registry.yarnpkg.com/gauge/-/gauge-4.0.3.tgz#286cf105c1962c659f0963058fb05116c1b82d3f"
|
||||
integrity sha512-ICw1DhAwMtb22rYFwEHgJcx1JCwJGv3x6G0OQUq56Nge+H4Q8JEwr8iveS0XFlsUNSI67F5ffMGK25bK4Pmskw==
|
||||
dependencies:
|
||||
aproba "^1.0.3 || ^2.0.0"
|
||||
color-support "^1.1.3"
|
||||
console-control-strings "^1.1.0"
|
||||
has-unicode "^2.0.1"
|
||||
signal-exit "^3.0.7"
|
||||
string-width "^4.2.3"
|
||||
strip-ansi "^6.0.1"
|
||||
wide-align "^1.1.5"
|
||||
|
||||
gauge@~2.7.3:
|
||||
version "2.7.4"
|
||||
resolved "https://registry.yarnpkg.com/gauge/-/gauge-2.7.4.tgz#2c03405c7538c39d7eb37b317022e325fb018bf7"
|
||||
@ -4350,7 +4239,7 @@ glob@7.1.7:
|
||||
once "^1.3.0"
|
||||
path-is-absolute "^1.0.0"
|
||||
|
||||
glob@^7.0.0, glob@^7.0.3, glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6, glob@^7.2.0:
|
||||
glob@^7.0.0, glob@^7.0.3, glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6:
|
||||
version "7.2.0"
|
||||
resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.0.tgz#d15535af7732e02e948f4c41628bd910293f6023"
|
||||
integrity sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==
|
||||
@ -4391,7 +4280,7 @@ graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.4:
|
||||
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.8.tgz#e412b8d33f5e006593cbd3cee6df9f2cebbe802a"
|
||||
integrity sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg==
|
||||
|
||||
graceful-fs@^4.2.6, graceful-fs@^4.2.9:
|
||||
graceful-fs@^4.2.9:
|
||||
version "4.2.9"
|
||||
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.9.tgz#041b05df45755e587a24942279b9d113146e1c96"
|
||||
integrity sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==
|
||||
@ -4503,11 +4392,6 @@ has@^1.0.3:
|
||||
dependencies:
|
||||
function-bind "^1.1.1"
|
||||
|
||||
hashids@^2.2.10:
|
||||
version "2.2.10"
|
||||
resolved "https://registry.yarnpkg.com/hashids/-/hashids-2.2.10.tgz#82f45538cf03ce73e31b78d1abe78d287cf760c4"
|
||||
integrity sha512-nXnYums7F8B5Y+GSThutLPlKMaamW1yjWNZVt0WModiJfdjaDZHnhYTWblS+h1OoBx3yjwiBwxldPP3nIbFSSA==
|
||||
|
||||
he@1.2.0, he@^1.2.0:
|
||||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f"
|
||||
@ -4618,11 +4502,6 @@ htmlparser2@^6.1.0:
|
||||
domutils "^2.5.2"
|
||||
entities "^2.0.0"
|
||||
|
||||
http-cache-semantics@^4.1.0:
|
||||
version "4.1.0"
|
||||
resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz#49e91c5cbf36c9b94bcfcd71c23d5249ec74e390"
|
||||
integrity sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==
|
||||
|
||||
http-errors@1.8.1:
|
||||
version "1.8.1"
|
||||
resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.8.1.tgz#7c3f28577cbc8a207388455dbd62295ed07bd68c"
|
||||
@ -4643,15 +4522,6 @@ http-proxy-agent@^4.0.0, http-proxy-agent@^4.0.1:
|
||||
agent-base "6"
|
||||
debug "4"
|
||||
|
||||
http-proxy-agent@^5.0.0:
|
||||
version "5.0.0"
|
||||
resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz#5129800203520d434f142bc78ff3c170800f2b43"
|
||||
integrity sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==
|
||||
dependencies:
|
||||
"@tootallnate/once" "2"
|
||||
agent-base "6"
|
||||
debug "4"
|
||||
|
||||
http-signature@~1.2.0:
|
||||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1"
|
||||
@ -4679,13 +4549,6 @@ human-signals@^2.1.0:
|
||||
resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-2.1.0.tgz#dc91fcba42e4d06e4abaed33b3e7a3c02f514ea0"
|
||||
integrity sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==
|
||||
|
||||
humanize-ms@^1.2.1:
|
||||
version "1.2.1"
|
||||
resolved "https://registry.yarnpkg.com/humanize-ms/-/humanize-ms-1.2.1.tgz#c46e3159a293f6b896da29316d8b6fe8bb79bbed"
|
||||
integrity sha1-xG4xWaKT9riW2ikxbYtv6Lt5u+0=
|
||||
dependencies:
|
||||
ms "^2.0.0"
|
||||
|
||||
iconv-lite@0.4.24, iconv-lite@^0.4.24, iconv-lite@^0.4.4:
|
||||
version "0.4.24"
|
||||
resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b"
|
||||
@ -4700,7 +4563,7 @@ iconv-lite@0.6.2:
|
||||
dependencies:
|
||||
safer-buffer ">= 2.1.2 < 3.0.0"
|
||||
|
||||
iconv-lite@0.6.3, iconv-lite@^0.6.2, iconv-lite@^0.6.3:
|
||||
iconv-lite@0.6.3, iconv-lite@^0.6.3:
|
||||
version "0.6.3"
|
||||
resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.6.3.tgz#a52f80bf38da1952eb5c681790719871a1a72501"
|
||||
integrity sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==
|
||||
@ -4750,16 +4613,6 @@ imurmurhash@^0.1.4:
|
||||
resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea"
|
||||
integrity sha1-khi5srkoojixPcT7a21XbyMUU+o=
|
||||
|
||||
indent-string@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-4.0.0.tgz#624f8f4497d619b2d9768531d58f4122854d7251"
|
||||
integrity sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==
|
||||
|
||||
infer-owner@^1.0.4:
|
||||
version "1.0.4"
|
||||
resolved "https://registry.yarnpkg.com/infer-owner/-/infer-owner-1.0.4.tgz#c4cefcaa8e51051c2a40ba2ce8a3d27295af9467"
|
||||
integrity sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==
|
||||
|
||||
inflight@^1.0.4:
|
||||
version "1.0.6"
|
||||
resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9"
|
||||
@ -4986,11 +4839,6 @@ is-interactive@^1.0.0:
|
||||
resolved "https://registry.yarnpkg.com/is-interactive/-/is-interactive-1.0.0.tgz#cea6e6ae5c870a7b0a0004070b7b587e0252912e"
|
||||
integrity sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==
|
||||
|
||||
is-lambda@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/is-lambda/-/is-lambda-1.0.1.tgz#3d9877899e6a53efc0160504cde15f82e6f061d5"
|
||||
integrity sha1-PZh3iZ5qU+/AFgUEzeFfgubwYdU=
|
||||
|
||||
is-negative-zero@^2.0.1:
|
||||
version "2.0.2"
|
||||
resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.2.tgz#7bf6f03a28003b8b3965de3ac26f664d765f3150"
|
||||
@ -6075,11 +5923,6 @@ lru-cache@^6.0.0:
|
||||
dependencies:
|
||||
yallist "^4.0.0"
|
||||
|
||||
lru-cache@^7.7.1:
|
||||
version "7.7.1"
|
||||
resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-7.7.1.tgz#03d2846b1ad2dcc7931a9340b8711d9798fcb0c6"
|
||||
integrity sha512-cRffBiTW8s73eH4aTXqBcTLU0xQnwGV3/imttRHGWCrbergmnK4D6JXQd8qin5z43HnDwRI+o7mVW0LEB+tpAw==
|
||||
|
||||
macos-release@^2.5.0:
|
||||
version "2.5.0"
|
||||
resolved "https://registry.yarnpkg.com/macos-release/-/macos-release-2.5.0.tgz#067c2c88b5f3fb3c56a375b2ec93826220fa1ff2"
|
||||
@ -6128,28 +5971,6 @@ make-error@1.x, make-error@^1.1.1:
|
||||
resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.6.tgz#2eb2e37ea9b67c4891f684a1394799af484cf7a2"
|
||||
integrity sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==
|
||||
|
||||
make-fetch-happen@^10.0.3:
|
||||
version "10.1.0"
|
||||
resolved "https://registry.yarnpkg.com/make-fetch-happen/-/make-fetch-happen-10.1.0.tgz#7232ef7002a635c04d4deac325df144f21871408"
|
||||
integrity sha512-HeP4QlkadP/Op+hE+Une1070kcyN85FshQObku3/rmzRh4zDcKXA19d2L3AQR6UoaX3uZmhSOpTLH15b1vOFvQ==
|
||||
dependencies:
|
||||
agentkeepalive "^4.2.1"
|
||||
cacache "^16.0.2"
|
||||
http-cache-semantics "^4.1.0"
|
||||
http-proxy-agent "^5.0.0"
|
||||
https-proxy-agent "^5.0.0"
|
||||
is-lambda "^1.0.1"
|
||||
lru-cache "^7.7.1"
|
||||
minipass "^3.1.6"
|
||||
minipass-collect "^1.0.2"
|
||||
minipass-fetch "^2.0.3"
|
||||
minipass-flush "^1.0.5"
|
||||
minipass-pipeline "^1.2.4"
|
||||
negotiator "^0.6.3"
|
||||
promise-retry "^2.0.1"
|
||||
socks-proxy-agent "^6.1.1"
|
||||
ssri "^8.0.1"
|
||||
|
||||
makeerror@1.0.12:
|
||||
version "1.0.12"
|
||||
resolved "https://registry.yarnpkg.com/makeerror/-/makeerror-1.0.12.tgz#3e5dd2079a82e812e983cc6610c4a2cb0eaa801a"
|
||||
@ -6253,45 +6074,6 @@ minimist@1.2.5, minimist@^1.2.0, minimist@^1.2.5:
|
||||
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602"
|
||||
integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==
|
||||
|
||||
minipass-collect@^1.0.2:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/minipass-collect/-/minipass-collect-1.0.2.tgz#22b813bf745dc6edba2576b940022ad6edc8c617"
|
||||
integrity sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==
|
||||
dependencies:
|
||||
minipass "^3.0.0"
|
||||
|
||||
minipass-fetch@^2.0.3:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/minipass-fetch/-/minipass-fetch-2.1.0.tgz#ca1754a5f857a3be99a9271277246ac0b44c3ff8"
|
||||
integrity sha512-H9U4UVBGXEyyWJnqYDCLp1PwD8XIkJ4akNHp1aGVI+2Ym7wQMlxDKi4IB4JbmyU+pl9pEs/cVrK6cOuvmbK4Sg==
|
||||
dependencies:
|
||||
minipass "^3.1.6"
|
||||
minipass-sized "^1.0.3"
|
||||
minizlib "^2.1.2"
|
||||
optionalDependencies:
|
||||
encoding "^0.1.13"
|
||||
|
||||
minipass-flush@^1.0.5:
|
||||
version "1.0.5"
|
||||
resolved "https://registry.yarnpkg.com/minipass-flush/-/minipass-flush-1.0.5.tgz#82e7135d7e89a50ffe64610a787953c4c4cbb373"
|
||||
integrity sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==
|
||||
dependencies:
|
||||
minipass "^3.0.0"
|
||||
|
||||
minipass-pipeline@^1.2.4:
|
||||
version "1.2.4"
|
||||
resolved "https://registry.yarnpkg.com/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz#68472f79711c084657c067c5c6ad93cddea8214c"
|
||||
integrity sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==
|
||||
dependencies:
|
||||
minipass "^3.0.0"
|
||||
|
||||
minipass-sized@^1.0.3:
|
||||
version "1.0.3"
|
||||
resolved "https://registry.yarnpkg.com/minipass-sized/-/minipass-sized-1.0.3.tgz#70ee5a7c5052070afacfbc22977ea79def353b70"
|
||||
integrity sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g==
|
||||
dependencies:
|
||||
minipass "^3.0.0"
|
||||
|
||||
minipass@^2.6.0, minipass@^2.9.0:
|
||||
version "2.9.0"
|
||||
resolved "https://registry.yarnpkg.com/minipass/-/minipass-2.9.0.tgz#e713762e7d3e32fed803115cf93e04bca9fcc9a6"
|
||||
@ -6300,7 +6082,7 @@ minipass@^2.6.0, minipass@^2.9.0:
|
||||
safe-buffer "^5.1.2"
|
||||
yallist "^3.0.0"
|
||||
|
||||
minipass@^3.0.0, minipass@^3.1.1, minipass@^3.1.6:
|
||||
minipass@^3.0.0:
|
||||
version "3.1.6"
|
||||
resolved "https://registry.yarnpkg.com/minipass/-/minipass-3.1.6.tgz#3b8150aa688a711a1521af5e8779c1d3bb4f45ee"
|
||||
integrity sha512-rty5kpw9/z8SX9dmxblFA6edItUmwJgMeYDZRrwlIVN27i8gysGbznJwUggw2V/FVqFSDdWy040ZPS811DYAqQ==
|
||||
@ -6314,7 +6096,7 @@ minizlib@^1.3.3:
|
||||
dependencies:
|
||||
minipass "^2.9.0"
|
||||
|
||||
minizlib@^2.1.1, minizlib@^2.1.2:
|
||||
minizlib@^2.1.1:
|
||||
version "2.1.2"
|
||||
resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-2.1.2.tgz#e90d3466ba209b932451508a11ce3d3632145931"
|
||||
integrity sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==
|
||||
@ -6686,7 +6468,7 @@ ms@2.1.2:
|
||||
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009"
|
||||
integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==
|
||||
|
||||
ms@2.1.3, ms@^2.0.0, ms@^2.1.1:
|
||||
ms@2.1.3, ms@^2.1.1:
|
||||
version "2.1.3"
|
||||
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2"
|
||||
integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==
|
||||
@ -6769,11 +6551,6 @@ negotiator@0.6.2:
|
||||
resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.2.tgz#feacf7ccf525a77ae9634436a64883ffeca346fb"
|
||||
integrity sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==
|
||||
|
||||
negotiator@^0.6.3:
|
||||
version "0.6.3"
|
||||
resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.3.tgz#58e323a72fedc0d6f9cd4d31fe49f51479590ccd"
|
||||
integrity sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==
|
||||
|
||||
neo-async@^2.6.0, neo-async@^2.6.2:
|
||||
version "2.6.2"
|
||||
resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f"
|
||||
@ -6816,14 +6593,7 @@ node-emoji@1.11.0:
|
||||
dependencies:
|
||||
lodash "^4.17.21"
|
||||
|
||||
node-fetch@^2.6.0, node-fetch@^2.6.1, node-fetch@^2.6.5:
|
||||
version "2.6.6"
|
||||
resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.6.tgz#1751a7c01834e8e1697758732e9efb6eeadfaf89"
|
||||
integrity sha512-Z8/6vRlTUChSdIgMa51jxQ4lrw/Jy5SOW10ObaA47/RElsAN2c5Pn8bTgFGWn/ibwzXTE8qwr1Yzx28vsecXEA==
|
||||
dependencies:
|
||||
whatwg-url "^5.0.0"
|
||||
|
||||
node-fetch@^2.6.7:
|
||||
node-fetch@^2.6.0, node-fetch@^2.6.1, node-fetch@^2.6.5, node-fetch@^2.6.7:
|
||||
version "2.6.7"
|
||||
resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.7.tgz#24de9fba827e3b4ae44dc8b20256a379160052ad"
|
||||
integrity sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==
|
||||
@ -6848,22 +6618,6 @@ node-gyp@3.x:
|
||||
tar "^2.0.0"
|
||||
which "1"
|
||||
|
||||
node-gyp@^9.0.0:
|
||||
version "9.0.0"
|
||||
resolved "https://registry.yarnpkg.com/node-gyp/-/node-gyp-9.0.0.tgz#e1da2067427f3eb5bb56820cb62bc6b1e4bd2089"
|
||||
integrity sha512-Ma6p4s+XCTPxCuAMrOA/IJRmVy16R8Sdhtwl4PrCr7IBlj4cPawF0vg/l7nOT1jPbuNS7lIRJpBSvVsXwEZuzw==
|
||||
dependencies:
|
||||
env-paths "^2.2.0"
|
||||
glob "^7.1.4"
|
||||
graceful-fs "^4.2.6"
|
||||
make-fetch-happen "^10.0.3"
|
||||
nopt "^5.0.0"
|
||||
npmlog "^6.0.0"
|
||||
rimraf "^3.0.2"
|
||||
semver "^7.3.5"
|
||||
tar "^6.1.2"
|
||||
which "^2.0.2"
|
||||
|
||||
node-int64@^0.4.0:
|
||||
version "0.4.0"
|
||||
resolved "https://registry.yarnpkg.com/node-int64/-/node-int64-0.4.0.tgz#87a9065cdb355d3182d8f94ce11188b825c68a3b"
|
||||
@ -6975,16 +6729,6 @@ npmlog@^5.0.1:
|
||||
gauge "^3.0.0"
|
||||
set-blocking "^2.0.0"
|
||||
|
||||
npmlog@^6.0.0:
|
||||
version "6.0.1"
|
||||
resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-6.0.1.tgz#06f1344a174c06e8de9c6c70834cfba2964bba17"
|
||||
integrity sha512-BTHDvY6nrRHuRfyjt1MAufLxYdVXZfd099H4+i1f0lPywNQyI4foeNXJRObB/uy+TYqUW0vAD9gbdSOXPst7Eg==
|
||||
dependencies:
|
||||
are-we-there-yet "^3.0.0"
|
||||
console-control-strings "^1.1.0"
|
||||
gauge "^4.0.0"
|
||||
set-blocking "^2.0.0"
|
||||
|
||||
nth-check@^2.0.1:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/nth-check/-/nth-check-2.0.1.tgz#2efe162f5c3da06a28959fbd3db75dbeea9f0fc2"
|
||||
@ -7198,13 +6942,6 @@ p-map@^2.1.0:
|
||||
resolved "https://registry.yarnpkg.com/p-map/-/p-map-2.1.0.tgz#310928feef9c9ecc65b68b17693018a665cea175"
|
||||
integrity sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==
|
||||
|
||||
p-map@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/p-map/-/p-map-4.0.0.tgz#bb2f95a5eda2ec168ec9274e06a747c3e2904d2b"
|
||||
integrity sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==
|
||||
dependencies:
|
||||
aggregate-error "^3.0.0"
|
||||
|
||||
p-try@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/p-try/-/p-try-1.0.0.tgz#cbc79cdbaf8fd4228e13f621f2b1a237c1b207b3"
|
||||
@ -7592,19 +7329,6 @@ process-warning@^1.0.0:
|
||||
resolved "https://registry.yarnpkg.com/process-warning/-/process-warning-1.0.0.tgz#980a0b25dc38cd6034181be4b7726d89066b4616"
|
||||
integrity sha512-du4wfLyj4yCZq1VupnVSZmRsPJsNuxoDQFdCFHLaYiEbFBD7QE0a+I4D7hOxrVnh78QE/YipFAj9lXHiXocV+Q==
|
||||
|
||||
promise-inflight@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/promise-inflight/-/promise-inflight-1.0.1.tgz#98472870bf228132fcbdd868129bad12c3c029e3"
|
||||
integrity sha1-mEcocL8igTL8vdhoEputEsPAKeM=
|
||||
|
||||
promise-retry@^2.0.1:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/promise-retry/-/promise-retry-2.0.1.tgz#ff747a13620ab57ba688f5fc67855410c370da22"
|
||||
integrity sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==
|
||||
dependencies:
|
||||
err-code "^2.0.2"
|
||||
retry "^0.12.0"
|
||||
|
||||
promise@^7.0.1:
|
||||
version "7.3.1"
|
||||
resolved "https://registry.yarnpkg.com/promise/-/promise-7.3.1.tgz#064b72602b18f90f29192b8b1bc418ffd1ebd3bf"
|
||||
@ -8074,11 +7798,6 @@ retry@0.13.1:
|
||||
resolved "https://registry.yarnpkg.com/retry/-/retry-0.13.1.tgz#185b1587acf67919d63b357349e03537b2484658"
|
||||
integrity sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==
|
||||
|
||||
retry@^0.12.0:
|
||||
version "0.12.0"
|
||||
resolved "https://registry.yarnpkg.com/retry/-/retry-0.12.0.tgz#1b42a6266a21f07421d1b0b54b7dc167b01c013b"
|
||||
integrity sha1-G0KmJmoh8HQh0bC1S33BZ7AcATs=
|
||||
|
||||
reusify@^1.0.4:
|
||||
version "1.0.4"
|
||||
resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76"
|
||||
@ -8326,11 +8045,6 @@ signal-exit@^3.0.0, signal-exit@^3.0.2, signal-exit@^3.0.3:
|
||||
resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.6.tgz#24e630c4b0f03fea446a2bd299e62b4a6ca8d0af"
|
||||
integrity sha512-sDl4qMFpijcGw22U5w63KmD3cZJfBuFlVNbVMKje2keoKML7X2UzWbc4XrmEbDwg0NXJc3yv4/ox7b+JWb57kQ==
|
||||
|
||||
signal-exit@^3.0.7:
|
||||
version "3.0.7"
|
||||
resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9"
|
||||
integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==
|
||||
|
||||
sisteransi@^1.0.5:
|
||||
version "1.0.5"
|
||||
resolved "https://registry.yarnpkg.com/sisteransi/-/sisteransi-1.0.5.tgz#134d681297756437cc05ca01370d3a7a571075ed"
|
||||
@ -8346,7 +8060,7 @@ slick@^1.12.2:
|
||||
resolved "https://registry.yarnpkg.com/slick/-/slick-1.12.2.tgz#bd048ddb74de7d1ca6915faa4a57570b3550c2d7"
|
||||
integrity sha1-vQSN23TefRymkV+qSldXCzVQwtc=
|
||||
|
||||
smart-buffer@^4.1.0, smart-buffer@^4.2.0:
|
||||
smart-buffer@^4.1.0:
|
||||
version "4.2.0"
|
||||
resolved "https://registry.yarnpkg.com/smart-buffer/-/smart-buffer-4.2.0.tgz#6e1d71fa4f18c05f7d0ff216dd16a481d0e8d9ae"
|
||||
integrity sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==
|
||||
@ -8360,15 +8074,6 @@ socks-proxy-agent@5, socks-proxy-agent@^5.0.0:
|
||||
debug "4"
|
||||
socks "^2.3.3"
|
||||
|
||||
socks-proxy-agent@^6.1.1:
|
||||
version "6.1.1"
|
||||
resolved "https://registry.yarnpkg.com/socks-proxy-agent/-/socks-proxy-agent-6.1.1.tgz#e664e8f1aaf4e1fb3df945f09e3d94f911137f87"
|
||||
integrity sha512-t8J0kG3csjA4g6FTbsMOWws+7R7vuRC8aQ/wy3/1OWmsgwA68zs/+cExQ0koSitUDXqhufF/YJr9wtNMZHw5Ew==
|
||||
dependencies:
|
||||
agent-base "^6.0.2"
|
||||
debug "^4.3.1"
|
||||
socks "^2.6.1"
|
||||
|
||||
socks@^2.3.3:
|
||||
version "2.6.1"
|
||||
resolved "https://registry.yarnpkg.com/socks/-/socks-2.6.1.tgz#989e6534a07cf337deb1b1c94aaa44296520d30e"
|
||||
@ -8377,14 +8082,6 @@ socks@^2.3.3:
|
||||
ip "^1.1.5"
|
||||
smart-buffer "^4.1.0"
|
||||
|
||||
socks@^2.6.1:
|
||||
version "2.6.2"
|
||||
resolved "https://registry.yarnpkg.com/socks/-/socks-2.6.2.tgz#ec042d7960073d40d94268ff3bb727dc685f111a"
|
||||
integrity sha512-zDZhHhZRY9PxRruRMR7kMhnf3I8hDs4S3f9RecfnGxvcBHQcKcIH/oUcEWffsfl1XxdYlA7nnlGbbTvPz9D8gA==
|
||||
dependencies:
|
||||
ip "^1.1.5"
|
||||
smart-buffer "^4.2.0"
|
||||
|
||||
sonic-boom@^2.2.0, sonic-boom@^2.2.1:
|
||||
version "2.4.2"
|
||||
resolved "https://registry.yarnpkg.com/sonic-boom/-/sonic-boom-2.4.2.tgz#34c0965b1a498abedaaca794c752d190f74b5e8f"
|
||||
@ -8465,13 +8162,6 @@ sshpk@^1.7.0:
|
||||
safer-buffer "^2.0.2"
|
||||
tweetnacl "~0.14.0"
|
||||
|
||||
ssri@^8.0.1:
|
||||
version "8.0.1"
|
||||
resolved "https://registry.yarnpkg.com/ssri/-/ssri-8.0.1.tgz#638e4e439e2ffbd2cd289776d5ca457c4f51a2af"
|
||||
integrity sha512-97qShzy1AiyxvPNIkLWoGua7xoQzzPjQ0HAH4B0rWKo7SZ6USuPcrUiAFrws0UH8RrbWmgq3LMTObhPIHbbBeQ==
|
||||
dependencies:
|
||||
minipass "^3.1.1"
|
||||
|
||||
stack-utils@^2.0.3:
|
||||
version "2.0.5"
|
||||
resolved "https://registry.yarnpkg.com/stack-utils/-/stack-utils-2.0.5.tgz#d25265fca995154659dbbfba3b49254778d2fdd5"
|
||||
@ -8745,7 +8435,7 @@ tar@^4:
|
||||
safe-buffer "^5.2.1"
|
||||
yallist "^3.1.1"
|
||||
|
||||
tar@^6.1.11, tar@^6.1.2:
|
||||
tar@^6.1.11:
|
||||
version "6.1.11"
|
||||
resolved "https://registry.yarnpkg.com/tar/-/tar-6.1.11.tgz#6760a38f003afa1b2ffd0ffe9e9abbd0eab3d621"
|
||||
integrity sha512-an/KZQzQUkZCkuoAA64hM92X0Urb6VpRhAFllDzz44U2mcD5scmT3zBc4VgVpkugF580+DQn8eAFSyoQt0tznA==
|
||||
@ -9103,20 +8793,6 @@ unbox-primitive@^1.0.1:
|
||||
has-symbols "^1.0.2"
|
||||
which-boxed-primitive "^1.0.2"
|
||||
|
||||
unique-filename@^1.1.1:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/unique-filename/-/unique-filename-1.1.1.tgz#1d69769369ada0583103a1e6ae87681b56573230"
|
||||
integrity sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==
|
||||
dependencies:
|
||||
unique-slug "^2.0.0"
|
||||
|
||||
unique-slug@^2.0.0:
|
||||
version "2.0.2"
|
||||
resolved "https://registry.yarnpkg.com/unique-slug/-/unique-slug-2.0.2.tgz#baabce91083fc64e945b0f3ad613e264f7cd4e6c"
|
||||
integrity sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w==
|
||||
dependencies:
|
||||
imurmurhash "^0.1.4"
|
||||
|
||||
universalify@^0.1.0, universalify@^0.1.2:
|
||||
version "0.1.2"
|
||||
resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66"
|
||||
@ -9367,14 +9043,14 @@ which@1:
|
||||
dependencies:
|
||||
isexe "^2.0.0"
|
||||
|
||||
which@^2.0.1, which@^2.0.2:
|
||||
which@^2.0.1:
|
||||
version "2.0.2"
|
||||
resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1"
|
||||
integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==
|
||||
dependencies:
|
||||
isexe "^2.0.0"
|
||||
|
||||
wide-align@^1.1.0, wide-align@^1.1.2, wide-align@^1.1.5:
|
||||
wide-align@^1.1.0, wide-align@^1.1.2:
|
||||
version "1.1.5"
|
||||
resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.5.tgz#df1d4c206854369ecf3c9a4898f1b23fbd9d15d3"
|
||||
integrity sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user