Compare commits
19 Commits
gh-action-
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c2c421baa6 | ||
|
|
b6f0c9d64a | ||
|
|
3b5a6c92af | ||
|
|
d86b02cf2e | ||
|
|
ef7cd7b3fb | ||
|
|
c71e87ec50 | ||
|
|
27aa5ebfb0 | ||
|
|
7ea4f51f4b | ||
|
|
b3cacb8481 | ||
|
|
6d85dc660a | ||
|
|
30c2bc9c05 | ||
|
|
99fe3d2fe0 | ||
|
|
5bc6047507 | ||
|
|
4a19bd5ca4 | ||
|
|
fe3821ad42 | ||
|
|
2d3589e13a | ||
|
|
5b717a2963 | ||
|
|
1e3f47c11c | ||
|
|
cfd8d288d4 |
149
.github/workflows/test.yml
vendored
149
.github/workflows/test.yml
vendored
@ -20,31 +20,6 @@ jobs:
|
|||||||
name: Run linters
|
name: Run linters
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
|
||||||
services:
|
|
||||||
maria:
|
|
||||||
image: mariadb
|
|
||||||
env:
|
|
||||||
MYSQL_ROOT_PASSWORD: root
|
|
||||||
MYSQL_DATABASE: ohmyform
|
|
||||||
options: >-
|
|
||||||
--health-cmd "mysqladmin ping"
|
|
||||||
--health-interval 10s
|
|
||||||
--health-timeout 5s
|
|
||||||
--health-retries 5
|
|
||||||
|
|
||||||
postgres:
|
|
||||||
image: postgres:10-alpine
|
|
||||||
env:
|
|
||||||
POSTGRES_USER: root
|
|
||||||
POSTGRES_PASSWORD: root
|
|
||||||
POSTGRES_DB: ohmyform
|
|
||||||
options: >-
|
|
||||||
--health-cmd pg_isready
|
|
||||||
--health-interval 10s
|
|
||||||
--health-timeout 5s
|
|
||||||
--health-retries 5
|
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Check out Git repository
|
- name: Check out Git repository
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v2
|
||||||
@ -67,20 +42,136 @@ jobs:
|
|||||||
- name: Typecheck
|
- name: Typecheck
|
||||||
uses: andoshin11/typescript-error-reporter-action@v1.0.2
|
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
|
- name: PostgreSQL Migrations
|
||||||
run: yarn typeorm migration:run
|
run: yarn typeorm migration:run
|
||||||
env:
|
env:
|
||||||
DATABASE_DRIVER: postgres
|
DATABASE_DRIVER: postgres
|
||||||
DATABASE_URL: postgresql://root@127.0.0.1:5432/ohmyform
|
|
||||||
|
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
|
- name: MariaDB Migrations
|
||||||
run: yarn typeorm migration:run
|
run: yarn typeorm migration:run
|
||||||
env:
|
env:
|
||||||
DATABASE_DRIVER: mariadb
|
DATABASE_DRIVER: mariadb
|
||||||
DATABASE_URL: mysql://root@127.0.0.1:3306/ohmyform
|
|
||||||
|
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
|
- name: SQLite Migrations
|
||||||
run: yarn typeorm migration:run
|
run: yarn typeorm migration:run --transaction none
|
||||||
env:
|
env:
|
||||||
DATABASE_DRIVER: sqlite
|
DATABASE_DRIVER: sqlite
|
||||||
DATABASE_URL: sqlite://data.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
|
||||||
|
|||||||
72
CHANGELOG.md
72
CHANGELOG.md
@ -4,11 +4,80 @@ All notable changes to this project will be documented in this file.
|
|||||||
|
|
||||||
The format is based on [Keep a Changelog](http://keepachangelog.com/)
|
The format is based on [Keep a Changelog](http://keepachangelog.com/)
|
||||||
and this project adheres to [Semantic Versioning](http://semver.org/).
|
and this project adheres to [Semantic Versioning](http://semver.org/).
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Template for next version
|
||||||
## [Unreleased]
|
## [Unreleased]
|
||||||
|
|
||||||
### Added
|
### 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
|
- logic backend components
|
||||||
- forms now have multiple notification
|
- forms now have multiple notification
|
||||||
- layout for forms
|
- layout for forms
|
||||||
@ -19,6 +88,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
|
|||||||
- ability to load submission by id if token is present
|
- ability to load submission by id if token is present
|
||||||
- anonymous form submissions (fixes https://github.com/ohmyform/ohmyform/issues/108)
|
- anonymous form submissions (fixes https://github.com/ohmyform/ohmyform/issues/108)
|
||||||
- ability to filter for partial / completed or empty submissions
|
- ability to filter for partial / completed or empty submissions
|
||||||
|
- migration tests for all commits
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
|
|||||||
@ -6,7 +6,7 @@ WORKDIR /usr/src/app
|
|||||||
RUN apk update && apk add curl bash && rm -rf /var/cache/apk/*
|
RUN apk update && apk add curl bash && rm -rf /var/cache/apk/*
|
||||||
|
|
||||||
# install node-prune (https://github.com/tj/node-prune)
|
# install node-prune (https://github.com/tj/node-prune)
|
||||||
RUN curl -sfL https://install.goreleaser.com/github.com/tj/node-prune.sh | bash -s -- -b /usr/local/bin
|
RUN curl -sf https://gobinaries.com/tj/node-prune | sh
|
||||||
|
|
||||||
# just copy everhing
|
# just copy everhing
|
||||||
COPY . .
|
COPY . .
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "ohmyform-api",
|
"name": "ohmyform-api",
|
||||||
"version": "1.0.0",
|
"version": "1.0.3",
|
||||||
"description": "",
|
"description": "",
|
||||||
"author": "",
|
"author": "",
|
||||||
"license": "AGPL-3.0-or-later",
|
"license": "AGPL-3.0-or-later",
|
||||||
@ -22,7 +22,8 @@
|
|||||||
"test:e2e": "jest --config ./test/jest-e2e.json",
|
"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: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: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: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"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@ardatan/aggregate-error": "^0.0.6",
|
"@ardatan/aggregate-error": "^0.0.6",
|
||||||
@ -50,6 +51,7 @@
|
|||||||
"graphql-subscriptions": "^2.0.0",
|
"graphql-subscriptions": "^2.0.0",
|
||||||
"graphql-tools": "^8.2.0",
|
"graphql-tools": "^8.2.0",
|
||||||
"handlebars": "^4.7.7",
|
"handlebars": "^4.7.7",
|
||||||
|
"hashids": "^2.2.10",
|
||||||
"html-to-text": "^8.1.0",
|
"html-to-text": "^8.1.0",
|
||||||
"inquirer": "^8.2.0",
|
"inquirer": "^8.2.0",
|
||||||
"ioredis": "^4.28.5",
|
"ioredis": "^4.28.5",
|
||||||
@ -83,7 +85,7 @@
|
|||||||
"@types/handlebars": "^4.1.0",
|
"@types/handlebars": "^4.1.0",
|
||||||
"@types/html-to-text": "^8.0.1",
|
"@types/html-to-text": "^8.0.1",
|
||||||
"@types/inquirer": "^8.2.0",
|
"@types/inquirer": "^8.2.0",
|
||||||
"@types/jest": "27.4.1",
|
"@types/jest": "^27.4.1",
|
||||||
"@types/mjml": "^4.7.0",
|
"@types/mjml": "^4.7.0",
|
||||||
"@types/node": "^17.0.21",
|
"@types/node": "^17.0.21",
|
||||||
"@types/passport-jwt": "^3.0.6",
|
"@types/passport-jwt": "^3.0.6",
|
||||||
@ -98,6 +100,7 @@
|
|||||||
"eslint-plugin-nestjs": "^1.2.3",
|
"eslint-plugin-nestjs": "^1.2.3",
|
||||||
"eslint-plugin-unused-imports": "^2.0.0",
|
"eslint-plugin-unused-imports": "^2.0.0",
|
||||||
"jest": "^27.5.1",
|
"jest": "^27.5.1",
|
||||||
|
"node-gyp": "^9.0.0",
|
||||||
"prettier": "^2.5.1",
|
"prettier": "^2.5.1",
|
||||||
"supertest": "^6.2.2",
|
"supertest": "^6.2.2",
|
||||||
"ts-jest": "27.1.3",
|
"ts-jest": "27.1.3",
|
||||||
|
|||||||
@ -1,11 +1,13 @@
|
|||||||
import { commands } from './command'
|
import { commands } from './command'
|
||||||
import { guards } from './guard'
|
import { guards } from './guard'
|
||||||
|
import { pipes } from './pipe'
|
||||||
import { resolvers } from './resolver'
|
import { resolvers } from './resolver'
|
||||||
import { services } from './service'
|
import { services } from './service'
|
||||||
|
|
||||||
export const providers = [
|
export const providers = [
|
||||||
...resolvers,
|
|
||||||
...commands,
|
...commands,
|
||||||
...services,
|
|
||||||
...guards,
|
...guards,
|
||||||
|
...pipes,
|
||||||
|
...resolvers,
|
||||||
|
...services,
|
||||||
]
|
]
|
||||||
|
|||||||
@ -1,8 +1,8 @@
|
|||||||
import { Field, ObjectType } from '@nestjs/graphql'
|
import { Field, ID, ObjectType } from '@nestjs/graphql'
|
||||||
|
|
||||||
@ObjectType('Deleted')
|
@ObjectType('Deleted')
|
||||||
export class DeletedModel {
|
export class DeletedModel {
|
||||||
@Field()
|
@Field(() => ID)
|
||||||
id: string
|
id: string
|
||||||
|
|
||||||
constructor(id: string) {
|
constructor(id: string) {
|
||||||
|
|||||||
@ -3,6 +3,8 @@ import { PageButtonEntity } from '../../entity/page.button.entity'
|
|||||||
|
|
||||||
@ObjectType('Button')
|
@ObjectType('Button')
|
||||||
export class ButtonModel {
|
export class ButtonModel {
|
||||||
|
readonly _id: number
|
||||||
|
|
||||||
@Field(() => ID)
|
@Field(() => ID)
|
||||||
readonly id: string
|
readonly id: string
|
||||||
|
|
||||||
@ -24,8 +26,9 @@ export class ButtonModel {
|
|||||||
@Field({ nullable: true })
|
@Field({ nullable: true })
|
||||||
readonly color?: string
|
readonly color?: string
|
||||||
|
|
||||||
constructor(button: Partial<PageButtonEntity>) {
|
constructor(id: string, button: Partial<PageButtonEntity>) {
|
||||||
this.id = button.id.toString()
|
this._id = button.id
|
||||||
|
this.id = id
|
||||||
this.url = button.url
|
this.url = button.url
|
||||||
this.action = button.action
|
this.action = button.action
|
||||||
this.text = button.text
|
this.text = button.text
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
import { Field, InputType } from '@nestjs/graphql'
|
import { Field, InputType } from '@nestjs/graphql'
|
||||||
|
import { PageInput } from './page.input'
|
||||||
|
|
||||||
@InputType('FormCreateInput')
|
@InputType('FormCreateInput')
|
||||||
export class FormCreateInput {
|
export class FormCreateInput {
|
||||||
@ -19,4 +20,10 @@ export class FormCreateInput {
|
|||||||
|
|
||||||
@Field({ nullable: true })
|
@Field({ nullable: true })
|
||||||
readonly layout: string
|
readonly layout: string
|
||||||
|
|
||||||
|
@Field({ nullable: true })
|
||||||
|
readonly startPage: PageInput
|
||||||
|
|
||||||
|
@Field({ nullable: true })
|
||||||
|
readonly endPage: PageInput
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,6 +3,8 @@ import { FormFieldLogicEntity } from '../../entity/form.field.logic.entity'
|
|||||||
|
|
||||||
@ObjectType('FormFieldLogic')
|
@ObjectType('FormFieldLogic')
|
||||||
export class FormFieldLogicModel {
|
export class FormFieldLogicModel {
|
||||||
|
readonly _id: number
|
||||||
|
|
||||||
@Field(() => ID)
|
@Field(() => ID)
|
||||||
readonly id: string
|
readonly id: string
|
||||||
|
|
||||||
@ -30,8 +32,9 @@ export class FormFieldLogicModel {
|
|||||||
@Field()
|
@Field()
|
||||||
readonly enabled: boolean
|
readonly enabled: boolean
|
||||||
|
|
||||||
constructor(document: FormFieldLogicEntity) {
|
constructor(id: string, document: FormFieldLogicEntity) {
|
||||||
this.id = document.id.toString()
|
this._id = document.id
|
||||||
|
this.id = id
|
||||||
this.enabled = document.enabled
|
this.enabled = document.enabled
|
||||||
|
|
||||||
this.formula = document.formula
|
this.formula = document.formula
|
||||||
|
|||||||
@ -1,11 +1,10 @@
|
|||||||
import { Field, ID, ObjectType } from '@nestjs/graphql'
|
import { Field, ID, ObjectType } from '@nestjs/graphql'
|
||||||
import { FormFieldEntity } from '../../entity/form.field.entity'
|
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')
|
@ObjectType('FormField')
|
||||||
export class FormFieldModel {
|
export class FormFieldModel {
|
||||||
|
readonly _id: number
|
||||||
|
|
||||||
@Field(() => ID)
|
@Field(() => ID)
|
||||||
readonly id: string
|
readonly id: string
|
||||||
|
|
||||||
@ -30,17 +29,9 @@ export class FormFieldModel {
|
|||||||
@Field({ nullable: true })
|
@Field({ nullable: true })
|
||||||
readonly defaultValue: string
|
readonly defaultValue: string
|
||||||
|
|
||||||
@Field(() => [FormFieldOptionModel])
|
constructor(id: string, document: FormFieldEntity) {
|
||||||
readonly options: FormFieldOptionModel[]
|
this._id = document.id
|
||||||
|
this.id = id
|
||||||
@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.idx = document.idx
|
||||||
this.title = document.title
|
this.title = document.title
|
||||||
this.slug = document.slug
|
this.slug = document.slug
|
||||||
@ -48,8 +39,5 @@ export class FormFieldModel {
|
|||||||
this.description = document.description
|
this.description = document.description
|
||||||
this.required = document.required
|
this.required = document.required
|
||||||
this.defaultValue = document.defaultValue
|
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,6 +3,8 @@ import { FormFieldOptionEntity } from '../../entity/form.field.option.entity'
|
|||||||
|
|
||||||
@ObjectType('FormFieldOption')
|
@ObjectType('FormFieldOption')
|
||||||
export class FormFieldOptionModel {
|
export class FormFieldOptionModel {
|
||||||
|
readonly _id: number
|
||||||
|
|
||||||
@Field(() => ID)
|
@Field(() => ID)
|
||||||
readonly id: string
|
readonly id: string
|
||||||
|
|
||||||
@ -15,8 +17,9 @@ export class FormFieldOptionModel {
|
|||||||
@Field()
|
@Field()
|
||||||
readonly value: string
|
readonly value: string
|
||||||
|
|
||||||
constructor(option: FormFieldOptionEntity) {
|
constructor(id: string, option: FormFieldOptionEntity) {
|
||||||
this.id = option.id.toString()
|
this._id = option.id
|
||||||
|
this.id = id
|
||||||
this.key = option.key
|
this.key = option.key
|
||||||
this.title = option.title
|
this.title = option.title
|
||||||
this.value = option.value
|
this.value = option.value
|
||||||
|
|||||||
@ -3,6 +3,8 @@ import { FormHookEntity } from '../../entity/form.hook.entity'
|
|||||||
|
|
||||||
@ObjectType('FormHook')
|
@ObjectType('FormHook')
|
||||||
export class FormHookModel {
|
export class FormHookModel {
|
||||||
|
readonly _id: number
|
||||||
|
|
||||||
@Field(() => ID)
|
@Field(() => ID)
|
||||||
readonly id: string
|
readonly id: string
|
||||||
|
|
||||||
@ -15,8 +17,9 @@ export class FormHookModel {
|
|||||||
@Field({ nullable: true })
|
@Field({ nullable: true })
|
||||||
readonly format?: string
|
readonly format?: string
|
||||||
|
|
||||||
constructor(hook: FormHookEntity) {
|
constructor(id, hook: FormHookEntity) {
|
||||||
this.id = hook.id.toString()
|
this._id = hook.id
|
||||||
|
this.id = id
|
||||||
this.enabled = hook.enabled
|
this.enabled = hook.enabled
|
||||||
this.url = hook.url
|
this.url = hook.url
|
||||||
this.format = hook.format
|
this.format = hook.format
|
||||||
|
|||||||
@ -3,6 +3,8 @@ import { FormEntity } from '../../entity/form.entity'
|
|||||||
|
|
||||||
@ObjectType('Form')
|
@ObjectType('Form')
|
||||||
export class FormModel {
|
export class FormModel {
|
||||||
|
readonly _id: number
|
||||||
|
|
||||||
@Field(() => ID)
|
@Field(() => ID)
|
||||||
readonly id: string
|
readonly id: string
|
||||||
|
|
||||||
@ -24,8 +26,9 @@ export class FormModel {
|
|||||||
@Field()
|
@Field()
|
||||||
readonly anonymousSubmission: boolean
|
readonly anonymousSubmission: boolean
|
||||||
|
|
||||||
constructor(form: FormEntity) {
|
constructor(id: string, form: FormEntity) {
|
||||||
this.id = form.id.toString()
|
this._id = form.id
|
||||||
|
this.id = id
|
||||||
this.title = form.title
|
this.title = form.title
|
||||||
this.created = form.created
|
this.created = form.created
|
||||||
this.lastModified = form.lastModified
|
this.lastModified = form.lastModified
|
||||||
|
|||||||
@ -3,6 +3,8 @@ import { FormNotificationEntity } from '../../entity/form.notification.entity'
|
|||||||
|
|
||||||
@ObjectType('FormNotification')
|
@ObjectType('FormNotification')
|
||||||
export class FormNotificationModel {
|
export class FormNotificationModel {
|
||||||
|
readonly _id: number
|
||||||
|
|
||||||
@Field(() => ID)
|
@Field(() => ID)
|
||||||
readonly id: string
|
readonly id: string
|
||||||
|
|
||||||
@ -27,8 +29,9 @@ export class FormNotificationModel {
|
|||||||
@Field()
|
@Field()
|
||||||
readonly enabled: boolean
|
readonly enabled: boolean
|
||||||
|
|
||||||
constructor(partial: Partial<FormNotificationEntity>) {
|
constructor(id: string, partial: Partial<FormNotificationEntity>) {
|
||||||
this.id = partial.id.toString()
|
this._id = partial.id
|
||||||
|
this.id = id
|
||||||
this.subject = partial.subject
|
this.subject = partial.subject
|
||||||
this.htmlTemplate = partial.htmlTemplate
|
this.htmlTemplate = partial.htmlTemplate
|
||||||
this.enabled = partial.enabled
|
this.enabled = partial.enabled
|
||||||
|
|||||||
@ -18,6 +18,6 @@ export class PageInput {
|
|||||||
@Field({ nullable: true })
|
@Field({ nullable: true })
|
||||||
readonly buttonText?: string
|
readonly buttonText?: string
|
||||||
|
|
||||||
@Field(() => [ButtonInput])
|
@Field(() => [ButtonInput], { nullable: true })
|
||||||
readonly buttons: ButtonInput[]
|
readonly buttons: ButtonInput[]
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,9 +1,10 @@
|
|||||||
import { Field, ID, ObjectType } from '@nestjs/graphql'
|
import { Field, ID, ObjectType } from '@nestjs/graphql'
|
||||||
import { PageEntity } from '../../entity/page.entity'
|
import { PageEntity } from '../../entity/page.entity'
|
||||||
import { ButtonModel } from './button.model'
|
|
||||||
|
|
||||||
@ObjectType('Page')
|
@ObjectType('Page')
|
||||||
export class PageModel {
|
export class PageModel {
|
||||||
|
readonly _id: number
|
||||||
|
|
||||||
@Field(() => ID)
|
@Field(() => ID)
|
||||||
readonly id: string
|
readonly id: string
|
||||||
|
|
||||||
@ -19,22 +20,18 @@ export class PageModel {
|
|||||||
@Field({ nullable: true })
|
@Field({ nullable: true })
|
||||||
readonly buttonText?: string
|
readonly buttonText?: string
|
||||||
|
|
||||||
@Field(() => [ButtonModel])
|
constructor(id: string, page?: Partial<PageEntity>) {
|
||||||
readonly buttons: ButtonModel[]
|
|
||||||
|
|
||||||
constructor(page: Partial<PageEntity>) {
|
|
||||||
if (!page) {
|
if (!page) {
|
||||||
this.id = Math.random().toString()
|
this.id = id
|
||||||
this.show = false
|
this.show = false
|
||||||
this.buttons = []
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
this.id = page.id.toString()
|
this._id = page.id
|
||||||
|
this.id = id
|
||||||
this.show = page.show
|
this.show = page.show
|
||||||
this.title = page.title
|
this.title = page.title
|
||||||
this.paragraph = page.paragraph
|
this.paragraph = page.paragraph
|
||||||
this.buttonText = page.buttonText
|
this.buttonText = page.buttonText
|
||||||
this.buttons = (page.buttons || []).map(button => new ButtonModel(button))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -7,8 +7,8 @@ export class ProfileModel extends UserModel {
|
|||||||
@Field(() => [String])
|
@Field(() => [String])
|
||||||
readonly roles: string[]
|
readonly roles: string[]
|
||||||
|
|
||||||
constructor(user: UserEntity) {
|
constructor(id: string, user: UserEntity) {
|
||||||
super(user)
|
super(id, user)
|
||||||
|
|
||||||
this.roles = user.roles
|
this.roles = user.roles
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,6 +3,8 @@ import { SubmissionFieldEntity } from '../../entity/submission.field.entity'
|
|||||||
|
|
||||||
@ObjectType('SubmissionField')
|
@ObjectType('SubmissionField')
|
||||||
export class SubmissionFieldModel {
|
export class SubmissionFieldModel {
|
||||||
|
readonly _id: number
|
||||||
|
|
||||||
@Field(() => ID)
|
@Field(() => ID)
|
||||||
readonly id: string
|
readonly id: string
|
||||||
|
|
||||||
@ -12,8 +14,9 @@ export class SubmissionFieldModel {
|
|||||||
@Field()
|
@Field()
|
||||||
readonly type: string
|
readonly type: string
|
||||||
|
|
||||||
constructor(field: SubmissionFieldEntity) {
|
constructor(id: string, field: SubmissionFieldEntity) {
|
||||||
this.id = field.id.toString()
|
this._id = field.id
|
||||||
|
this.id = id
|
||||||
this.value = JSON.stringify(field.content)
|
this.value = JSON.stringify(field.content)
|
||||||
this.type = field.type
|
this.type = field.type
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,8 +5,10 @@ import { GeoLocationModel } from './geo.location.model'
|
|||||||
|
|
||||||
@ObjectType('Submission')
|
@ObjectType('Submission')
|
||||||
export class SubmissionModel {
|
export class SubmissionModel {
|
||||||
|
readonly _id: number
|
||||||
|
|
||||||
@Field(() => ID)
|
@Field(() => ID)
|
||||||
readonly id: number
|
readonly id: string
|
||||||
|
|
||||||
@Field()
|
@Field()
|
||||||
readonly ipAddr: string
|
readonly ipAddr: string
|
||||||
@ -29,8 +31,9 @@ export class SubmissionModel {
|
|||||||
@Field({ nullable: true })
|
@Field({ nullable: true })
|
||||||
readonly lastModified?: Date
|
readonly lastModified?: Date
|
||||||
|
|
||||||
constructor(submission: SubmissionEntity) {
|
constructor(id: string, submission: SubmissionEntity) {
|
||||||
this.id = submission.id
|
this._id = submission.id
|
||||||
|
this.id = id
|
||||||
|
|
||||||
this.ipAddr = submission.ipAddr
|
this.ipAddr = submission.ipAddr
|
||||||
this.geoLocation = new GeoLocationModel(submission.geoLocation)
|
this.geoLocation = new GeoLocationModel(submission.geoLocation)
|
||||||
|
|||||||
@ -3,6 +3,8 @@ import { SubmissionEntity } from '../../entity/submission.entity'
|
|||||||
|
|
||||||
@ObjectType('SubmissionProgress')
|
@ObjectType('SubmissionProgress')
|
||||||
export class SubmissionProgressModel {
|
export class SubmissionProgressModel {
|
||||||
|
readonly _id: number
|
||||||
|
|
||||||
@Field(() => ID)
|
@Field(() => ID)
|
||||||
readonly id: string
|
readonly id: string
|
||||||
|
|
||||||
@ -18,8 +20,9 @@ export class SubmissionProgressModel {
|
|||||||
@Field({ nullable: true })
|
@Field({ nullable: true })
|
||||||
readonly lastModified?: Date
|
readonly lastModified?: Date
|
||||||
|
|
||||||
constructor(submission: Partial<SubmissionEntity>) {
|
constructor(id: string, submission: Partial<SubmissionEntity>) {
|
||||||
this.id = submission.id.toString()
|
this._id = submission.id
|
||||||
|
this.id = id
|
||||||
|
|
||||||
this.timeElapsed = submission.timeElapsed
|
this.timeElapsed = submission.timeElapsed
|
||||||
this.percentageComplete = submission.percentageComplete
|
this.percentageComplete = submission.percentageComplete
|
||||||
|
|||||||
@ -3,6 +3,8 @@ import { UserEntity } from '../../entity/user.entity'
|
|||||||
|
|
||||||
@ObjectType('User')
|
@ObjectType('User')
|
||||||
export class UserModel {
|
export class UserModel {
|
||||||
|
readonly _id: number
|
||||||
|
|
||||||
@Field(() => ID)
|
@Field(() => ID)
|
||||||
readonly id: string
|
readonly id: string
|
||||||
|
|
||||||
@ -36,8 +38,9 @@ export class UserModel {
|
|||||||
@Field({ nullable: true })
|
@Field({ nullable: true })
|
||||||
readonly lastModified: Date
|
readonly lastModified: Date
|
||||||
|
|
||||||
constructor(user: UserEntity) {
|
constructor(id: string, user: UserEntity) {
|
||||||
this.id = user.id.toString()
|
this._id = user.id
|
||||||
|
this.id = id
|
||||||
this.username = user.username
|
this.username = user.username
|
||||||
this.email = user.email
|
this.email = user.email
|
||||||
|
|
||||||
|
|||||||
@ -72,4 +72,10 @@ export class FormEntity {
|
|||||||
|
|
||||||
@UpdateDateColumn()
|
@UpdateDateColumn()
|
||||||
public lastModified: Date
|
public lastModified: Date
|
||||||
|
|
||||||
|
constructor(partial?: Partial<FormEntity>) {
|
||||||
|
if (partial) {
|
||||||
|
Object.assign(this, partial)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,8 +2,12 @@ import { Column, Entity, ManyToOne, PrimaryGeneratedColumn, RelationId } from 't
|
|||||||
import { FormFieldEntity } from './form.field.entity'
|
import { FormFieldEntity } from './form.field.entity'
|
||||||
import { SubmissionEntity } from './submission.entity'
|
import { SubmissionEntity } from './submission.entity'
|
||||||
|
|
||||||
export interface SubmissionFieldContent {
|
type Simple = string | number | boolean
|
||||||
[key: string]: string | string[] | number | number[] | boolean | boolean[]
|
|
||||||
|
export type SubmissionFieldContent = Simple | Simple[] | {
|
||||||
|
[key: string]: Simple | Simple[] | {
|
||||||
|
[key: string]: Simple | Simple[]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Entity({ name: 'submission_field' })
|
@Entity({ name: 'submission_field' })
|
||||||
|
|||||||
@ -1,9 +1,10 @@
|
|||||||
import { MigrationInterface, QueryRunner } from 'typeorm'
|
import { QueryRunner } from 'typeorm'
|
||||||
|
import { SqliteMigration } from '../sqlite.migration'
|
||||||
|
|
||||||
export class initial1619723437787 implements MigrationInterface {
|
export class initial1619723437787 extends SqliteMigration {
|
||||||
name = 'initial1619723437787'
|
name = 'initial1619723437787'
|
||||||
|
|
||||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
public async realUp(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 "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 "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)');
|
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)');
|
||||||
@ -16,13 +17,10 @@ export class initial1619723437787 implements MigrationInterface {
|
|||||||
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 "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 "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)');
|
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 down(queryRunner: QueryRunner): Promise<void> {
|
public async realDown(queryRunner: QueryRunner): Promise<void> {
|
||||||
await queryRunner.query('DROP TABLE "form"');
|
await queryRunner.query('DROP TABLE "form"');
|
||||||
await queryRunner.query('DROP TABLE "submission"');
|
await queryRunner.query('DROP TABLE "submission"');
|
||||||
await queryRunner.query('DROP TABLE "form_visitor"');
|
await queryRunner.query('DROP TABLE "form_visitor"');
|
||||||
|
|||||||
@ -1,13 +1,14 @@
|
|||||||
import { MigrationInterface, QueryRunner } from 'typeorm'
|
import { QueryRunner } from 'typeorm'
|
||||||
|
import { SqliteMigration } from '../sqlite.migration'
|
||||||
|
|
||||||
export class defaultValue1645952169100 implements MigrationInterface {
|
export class defaultValue1645952169100 extends SqliteMigration {
|
||||||
name = 'defaultValue1645952169100'
|
name = 'defaultValue1645952169100'
|
||||||
|
|
||||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
public async realUp(queryRunner: QueryRunner): Promise<void> {
|
||||||
await queryRunner.query('ALTER TABLE "form_field" RENAME COLUMN "value" TO "defaultValue"');
|
await queryRunner.query('ALTER TABLE "form_field" RENAME COLUMN "value" TO "defaultValue"');
|
||||||
}
|
}
|
||||||
|
|
||||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
public async realDown(queryRunner: QueryRunner): Promise<void> {
|
||||||
await queryRunner.query('ALTER TABLE "form_field" RENAME COLUMN "defaultValue" TO "value"');
|
await queryRunner.query('ALTER TABLE "form_field" RENAME COLUMN "defaultValue" TO "value"');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
19
src/pipe/form/form.by.id.pipe.ts
Normal file
19
src/pipe/form/form.by.id.pipe.ts
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
3
src/pipe/form/index.ts
Normal file
3
src/pipe/form/index.ts
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
import { FormByIdPipe } from './form.by.id.pipe'
|
||||||
|
|
||||||
|
export const formPipes = [FormByIdPipe]
|
||||||
9
src/pipe/index.ts
Normal file
9
src/pipe/index.ts
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
import { formPipes } from './form'
|
||||||
|
import { submissionPipes } from './submission'
|
||||||
|
import { userPipes } from './user'
|
||||||
|
|
||||||
|
export const pipes = [
|
||||||
|
...formPipes,
|
||||||
|
...submissionPipes,
|
||||||
|
...userPipes,
|
||||||
|
]
|
||||||
3
src/pipe/submission/index.ts
Normal file
3
src/pipe/submission/index.ts
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
import { SubmissionByIdPipe } from './submission.by.id.pipe'
|
||||||
|
|
||||||
|
export const submissionPipes = [SubmissionByIdPipe]
|
||||||
19
src/pipe/submission/submission.by.id.pipe.ts
Normal file
19
src/pipe/submission/submission.by.id.pipe.ts
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
3
src/pipe/user/index.ts
Normal file
3
src/pipe/user/index.ts
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
import { UserByIdPipe } from './user.by.id.pipe'
|
||||||
|
|
||||||
|
export const userPipes = [UserByIdPipe]
|
||||||
19
src/pipe/user/user.by.id.pipe.ts
Normal file
19
src/pipe/user/user.by.id.pipe.ts
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
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,12 +1,10 @@
|
|||||||
|
|
||||||
type ID = string | number
|
|
||||||
|
|
||||||
export class ContextCache<A = any> {
|
export class ContextCache<A = any> {
|
||||||
private cache: {
|
private cache: {
|
||||||
[key: string]: any
|
[key: string]: any
|
||||||
} = {}
|
} = {}
|
||||||
|
|
||||||
public getCacheKey(type: string, id: ID): string {
|
public getCacheKey(type: string, id: number): string {
|
||||||
return `${type}:${id}`
|
return `${type}:${id}`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -7,12 +7,14 @@ import { FormModel } from '../../dto/form/form.model'
|
|||||||
import { FormEntity } from '../../entity/form.entity'
|
import { FormEntity } from '../../entity/form.entity'
|
||||||
import { UserEntity } from '../../entity/user.entity'
|
import { UserEntity } from '../../entity/user.entity'
|
||||||
import { FormCreateService } from '../../service/form/form.create.service'
|
import { FormCreateService } from '../../service/form/form.create.service'
|
||||||
|
import { IdService } from '../../service/id.service'
|
||||||
import { ContextCache } from '../context.cache'
|
import { ContextCache } from '../context.cache'
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class FormCreateMutation {
|
export class FormCreateMutation {
|
||||||
constructor(
|
constructor(
|
||||||
private readonly createService: FormCreateService
|
private readonly createService: FormCreateService,
|
||||||
|
private readonly idService: IdService,
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -27,6 +29,6 @@ export class FormCreateMutation {
|
|||||||
|
|
||||||
cache.add(cache.getCacheKey(FormEntity.name, form.id), form)
|
cache.add(cache.getCacheKey(FormEntity.name, form.id), form)
|
||||||
|
|
||||||
return new FormModel(form)
|
return new FormModel(this.idService.encode(form.id), form)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,15 +3,19 @@ import { Args, ID, Mutation } from '@nestjs/graphql'
|
|||||||
import { Roles } from '../../decorator/roles.decorator'
|
import { Roles } from '../../decorator/roles.decorator'
|
||||||
import { User } from '../../decorator/user.decorator'
|
import { User } from '../../decorator/user.decorator'
|
||||||
import { DeletedModel } from '../../dto/deleted.model'
|
import { DeletedModel } from '../../dto/deleted.model'
|
||||||
|
import { FormEntity } from '../../entity/form.entity'
|
||||||
import { UserEntity } from '../../entity/user.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 { FormDeleteService } from '../../service/form/form.delete.service'
|
||||||
import { FormService } from '../../service/form/form.service'
|
import { FormService } from '../../service/form/form.service'
|
||||||
|
import { IdService } from '../../service/id.service'
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class FormDeleteMutation {
|
export class FormDeleteMutation {
|
||||||
constructor(
|
constructor(
|
||||||
private readonly deleteService: FormDeleteService,
|
private readonly deleteService: FormDeleteService,
|
||||||
private readonly formService: FormService,
|
private readonly formService: FormService,
|
||||||
|
private readonly idService: IdService,
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -19,16 +23,14 @@ export class FormDeleteMutation {
|
|||||||
@Roles('admin')
|
@Roles('admin')
|
||||||
async deleteForm(
|
async deleteForm(
|
||||||
@User() user: UserEntity,
|
@User() user: UserEntity,
|
||||||
@Args({ name: 'id', type: () => ID}) id: string,
|
@Args('id', {type: () => ID}, FormByIdPipe) form: FormEntity,
|
||||||
): Promise<DeletedModel> {
|
): Promise<DeletedModel> {
|
||||||
const form = await this.formService.findById(id)
|
|
||||||
|
|
||||||
if (!form.isLive && !this.formService.isAdmin(form, user)) {
|
if (!form.isLive && !this.formService.isAdmin(form, user)) {
|
||||||
throw new Error('invalid form')
|
throw new Error('invalid form')
|
||||||
}
|
}
|
||||||
|
|
||||||
await this.deleteService.delete(id)
|
await this.deleteService.delete(form.id)
|
||||||
|
|
||||||
return new DeletedModel(id)
|
return new DeletedModel(this.idService.encode(form.id))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
73
src/resolver/form/form.field.resolver.ts
Normal file
73
src/resolver/form/form.field.resolver.ts
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
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,12 +7,14 @@ import { FormPagerModel } from '../../dto/form/form.pager.model'
|
|||||||
import { FormEntity } from '../../entity/form.entity'
|
import { FormEntity } from '../../entity/form.entity'
|
||||||
import { UserEntity } from '../../entity/user.entity'
|
import { UserEntity } from '../../entity/user.entity'
|
||||||
import { FormService } from '../../service/form/form.service'
|
import { FormService } from '../../service/form/form.service'
|
||||||
|
import { IdService } from '../../service/id.service'
|
||||||
import { ContextCache } from '../context.cache'
|
import { ContextCache } from '../context.cache'
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class FormListQuery {
|
export class FormListQuery {
|
||||||
constructor(
|
constructor(
|
||||||
private readonly formService: FormService,
|
private readonly formService: FormService,
|
||||||
|
private readonly idService: IdService,
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -34,7 +36,7 @@ export class FormListQuery {
|
|||||||
forms.forEach(form => cache.add(cache.getCacheKey(FormEntity.name, form.id), form))
|
forms.forEach(form => cache.add(cache.getCacheKey(FormEntity.name, form.id), form))
|
||||||
|
|
||||||
return new FormPagerModel(
|
return new FormPagerModel(
|
||||||
forms.map(form => new FormModel(form)),
|
forms.map(form => new FormModel(this.idService.encode(form.id), form)),
|
||||||
total,
|
total,
|
||||||
limit,
|
limit,
|
||||||
start,
|
start,
|
||||||
|
|||||||
@ -4,30 +4,31 @@ import { User } from '../../decorator/user.decorator'
|
|||||||
import { FormModel } from '../../dto/form/form.model'
|
import { FormModel } from '../../dto/form/form.model'
|
||||||
import { FormEntity } from '../../entity/form.entity'
|
import { FormEntity } from '../../entity/form.entity'
|
||||||
import { UserEntity } from '../../entity/user.entity'
|
import { UserEntity } from '../../entity/user.entity'
|
||||||
|
import { FormByIdPipe } from '../../pipe/form/form.by.id.pipe'
|
||||||
import { FormService } from '../../service/form/form.service'
|
import { FormService } from '../../service/form/form.service'
|
||||||
|
import { IdService } from '../../service/id.service'
|
||||||
import { ContextCache } from '../context.cache'
|
import { ContextCache } from '../context.cache'
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class FormQuery {
|
export class FormQuery {
|
||||||
constructor(
|
constructor(
|
||||||
private readonly formService: FormService,
|
private readonly formService: FormService,
|
||||||
|
private readonly idService: IdService,
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Query(() => FormModel)
|
@Query(() => FormModel)
|
||||||
async getFormById(
|
getFormById(
|
||||||
@User() user: UserEntity,
|
@User() user: UserEntity,
|
||||||
@Args('id', {type: () => ID}) id,
|
@Args('id', {type: () => ID}, FormByIdPipe) form: FormEntity,
|
||||||
@Context('cache') cache: ContextCache,
|
@Context('cache') cache: ContextCache,
|
||||||
): Promise<FormModel> {
|
): FormModel {
|
||||||
const form = await this.formService.findById(id)
|
|
||||||
|
|
||||||
if (!form.isLive && !this.formService.isAdmin(form, user)) {
|
if (!form.isLive && !this.formService.isAdmin(form, user)) {
|
||||||
throw new Error('invalid form')
|
throw new Error('invalid form')
|
||||||
}
|
}
|
||||||
|
|
||||||
cache.add(cache.getCacheKey(FormEntity.name, form.id), form)
|
cache.add(cache.getCacheKey(FormEntity.name, form.id), form)
|
||||||
|
|
||||||
return new FormModel(form)
|
return new FormModel(this.idService.encode(form.id), form)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -9,14 +9,18 @@ import { FormNotificationModel } from '../../dto/form/form.notification.model'
|
|||||||
import { PageModel } from '../../dto/form/page.model'
|
import { PageModel } from '../../dto/form/page.model'
|
||||||
import { UserModel } from '../../dto/user/user.model'
|
import { UserModel } from '../../dto/user/user.model'
|
||||||
import { FormEntity } from '../../entity/form.entity'
|
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 { UserEntity } from '../../entity/user.entity'
|
||||||
import { FormService } from '../../service/form/form.service'
|
import { FormService } from '../../service/form/form.service'
|
||||||
|
import { IdService } from '../../service/id.service'
|
||||||
import { ContextCache } from '../context.cache'
|
import { ContextCache } from '../context.cache'
|
||||||
|
|
||||||
@Resolver(() => FormModel)
|
@Resolver(() => FormModel)
|
||||||
export class FormResolver {
|
export class FormResolver {
|
||||||
constructor(
|
constructor(
|
||||||
private readonly formService: FormService,
|
private readonly formService: FormService,
|
||||||
|
private readonly idService: IdService,
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -26,20 +30,45 @@ export class FormResolver {
|
|||||||
@Parent() parent: FormModel,
|
@Parent() parent: FormModel,
|
||||||
@Context('cache') cache: ContextCache,
|
@Context('cache') cache: ContextCache,
|
||||||
): Promise<FormFieldModel[]> {
|
): 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))
|
||||||
|
|
||||||
return form.fields?.map(field => new FormFieldModel(field)).sort((a,b) => a.idx - b.idx) || []
|
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,
|
||||||
|
)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ResolveField(() => [FormHookModel])
|
@ResolveField(() => [FormHookModel])
|
||||||
|
@Roles('admin')
|
||||||
async hooks(
|
async hooks(
|
||||||
@User() user: UserEntity,
|
@User() user: UserEntity,
|
||||||
@Parent() parent: FormModel,
|
@Parent() parent: FormModel,
|
||||||
@Context('cache') cache: ContextCache,
|
@Context('cache') cache: ContextCache,
|
||||||
): Promise<FormHookModel[]> {
|
): 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))
|
||||||
|
|
||||||
return form.hooks?.map(hook => new FormHookModel(hook)) || []
|
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
|
||||||
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ResolveField(() => Boolean)
|
@ResolveField(() => Boolean)
|
||||||
@ -49,7 +78,7 @@ export class FormResolver {
|
|||||||
@Parent() parent: FormModel,
|
@Parent() parent: FormModel,
|
||||||
@Context('cache') cache: ContextCache,
|
@Context('cache') cache: ContextCache,
|
||||||
): Promise<boolean> {
|
): 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)) {
|
if (!this.formService.isAdmin(form, user)) {
|
||||||
throw new Error('no access to field')
|
throw new Error('no access to field')
|
||||||
@ -65,13 +94,20 @@ export class FormResolver {
|
|||||||
@Parent() parent: FormModel,
|
@Parent() parent: FormModel,
|
||||||
@Context('cache') cache: ContextCache,
|
@Context('cache') cache: ContextCache,
|
||||||
): Promise<FormNotificationModel[]> {
|
): 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)) {
|
if (!this.formService.isAdmin(form, user)) {
|
||||||
throw new Error('no access to field')
|
throw new Error('no access to field')
|
||||||
}
|
}
|
||||||
|
|
||||||
return form.notifications?.map(notification => new FormNotificationModel(notification)) || []
|
if (!form.notifications) {
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
|
||||||
|
return form.notifications.map(notification => new FormNotificationModel(
|
||||||
|
this.idService.encode(notification.id),
|
||||||
|
notification
|
||||||
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ResolveField(() => DesignModel)
|
@ResolveField(() => DesignModel)
|
||||||
@ -80,7 +116,7 @@ export class FormResolver {
|
|||||||
@Parent() parent: FormModel,
|
@Parent() parent: FormModel,
|
||||||
@Context('cache') cache: ContextCache,
|
@Context('cache') cache: ContextCache,
|
||||||
): Promise<DesignModel> {
|
): 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)
|
return new DesignModel(form.design)
|
||||||
}
|
}
|
||||||
@ -90,9 +126,21 @@ export class FormResolver {
|
|||||||
@Parent() parent: FormModel,
|
@Parent() parent: FormModel,
|
||||||
@Context('cache') cache: ContextCache,
|
@Context('cache') cache: ContextCache,
|
||||||
): Promise<PageModel> {
|
): Promise<PageModel> {
|
||||||
const form = await cache.get<FormEntity>(cache.getCacheKey(FormEntity.name, parent.id))
|
const { startPage } = await cache.get<FormEntity>(cache.getCacheKey(
|
||||||
|
FormEntity.name,
|
||||||
|
parent._id
|
||||||
|
))
|
||||||
|
|
||||||
return new PageModel(form.startPage)
|
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())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ResolveField(() => PageModel)
|
@ResolveField(() => PageModel)
|
||||||
@ -100,9 +148,18 @@ export class FormResolver {
|
|||||||
@Parent() parent: FormModel,
|
@Parent() parent: FormModel,
|
||||||
@Context('cache') cache: ContextCache,
|
@Context('cache') cache: ContextCache,
|
||||||
): Promise<PageModel> {
|
): Promise<PageModel> {
|
||||||
const form = await cache.get<FormEntity>(cache.getCacheKey(FormEntity.name, parent.id))
|
const { endPage } = await cache.get<FormEntity>(cache.getCacheKey(FormEntity.name, parent._id))
|
||||||
|
|
||||||
return new PageModel(form.endPage)
|
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())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ResolveField(() => UserModel, { nullable: true })
|
@ResolveField(() => UserModel, { nullable: true })
|
||||||
@ -111,12 +168,12 @@ export class FormResolver {
|
|||||||
@Parent() parent: FormModel,
|
@Parent() parent: FormModel,
|
||||||
@Context('cache') cache: ContextCache,
|
@Context('cache') cache: ContextCache,
|
||||||
): Promise<UserModel> {
|
): 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) {
|
if (!form.admin) {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
return new UserModel(form.admin)
|
return new UserModel(this.idService.encode(form.admin.id), form.admin)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -8,6 +8,7 @@ import { FormEntity } from '../../entity/form.entity'
|
|||||||
import { UserEntity } from '../../entity/user.entity'
|
import { UserEntity } from '../../entity/user.entity'
|
||||||
import { FormService } from '../../service/form/form.service'
|
import { FormService } from '../../service/form/form.service'
|
||||||
import { FormUpdateService } from '../../service/form/form.update.service'
|
import { FormUpdateService } from '../../service/form/form.update.service'
|
||||||
|
import { IdService } from '../../service/id.service'
|
||||||
import { ContextCache } from '../context.cache'
|
import { ContextCache } from '../context.cache'
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
@ -15,6 +16,7 @@ export class FormUpdateMutation {
|
|||||||
constructor(
|
constructor(
|
||||||
private readonly updateService: FormUpdateService,
|
private readonly updateService: FormUpdateService,
|
||||||
private readonly formService: FormService,
|
private readonly formService: FormService,
|
||||||
|
private readonly idService: IdService,
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -25,7 +27,7 @@ export class FormUpdateMutation {
|
|||||||
@Args({ name: 'form', type: () => FormUpdateInput }) input: FormUpdateInput,
|
@Args({ name: 'form', type: () => FormUpdateInput }) input: FormUpdateInput,
|
||||||
@Context('cache') cache: ContextCache,
|
@Context('cache') cache: ContextCache,
|
||||||
): Promise<FormModel> {
|
): Promise<FormModel> {
|
||||||
const form = await this.formService.findById(input.id)
|
const form = await this.formService.findById(this.idService.decode(input.id))
|
||||||
|
|
||||||
if (!form.isLive && !this.formService.isAdmin(form, user)) {
|
if (!form.isLive && !this.formService.isAdmin(form, user)) {
|
||||||
throw new Error('invalid form')
|
throw new Error('invalid form')
|
||||||
@ -35,6 +37,6 @@ export class FormUpdateMutation {
|
|||||||
|
|
||||||
cache.add(cache.getCacheKey(FormEntity.name, form.id), form)
|
cache.add(cache.getCacheKey(FormEntity.name, form.id), form)
|
||||||
|
|
||||||
return new FormModel(form)
|
return new FormModel(this.idService.encode(form.id), form)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,19 +1,23 @@
|
|||||||
import { FormCreateMutation } from './form.create.mutation'
|
import { FormCreateMutation } from './form.create.mutation'
|
||||||
import { FormDeleteMutation } from './form.delete.mutation'
|
import { FormDeleteMutation } from './form.delete.mutation'
|
||||||
|
import { FormFieldResolver } from './form.field.resolver'
|
||||||
import { FormListQuery } from './form.list.query'
|
import { FormListQuery } from './form.list.query'
|
||||||
import { FormQuery } from './form.query'
|
import { FormQuery } from './form.query'
|
||||||
import { FormResolver } from './form.resolver'
|
import { FormResolver } from './form.resolver'
|
||||||
import { FormStatisticQuery } from './form.statistic.query'
|
import { FormStatisticQuery } from './form.statistic.query'
|
||||||
import { FormStatisticResolver } from './form.statistic.resolver'
|
import { FormStatisticResolver } from './form.statistic.resolver'
|
||||||
import { FormUpdateMutation } from './form.update.mutation'
|
import { FormUpdateMutation } from './form.update.mutation'
|
||||||
|
import { PageResolver } from './page.resolver'
|
||||||
|
|
||||||
export const formResolvers = [
|
export const formResolvers = [
|
||||||
FormCreateMutation,
|
FormCreateMutation,
|
||||||
FormDeleteMutation,
|
FormDeleteMutation,
|
||||||
|
FormFieldResolver,
|
||||||
FormQuery,
|
FormQuery,
|
||||||
FormResolver,
|
FormResolver,
|
||||||
FormListQuery,
|
FormListQuery,
|
||||||
FormStatisticQuery,
|
FormStatisticQuery,
|
||||||
FormStatisticResolver,
|
FormStatisticResolver,
|
||||||
FormUpdateMutation,
|
FormUpdateMutation,
|
||||||
|
PageResolver,
|
||||||
]
|
]
|
||||||
|
|||||||
32
src/resolver/form/page.resolver.ts
Normal file
32
src/resolver/form/page.resolver.ts
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
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,10 +4,16 @@ import { Roles } from '../../decorator/roles.decorator'
|
|||||||
import { User } from '../../decorator/user.decorator'
|
import { User } from '../../decorator/user.decorator'
|
||||||
import { ProfileModel } from '../../dto/profile/profile.model'
|
import { ProfileModel } from '../../dto/profile/profile.model'
|
||||||
import { UserEntity } from '../../entity/user.entity'
|
import { UserEntity } from '../../entity/user.entity'
|
||||||
|
import { IdService } from '../../service/id.service'
|
||||||
import { ContextCache } from '../context.cache'
|
import { ContextCache } from '../context.cache'
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class ProfileQuery {
|
export class ProfileQuery {
|
||||||
|
constructor(
|
||||||
|
private readonly idService: IdService,
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
|
||||||
@Query(() => ProfileModel)
|
@Query(() => ProfileModel)
|
||||||
@Roles('user')
|
@Roles('user')
|
||||||
public me(
|
public me(
|
||||||
@ -16,6 +22,6 @@ export class ProfileQuery {
|
|||||||
): ProfileModel {
|
): ProfileModel {
|
||||||
cache.add(cache.getCacheKey(UserEntity.name, user.id), user)
|
cache.add(cache.getCacheKey(UserEntity.name, user.id), user)
|
||||||
|
|
||||||
return new ProfileModel(user)
|
return new ProfileModel(this.idService.encode(user.id), user)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,6 +5,7 @@ import { User } from '../../decorator/user.decorator'
|
|||||||
import { ProfileModel } from '../../dto/profile/profile.model'
|
import { ProfileModel } from '../../dto/profile/profile.model'
|
||||||
import { ProfileUpdateInput } from '../../dto/profile/profile.update.input'
|
import { ProfileUpdateInput } from '../../dto/profile/profile.update.input'
|
||||||
import { UserEntity } from '../../entity/user.entity'
|
import { UserEntity } from '../../entity/user.entity'
|
||||||
|
import { IdService } from '../../service/id.service'
|
||||||
import { ProfileUpdateService } from '../../service/profile/profile.update.service'
|
import { ProfileUpdateService } from '../../service/profile/profile.update.service'
|
||||||
import { ContextCache } from '../context.cache'
|
import { ContextCache } from '../context.cache'
|
||||||
|
|
||||||
@ -12,6 +13,7 @@ import { ContextCache } from '../context.cache'
|
|||||||
export class ProfileUpdateMutation {
|
export class ProfileUpdateMutation {
|
||||||
constructor(
|
constructor(
|
||||||
private readonly updateService: ProfileUpdateService,
|
private readonly updateService: ProfileUpdateService,
|
||||||
|
private readonly idService: IdService,
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -26,7 +28,7 @@ export class ProfileUpdateMutation {
|
|||||||
|
|
||||||
cache.add(cache.getCacheKey(UserEntity.name, user.id), user)
|
cache.add(cache.getCacheKey(UserEntity.name, user.id), user)
|
||||||
|
|
||||||
return new ProfileModel(user)
|
return new ProfileModel(this.idService.encode(user.id), user)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Mutation(() => ProfileModel)
|
@Mutation(() => ProfileModel)
|
||||||
@ -40,6 +42,6 @@ export class ProfileUpdateMutation {
|
|||||||
|
|
||||||
cache.add(cache.getCacheKey(UserEntity.name, user.id), user)
|
cache.add(cache.getCacheKey(UserEntity.name, user.id), user)
|
||||||
|
|
||||||
return new ProfileModel(user)
|
return new ProfileModel(this.idService.encode(user.id), user)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,12 +4,14 @@ import { SubmissionFieldModel } from '../../dto/submission/submission.field.mode
|
|||||||
import { FormFieldEntity } from '../../entity/form.field.entity'
|
import { FormFieldEntity } from '../../entity/form.field.entity'
|
||||||
import { SubmissionFieldEntity } from '../../entity/submission.field.entity'
|
import { SubmissionFieldEntity } from '../../entity/submission.field.entity'
|
||||||
import { FormFieldService } from '../../service/form/form.field.service'
|
import { FormFieldService } from '../../service/form/form.field.service'
|
||||||
|
import { IdService } from '../../service/id.service'
|
||||||
import { ContextCache } from '../context.cache'
|
import { ContextCache } from '../context.cache'
|
||||||
|
|
||||||
@Resolver(() => SubmissionFieldModel)
|
@Resolver(() => SubmissionFieldModel)
|
||||||
export class SubmissionFieldResolver {
|
export class SubmissionFieldResolver {
|
||||||
constructor(
|
constructor(
|
||||||
private readonly formFieldService: FormFieldService,
|
private readonly formFieldService: FormFieldService,
|
||||||
|
private readonly idService: IdService,
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -19,7 +21,7 @@ export class SubmissionFieldResolver {
|
|||||||
@Context('cache') cache: ContextCache,
|
@Context('cache') cache: ContextCache,
|
||||||
): Promise<FormFieldModel> {
|
): Promise<FormFieldModel> {
|
||||||
const submissionField = await cache.get<SubmissionFieldEntity>(
|
const submissionField = await cache.get<SubmissionFieldEntity>(
|
||||||
cache.getCacheKey(SubmissionFieldEntity.name, parent.id)
|
cache.getCacheKey(SubmissionFieldEntity.name, parent._id)
|
||||||
)
|
)
|
||||||
|
|
||||||
const field = await cache.get<FormFieldEntity>(
|
const field = await cache.get<FormFieldEntity>(
|
||||||
@ -33,6 +35,9 @@ export class SubmissionFieldResolver {
|
|||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
return new FormFieldModel(field)
|
return new FormFieldModel(
|
||||||
|
this.idService.encode(field.id),
|
||||||
|
field,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,33 +2,31 @@ import { Injectable } from '@nestjs/common'
|
|||||||
import { Args, Context, ID, Mutation } from '@nestjs/graphql'
|
import { Args, Context, ID, Mutation } from '@nestjs/graphql'
|
||||||
import { User } from '../../decorator/user.decorator'
|
import { User } from '../../decorator/user.decorator'
|
||||||
import { SubmissionProgressModel } from '../../dto/submission/submission.progress.model'
|
import { SubmissionProgressModel } from '../../dto/submission/submission.progress.model'
|
||||||
import { SubmissionSetFieldInput } from '../../dto/submission/submission.set.field.input'
|
|
||||||
import { SubmissionEntity } from '../../entity/submission.entity'
|
import { SubmissionEntity } from '../../entity/submission.entity'
|
||||||
import { UserEntity } from '../../entity/user.entity'
|
import { UserEntity } from '../../entity/user.entity'
|
||||||
import { SubmissionService } from '../../service/submission/submission.service'
|
import { SubmissionByIdPipe } from '../../pipe/submission/submission.by.id.pipe'
|
||||||
|
import { IdService } from '../../service/id.service'
|
||||||
import { SubmissionSetFieldService } from '../../service/submission/submission.set.field.service'
|
import { SubmissionSetFieldService } from '../../service/submission/submission.set.field.service'
|
||||||
import { ContextCache } from '../context.cache'
|
import { ContextCache } from '../context.cache'
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class SubmissionFinishMutation {
|
export class SubmissionFinishMutation {
|
||||||
constructor(
|
constructor(
|
||||||
private readonly submissionService: SubmissionService,
|
|
||||||
private readonly setFieldService: SubmissionSetFieldService,
|
private readonly setFieldService: SubmissionSetFieldService,
|
||||||
|
private readonly idService: IdService,
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Mutation(() => SubmissionProgressModel)
|
@Mutation(() => SubmissionProgressModel)
|
||||||
async submissionFinish(
|
async submissionFinish(
|
||||||
@User() user: UserEntity,
|
@User() user: UserEntity,
|
||||||
@Args({ name: 'submission', type: () => ID }) id: string,
|
@Args({ name: 'submission', type: () => ID }, SubmissionByIdPipe) submission: SubmissionEntity,
|
||||||
@Context('cache') cache: ContextCache,
|
@Context('cache') cache: ContextCache,
|
||||||
): Promise<SubmissionProgressModel> {
|
): Promise<SubmissionProgressModel> {
|
||||||
const submission = await this.submissionService.findById(id)
|
|
||||||
|
|
||||||
await this.setFieldService.finishSubmission(submission)
|
await this.setFieldService.finishSubmission(submission)
|
||||||
|
|
||||||
cache.add(cache.getCacheKey(SubmissionEntity.name, submission.id), submission)
|
cache.add(cache.getCacheKey(SubmissionEntity.name, submission.id), submission)
|
||||||
|
|
||||||
return new SubmissionProgressModel(submission)
|
return new SubmissionProgressModel(this.idService.encode(submission.id), submission)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,31 +4,31 @@ import { User } from '../../decorator/user.decorator'
|
|||||||
import { SubmissionModel } from '../../dto/submission/submission.model'
|
import { SubmissionModel } from '../../dto/submission/submission.model'
|
||||||
import { SubmissionPagerFilterInput } from '../../dto/submission/submission.pager.filter.input'
|
import { SubmissionPagerFilterInput } from '../../dto/submission/submission.pager.filter.input'
|
||||||
import { SubmissionPagerModel } from '../../dto/submission/submission.pager.model'
|
import { SubmissionPagerModel } from '../../dto/submission/submission.pager.model'
|
||||||
|
import { FormEntity } from '../../entity/form.entity'
|
||||||
import { SubmissionEntity } from '../../entity/submission.entity'
|
import { SubmissionEntity } from '../../entity/submission.entity'
|
||||||
import { UserEntity } from '../../entity/user.entity'
|
import { UserEntity } from '../../entity/user.entity'
|
||||||
import { FormService } from '../../service/form/form.service'
|
import { FormByIdPipe } from '../../pipe/form/form.by.id.pipe'
|
||||||
|
import { IdService } from '../../service/id.service'
|
||||||
import { SubmissionService } from '../../service/submission/submission.service'
|
import { SubmissionService } from '../../service/submission/submission.service'
|
||||||
import { ContextCache } from '../context.cache'
|
import { ContextCache } from '../context.cache'
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class SubmissionListQuery {
|
export class SubmissionListQuery {
|
||||||
constructor(
|
constructor(
|
||||||
private readonly formService: FormService,
|
|
||||||
private readonly submissionService: SubmissionService,
|
private readonly submissionService: SubmissionService,
|
||||||
|
private readonly idService: IdService,
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Query(() => SubmissionPagerModel)
|
@Query(() => SubmissionPagerModel)
|
||||||
async listSubmissions(
|
async listSubmissions(
|
||||||
@User() user: UserEntity,
|
@User() user: UserEntity,
|
||||||
@Args('form', {type: () => ID}) id: string,
|
@Args('form', {type: () => ID}, FormByIdPipe) form: FormEntity,
|
||||||
@Args('start', {type: () => Int, defaultValue: 0, nullable: true}) start: number,
|
@Args('start', {type: () => Int, defaultValue: 0, nullable: true}) start: number,
|
||||||
@Args('limit', {type: () => Int, defaultValue: 50, nullable: true}) limit: number,
|
@Args('limit', {type: () => Int, defaultValue: 50, nullable: true}) limit: number,
|
||||||
@Args('filter', {type: () => SubmissionPagerFilterInput, defaultValue: new SubmissionPagerFilterInput()}) filter: SubmissionPagerFilterInput,
|
@Args('filter', {type: () => SubmissionPagerFilterInput, defaultValue: new SubmissionPagerFilterInput()}) filter: SubmissionPagerFilterInput,
|
||||||
@Context('cache') cache: ContextCache,
|
@Context('cache') cache: ContextCache,
|
||||||
): Promise<SubmissionPagerModel> {
|
): Promise<SubmissionPagerModel> {
|
||||||
const form = await this.formService.findById(id)
|
|
||||||
|
|
||||||
const [submissions, total] = await this.submissionService.find(
|
const [submissions, total] = await this.submissionService.find(
|
||||||
form,
|
form,
|
||||||
start,
|
start,
|
||||||
@ -42,7 +42,10 @@ export class SubmissionListQuery {
|
|||||||
})
|
})
|
||||||
|
|
||||||
return new SubmissionPagerModel(
|
return new SubmissionPagerModel(
|
||||||
submissions.map(submission => new SubmissionModel(submission)),
|
submissions.map(submission => new SubmissionModel(
|
||||||
|
this.idService.encode(submission.id),
|
||||||
|
submission
|
||||||
|
)),
|
||||||
total,
|
total,
|
||||||
limit,
|
limit,
|
||||||
start,
|
start,
|
||||||
|
|||||||
@ -4,8 +4,9 @@ import { User } from '../../decorator/user.decorator'
|
|||||||
import { SubmissionModel } from '../../dto/submission/submission.model'
|
import { SubmissionModel } from '../../dto/submission/submission.model'
|
||||||
import { SubmissionEntity } from '../../entity/submission.entity'
|
import { SubmissionEntity } from '../../entity/submission.entity'
|
||||||
import { UserEntity } from '../../entity/user.entity'
|
import { UserEntity } from '../../entity/user.entity'
|
||||||
|
import { SubmissionByIdPipe } from '../../pipe/submission/submission.by.id.pipe'
|
||||||
import { FormService } from '../../service/form/form.service'
|
import { FormService } from '../../service/form/form.service'
|
||||||
import { SubmissionService } from '../../service/submission/submission.service'
|
import { IdService } from '../../service/id.service'
|
||||||
import { SubmissionTokenService } from '../../service/submission/submission.token.service'
|
import { SubmissionTokenService } from '../../service/submission/submission.token.service'
|
||||||
import { ContextCache } from '../context.cache'
|
import { ContextCache } from '../context.cache'
|
||||||
|
|
||||||
@ -13,20 +14,18 @@ import { ContextCache } from '../context.cache'
|
|||||||
export class SubmissionQuery {
|
export class SubmissionQuery {
|
||||||
constructor(
|
constructor(
|
||||||
private readonly formService: FormService,
|
private readonly formService: FormService,
|
||||||
private readonly submissionService: SubmissionService,
|
|
||||||
private readonly tokenService: SubmissionTokenService,
|
private readonly tokenService: SubmissionTokenService,
|
||||||
|
private readonly idService: IdService,
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Query(() => SubmissionModel)
|
@Query(() => SubmissionModel)
|
||||||
async getSubmissionById(
|
async getSubmissionById(
|
||||||
@User() user: UserEntity,
|
@User() user: UserEntity,
|
||||||
@Args('id', {type: () => ID}) id: string,
|
@Args('id', {type: () => ID}, SubmissionByIdPipe) submission: SubmissionEntity,
|
||||||
@Args('token', {nullable: true}) token: string,
|
@Args('token', {nullable: true}) token: string,
|
||||||
@Context('cache') cache: ContextCache,
|
@Context('cache') cache: ContextCache,
|
||||||
): Promise<SubmissionModel> {
|
): Promise<SubmissionModel> {
|
||||||
const submission = await this.submissionService.findById(id)
|
|
||||||
|
|
||||||
if (
|
if (
|
||||||
!await this.tokenService.verify(token, submission.tokenHash)
|
!await this.tokenService.verify(token, submission.tokenHash)
|
||||||
&& !this.formService.isAdmin(submission.form, user)
|
&& !this.formService.isAdmin(submission.form, user)
|
||||||
@ -36,6 +35,6 @@ export class SubmissionQuery {
|
|||||||
|
|
||||||
cache.add(cache.getCacheKey(SubmissionEntity.name, submission.id), submission)
|
cache.add(cache.getCacheKey(SubmissionEntity.name, submission.id), submission)
|
||||||
|
|
||||||
return new SubmissionModel(submission)
|
return new SubmissionModel(this.idService.encode(submission.id), submission)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,10 +5,16 @@ import { SubmissionModel } from '../../dto/submission/submission.model'
|
|||||||
import { SubmissionEntity } from '../../entity/submission.entity'
|
import { SubmissionEntity } from '../../entity/submission.entity'
|
||||||
import { SubmissionFieldEntity } from '../../entity/submission.field.entity'
|
import { SubmissionFieldEntity } from '../../entity/submission.field.entity'
|
||||||
import { UserEntity } from '../../entity/user.entity'
|
import { UserEntity } from '../../entity/user.entity'
|
||||||
|
import { IdService } from '../../service/id.service'
|
||||||
import { ContextCache } from '../context.cache'
|
import { ContextCache } from '../context.cache'
|
||||||
|
|
||||||
@Resolver(() => SubmissionModel)
|
@Resolver(() => SubmissionModel)
|
||||||
export class SubmissionResolver {
|
export class SubmissionResolver {
|
||||||
|
constructor(
|
||||||
|
private readonly idService: IdService,
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
|
||||||
@ResolveField(() => [SubmissionFieldModel])
|
@ResolveField(() => [SubmissionFieldModel])
|
||||||
async fields(
|
async fields(
|
||||||
@User() user: UserEntity,
|
@User() user: UserEntity,
|
||||||
@ -16,12 +22,12 @@ export class SubmissionResolver {
|
|||||||
@Context('cache') cache: ContextCache,
|
@Context('cache') cache: ContextCache,
|
||||||
): Promise<SubmissionFieldModel[]> {
|
): Promise<SubmissionFieldModel[]> {
|
||||||
const submission = await cache.get<SubmissionEntity>(
|
const submission = await cache.get<SubmissionEntity>(
|
||||||
cache.getCacheKey(SubmissionEntity.name, parent.id)
|
cache.getCacheKey(SubmissionEntity.name, parent._id)
|
||||||
)
|
)
|
||||||
|
|
||||||
return submission.fields.map(field => {
|
return submission.fields.map(field => {
|
||||||
cache.add(cache.getCacheKey(SubmissionFieldEntity.name, field.id), field)
|
cache.add(cache.getCacheKey(SubmissionFieldEntity.name, field.id), field)
|
||||||
return new SubmissionFieldModel(field)
|
return new SubmissionFieldModel(this.idService.encode(field.id), field)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,6 +5,8 @@ import { SubmissionProgressModel } from '../../dto/submission/submission.progres
|
|||||||
import { SubmissionSetFieldInput } from '../../dto/submission/submission.set.field.input'
|
import { SubmissionSetFieldInput } from '../../dto/submission/submission.set.field.input'
|
||||||
import { SubmissionEntity } from '../../entity/submission.entity'
|
import { SubmissionEntity } from '../../entity/submission.entity'
|
||||||
import { UserEntity } from '../../entity/user.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 { SubmissionService } from '../../service/submission/submission.service'
|
||||||
import { SubmissionSetFieldService } from '../../service/submission/submission.set.field.service'
|
import { SubmissionSetFieldService } from '../../service/submission/submission.set.field.service'
|
||||||
import { ContextCache } from '../context.cache'
|
import { ContextCache } from '../context.cache'
|
||||||
@ -14,18 +16,17 @@ export class SubmissionSetFieldMutation {
|
|||||||
constructor(
|
constructor(
|
||||||
private readonly submissionService: SubmissionService,
|
private readonly submissionService: SubmissionService,
|
||||||
private readonly setFieldService: SubmissionSetFieldService,
|
private readonly setFieldService: SubmissionSetFieldService,
|
||||||
|
private readonly idService: IdService,
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Mutation(() => SubmissionProgressModel)
|
@Mutation(() => SubmissionProgressModel)
|
||||||
async submissionSetField(
|
async submissionSetField(
|
||||||
@User() user: UserEntity,
|
@User() user: UserEntity,
|
||||||
@Args({ name: 'submission', type: () => ID }) id: string,
|
@Args({ name: 'submission', type: () => ID }, SubmissionByIdPipe) submission: SubmissionEntity,
|
||||||
@Args({ name: 'field', type: () => SubmissionSetFieldInput }) input: SubmissionSetFieldInput,
|
@Args({ name: 'field', type: () => SubmissionSetFieldInput }) input: SubmissionSetFieldInput,
|
||||||
@Context('cache') cache: ContextCache,
|
@Context('cache') cache: ContextCache,
|
||||||
): Promise<SubmissionProgressModel> {
|
): Promise<SubmissionProgressModel> {
|
||||||
const submission = await this.submissionService.findById(id)
|
|
||||||
|
|
||||||
if (!await this.submissionService.isOwner(submission, input.token)) {
|
if (!await this.submissionService.isOwner(submission, input.token)) {
|
||||||
throw new Error('no access to submission')
|
throw new Error('no access to submission')
|
||||||
}
|
}
|
||||||
@ -34,6 +35,6 @@ export class SubmissionSetFieldMutation {
|
|||||||
|
|
||||||
cache.add(cache.getCacheKey(SubmissionEntity.name, submission.id), submission)
|
cache.add(cache.getCacheKey(SubmissionEntity.name, submission.id), submission)
|
||||||
|
|
||||||
return new SubmissionProgressModel(submission)
|
return new SubmissionProgressModel(this.idService.encode(submission.id), submission)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,9 +4,12 @@ import { IpAddress } from '../../decorator/ip.address.decorator'
|
|||||||
import { User } from '../../decorator/user.decorator'
|
import { User } from '../../decorator/user.decorator'
|
||||||
import { SubmissionProgressModel } from '../../dto/submission/submission.progress.model'
|
import { SubmissionProgressModel } from '../../dto/submission/submission.progress.model'
|
||||||
import { SubmissionStartInput } from '../../dto/submission/submission.start.input'
|
import { SubmissionStartInput } from '../../dto/submission/submission.start.input'
|
||||||
|
import { FormEntity } from '../../entity/form.entity'
|
||||||
import { SubmissionEntity } from '../../entity/submission.entity'
|
import { SubmissionEntity } from '../../entity/submission.entity'
|
||||||
import { UserEntity } from '../../entity/user.entity'
|
import { UserEntity } from '../../entity/user.entity'
|
||||||
|
import { FormByIdPipe } from '../../pipe/form/form.by.id.pipe'
|
||||||
import { FormService } from '../../service/form/form.service'
|
import { FormService } from '../../service/form/form.service'
|
||||||
|
import { IdService } from '../../service/id.service'
|
||||||
import { SubmissionStartService } from '../../service/submission/submission.start.service'
|
import { SubmissionStartService } from '../../service/submission/submission.start.service'
|
||||||
import { ContextCache } from '../context.cache'
|
import { ContextCache } from '../context.cache'
|
||||||
|
|
||||||
@ -15,19 +18,18 @@ export class SubmissionStartMutation {
|
|||||||
constructor(
|
constructor(
|
||||||
private readonly startService: SubmissionStartService,
|
private readonly startService: SubmissionStartService,
|
||||||
private readonly formService: FormService,
|
private readonly formService: FormService,
|
||||||
|
private readonly idService: IdService,
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Mutation(() => SubmissionProgressModel)
|
@Mutation(() => SubmissionProgressModel)
|
||||||
async submissionStart(
|
async submissionStart(
|
||||||
@User() user: UserEntity,
|
@User() user: UserEntity,
|
||||||
@Args({ name: 'form', type: () => ID }) id: string,
|
@Args({ name: 'form', type: () => ID }, FormByIdPipe) form: FormEntity,
|
||||||
@Args({ name: 'submission', type: () => SubmissionStartInput }) input: SubmissionStartInput,
|
@Args({ name: 'submission', type: () => SubmissionStartInput }) input: SubmissionStartInput,
|
||||||
@IpAddress() ipAddr: string,
|
@IpAddress() ipAddr: string,
|
||||||
@Context('cache') cache: ContextCache,
|
@Context('cache') cache: ContextCache,
|
||||||
): Promise<SubmissionProgressModel> {
|
): Promise<SubmissionProgressModel> {
|
||||||
const form = await this.formService.findById(id)
|
|
||||||
|
|
||||||
if (!form.isLive && !this.formService.isAdmin(form, user)) {
|
if (!form.isLive && !this.formService.isAdmin(form, user)) {
|
||||||
throw new Error('invalid form')
|
throw new Error('invalid form')
|
||||||
}
|
}
|
||||||
@ -36,6 +38,6 @@ export class SubmissionStartMutation {
|
|||||||
|
|
||||||
cache.add(cache.getCacheKey(SubmissionEntity.name, submission.id), submission)
|
cache.add(cache.getCacheKey(SubmissionEntity.name, submission.id), submission)
|
||||||
|
|
||||||
return new SubmissionProgressModel(submission)
|
return new SubmissionProgressModel(this.idService.encode(submission.id), submission)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,12 +4,15 @@ import { Roles } from '../../decorator/roles.decorator'
|
|||||||
import { User } from '../../decorator/user.decorator'
|
import { User } from '../../decorator/user.decorator'
|
||||||
import { DeletedModel } from '../../dto/deleted.model'
|
import { DeletedModel } from '../../dto/deleted.model'
|
||||||
import { UserEntity } from '../../entity/user.entity'
|
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'
|
import { UserDeleteService } from '../../service/user/user.delete.service'
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class UserDeleteMutation {
|
export class UserDeleteMutation {
|
||||||
constructor(
|
constructor(
|
||||||
private readonly deleteService: UserDeleteService,
|
private readonly deleteService: UserDeleteService,
|
||||||
|
private readonly idService: IdService,
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -17,14 +20,14 @@ export class UserDeleteMutation {
|
|||||||
@Roles('admin')
|
@Roles('admin')
|
||||||
async deleteUser(
|
async deleteUser(
|
||||||
@User() auth: UserEntity,
|
@User() auth: UserEntity,
|
||||||
@Args({ name: 'id', type: () => ID}) id: string,
|
@Args({ name: 'id', type: () => ID}, UserByIdPipe) user: UserEntity,
|
||||||
): Promise<DeletedModel> {
|
): Promise<DeletedModel> {
|
||||||
if (auth.id.toString() === id) {
|
if (auth.id === user.id) {
|
||||||
throw new Error('cannot delete your own user')
|
throw new Error('cannot delete your own user')
|
||||||
}
|
}
|
||||||
|
|
||||||
await this.deleteService.delete(id)
|
await this.deleteService.delete(user.id)
|
||||||
|
|
||||||
return new DeletedModel(id)
|
return new DeletedModel(this.idService.encode(user.id))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,6 +3,7 @@ import { Roles } from '../../decorator/roles.decorator'
|
|||||||
import { UserModel } from '../../dto/user/user.model'
|
import { UserModel } from '../../dto/user/user.model'
|
||||||
import { UserPagerModel } from '../../dto/user/user.pager.model'
|
import { UserPagerModel } from '../../dto/user/user.pager.model'
|
||||||
import { UserEntity } from '../../entity/user.entity'
|
import { UserEntity } from '../../entity/user.entity'
|
||||||
|
import { IdService } from '../../service/id.service'
|
||||||
import { UserService } from '../../service/user/user.service'
|
import { UserService } from '../../service/user/user.service'
|
||||||
import { ContextCache } from '../context.cache'
|
import { ContextCache } from '../context.cache'
|
||||||
|
|
||||||
@ -10,6 +11,7 @@ import { ContextCache } from '../context.cache'
|
|||||||
export class UserListQuery {
|
export class UserListQuery {
|
||||||
constructor(
|
constructor(
|
||||||
private readonly userService: UserService,
|
private readonly userService: UserService,
|
||||||
|
private readonly idService: IdService,
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -25,7 +27,7 @@ export class UserListQuery {
|
|||||||
return new UserPagerModel(
|
return new UserPagerModel(
|
||||||
entities.map(entity => {
|
entities.map(entity => {
|
||||||
cache.add(cache.getCacheKey(UserEntity.name, entity.id), entity)
|
cache.add(cache.getCacheKey(UserEntity.name, entity.id), entity)
|
||||||
return new UserModel(entity)
|
return new UserModel(this.idService.encode(entity.id), entity)
|
||||||
}),
|
}),
|
||||||
total,
|
total,
|
||||||
limit,
|
limit,
|
||||||
|
|||||||
@ -3,26 +3,25 @@ import { Args, Context, ID, Query } from '@nestjs/graphql'
|
|||||||
import { Roles } from '../../decorator/roles.decorator'
|
import { Roles } from '../../decorator/roles.decorator'
|
||||||
import { UserModel } from '../../dto/user/user.model'
|
import { UserModel } from '../../dto/user/user.model'
|
||||||
import { UserEntity } from '../../entity/user.entity'
|
import { UserEntity } from '../../entity/user.entity'
|
||||||
import { UserService } from '../../service/user/user.service'
|
import { UserByIdPipe } from '../../pipe/user/user.by.id.pipe'
|
||||||
|
import { IdService } from '../../service/id.service'
|
||||||
import { ContextCache } from '../context.cache'
|
import { ContextCache } from '../context.cache'
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class UserQuery {
|
export class UserQuery {
|
||||||
constructor(
|
constructor(
|
||||||
private readonly userService: UserService,
|
private readonly idService: IdService,
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Query(() => UserModel)
|
@Query(() => UserModel)
|
||||||
@Roles('admin')
|
@Roles('admin')
|
||||||
public async getUserById(
|
public getUserById(
|
||||||
@Args('id', {type: () => ID}) id: string,
|
@Args('id', {type: () => ID}, UserByIdPipe) user: UserEntity,
|
||||||
@Context('cache') cache: ContextCache,
|
@Context('cache') cache: ContextCache,
|
||||||
): Promise<UserModel> {
|
): UserModel {
|
||||||
const user = await this.userService.findById(id)
|
|
||||||
|
|
||||||
cache.add(cache.getCacheKey(UserEntity.name, user.id), user)
|
cache.add(cache.getCacheKey(UserEntity.name, user.id), user)
|
||||||
|
|
||||||
return new UserModel(user)
|
return new UserModel(this.idService.encode(user.id), user)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -21,7 +21,7 @@ export class UserResolver {
|
|||||||
@Context('cache') cache: ContextCache,
|
@Context('cache') cache: ContextCache,
|
||||||
): Promise<string[]> {
|
): Promise<string[]> {
|
||||||
return this.returnFieldForSuperuser(
|
return this.returnFieldForSuperuser(
|
||||||
await cache.get<UserEntity>(cache.getCacheKey(UserEntity.name, parent.id)),
|
await cache.get<UserEntity>(cache.getCacheKey(UserEntity.name, parent._id)),
|
||||||
user,
|
user,
|
||||||
c => c.roles
|
c => c.roles
|
||||||
)
|
)
|
||||||
|
|||||||
@ -5,6 +5,7 @@ import { User } from '../../decorator/user.decorator'
|
|||||||
import { UserModel } from '../../dto/user/user.model'
|
import { UserModel } from '../../dto/user/user.model'
|
||||||
import { UserUpdateInput } from '../../dto/user/user.update.input'
|
import { UserUpdateInput } from '../../dto/user/user.update.input'
|
||||||
import { UserEntity } from '../../entity/user.entity'
|
import { UserEntity } from '../../entity/user.entity'
|
||||||
|
import { IdService } from '../../service/id.service'
|
||||||
import { UserService } from '../../service/user/user.service'
|
import { UserService } from '../../service/user/user.service'
|
||||||
import { UserUpdateService } from '../../service/user/user.update.service'
|
import { UserUpdateService } from '../../service/user/user.update.service'
|
||||||
import { ContextCache } from '../context.cache'
|
import { ContextCache } from '../context.cache'
|
||||||
@ -14,6 +15,7 @@ export class UserUpdateMutation {
|
|||||||
constructor(
|
constructor(
|
||||||
private readonly updateService: UserUpdateService,
|
private readonly updateService: UserUpdateService,
|
||||||
private readonly userService: UserService,
|
private readonly userService: UserService,
|
||||||
|
private readonly idService: IdService,
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -28,12 +30,12 @@ export class UserUpdateMutation {
|
|||||||
throw new Error('cannot update your own user')
|
throw new Error('cannot update your own user')
|
||||||
}
|
}
|
||||||
|
|
||||||
const user = await this.userService.findById(input.id)
|
const user = await this.userService.findById(this.idService.decode(input.id))
|
||||||
|
|
||||||
await this.updateService.update(user, input)
|
await this.updateService.update(user, input)
|
||||||
|
|
||||||
cache.add(cache.getCacheKey(UserEntity.name, user.id), user)
|
cache.add(cache.getCacheKey(UserEntity.name, user.id), user)
|
||||||
|
|
||||||
return new UserModel(user)
|
return new UserModel(this.idService.encode(user.id), user)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,13 +3,16 @@ import { InjectRepository } from '@nestjs/typeorm'
|
|||||||
import { Repository } from 'typeorm'
|
import { Repository } from 'typeorm'
|
||||||
import { FormCreateInput } from '../../dto/form/form.create.input'
|
import { FormCreateInput } from '../../dto/form/form.create.input'
|
||||||
import { FormEntity } from '../../entity/form.entity'
|
import { FormEntity } from '../../entity/form.entity'
|
||||||
|
import { PageEntity } from '../../entity/page.entity'
|
||||||
import { UserEntity } from '../../entity/user.entity'
|
import { UserEntity } from '../../entity/user.entity'
|
||||||
|
import { FormPageCreateService } from './form.page.create.service'
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class FormCreateService {
|
export class FormCreateService {
|
||||||
constructor(
|
constructor(
|
||||||
@InjectRepository(FormEntity)
|
@InjectRepository(FormEntity)
|
||||||
private readonly formRepository: Repository<FormEntity>
|
private readonly formRepository: Repository<FormEntity>,
|
||||||
|
private readonly formPageCreateService: FormPageCreateService,
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -23,9 +26,14 @@ export class FormCreateService {
|
|||||||
form.language = input.language || 'en'
|
form.language = input.language || 'en'
|
||||||
form.design.layout = input.layout
|
form.design.layout = input.layout
|
||||||
|
|
||||||
|
|
||||||
|
form.endPage = this.formPageCreateService.create(input.endPage)
|
||||||
|
form.startPage = this.formPageCreateService.create(input.startPage)
|
||||||
|
|
||||||
form.admin = admin
|
form.admin = admin
|
||||||
|
|
||||||
return await this.formRepository.save(form)
|
return await this.formRepository.save(form)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -14,15 +14,13 @@ export class FormDeleteService {
|
|||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
async delete(id: string): Promise<void> {
|
async delete(id: number): Promise<void> {
|
||||||
await this.submissionRepository.createQueryBuilder('s')
|
await this.submissionRepository.delete({
|
||||||
.delete()
|
form: new FormEntity({ id }),
|
||||||
.where('s.form = :form', { form: id })
|
})
|
||||||
.execute()
|
|
||||||
|
|
||||||
await this.formRepository.createQueryBuilder('f')
|
await this.formRepository.delete({
|
||||||
.delete()
|
id,
|
||||||
.where('f.id = :form', { form: id })
|
})
|
||||||
.execute()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
44
src/service/form/form.page.create.service.ts
Normal file
44
src/service/form/form.page.create.service.ts
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
73
src/service/form/form.page.update.service.ts
Normal file
73
src/service/form/form.page.update.service.ts
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
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,6 +10,8 @@ import { FormHookEntity } from '../../entity/form.hook.entity'
|
|||||||
import { FormNotificationEntity } from '../../entity/form.notification.entity'
|
import { FormNotificationEntity } from '../../entity/form.notification.entity'
|
||||||
import { PageButtonEntity } from '../../entity/page.button.entity'
|
import { PageButtonEntity } from '../../entity/page.button.entity'
|
||||||
import { PageEntity } from '../../entity/page.entity'
|
import { PageEntity } from '../../entity/page.entity'
|
||||||
|
import { IdService } from '../id.service'
|
||||||
|
import { FormPageUpdateService } from './form.page.update.service'
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class FormUpdateService {
|
export class FormUpdateService {
|
||||||
@ -20,6 +22,8 @@ export class FormUpdateService {
|
|||||||
private readonly formFieldRepository: Repository<FormFieldEntity>,
|
private readonly formFieldRepository: Repository<FormFieldEntity>,
|
||||||
@InjectRepository(FormHookEntity)
|
@InjectRepository(FormHookEntity)
|
||||||
private readonly formHookRepository: Repository<FormHookEntity>,
|
private readonly formHookRepository: Repository<FormHookEntity>,
|
||||||
|
private readonly idService: IdService,
|
||||||
|
private readonly pageService: FormPageUpdateService,
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -259,87 +263,11 @@ export class FormUpdateService {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
if (input.startPage !== undefined) {
|
if (input.startPage !== undefined) {
|
||||||
if (!form.startPage) {
|
form.startPage = this.pageService.update(form.startPage, input.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) {
|
if (input.endPage !== undefined) {
|
||||||
if (!form.endPage) {
|
form.endPage = this.pageService.update(form.endPage, input.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)
|
await this.formRepository.save(form)
|
||||||
@ -347,12 +275,12 @@ export class FormUpdateService {
|
|||||||
return form
|
return form
|
||||||
}
|
}
|
||||||
|
|
||||||
private findByIdInList<T>(list: T[], id: string, fallback: T): T {
|
private findByIdInList<T extends { id: number }>(list: T[], id: string, fallback: T): T {
|
||||||
if (!list) {
|
if (!list || /^NEW-/.test(id) || !id) {
|
||||||
return fallback
|
return fallback
|
||||||
}
|
}
|
||||||
|
|
||||||
const found = list.find((value: any) => String(value.id) === String(id))
|
const found = list.find((value) => value.id === this.idService.decode(id))
|
||||||
|
|
||||||
if (found) {
|
if (found) {
|
||||||
return found
|
return found
|
||||||
|
|||||||
@ -1,6 +1,8 @@
|
|||||||
import { FormCreateService } from './form.create.service'
|
import { FormCreateService } from './form.create.service'
|
||||||
import { FormDeleteService } from './form.delete.service'
|
import { FormDeleteService } from './form.delete.service'
|
||||||
import { FormFieldService } from './form.field.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 { FormService } from './form.service'
|
||||||
import { FormStatisticService } from './form.statistic.service'
|
import { FormStatisticService } from './form.statistic.service'
|
||||||
import { FormUpdateService } from './form.update.service'
|
import { FormUpdateService } from './form.update.service'
|
||||||
@ -9,6 +11,8 @@ export const formServices = [
|
|||||||
FormCreateService,
|
FormCreateService,
|
||||||
FormDeleteService,
|
FormDeleteService,
|
||||||
FormFieldService,
|
FormFieldService,
|
||||||
|
FormPageCreateService,
|
||||||
|
FormPageUpdateService,
|
||||||
FormService,
|
FormService,
|
||||||
FormStatisticService,
|
FormStatisticService,
|
||||||
FormUpdateService,
|
FormUpdateService,
|
||||||
|
|||||||
32
src/service/id.service.ts
Normal file
32
src/service/id.service.ts
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
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,6 +5,7 @@ import Redis from 'ioredis'
|
|||||||
import { PinoLogger } from 'nestjs-pino'
|
import { PinoLogger } from 'nestjs-pino'
|
||||||
import { authServices } from './auth'
|
import { authServices } from './auth'
|
||||||
import { formServices } from './form'
|
import { formServices } from './form'
|
||||||
|
import { IdService } from './id.service'
|
||||||
import { InstallationMetricsService } from './installation.metrics.service'
|
import { InstallationMetricsService } from './installation.metrics.service'
|
||||||
import { MailService } from './mail.service'
|
import { MailService } from './mail.service'
|
||||||
import { profileServices } from './profile'
|
import { profileServices } from './profile'
|
||||||
@ -44,4 +45,5 @@ export const services = [
|
|||||||
})
|
})
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
IdService,
|
||||||
]
|
]
|
||||||
|
|||||||
@ -25,12 +25,12 @@ export class SubmissionNotificationService {
|
|||||||
try {
|
try {
|
||||||
const to = this.getEmail(
|
const to = this.getEmail(
|
||||||
submission,
|
submission,
|
||||||
notification.toField.id,
|
notification.toField?.id,
|
||||||
notification.toEmail
|
notification.toEmail
|
||||||
)
|
)
|
||||||
const from = this.getEmail(
|
const from = this.getEmail(
|
||||||
submission,
|
submission,
|
||||||
notification.fromField.id,
|
notification.fromField?.id,
|
||||||
notification.fromEmail
|
notification.fromEmail
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -73,14 +73,18 @@ export class SubmissionNotificationService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private getEmail(submission: SubmissionEntity, fieldId: number, fallback: string): string {
|
private getEmail(submission: SubmissionEntity, fieldId: number, fallback: string): string {
|
||||||
|
if (!fieldId) {
|
||||||
|
return fallback
|
||||||
|
}
|
||||||
|
|
||||||
const data = submission.fields.find(field => field.fieldId === fieldId)?.content
|
const data = submission.fields.find(field => field.fieldId === fieldId)?.content
|
||||||
|
|
||||||
if (!data) {
|
if (!data) {
|
||||||
return fallback
|
return fallback
|
||||||
}
|
}
|
||||||
|
|
||||||
if (typeof data.value === 'string') {
|
if (typeof data === 'string') {
|
||||||
return data.value
|
return data
|
||||||
}
|
}
|
||||||
|
|
||||||
return fallback
|
return fallback
|
||||||
|
|||||||
@ -58,7 +58,7 @@ export class SubmissionService {
|
|||||||
return await qb.getManyAndCount()
|
return await qb.getManyAndCount()
|
||||||
}
|
}
|
||||||
|
|
||||||
async findById(id: string): Promise<SubmissionEntity> {
|
async findById(id: number): Promise<SubmissionEntity> {
|
||||||
const submission = await this.submissionRepository.findOne(id);
|
const submission = await this.submissionRepository.findOne(id);
|
||||||
|
|
||||||
if (!submission) {
|
if (!submission) {
|
||||||
|
|||||||
@ -7,6 +7,7 @@ import { Repository } from 'typeorm'
|
|||||||
import { SubmissionSetFieldInput } from '../../dto/submission/submission.set.field.input'
|
import { SubmissionSetFieldInput } from '../../dto/submission/submission.set.field.input'
|
||||||
import { SubmissionEntity } from '../../entity/submission.entity'
|
import { SubmissionEntity } from '../../entity/submission.entity'
|
||||||
import { SubmissionFieldContent, SubmissionFieldEntity } from '../../entity/submission.field.entity'
|
import { SubmissionFieldContent, SubmissionFieldEntity } from '../../entity/submission.field.entity'
|
||||||
|
import { IdService } from '../id.service'
|
||||||
import { SubmissionHookService } from './submission.hook.service'
|
import { SubmissionHookService } from './submission.hook.service'
|
||||||
import { SubmissionNotificationService } from './submission.notification.service'
|
import { SubmissionNotificationService } from './submission.notification.service'
|
||||||
|
|
||||||
@ -19,13 +20,16 @@ export class SubmissionSetFieldService {
|
|||||||
private readonly submissionFieldRepository: Repository<SubmissionFieldEntity>,
|
private readonly submissionFieldRepository: Repository<SubmissionFieldEntity>,
|
||||||
private readonly webHook: SubmissionHookService,
|
private readonly webHook: SubmissionHookService,
|
||||||
private readonly notifications: SubmissionNotificationService,
|
private readonly notifications: SubmissionNotificationService,
|
||||||
|
private readonly idService: IdService,
|
||||||
private readonly logger: PinoLogger,
|
private readonly logger: PinoLogger,
|
||||||
) {
|
) {
|
||||||
logger.setContext(this.constructor.name)
|
logger.setContext(this.constructor.name)
|
||||||
}
|
}
|
||||||
|
|
||||||
async saveField(submission: SubmissionEntity, input: SubmissionSetFieldInput): Promise<void> {
|
async saveField(submission: SubmissionEntity, input: SubmissionSetFieldInput): Promise<void> {
|
||||||
let field = submission.fields.find(field => field.field.id.toString() === input.field)
|
const formFieldId = this.idService.decode(input.field)
|
||||||
|
|
||||||
|
let field = submission.fields.find(field => field.field.id === formFieldId)
|
||||||
|
|
||||||
submission.timeElapsed = dayjs().diff(dayjs(submission.created), 'second')
|
submission.timeElapsed = dayjs().diff(dayjs(submission.created), 'second')
|
||||||
|
|
||||||
@ -38,7 +42,7 @@ export class SubmissionSetFieldService {
|
|||||||
field = new SubmissionFieldEntity()
|
field = new SubmissionFieldEntity()
|
||||||
|
|
||||||
field.submission = submission
|
field.submission = submission
|
||||||
field.field = submission.form.fields.find(field => field.id.toString() === input.field)
|
field.field = submission.form.fields.find(field => field.id === formFieldId)
|
||||||
field.type = field.field.type
|
field.type = field.field.type
|
||||||
field.content = this.parseData(field, input.data)
|
field.content = this.parseData(field, input.data)
|
||||||
|
|
||||||
@ -84,7 +88,7 @@ export class SubmissionSetFieldService {
|
|||||||
field: SubmissionFieldEntity,
|
field: SubmissionFieldEntity,
|
||||||
data: string
|
data: string
|
||||||
): SubmissionFieldContent {
|
): SubmissionFieldContent {
|
||||||
let raw: { [key: string]: unknown }
|
let raw: SubmissionFieldContent
|
||||||
|
|
||||||
const context = {
|
const context = {
|
||||||
field: field.fieldId,
|
field: field.fieldId,
|
||||||
@ -92,21 +96,49 @@ export class SubmissionSetFieldService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
raw = JSON.parse(data) as { [key: string]: unknown }
|
raw = JSON.parse(data) as SubmissionFieldContent
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
this.logger.warn(context, 'received invalid data for field')
|
this.logger.warn(context, 'received invalid data for field')
|
||||||
return { value: null }
|
return { value: null }
|
||||||
}
|
}
|
||||||
|
|
||||||
if (typeof raw !== 'object' || Array.isArray(raw)) {
|
if (Array.isArray(raw)) {
|
||||||
this.logger.warn(context, 'only object supported for data')
|
return raw.map((row: unknown, index) => {
|
||||||
return { value: null }
|
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
|
||||||
}
|
}
|
||||||
|
|
||||||
// now ensure data structure
|
// now ensure data structure
|
||||||
const result = {
|
const result = {}
|
||||||
value: null,
|
|
||||||
}
|
|
||||||
|
|
||||||
let valid = true
|
let valid = true
|
||||||
|
|
||||||
@ -147,6 +179,48 @@ export class SubmissionSetFieldService {
|
|||||||
return
|
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({
|
this.logger.warn({
|
||||||
...context,
|
...context,
|
||||||
path: String(key),
|
path: String(key),
|
||||||
|
|||||||
@ -11,7 +11,7 @@ export class UserDeleteService {
|
|||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
async delete(id: string): Promise<void> {
|
async delete(id: number): Promise<void> {
|
||||||
await this.userRepository.delete(id)
|
await this.userRepository.delete(id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -26,7 +26,7 @@ export class UserService {
|
|||||||
return await qb.getManyAndCount()
|
return await qb.getManyAndCount()
|
||||||
}
|
}
|
||||||
|
|
||||||
async findById(id: string): Promise<UserEntity> {
|
async findById(id: number): Promise<UserEntity> {
|
||||||
const user = await this.userRepository.findOne(id);
|
const user = await this.userRepository.findOne(id);
|
||||||
|
|
||||||
if (!user) {
|
if (!user) {
|
||||||
|
|||||||
@ -16,15 +16,15 @@ export class UserUpdateService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async update(user: UserEntity, input: UserUpdateInput): Promise<UserEntity> {
|
async update(user: UserEntity, input: UserUpdateInput): Promise<UserEntity> {
|
||||||
if (input.firstName !== undefined) {
|
if (this.shouldUpdate(input, user, 'firstName')) {
|
||||||
user.firstName = input.firstName
|
user.firstName = input.firstName
|
||||||
}
|
}
|
||||||
|
|
||||||
if (input.lastName !== undefined) {
|
if (this.shouldUpdate(input, user, 'lastName')) {
|
||||||
user.lastName = input.lastName
|
user.lastName = input.lastName
|
||||||
}
|
}
|
||||||
|
|
||||||
if (input.email !== undefined) {
|
if (this.shouldUpdate(input, user, 'email')) {
|
||||||
user.email = input.email
|
user.email = input.email
|
||||||
user.emailVerified = false
|
user.emailVerified = false
|
||||||
// TODO request email verification
|
// TODO request email verification
|
||||||
@ -34,15 +34,15 @@ export class UserUpdateService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (input.username !== undefined) {
|
if (this.shouldUpdate(input, user, 'username')) {
|
||||||
user.username = input.username
|
user.username = input.username
|
||||||
}
|
}
|
||||||
|
|
||||||
if (input.roles !== undefined) {
|
if (this.shouldUpdate(input, user, 'roles')) {
|
||||||
user.roles = input.roles as rolesType
|
user.roles = input.roles as rolesType
|
||||||
}
|
}
|
||||||
|
|
||||||
if (input.language !== undefined) {
|
if (this.shouldUpdate(input, user, 'language')) {
|
||||||
user.language = input.language
|
user.language = input.language
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -54,4 +54,16 @@ export class UserUpdateService {
|
|||||||
|
|
||||||
return user
|
return user
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private shouldUpdate(
|
||||||
|
input: UserUpdateInput,
|
||||||
|
user: UserEntity,
|
||||||
|
property: keyof UserUpdateInput
|
||||||
|
): boolean {
|
||||||
|
if (input[property] === undefined) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return input[property] == user[property]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
345
yarn.lock
345
yarn.lock
@ -532,6 +532,11 @@
|
|||||||
minimatch "^3.0.4"
|
minimatch "^3.0.4"
|
||||||
strip-json-comments "^3.1.1"
|
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":
|
"@graphql-tools/merge@8.2.2":
|
||||||
version "8.2.2"
|
version "8.2.2"
|
||||||
resolved "https://registry.yarnpkg.com/@graphql-tools/merge/-/merge-8.2.2.tgz#433566c662a33f5a9c3cc5f3ce3753fb0019477a"
|
resolved "https://registry.yarnpkg.com/@graphql-tools/merge/-/merge-8.2.2.tgz#433566c662a33f5a9c3cc5f3ce3753fb0019477a"
|
||||||
@ -1070,6 +1075,22 @@
|
|||||||
"@nodelib/fs.scandir" "2.1.5"
|
"@nodelib/fs.scandir" "2.1.5"
|
||||||
fastq "^1.6.0"
|
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":
|
"@nuxtjs/opencollective@0.3.2":
|
||||||
version "0.3.2"
|
version "0.3.2"
|
||||||
resolved "https://registry.yarnpkg.com/@nuxtjs/opencollective/-/opencollective-0.3.2.tgz#620ce1044f7ac77185e825e1936115bb38e2681c"
|
resolved "https://registry.yarnpkg.com/@nuxtjs/opencollective/-/opencollective-0.3.2.tgz#620ce1044f7ac77185e825e1936115bb38e2681c"
|
||||||
@ -1164,6 +1185,11 @@
|
|||||||
resolved "https://registry.yarnpkg.com/@tootallnate/once/-/once-1.1.2.tgz#ccb91445360179a04e7fe6aff78c00ffc1eeaf82"
|
resolved "https://registry.yarnpkg.com/@tootallnate/once/-/once-1.1.2.tgz#ccb91445360179a04e7fe6aff78c00ffc1eeaf82"
|
||||||
integrity sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==
|
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":
|
"@tsconfig/node10@^1.0.7":
|
||||||
version "1.0.8"
|
version "1.0.8"
|
||||||
resolved "https://registry.yarnpkg.com/@tsconfig/node10/-/node10-1.0.8.tgz#c1e4e80d6f964fbecb3359c43bd48b40f7cadad9"
|
resolved "https://registry.yarnpkg.com/@tsconfig/node10/-/node10-1.0.8.tgz#c1e4e80d6f964fbecb3359c43bd48b40f7cadad9"
|
||||||
@ -1356,7 +1382,7 @@
|
|||||||
dependencies:
|
dependencies:
|
||||||
"@types/istanbul-lib-report" "*"
|
"@types/istanbul-lib-report" "*"
|
||||||
|
|
||||||
"@types/jest@27.4.1":
|
"@types/jest@^27.4.1":
|
||||||
version "27.4.1"
|
version "27.4.1"
|
||||||
resolved "https://registry.yarnpkg.com/@types/jest/-/jest-27.4.1.tgz#185cbe2926eaaf9662d340cc02e548ce9e11ab6d"
|
resolved "https://registry.yarnpkg.com/@types/jest/-/jest-27.4.1.tgz#185cbe2926eaaf9662d340cc02e548ce9e11ab6d"
|
||||||
integrity sha512-23iPJADSmicDVrWk+HT58LMJtzLAnB2AgIzplQuq/bSrGaxCrlvRFjGbXmamnnk/mAmCdLStiGqggu28ocUyiw==
|
integrity sha512-23iPJADSmicDVrWk+HT58LMJtzLAnB2AgIzplQuq/bSrGaxCrlvRFjGbXmamnnk/mAmCdLStiGqggu28ocUyiw==
|
||||||
@ -1837,6 +1863,23 @@ agent-base@6, agent-base@^6.0.0, agent-base@^6.0.2:
|
|||||||
dependencies:
|
dependencies:
|
||||||
debug "4"
|
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:
|
ajv-formats@2.1.1:
|
||||||
version "2.1.1"
|
version "2.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/ajv-formats/-/ajv-formats-2.1.1.tgz#6e669400659eb74973bbf2e33327180a0996b520"
|
resolved "https://registry.yarnpkg.com/ajv-formats/-/ajv-formats-2.1.1.tgz#6e669400659eb74973bbf2e33327180a0996b520"
|
||||||
@ -2064,6 +2107,14 @@ are-we-there-yet@^2.0.0:
|
|||||||
delegates "^1.0.0"
|
delegates "^1.0.0"
|
||||||
readable-stream "^3.6.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:
|
are-we-there-yet@~1.1.2:
|
||||||
version "1.1.7"
|
version "1.1.7"
|
||||||
resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-1.1.7.tgz#b15474a932adab4ff8a50d9adfa7e4e926f21146"
|
resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-1.1.7.tgz#b15474a932adab4ff8a50d9adfa7e4e926f21146"
|
||||||
@ -2436,6 +2487,30 @@ bytes@3.1.1:
|
|||||||
resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.1.tgz#3f018291cb4cbad9accb6e6970bca9c8889e879a"
|
resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.1.tgz#3f018291cb4cbad9accb6e6970bca9c8889e879a"
|
||||||
integrity sha512-dWe4nWO/ruEOY7HkUJ5gFt1DCFV9zPRoJr8pV0/ASQermOZjtq8jMjOprC0Kd10GLN+l7xaUPvxzJFWtxGu8Fg==
|
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:
|
call-bind@^1.0.0, call-bind@^1.0.2:
|
||||||
version "1.0.2"
|
version "1.0.2"
|
||||||
resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c"
|
resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c"
|
||||||
@ -2645,6 +2720,11 @@ clean-css@^4.2.1:
|
|||||||
dependencies:
|
dependencies:
|
||||||
source-map "~0.6.0"
|
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:
|
cli-cursor@^3.1.0:
|
||||||
version "3.1.0"
|
version "3.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-3.1.0.tgz#264305a7ae490d1d03bf0c9ba7c925d1753af307"
|
resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-3.1.0.tgz#264305a7ae490d1d03bf0c9ba7c925d1753af307"
|
||||||
@ -2741,7 +2821,7 @@ color-name@~1.1.4:
|
|||||||
resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2"
|
resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2"
|
||||||
integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==
|
integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==
|
||||||
|
|
||||||
color-support@^1.1.2:
|
color-support@^1.1.2, color-support@^1.1.3:
|
||||||
version "1.1.3"
|
version "1.1.3"
|
||||||
resolved "https://registry.yarnpkg.com/color-support/-/color-support-1.1.3.tgz#93834379a1cc9a0c61f82f52f0d04322251bd5a2"
|
resolved "https://registry.yarnpkg.com/color-support/-/color-support-1.1.3.tgz#93834379a1cc9a0c61f82f52f0d04322251bd5a2"
|
||||||
integrity sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==
|
integrity sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==
|
||||||
@ -3093,7 +3173,7 @@ denque@^2.0.1:
|
|||||||
resolved "https://registry.yarnpkg.com/denque/-/denque-2.0.1.tgz#bcef4c1b80dc32efe97515744f21a4229ab8934a"
|
resolved "https://registry.yarnpkg.com/denque/-/denque-2.0.1.tgz#bcef4c1b80dc32efe97515744f21a4229ab8934a"
|
||||||
integrity sha512-tfiWc6BQLXNLpNiR5iGd0Ocu3P3VpxfzFiqubLgMfhfOw9WyvgJBd46CClNn9k3qfbjvT//0cf7AlYRX/OslMQ==
|
integrity sha512-tfiWc6BQLXNLpNiR5iGd0Ocu3P3VpxfzFiqubLgMfhfOw9WyvgJBd46CClNn9k3qfbjvT//0cf7AlYRX/OslMQ==
|
||||||
|
|
||||||
depd@~1.1.2:
|
depd@^1.1.2, depd@~1.1.2:
|
||||||
version "1.1.2"
|
version "1.1.2"
|
||||||
resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9"
|
resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9"
|
||||||
integrity sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=
|
integrity sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=
|
||||||
@ -3350,6 +3430,13 @@ encoding-japanese@1.0.30:
|
|||||||
resolved "https://registry.yarnpkg.com/encoding-japanese/-/encoding-japanese-1.0.30.tgz#537c4d62881767925d601acb4c79fb14db81703a"
|
resolved "https://registry.yarnpkg.com/encoding-japanese/-/encoding-japanese-1.0.30.tgz#537c4d62881767925d601acb4c79fb14db81703a"
|
||||||
integrity sha512-bd/DFLAoJetvv7ar/KIpE3CNO8wEuyrt9Xuw6nSMiZ+Vrz/Q21BPsMHvARL2Wz6IKHKXgb+DWZqtRg1vql9cBg==
|
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:
|
end-of-stream@^1.1.0, end-of-stream@^1.4.1:
|
||||||
version "1.4.4"
|
version "1.4.4"
|
||||||
resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0"
|
resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0"
|
||||||
@ -3375,6 +3462,16 @@ entities@^2.0.0:
|
|||||||
resolved "https://registry.yarnpkg.com/entities/-/entities-2.2.0.tgz#098dc90ebb83d8dffa089d55256b351d34c4da55"
|
resolved "https://registry.yarnpkg.com/entities/-/entities-2.2.0.tgz#098dc90ebb83d8dffa089d55256b351d34c4da55"
|
||||||
integrity sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==
|
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:
|
error-ex@^1.3.1:
|
||||||
version "1.3.2"
|
version "1.3.2"
|
||||||
resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf"
|
resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf"
|
||||||
@ -4059,7 +4156,7 @@ fs-minipass@^1.2.7:
|
|||||||
dependencies:
|
dependencies:
|
||||||
minipass "^2.6.0"
|
minipass "^2.6.0"
|
||||||
|
|
||||||
fs-minipass@^2.0.0:
|
fs-minipass@^2.0.0, fs-minipass@^2.1.0:
|
||||||
version "2.1.0"
|
version "2.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-2.1.0.tgz#7f5036fdbf12c63c169190cbe4199c852271f9fb"
|
resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-2.1.0.tgz#7f5036fdbf12c63c169190cbe4199c852271f9fb"
|
||||||
integrity sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==
|
integrity sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==
|
||||||
@ -4124,6 +4221,20 @@ gauge@^3.0.0:
|
|||||||
strip-ansi "^6.0.1"
|
strip-ansi "^6.0.1"
|
||||||
wide-align "^1.1.2"
|
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:
|
gauge@~2.7.3:
|
||||||
version "2.7.4"
|
version "2.7.4"
|
||||||
resolved "https://registry.yarnpkg.com/gauge/-/gauge-2.7.4.tgz#2c03405c7538c39d7eb37b317022e325fb018bf7"
|
resolved "https://registry.yarnpkg.com/gauge/-/gauge-2.7.4.tgz#2c03405c7538c39d7eb37b317022e325fb018bf7"
|
||||||
@ -4239,7 +4350,7 @@ glob@7.1.7:
|
|||||||
once "^1.3.0"
|
once "^1.3.0"
|
||||||
path-is-absolute "^1.0.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.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:
|
||||||
version "7.2.0"
|
version "7.2.0"
|
||||||
resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.0.tgz#d15535af7732e02e948f4c41628bd910293f6023"
|
resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.0.tgz#d15535af7732e02e948f4c41628bd910293f6023"
|
||||||
integrity sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==
|
integrity sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==
|
||||||
@ -4280,7 +4391,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"
|
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.8.tgz#e412b8d33f5e006593cbd3cee6df9f2cebbe802a"
|
||||||
integrity sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg==
|
integrity sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg==
|
||||||
|
|
||||||
graceful-fs@^4.2.9:
|
graceful-fs@^4.2.6, graceful-fs@^4.2.9:
|
||||||
version "4.2.9"
|
version "4.2.9"
|
||||||
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.9.tgz#041b05df45755e587a24942279b9d113146e1c96"
|
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.9.tgz#041b05df45755e587a24942279b9d113146e1c96"
|
||||||
integrity sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==
|
integrity sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==
|
||||||
@ -4392,6 +4503,11 @@ has@^1.0.3:
|
|||||||
dependencies:
|
dependencies:
|
||||||
function-bind "^1.1.1"
|
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:
|
he@1.2.0, he@^1.2.0:
|
||||||
version "1.2.0"
|
version "1.2.0"
|
||||||
resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f"
|
resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f"
|
||||||
@ -4502,6 +4618,11 @@ htmlparser2@^6.1.0:
|
|||||||
domutils "^2.5.2"
|
domutils "^2.5.2"
|
||||||
entities "^2.0.0"
|
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:
|
http-errors@1.8.1:
|
||||||
version "1.8.1"
|
version "1.8.1"
|
||||||
resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.8.1.tgz#7c3f28577cbc8a207388455dbd62295ed07bd68c"
|
resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.8.1.tgz#7c3f28577cbc8a207388455dbd62295ed07bd68c"
|
||||||
@ -4522,6 +4643,15 @@ http-proxy-agent@^4.0.0, http-proxy-agent@^4.0.1:
|
|||||||
agent-base "6"
|
agent-base "6"
|
||||||
debug "4"
|
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:
|
http-signature@~1.2.0:
|
||||||
version "1.2.0"
|
version "1.2.0"
|
||||||
resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1"
|
resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1"
|
||||||
@ -4549,6 +4679,13 @@ human-signals@^2.1.0:
|
|||||||
resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-2.1.0.tgz#dc91fcba42e4d06e4abaed33b3e7a3c02f514ea0"
|
resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-2.1.0.tgz#dc91fcba42e4d06e4abaed33b3e7a3c02f514ea0"
|
||||||
integrity sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==
|
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:
|
iconv-lite@0.4.24, iconv-lite@^0.4.24, iconv-lite@^0.4.4:
|
||||||
version "0.4.24"
|
version "0.4.24"
|
||||||
resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b"
|
resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b"
|
||||||
@ -4563,7 +4700,7 @@ iconv-lite@0.6.2:
|
|||||||
dependencies:
|
dependencies:
|
||||||
safer-buffer ">= 2.1.2 < 3.0.0"
|
safer-buffer ">= 2.1.2 < 3.0.0"
|
||||||
|
|
||||||
iconv-lite@0.6.3, iconv-lite@^0.6.3:
|
iconv-lite@0.6.3, iconv-lite@^0.6.2, iconv-lite@^0.6.3:
|
||||||
version "0.6.3"
|
version "0.6.3"
|
||||||
resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.6.3.tgz#a52f80bf38da1952eb5c681790719871a1a72501"
|
resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.6.3.tgz#a52f80bf38da1952eb5c681790719871a1a72501"
|
||||||
integrity sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==
|
integrity sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==
|
||||||
@ -4613,6 +4750,16 @@ imurmurhash@^0.1.4:
|
|||||||
resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea"
|
resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea"
|
||||||
integrity sha1-khi5srkoojixPcT7a21XbyMUU+o=
|
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:
|
inflight@^1.0.4:
|
||||||
version "1.0.6"
|
version "1.0.6"
|
||||||
resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9"
|
resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9"
|
||||||
@ -4839,6 +4986,11 @@ is-interactive@^1.0.0:
|
|||||||
resolved "https://registry.yarnpkg.com/is-interactive/-/is-interactive-1.0.0.tgz#cea6e6ae5c870a7b0a0004070b7b587e0252912e"
|
resolved "https://registry.yarnpkg.com/is-interactive/-/is-interactive-1.0.0.tgz#cea6e6ae5c870a7b0a0004070b7b587e0252912e"
|
||||||
integrity sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==
|
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:
|
is-negative-zero@^2.0.1:
|
||||||
version "2.0.2"
|
version "2.0.2"
|
||||||
resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.2.tgz#7bf6f03a28003b8b3965de3ac26f664d765f3150"
|
resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.2.tgz#7bf6f03a28003b8b3965de3ac26f664d765f3150"
|
||||||
@ -5923,6 +6075,11 @@ lru-cache@^6.0.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
yallist "^4.0.0"
|
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:
|
macos-release@^2.5.0:
|
||||||
version "2.5.0"
|
version "2.5.0"
|
||||||
resolved "https://registry.yarnpkg.com/macos-release/-/macos-release-2.5.0.tgz#067c2c88b5f3fb3c56a375b2ec93826220fa1ff2"
|
resolved "https://registry.yarnpkg.com/macos-release/-/macos-release-2.5.0.tgz#067c2c88b5f3fb3c56a375b2ec93826220fa1ff2"
|
||||||
@ -5971,6 +6128,28 @@ make-error@1.x, make-error@^1.1.1:
|
|||||||
resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.6.tgz#2eb2e37ea9b67c4891f684a1394799af484cf7a2"
|
resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.6.tgz#2eb2e37ea9b67c4891f684a1394799af484cf7a2"
|
||||||
integrity sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==
|
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:
|
makeerror@1.0.12:
|
||||||
version "1.0.12"
|
version "1.0.12"
|
||||||
resolved "https://registry.yarnpkg.com/makeerror/-/makeerror-1.0.12.tgz#3e5dd2079a82e812e983cc6610c4a2cb0eaa801a"
|
resolved "https://registry.yarnpkg.com/makeerror/-/makeerror-1.0.12.tgz#3e5dd2079a82e812e983cc6610c4a2cb0eaa801a"
|
||||||
@ -6074,6 +6253,45 @@ minimist@1.2.5, minimist@^1.2.0, minimist@^1.2.5:
|
|||||||
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602"
|
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602"
|
||||||
integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==
|
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:
|
minipass@^2.6.0, minipass@^2.9.0:
|
||||||
version "2.9.0"
|
version "2.9.0"
|
||||||
resolved "https://registry.yarnpkg.com/minipass/-/minipass-2.9.0.tgz#e713762e7d3e32fed803115cf93e04bca9fcc9a6"
|
resolved "https://registry.yarnpkg.com/minipass/-/minipass-2.9.0.tgz#e713762e7d3e32fed803115cf93e04bca9fcc9a6"
|
||||||
@ -6082,7 +6300,7 @@ minipass@^2.6.0, minipass@^2.9.0:
|
|||||||
safe-buffer "^5.1.2"
|
safe-buffer "^5.1.2"
|
||||||
yallist "^3.0.0"
|
yallist "^3.0.0"
|
||||||
|
|
||||||
minipass@^3.0.0:
|
minipass@^3.0.0, minipass@^3.1.1, minipass@^3.1.6:
|
||||||
version "3.1.6"
|
version "3.1.6"
|
||||||
resolved "https://registry.yarnpkg.com/minipass/-/minipass-3.1.6.tgz#3b8150aa688a711a1521af5e8779c1d3bb4f45ee"
|
resolved "https://registry.yarnpkg.com/minipass/-/minipass-3.1.6.tgz#3b8150aa688a711a1521af5e8779c1d3bb4f45ee"
|
||||||
integrity sha512-rty5kpw9/z8SX9dmxblFA6edItUmwJgMeYDZRrwlIVN27i8gysGbznJwUggw2V/FVqFSDdWy040ZPS811DYAqQ==
|
integrity sha512-rty5kpw9/z8SX9dmxblFA6edItUmwJgMeYDZRrwlIVN27i8gysGbznJwUggw2V/FVqFSDdWy040ZPS811DYAqQ==
|
||||||
@ -6096,7 +6314,7 @@ minizlib@^1.3.3:
|
|||||||
dependencies:
|
dependencies:
|
||||||
minipass "^2.9.0"
|
minipass "^2.9.0"
|
||||||
|
|
||||||
minizlib@^2.1.1:
|
minizlib@^2.1.1, minizlib@^2.1.2:
|
||||||
version "2.1.2"
|
version "2.1.2"
|
||||||
resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-2.1.2.tgz#e90d3466ba209b932451508a11ce3d3632145931"
|
resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-2.1.2.tgz#e90d3466ba209b932451508a11ce3d3632145931"
|
||||||
integrity sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==
|
integrity sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==
|
||||||
@ -6468,7 +6686,7 @@ ms@2.1.2:
|
|||||||
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009"
|
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009"
|
||||||
integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==
|
integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==
|
||||||
|
|
||||||
ms@2.1.3, ms@^2.1.1:
|
ms@2.1.3, ms@^2.0.0, ms@^2.1.1:
|
||||||
version "2.1.3"
|
version "2.1.3"
|
||||||
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2"
|
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2"
|
||||||
integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==
|
integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==
|
||||||
@ -6551,6 +6769,11 @@ negotiator@0.6.2:
|
|||||||
resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.2.tgz#feacf7ccf525a77ae9634436a64883ffeca346fb"
|
resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.2.tgz#feacf7ccf525a77ae9634436a64883ffeca346fb"
|
||||||
integrity sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==
|
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:
|
neo-async@^2.6.0, neo-async@^2.6.2:
|
||||||
version "2.6.2"
|
version "2.6.2"
|
||||||
resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f"
|
resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f"
|
||||||
@ -6625,6 +6848,22 @@ node-gyp@3.x:
|
|||||||
tar "^2.0.0"
|
tar "^2.0.0"
|
||||||
which "1"
|
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:
|
node-int64@^0.4.0:
|
||||||
version "0.4.0"
|
version "0.4.0"
|
||||||
resolved "https://registry.yarnpkg.com/node-int64/-/node-int64-0.4.0.tgz#87a9065cdb355d3182d8f94ce11188b825c68a3b"
|
resolved "https://registry.yarnpkg.com/node-int64/-/node-int64-0.4.0.tgz#87a9065cdb355d3182d8f94ce11188b825c68a3b"
|
||||||
@ -6736,6 +6975,16 @@ npmlog@^5.0.1:
|
|||||||
gauge "^3.0.0"
|
gauge "^3.0.0"
|
||||||
set-blocking "^2.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:
|
nth-check@^2.0.1:
|
||||||
version "2.0.1"
|
version "2.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/nth-check/-/nth-check-2.0.1.tgz#2efe162f5c3da06a28959fbd3db75dbeea9f0fc2"
|
resolved "https://registry.yarnpkg.com/nth-check/-/nth-check-2.0.1.tgz#2efe162f5c3da06a28959fbd3db75dbeea9f0fc2"
|
||||||
@ -6949,6 +7198,13 @@ p-map@^2.1.0:
|
|||||||
resolved "https://registry.yarnpkg.com/p-map/-/p-map-2.1.0.tgz#310928feef9c9ecc65b68b17693018a665cea175"
|
resolved "https://registry.yarnpkg.com/p-map/-/p-map-2.1.0.tgz#310928feef9c9ecc65b68b17693018a665cea175"
|
||||||
integrity sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==
|
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:
|
p-try@^1.0.0:
|
||||||
version "1.0.0"
|
version "1.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/p-try/-/p-try-1.0.0.tgz#cbc79cdbaf8fd4228e13f621f2b1a237c1b207b3"
|
resolved "https://registry.yarnpkg.com/p-try/-/p-try-1.0.0.tgz#cbc79cdbaf8fd4228e13f621f2b1a237c1b207b3"
|
||||||
@ -7336,6 +7592,19 @@ process-warning@^1.0.0:
|
|||||||
resolved "https://registry.yarnpkg.com/process-warning/-/process-warning-1.0.0.tgz#980a0b25dc38cd6034181be4b7726d89066b4616"
|
resolved "https://registry.yarnpkg.com/process-warning/-/process-warning-1.0.0.tgz#980a0b25dc38cd6034181be4b7726d89066b4616"
|
||||||
integrity sha512-du4wfLyj4yCZq1VupnVSZmRsPJsNuxoDQFdCFHLaYiEbFBD7QE0a+I4D7hOxrVnh78QE/YipFAj9lXHiXocV+Q==
|
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:
|
promise@^7.0.1:
|
||||||
version "7.3.1"
|
version "7.3.1"
|
||||||
resolved "https://registry.yarnpkg.com/promise/-/promise-7.3.1.tgz#064b72602b18f90f29192b8b1bc418ffd1ebd3bf"
|
resolved "https://registry.yarnpkg.com/promise/-/promise-7.3.1.tgz#064b72602b18f90f29192b8b1bc418ffd1ebd3bf"
|
||||||
@ -7805,6 +8074,11 @@ retry@0.13.1:
|
|||||||
resolved "https://registry.yarnpkg.com/retry/-/retry-0.13.1.tgz#185b1587acf67919d63b357349e03537b2484658"
|
resolved "https://registry.yarnpkg.com/retry/-/retry-0.13.1.tgz#185b1587acf67919d63b357349e03537b2484658"
|
||||||
integrity sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==
|
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:
|
reusify@^1.0.4:
|
||||||
version "1.0.4"
|
version "1.0.4"
|
||||||
resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76"
|
resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76"
|
||||||
@ -8052,6 +8326,11 @@ 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"
|
resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.6.tgz#24e630c4b0f03fea446a2bd299e62b4a6ca8d0af"
|
||||||
integrity sha512-sDl4qMFpijcGw22U5w63KmD3cZJfBuFlVNbVMKje2keoKML7X2UzWbc4XrmEbDwg0NXJc3yv4/ox7b+JWb57kQ==
|
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:
|
sisteransi@^1.0.5:
|
||||||
version "1.0.5"
|
version "1.0.5"
|
||||||
resolved "https://registry.yarnpkg.com/sisteransi/-/sisteransi-1.0.5.tgz#134d681297756437cc05ca01370d3a7a571075ed"
|
resolved "https://registry.yarnpkg.com/sisteransi/-/sisteransi-1.0.5.tgz#134d681297756437cc05ca01370d3a7a571075ed"
|
||||||
@ -8067,7 +8346,7 @@ slick@^1.12.2:
|
|||||||
resolved "https://registry.yarnpkg.com/slick/-/slick-1.12.2.tgz#bd048ddb74de7d1ca6915faa4a57570b3550c2d7"
|
resolved "https://registry.yarnpkg.com/slick/-/slick-1.12.2.tgz#bd048ddb74de7d1ca6915faa4a57570b3550c2d7"
|
||||||
integrity sha1-vQSN23TefRymkV+qSldXCzVQwtc=
|
integrity sha1-vQSN23TefRymkV+qSldXCzVQwtc=
|
||||||
|
|
||||||
smart-buffer@^4.1.0:
|
smart-buffer@^4.1.0, smart-buffer@^4.2.0:
|
||||||
version "4.2.0"
|
version "4.2.0"
|
||||||
resolved "https://registry.yarnpkg.com/smart-buffer/-/smart-buffer-4.2.0.tgz#6e1d71fa4f18c05f7d0ff216dd16a481d0e8d9ae"
|
resolved "https://registry.yarnpkg.com/smart-buffer/-/smart-buffer-4.2.0.tgz#6e1d71fa4f18c05f7d0ff216dd16a481d0e8d9ae"
|
||||||
integrity sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==
|
integrity sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==
|
||||||
@ -8081,6 +8360,15 @@ socks-proxy-agent@5, socks-proxy-agent@^5.0.0:
|
|||||||
debug "4"
|
debug "4"
|
||||||
socks "^2.3.3"
|
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:
|
socks@^2.3.3:
|
||||||
version "2.6.1"
|
version "2.6.1"
|
||||||
resolved "https://registry.yarnpkg.com/socks/-/socks-2.6.1.tgz#989e6534a07cf337deb1b1c94aaa44296520d30e"
|
resolved "https://registry.yarnpkg.com/socks/-/socks-2.6.1.tgz#989e6534a07cf337deb1b1c94aaa44296520d30e"
|
||||||
@ -8089,6 +8377,14 @@ socks@^2.3.3:
|
|||||||
ip "^1.1.5"
|
ip "^1.1.5"
|
||||||
smart-buffer "^4.1.0"
|
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:
|
sonic-boom@^2.2.0, sonic-boom@^2.2.1:
|
||||||
version "2.4.2"
|
version "2.4.2"
|
||||||
resolved "https://registry.yarnpkg.com/sonic-boom/-/sonic-boom-2.4.2.tgz#34c0965b1a498abedaaca794c752d190f74b5e8f"
|
resolved "https://registry.yarnpkg.com/sonic-boom/-/sonic-boom-2.4.2.tgz#34c0965b1a498abedaaca794c752d190f74b5e8f"
|
||||||
@ -8169,6 +8465,13 @@ sshpk@^1.7.0:
|
|||||||
safer-buffer "^2.0.2"
|
safer-buffer "^2.0.2"
|
||||||
tweetnacl "~0.14.0"
|
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:
|
stack-utils@^2.0.3:
|
||||||
version "2.0.5"
|
version "2.0.5"
|
||||||
resolved "https://registry.yarnpkg.com/stack-utils/-/stack-utils-2.0.5.tgz#d25265fca995154659dbbfba3b49254778d2fdd5"
|
resolved "https://registry.yarnpkg.com/stack-utils/-/stack-utils-2.0.5.tgz#d25265fca995154659dbbfba3b49254778d2fdd5"
|
||||||
@ -8442,7 +8745,7 @@ tar@^4:
|
|||||||
safe-buffer "^5.2.1"
|
safe-buffer "^5.2.1"
|
||||||
yallist "^3.1.1"
|
yallist "^3.1.1"
|
||||||
|
|
||||||
tar@^6.1.11:
|
tar@^6.1.11, tar@^6.1.2:
|
||||||
version "6.1.11"
|
version "6.1.11"
|
||||||
resolved "https://registry.yarnpkg.com/tar/-/tar-6.1.11.tgz#6760a38f003afa1b2ffd0ffe9e9abbd0eab3d621"
|
resolved "https://registry.yarnpkg.com/tar/-/tar-6.1.11.tgz#6760a38f003afa1b2ffd0ffe9e9abbd0eab3d621"
|
||||||
integrity sha512-an/KZQzQUkZCkuoAA64hM92X0Urb6VpRhAFllDzz44U2mcD5scmT3zBc4VgVpkugF580+DQn8eAFSyoQt0tznA==
|
integrity sha512-an/KZQzQUkZCkuoAA64hM92X0Urb6VpRhAFllDzz44U2mcD5scmT3zBc4VgVpkugF580+DQn8eAFSyoQt0tznA==
|
||||||
@ -8800,6 +9103,20 @@ unbox-primitive@^1.0.1:
|
|||||||
has-symbols "^1.0.2"
|
has-symbols "^1.0.2"
|
||||||
which-boxed-primitive "^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:
|
universalify@^0.1.0, universalify@^0.1.2:
|
||||||
version "0.1.2"
|
version "0.1.2"
|
||||||
resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66"
|
resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66"
|
||||||
@ -9050,14 +9367,14 @@ which@1:
|
|||||||
dependencies:
|
dependencies:
|
||||||
isexe "^2.0.0"
|
isexe "^2.0.0"
|
||||||
|
|
||||||
which@^2.0.1:
|
which@^2.0.1, which@^2.0.2:
|
||||||
version "2.0.2"
|
version "2.0.2"
|
||||||
resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1"
|
resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1"
|
||||||
integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==
|
integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==
|
||||||
dependencies:
|
dependencies:
|
||||||
isexe "^2.0.0"
|
isexe "^2.0.0"
|
||||||
|
|
||||||
wide-align@^1.1.0, wide-align@^1.1.2:
|
wide-align@^1.1.0, wide-align@^1.1.2, wide-align@^1.1.5:
|
||||||
version "1.1.5"
|
version "1.1.5"
|
||||||
resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.5.tgz#df1d4c206854369ecf3c9a4898f1b23fbd9d15d3"
|
resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.5.tgz#df1d4c206854369ecf3c9a4898f1b23fbd9d15d3"
|
||||||
integrity sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==
|
integrity sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user