Compare commits

...

10 Commits

17 changed files with 169 additions and 456 deletions

View File

@ -4,7 +4,8 @@
"./coverage/**", "./coverage/**",
"public/**", "public/**",
"./node_modules", "./node_modules",
"docker_node_modules/**" "docker_node_modules/**",
"./db/**"
], ],
"globbyOptions": { "gitignore": true }, "globbyOptions": { "gitignore": true },
"rules": { "rules": {

View File

@ -4,6 +4,8 @@ services:
image: mongo:4.4-bionic image: mongo:4.4-bionic
ports: ports:
- "127.0.0.1:${PORT:-2076}7:27017" - "127.0.0.1:${PORT:-2076}7:27017"
volumes:
- "${DB_VOLUME_PATH:-./db}:/data/db"
test: test:
image: sealious-app:latest image: sealious-app:latest

466
package-lock.json generated
View File

@ -13,11 +13,10 @@
"@hotwired/turbo": "^8.0.2", "@hotwired/turbo": "^8.0.2",
"@koa/router": "^12.0.1", "@koa/router": "^12.0.1",
"@sealcode/add-to-head": "^1.0.0", "@sealcode/add-to-head": "^1.0.0",
"@sealcode/crud-ui": "^0.0.18",
"@sealcode/file-manager": "^1.0.2", "@sealcode/file-manager": "^1.0.2",
"@sealcode/jdd": "^0.8.0", "@sealcode/jdd": "^0.8.1",
"@sealcode/jdd-editor": "^0.2.1", "@sealcode/jdd-editor": "^0.2.4",
"@sealcode/sealgen": "^0.19.0", "@sealcode/sealgen": "^0.19.6",
"@sealcode/simplemde": "^1.12.1", "@sealcode/simplemde": "^1.12.1",
"@sealcode/sortable": "^0.0.1", "@sealcode/sortable": "^0.0.1",
"@sealcode/ts-predicates": "^0.6.2", "@sealcode/ts-predicates": "^0.6.2",
@ -44,7 +43,7 @@
"nyc": "^17.1.0", "nyc": "^17.1.0",
"object-path": "^0.11.8", "object-path": "^0.11.8",
"qs": "^6.12.0", "qs": "^6.12.0",
"sealious": "^0.21.20", "sealious": "^0.21.30",
"slug": "^9.1.0", "slug": "^9.1.0",
"stimulus": "^3.2.2", "stimulus": "^3.2.2",
"tempstream": "^0.4.6", "tempstream": "^0.4.6",
@ -1339,112 +1338,6 @@
"ansi-html-stream": "index.js" "ansi-html-stream": "index.js"
} }
}, },
"node_modules/@sealcode/crud-ui": {
"version": "0.0.18",
"resolved": "https://registry.npmjs.org/@sealcode/crud-ui/-/crud-ui-0.0.18.tgz",
"integrity": "sha512-brzQxDpqMe11C+d794izJabrSqxUGv5BzMKY3wMJiuHD1K0WJD09Vkg35GWwRD7RdfXFt7uncSswqyYMBlKDAg==",
"dependencies": {
"@koa/router": "^13.1.0",
"@sealcode/sealgen": "^0.18.5",
"@types/koa__router": "^12.0.4",
"escape-goat": "^4.0.0",
"qs": "^6.13.0",
"tempstream": "^0.4.5"
}
},
"node_modules/@sealcode/crud-ui/node_modules/@koa/router": {
"version": "13.1.1",
"resolved": "https://registry.npmjs.org/@koa/router/-/router-13.1.1.tgz",
"integrity": "sha512-JQEuMANYRVHs7lm7KY9PCIjkgJk73h4m4J+g2mkw2Vo1ugPZ17UJVqEH8F+HeAdjKz5do1OaLe7ArDz+z308gw==",
"dependencies": {
"debug": "^4.4.1",
"http-errors": "^2.0.0",
"koa-compose": "^4.1.0",
"path-to-regexp": "^6.3.0"
},
"engines": {
"node": ">= 18"
}
},
"node_modules/@sealcode/crud-ui/node_modules/@sealcode/sealgen": {
"version": "0.18.10",
"resolved": "https://registry.npmjs.org/@sealcode/sealgen/-/sealgen-0.18.10.tgz",
"integrity": "sha512-Q+Wkeq01TFHXPM+LoRMbe9fqakSqgJnJxmjsw9Jzhm3dKBchTfj8BvRd1XWERWZZizCWmzkshLNoVx0kjyZ7rA==",
"license": "ISC",
"dependencies": {
"@koa/router": "^12.0.1",
"@sealcode/file-manager": "^1.0.2",
"@sealcode/ts-predicates": "^0.4.3",
"chokidar": "^3.6.0",
"colord": "^2.9.3",
"deepmerge": "^4.3.1",
"esbuild": "^0.20.0",
"escape-goat": "^4.0.0",
"fonsta": "^1.1.1",
"google-fonts-helper": "^3.4.1",
"husky": "^9.1.7",
"is-what": "^4.1.16",
"js-convert-case": "^4.2.0",
"json5": "^2.2.3",
"locreq": "^3.0.0",
"md5": "^2.3.0",
"merge": "^2.1.1",
"prettier": "^2.7.1",
"prompts": "^2.4.2",
"recursive-readdir": "^2.2.3",
"tempfile": "^5.0.0",
"tempstream": "^0.4.6",
"tiny-glob": "^0.2.9",
"wcag-contrast": "^3.0.0",
"ws": "^8.16.0",
"yargs": "^17.6.2"
},
"bin": {
"sealgen": "lib/cli.js"
},
"peerDependencies": {
"koa": "^2.13.0",
"koa-responsive-image-router": "^0.2.24",
"sealious": "^0.21"
}
},
"node_modules/@sealcode/crud-ui/node_modules/@sealcode/sealgen/node_modules/@koa/router": {
"version": "12.0.2",
"resolved": "https://registry.npmjs.org/@koa/router/-/router-12.0.2.tgz",
"integrity": "sha512-sYcHglGKTxGF+hQ6x67xDfkE9o+NhVlRHBqq6gLywaMc6CojK/5vFZByphdonKinYlMLkEkacm+HEse9HzwgTA==",
"license": "MIT",
"dependencies": {
"debug": "^4.3.4",
"http-errors": "^2.0.0",
"koa-compose": "^4.1.0",
"methods": "^1.1.2",
"path-to-regexp": "^6.3.0"
},
"engines": {
"node": ">= 12"
}
},
"node_modules/@sealcode/crud-ui/node_modules/@sealcode/ts-predicates": {
"version": "0.4.3",
"resolved": "https://registry.npmjs.org/@sealcode/ts-predicates/-/ts-predicates-0.4.3.tgz",
"integrity": "sha512-UNSEacu7Ye8q0N8AJCJy37oJvv3w2OXKGkUnP7xO5lOY9DQviDPRDQhVaZdJ3/xMzXLm4UE3389ihctrPaov/A==",
"license": "ISC"
},
"node_modules/@sealcode/crud-ui/node_modules/prettier": {
"version": "2.8.8",
"resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz",
"integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==",
"license": "MIT",
"bin": {
"prettier": "bin-prettier.js"
},
"engines": {
"node": ">=10.13.0"
},
"funding": {
"url": "https://github.com/prettier/prettier?sponsor=1"
}
},
"node_modules/@sealcode/file-manager": { "node_modules/@sealcode/file-manager": {
"version": "1.0.2", "version": "1.0.2",
"resolved": "https://registry.npmjs.org/@sealcode/file-manager/-/file-manager-1.0.2.tgz", "resolved": "https://registry.npmjs.org/@sealcode/file-manager/-/file-manager-1.0.2.tgz",
@ -1458,9 +1351,9 @@
} }
}, },
"node_modules/@sealcode/jdd": { "node_modules/@sealcode/jdd": {
"version": "0.8.0", "version": "0.8.1",
"resolved": "https://registry.npmjs.org/@sealcode/jdd/-/jdd-0.8.0.tgz", "resolved": "https://registry.npmjs.org/@sealcode/jdd/-/jdd-0.8.1.tgz",
"integrity": "sha512-0esGO0j922FK3rYs+OmWbp0SWAQWkPaidNzvrq2dyaj0SyPU7B0vZZOYjzboICyvqBkMZWbf+YXNK/zzYs18EA==", "integrity": "sha512-UnFS+6q7808kK9NsyagNW/rap9BLkOe60OYM3VeZZd68NvP5SWLQSDvMMrf7IIM50VKDnUx0xf0qLX/9e+IBdA==",
"dependencies": { "dependencies": {
"@sealcode/file-manager": "^1.0.2", "@sealcode/file-manager": "^1.0.2",
"@sealcode/ts-predicates": "^0.5.3", "@sealcode/ts-predicates": "^0.5.3",
@ -1481,14 +1374,14 @@
} }
}, },
"node_modules/@sealcode/jdd-editor": { "node_modules/@sealcode/jdd-editor": {
"version": "0.2.1", "version": "0.2.4",
"resolved": "https://registry.npmjs.org/@sealcode/jdd-editor/-/jdd-editor-0.2.1.tgz", "resolved": "https://registry.npmjs.org/@sealcode/jdd-editor/-/jdd-editor-0.2.4.tgz",
"integrity": "sha512-6JrUtIaBHqB6/gLHE0dXk83zohHz8X0hrT8DtdMTGt5ZDNlXylqkCWwXC4GVV0C6eLsP1ue6fKRo0oYjoiptsQ==", "integrity": "sha512-Fwp/kb3ViRR+XawMUI1sc9LAOzyjVevHa4MFI4xTzZDvQZCPyaDUoPe20yCoF5BKNqVw4GbkAXG4idJfJ0shyA==",
"dependencies": { "dependencies": {
"@koa/router": "^13.1.0", "@koa/router": "^13.1.0",
"@sealcode/jdd": "^0.8.0", "@sealcode/jdd": "^0.8.1",
"@sealcode/sealcodemirror": "^5.70.0-beta5", "@sealcode/sealcodemirror": "^5.70.0-beta5",
"@sealcode/sealgen": "^0.18", "@sealcode/sealgen": "^0.19.6",
"@types/object-path": "^0.11.4", "@types/object-path": "^0.11.4",
"@types/throttle-debounce": "^5.0.2", "@types/throttle-debounce": "^5.0.2",
"@types/turndown": "^5.0.5", "@types/turndown": "^5.0.5",
@ -1514,85 +1407,6 @@
"node": ">= 18" "node": ">= 18"
} }
}, },
"node_modules/@sealcode/jdd-editor/node_modules/@sealcode/sealgen": {
"version": "0.18.10",
"resolved": "https://registry.npmjs.org/@sealcode/sealgen/-/sealgen-0.18.10.tgz",
"integrity": "sha512-Q+Wkeq01TFHXPM+LoRMbe9fqakSqgJnJxmjsw9Jzhm3dKBchTfj8BvRd1XWERWZZizCWmzkshLNoVx0kjyZ7rA==",
"license": "ISC",
"dependencies": {
"@koa/router": "^12.0.1",
"@sealcode/file-manager": "^1.0.2",
"@sealcode/ts-predicates": "^0.4.3",
"chokidar": "^3.6.0",
"colord": "^2.9.3",
"deepmerge": "^4.3.1",
"esbuild": "^0.20.0",
"escape-goat": "^4.0.0",
"fonsta": "^1.1.1",
"google-fonts-helper": "^3.4.1",
"husky": "^9.1.7",
"is-what": "^4.1.16",
"js-convert-case": "^4.2.0",
"json5": "^2.2.3",
"locreq": "^3.0.0",
"md5": "^2.3.0",
"merge": "^2.1.1",
"prettier": "^2.7.1",
"prompts": "^2.4.2",
"recursive-readdir": "^2.2.3",
"tempfile": "^5.0.0",
"tempstream": "^0.4.6",
"tiny-glob": "^0.2.9",
"wcag-contrast": "^3.0.0",
"ws": "^8.16.0",
"yargs": "^17.6.2"
},
"bin": {
"sealgen": "lib/cli.js"
},
"peerDependencies": {
"koa": "^2.13.0",
"koa-responsive-image-router": "^0.2.24",
"sealious": "^0.21"
}
},
"node_modules/@sealcode/jdd-editor/node_modules/@sealcode/sealgen/node_modules/@koa/router": {
"version": "12.0.2",
"resolved": "https://registry.npmjs.org/@koa/router/-/router-12.0.2.tgz",
"integrity": "sha512-sYcHglGKTxGF+hQ6x67xDfkE9o+NhVlRHBqq6gLywaMc6CojK/5vFZByphdonKinYlMLkEkacm+HEse9HzwgTA==",
"license": "MIT",
"dependencies": {
"debug": "^4.3.4",
"http-errors": "^2.0.0",
"koa-compose": "^4.1.0",
"methods": "^1.1.2",
"path-to-regexp": "^6.3.0"
},
"engines": {
"node": ">= 12"
}
},
"node_modules/@sealcode/jdd-editor/node_modules/@sealcode/ts-predicates": {
"version": "0.4.3",
"resolved": "https://registry.npmjs.org/@sealcode/ts-predicates/-/ts-predicates-0.4.3.tgz",
"integrity": "sha512-UNSEacu7Ye8q0N8AJCJy37oJvv3w2OXKGkUnP7xO5lOY9DQviDPRDQhVaZdJ3/xMzXLm4UE3389ihctrPaov/A==",
"license": "ISC"
},
"node_modules/@sealcode/jdd-editor/node_modules/prettier": {
"version": "2.8.8",
"resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz",
"integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==",
"license": "MIT",
"bin": {
"prettier": "bin-prettier.js"
},
"engines": {
"node": ">=10.13.0"
},
"funding": {
"url": "https://github.com/prettier/prettier?sponsor=1"
}
},
"node_modules/@sealcode/jdd/node_modules/@sealcode/ts-predicates": { "node_modules/@sealcode/jdd/node_modules/@sealcode/ts-predicates": {
"version": "0.5.3", "version": "0.5.3",
"resolved": "https://registry.npmjs.org/@sealcode/ts-predicates/-/ts-predicates-0.5.3.tgz", "resolved": "https://registry.npmjs.org/@sealcode/ts-predicates/-/ts-predicates-0.5.3.tgz",
@ -1618,16 +1432,16 @@
"integrity": "sha512-pDsGlk2KokQkwzsJDBUWJFDRpEoxxth6TMQGDJyCTmWnd1Vn+cQb5moXDKaf7cXnWb9Y6QtdNX/fPzM/3RH2Cg==" "integrity": "sha512-pDsGlk2KokQkwzsJDBUWJFDRpEoxxth6TMQGDJyCTmWnd1Vn+cQb5moXDKaf7cXnWb9Y6QtdNX/fPzM/3RH2Cg=="
}, },
"node_modules/@sealcode/sealgen": { "node_modules/@sealcode/sealgen": {
"version": "0.19.0", "version": "0.19.6",
"resolved": "https://registry.npmjs.org/@sealcode/sealgen/-/sealgen-0.19.0.tgz", "resolved": "https://registry.npmjs.org/@sealcode/sealgen/-/sealgen-0.19.6.tgz",
"integrity": "sha512-fnHg/1b+w4E0G4VUSk+Qh+rsHneh1F9LSXZBnQW3fF1+WdSUWgeaVMqUPpN6CXNmze1k7dMWQIjdXAS/AYgpFA==", "integrity": "sha512-dUccXEGSTlZrkrzkta2cObQUDBzbTrfYLZkbZer6E9nyYKB/7Jbj03R+C3wGxfwvrsewGfHiar+v8JHjOiguyQ==",
"license": "ISC",
"dependencies": { "dependencies": {
"@koa/router": "^12.0.1", "@koa/router": "^12.0.1",
"@sealcode/file-manager": "^1.0.2", "@sealcode/file-manager": "^1.0.2",
"@sealcode/ts-predicates": "^0.4.3", "@sealcode/ts-predicates": "^0.4.3",
"chokidar": "^3.6.0", "chokidar": "^3.6.0",
"colord": "^2.9.3", "colord": "^2.9.3",
"country-codes-list": "^2.0.0",
"deepmerge": "^4.3.1", "deepmerge": "^4.3.1",
"esbuild": "^0.20.0", "esbuild": "^0.20.0",
"escape-goat": "^4.0.0", "escape-goat": "^4.0.0",
@ -1640,7 +1454,7 @@
"locreq": "^3.0.0", "locreq": "^3.0.0",
"md5": "^2.3.0", "md5": "^2.3.0",
"merge": "^2.1.1", "merge": "^2.1.1",
"prettier": "^2.7.1", "prettier": "^3.6.2",
"prompts": "^2.4.2", "prompts": "^2.4.2",
"recursive-readdir": "^2.2.3", "recursive-readdir": "^2.2.3",
"tempfile": "^5.0.0", "tempfile": "^5.0.0",
@ -1656,7 +1470,7 @@
"peerDependencies": { "peerDependencies": {
"koa": "^2.13.0", "koa": "^2.13.0",
"koa-responsive-image-router": "^0.2.24", "koa-responsive-image-router": "^0.2.24",
"sealious": "^0.21", "sealious": "^0.21.20",
"stimulus": "^3.2.2" "stimulus": "^3.2.2"
} }
}, },
@ -1665,20 +1479,6 @@
"resolved": "https://registry.npmjs.org/@sealcode/ts-predicates/-/ts-predicates-0.4.3.tgz", "resolved": "https://registry.npmjs.org/@sealcode/ts-predicates/-/ts-predicates-0.4.3.tgz",
"integrity": "sha512-UNSEacu7Ye8q0N8AJCJy37oJvv3w2OXKGkUnP7xO5lOY9DQviDPRDQhVaZdJ3/xMzXLm4UE3389ihctrPaov/A==" "integrity": "sha512-UNSEacu7Ye8q0N8AJCJy37oJvv3w2OXKGkUnP7xO5lOY9DQviDPRDQhVaZdJ3/xMzXLm4UE3389ihctrPaov/A=="
}, },
"node_modules/@sealcode/sealgen/node_modules/prettier": {
"version": "2.8.8",
"resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz",
"integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==",
"bin": {
"prettier": "bin-prettier.js"
},
"engines": {
"node": ">=10.13.0"
},
"funding": {
"url": "https://github.com/prettier/prettier?sponsor=1"
}
},
"node_modules/@sealcode/simplemde": { "node_modules/@sealcode/simplemde": {
"version": "1.12.1", "version": "1.12.1",
"resolved": "https://registry.npmjs.org/@sealcode/simplemde/-/simplemde-1.12.1.tgz", "resolved": "https://registry.npmjs.org/@sealcode/simplemde/-/simplemde-1.12.1.tgz",
@ -2005,6 +1805,7 @@
"version": "12.0.4", "version": "12.0.4",
"resolved": "https://registry.npmjs.org/@types/koa__router/-/koa__router-12.0.4.tgz", "resolved": "https://registry.npmjs.org/@types/koa__router/-/koa__router-12.0.4.tgz",
"integrity": "sha512-Y7YBbSmfXZpa/m5UGGzb7XadJIRBRnwNY9cdAojZGp65Cpe5MAP3mOZE7e3bImt8dfKS4UFcR16SLH8L/z7PBw==", "integrity": "sha512-Y7YBbSmfXZpa/m5UGGzb7XadJIRBRnwNY9cdAojZGp65Cpe5MAP3mOZE7e3bImt8dfKS4UFcR16SLH8L/z7PBw==",
"dev": true,
"dependencies": { "dependencies": {
"@types/koa": "*" "@types/koa": "*"
} }
@ -3168,15 +2969,6 @@
"resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz",
"integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==" "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww=="
}, },
"node_modules/boom": {
"version": "7.3.0",
"resolved": "https://registry.npmjs.org/boom/-/boom-7.3.0.tgz",
"integrity": "sha512-Swpoyi2t5+GhOEGw8rEsKvTxFLIDiiKoUc2gsoV6Lyr43LHBIzch3k2MvYUs8RTROrIkVJ3Al0TkaOGjnb+B6A==",
"deprecated": "This module has moved and is now available at @hapi/boom. Please update your dependencies as this version is no longer maintained an may contain bugs and security issues.",
"dependencies": {
"hoek": "6.x.x"
}
},
"node_modules/brace-expansion": { "node_modules/brace-expansion": {
"version": "2.0.2", "version": "2.0.2",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz",
@ -3998,6 +3790,11 @@
} }
} }
}, },
"node_modules/country-codes-list": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/country-codes-list/-/country-codes-list-2.0.0.tgz",
"integrity": "sha512-KZqq/LBdCD76hQCa6nOx0bA/nIjYly1OtV8+Bbt/4SW+mJEqGk7oZHjUj7PRrV0gXJJKs6Tv2cIntFdofBByvA=="
},
"node_modules/create-error-class": { "node_modules/create-error-class": {
"version": "3.0.2", "version": "3.0.2",
"resolved": "https://registry.npmjs.org/create-error-class/-/create-error-class-3.0.2.tgz", "resolved": "https://registry.npmjs.org/create-error-class/-/create-error-class-3.0.2.tgz",
@ -7046,12 +6843,6 @@
"node": "*" "node": "*"
} }
}, },
"node_modules/hoek": {
"version": "6.1.3",
"resolved": "https://registry.npmjs.org/hoek/-/hoek-6.1.3.tgz",
"integrity": "sha512-YXXAAhmF9zpQbC7LEcREFtXfGq5K1fmd+4PHkBq8NUqmzW3G+Dq10bI/i0KucLRwss3YYFQ0fSfoxBZYiGUqtQ==",
"deprecated": "This module has moved and is now available at @hapi/hoek. Please update your dependencies as this version is no longer maintained an may contain bugs and security issues."
},
"node_modules/hookable": { "node_modules/hookable": {
"version": "5.5.3", "version": "5.5.3",
"resolved": "https://registry.npmjs.org/hookable/-/hookable-5.5.3.tgz", "resolved": "https://registry.npmjs.org/hookable/-/hookable-5.5.3.tgz",
@ -11356,7 +11147,6 @@
"version": "3.6.2", "version": "3.6.2",
"resolved": "https://registry.npmjs.org/prettier/-/prettier-3.6.2.tgz", "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.6.2.tgz",
"integrity": "sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ==", "integrity": "sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ==",
"dev": true,
"bin": { "bin": {
"prettier": "bin/prettier.cjs" "prettier": "bin/prettier.cjs"
}, },
@ -12226,9 +12016,9 @@
"peer": true "peer": true
}, },
"node_modules/sealious": { "node_modules/sealious": {
"version": "0.21.20", "version": "0.21.30",
"resolved": "https://registry.npmjs.org/sealious/-/sealious-0.21.20.tgz", "resolved": "https://registry.npmjs.org/sealious/-/sealious-0.21.30.tgz",
"integrity": "sha512-O4ac6jHkL3tP8UcN/3ybmOHMSo17IRaAFt5/FDixw+6upcQw8QeXuQgf7DR8gKdmNbNCiWLjqGoksw6GeQFWgg==", "integrity": "sha512-EWmqqFpDdgMvBmqAnaoX3FN2TmWdEgA1MgCUoQNB0iwUSl5m2Ghpd3W3eoM4H0Nr6bTr1ogJaOsAZJJFlIdc0Q==",
"dependencies": { "dependencies": {
"@koa/router": "^12.0.1", "@koa/router": "^12.0.1",
"@sealcode/file-manager": "^1.0.1", "@sealcode/file-manager": "^1.0.1",
@ -12250,12 +12040,12 @@
"@types/object-hash": "^1.3.3", "@types/object-hash": "^1.3.3",
"@types/sanitize-html": "^2.11.0", "@types/sanitize-html": "^2.11.0",
"@types/uuid": "^8.3.0", "@types/uuid": "^8.3.0",
"boom": "^7.3.0",
"chalk": "^4.1.0", "chalk": "^4.1.0",
"clone": "^1.0.2", "clone": "^1.0.2",
"color": "latest", "color": "latest",
"color-hash": "^1.0.3", "color-hash": "^1.0.3",
"commonmark": "^0.31.0", "commonmark": "^0.31.0",
"country-codes-list": "^2.0.0",
"cron": "^2.1.0", "cron": "^2.1.0",
"csv-stringify": "^6.4.5", "csv-stringify": "^6.4.5",
"deepmerge": "^4.2.2", "deepmerge": "^4.2.2",
@ -16081,89 +15871,6 @@
"ansi_up": "^5.0.1" "ansi_up": "^5.0.1"
} }
}, },
"@sealcode/crud-ui": {
"version": "0.0.18",
"resolved": "https://registry.npmjs.org/@sealcode/crud-ui/-/crud-ui-0.0.18.tgz",
"integrity": "sha512-brzQxDpqMe11C+d794izJabrSqxUGv5BzMKY3wMJiuHD1K0WJD09Vkg35GWwRD7RdfXFt7uncSswqyYMBlKDAg==",
"requires": {
"@koa/router": "^13.1.0",
"@sealcode/sealgen": "^0.18.5",
"@types/koa__router": "^12.0.4",
"escape-goat": "^4.0.0",
"qs": "^6.13.0",
"tempstream": "^0.4.5"
},
"dependencies": {
"@koa/router": {
"version": "13.1.1",
"resolved": "https://registry.npmjs.org/@koa/router/-/router-13.1.1.tgz",
"integrity": "sha512-JQEuMANYRVHs7lm7KY9PCIjkgJk73h4m4J+g2mkw2Vo1ugPZ17UJVqEH8F+HeAdjKz5do1OaLe7ArDz+z308gw==",
"requires": {
"debug": "^4.4.1",
"http-errors": "^2.0.0",
"koa-compose": "^4.1.0",
"path-to-regexp": "^6.3.0"
}
},
"@sealcode/sealgen": {
"version": "0.18.10",
"resolved": "https://registry.npmjs.org/@sealcode/sealgen/-/sealgen-0.18.10.tgz",
"integrity": "sha512-Q+Wkeq01TFHXPM+LoRMbe9fqakSqgJnJxmjsw9Jzhm3dKBchTfj8BvRd1XWERWZZizCWmzkshLNoVx0kjyZ7rA==",
"requires": {
"@koa/router": "^12.0.1",
"@sealcode/file-manager": "^1.0.2",
"@sealcode/ts-predicates": "^0.4.3",
"chokidar": "^3.6.0",
"colord": "^2.9.3",
"deepmerge": "^4.3.1",
"esbuild": "^0.20.0",
"escape-goat": "^4.0.0",
"fonsta": "^1.1.1",
"google-fonts-helper": "^3.4.1",
"husky": "^9.1.7",
"is-what": "^4.1.16",
"js-convert-case": "^4.2.0",
"json5": "^2.2.3",
"locreq": "^3.0.0",
"md5": "^2.3.0",
"merge": "^2.1.1",
"prettier": "^2.7.1",
"prompts": "^2.4.2",
"recursive-readdir": "^2.2.3",
"tempfile": "^5.0.0",
"tempstream": "^0.4.6",
"tiny-glob": "^0.2.9",
"wcag-contrast": "^3.0.0",
"ws": "^8.16.0",
"yargs": "^17.6.2"
},
"dependencies": {
"@koa/router": {
"version": "12.0.2",
"resolved": "https://registry.npmjs.org/@koa/router/-/router-12.0.2.tgz",
"integrity": "sha512-sYcHglGKTxGF+hQ6x67xDfkE9o+NhVlRHBqq6gLywaMc6CojK/5vFZByphdonKinYlMLkEkacm+HEse9HzwgTA==",
"requires": {
"debug": "^4.3.4",
"http-errors": "^2.0.0",
"koa-compose": "^4.1.0",
"methods": "^1.1.2",
"path-to-regexp": "^6.3.0"
}
}
}
},
"@sealcode/ts-predicates": {
"version": "0.4.3",
"resolved": "https://registry.npmjs.org/@sealcode/ts-predicates/-/ts-predicates-0.4.3.tgz",
"integrity": "sha512-UNSEacu7Ye8q0N8AJCJy37oJvv3w2OXKGkUnP7xO5lOY9DQviDPRDQhVaZdJ3/xMzXLm4UE3389ihctrPaov/A=="
},
"prettier": {
"version": "2.8.8",
"resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz",
"integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q=="
}
}
},
"@sealcode/file-manager": { "@sealcode/file-manager": {
"version": "1.0.2", "version": "1.0.2",
"resolved": "https://registry.npmjs.org/@sealcode/file-manager/-/file-manager-1.0.2.tgz", "resolved": "https://registry.npmjs.org/@sealcode/file-manager/-/file-manager-1.0.2.tgz",
@ -16177,9 +15884,9 @@
} }
}, },
"@sealcode/jdd": { "@sealcode/jdd": {
"version": "0.8.0", "version": "0.8.1",
"resolved": "https://registry.npmjs.org/@sealcode/jdd/-/jdd-0.8.0.tgz", "resolved": "https://registry.npmjs.org/@sealcode/jdd/-/jdd-0.8.1.tgz",
"integrity": "sha512-0esGO0j922FK3rYs+OmWbp0SWAQWkPaidNzvrq2dyaj0SyPU7B0vZZOYjzboICyvqBkMZWbf+YXNK/zzYs18EA==", "integrity": "sha512-UnFS+6q7808kK9NsyagNW/rap9BLkOe60OYM3VeZZd68NvP5SWLQSDvMMrf7IIM50VKDnUx0xf0qLX/9e+IBdA==",
"requires": { "requires": {
"@sealcode/file-manager": "^1.0.2", "@sealcode/file-manager": "^1.0.2",
"@sealcode/ts-predicates": "^0.5.3", "@sealcode/ts-predicates": "^0.5.3",
@ -16209,14 +15916,14 @@
} }
}, },
"@sealcode/jdd-editor": { "@sealcode/jdd-editor": {
"version": "0.2.1", "version": "0.2.4",
"resolved": "https://registry.npmjs.org/@sealcode/jdd-editor/-/jdd-editor-0.2.1.tgz", "resolved": "https://registry.npmjs.org/@sealcode/jdd-editor/-/jdd-editor-0.2.4.tgz",
"integrity": "sha512-6JrUtIaBHqB6/gLHE0dXk83zohHz8X0hrT8DtdMTGt5ZDNlXylqkCWwXC4GVV0C6eLsP1ue6fKRo0oYjoiptsQ==", "integrity": "sha512-Fwp/kb3ViRR+XawMUI1sc9LAOzyjVevHa4MFI4xTzZDvQZCPyaDUoPe20yCoF5BKNqVw4GbkAXG4idJfJ0shyA==",
"requires": { "requires": {
"@koa/router": "^13.1.0", "@koa/router": "^13.1.0",
"@sealcode/jdd": "^0.8.0", "@sealcode/jdd": "^0.8.1",
"@sealcode/sealcodemirror": "^5.70.0-beta5", "@sealcode/sealcodemirror": "^5.70.0-beta5",
"@sealcode/sealgen": "^0.18", "@sealcode/sealgen": "^0.19.6",
"@types/object-path": "^0.11.4", "@types/object-path": "^0.11.4",
"@types/throttle-debounce": "^5.0.2", "@types/throttle-debounce": "^5.0.2",
"@types/turndown": "^5.0.5", "@types/turndown": "^5.0.5",
@ -16238,63 +15945,6 @@
"koa-compose": "^4.1.0", "koa-compose": "^4.1.0",
"path-to-regexp": "^6.3.0" "path-to-regexp": "^6.3.0"
} }
},
"@sealcode/sealgen": {
"version": "0.18.10",
"resolved": "https://registry.npmjs.org/@sealcode/sealgen/-/sealgen-0.18.10.tgz",
"integrity": "sha512-Q+Wkeq01TFHXPM+LoRMbe9fqakSqgJnJxmjsw9Jzhm3dKBchTfj8BvRd1XWERWZZizCWmzkshLNoVx0kjyZ7rA==",
"requires": {
"@koa/router": "^12.0.1",
"@sealcode/file-manager": "^1.0.2",
"@sealcode/ts-predicates": "^0.4.3",
"chokidar": "^3.6.0",
"colord": "^2.9.3",
"deepmerge": "^4.3.1",
"esbuild": "^0.20.0",
"escape-goat": "^4.0.0",
"fonsta": "^1.1.1",
"google-fonts-helper": "^3.4.1",
"husky": "^9.1.7",
"is-what": "^4.1.16",
"js-convert-case": "^4.2.0",
"json5": "^2.2.3",
"locreq": "^3.0.0",
"md5": "^2.3.0",
"merge": "^2.1.1",
"prettier": "^2.7.1",
"prompts": "^2.4.2",
"recursive-readdir": "^2.2.3",
"tempfile": "^5.0.0",
"tempstream": "^0.4.6",
"tiny-glob": "^0.2.9",
"wcag-contrast": "^3.0.0",
"ws": "^8.16.0",
"yargs": "^17.6.2"
},
"dependencies": {
"@koa/router": {
"version": "12.0.2",
"resolved": "https://registry.npmjs.org/@koa/router/-/router-12.0.2.tgz",
"integrity": "sha512-sYcHglGKTxGF+hQ6x67xDfkE9o+NhVlRHBqq6gLywaMc6CojK/5vFZByphdonKinYlMLkEkacm+HEse9HzwgTA==",
"requires": {
"debug": "^4.3.4",
"http-errors": "^2.0.0",
"koa-compose": "^4.1.0",
"methods": "^1.1.2",
"path-to-regexp": "^6.3.0"
}
}
}
},
"@sealcode/ts-predicates": {
"version": "0.4.3",
"resolved": "https://registry.npmjs.org/@sealcode/ts-predicates/-/ts-predicates-0.4.3.tgz",
"integrity": "sha512-UNSEacu7Ye8q0N8AJCJy37oJvv3w2OXKGkUnP7xO5lOY9DQviDPRDQhVaZdJ3/xMzXLm4UE3389ihctrPaov/A=="
},
"prettier": {
"version": "2.8.8",
"resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz",
"integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q=="
} }
} }
}, },
@ -16304,15 +15954,16 @@
"integrity": "sha512-pDsGlk2KokQkwzsJDBUWJFDRpEoxxth6TMQGDJyCTmWnd1Vn+cQb5moXDKaf7cXnWb9Y6QtdNX/fPzM/3RH2Cg==" "integrity": "sha512-pDsGlk2KokQkwzsJDBUWJFDRpEoxxth6TMQGDJyCTmWnd1Vn+cQb5moXDKaf7cXnWb9Y6QtdNX/fPzM/3RH2Cg=="
}, },
"@sealcode/sealgen": { "@sealcode/sealgen": {
"version": "0.19.0", "version": "0.19.6",
"resolved": "https://registry.npmjs.org/@sealcode/sealgen/-/sealgen-0.19.0.tgz", "resolved": "https://registry.npmjs.org/@sealcode/sealgen/-/sealgen-0.19.6.tgz",
"integrity": "sha512-fnHg/1b+w4E0G4VUSk+Qh+rsHneh1F9LSXZBnQW3fF1+WdSUWgeaVMqUPpN6CXNmze1k7dMWQIjdXAS/AYgpFA==", "integrity": "sha512-dUccXEGSTlZrkrzkta2cObQUDBzbTrfYLZkbZer6E9nyYKB/7Jbj03R+C3wGxfwvrsewGfHiar+v8JHjOiguyQ==",
"requires": { "requires": {
"@koa/router": "^12.0.1", "@koa/router": "^12.0.1",
"@sealcode/file-manager": "^1.0.2", "@sealcode/file-manager": "^1.0.2",
"@sealcode/ts-predicates": "^0.4.3", "@sealcode/ts-predicates": "^0.4.3",
"chokidar": "^3.6.0", "chokidar": "^3.6.0",
"colord": "^2.9.3", "colord": "^2.9.3",
"country-codes-list": "^2.0.0",
"deepmerge": "^4.3.1", "deepmerge": "^4.3.1",
"esbuild": "^0.20.0", "esbuild": "^0.20.0",
"escape-goat": "^4.0.0", "escape-goat": "^4.0.0",
@ -16325,7 +15976,7 @@
"locreq": "^3.0.0", "locreq": "^3.0.0",
"md5": "^2.3.0", "md5": "^2.3.0",
"merge": "^2.1.1", "merge": "^2.1.1",
"prettier": "^2.7.1", "prettier": "^3.6.2",
"prompts": "^2.4.2", "prompts": "^2.4.2",
"recursive-readdir": "^2.2.3", "recursive-readdir": "^2.2.3",
"tempfile": "^5.0.0", "tempfile": "^5.0.0",
@ -16340,11 +15991,6 @@
"version": "0.4.3", "version": "0.4.3",
"resolved": "https://registry.npmjs.org/@sealcode/ts-predicates/-/ts-predicates-0.4.3.tgz", "resolved": "https://registry.npmjs.org/@sealcode/ts-predicates/-/ts-predicates-0.4.3.tgz",
"integrity": "sha512-UNSEacu7Ye8q0N8AJCJy37oJvv3w2OXKGkUnP7xO5lOY9DQviDPRDQhVaZdJ3/xMzXLm4UE3389ihctrPaov/A==" "integrity": "sha512-UNSEacu7Ye8q0N8AJCJy37oJvv3w2OXKGkUnP7xO5lOY9DQviDPRDQhVaZdJ3/xMzXLm4UE3389ihctrPaov/A=="
},
"prettier": {
"version": "2.8.8",
"resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz",
"integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q=="
} }
} }
}, },
@ -16653,6 +16299,7 @@
"version": "12.0.4", "version": "12.0.4",
"resolved": "https://registry.npmjs.org/@types/koa__router/-/koa__router-12.0.4.tgz", "resolved": "https://registry.npmjs.org/@types/koa__router/-/koa__router-12.0.4.tgz",
"integrity": "sha512-Y7YBbSmfXZpa/m5UGGzb7XadJIRBRnwNY9cdAojZGp65Cpe5MAP3mOZE7e3bImt8dfKS4UFcR16SLH8L/z7PBw==", "integrity": "sha512-Y7YBbSmfXZpa/m5UGGzb7XadJIRBRnwNY9cdAojZGp65Cpe5MAP3mOZE7e3bImt8dfKS4UFcR16SLH8L/z7PBw==",
"dev": true,
"requires": { "requires": {
"@types/koa": "*" "@types/koa": "*"
} }
@ -17557,14 +17204,6 @@
"resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz",
"integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==" "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww=="
}, },
"boom": {
"version": "7.3.0",
"resolved": "https://registry.npmjs.org/boom/-/boom-7.3.0.tgz",
"integrity": "sha512-Swpoyi2t5+GhOEGw8rEsKvTxFLIDiiKoUc2gsoV6Lyr43LHBIzch3k2MvYUs8RTROrIkVJ3Al0TkaOGjnb+B6A==",
"requires": {
"hoek": "6.x.x"
}
},
"brace-expansion": { "brace-expansion": {
"version": "2.0.2", "version": "2.0.2",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz",
@ -18148,6 +17787,11 @@
"parse-json": "^5.2.0" "parse-json": "^5.2.0"
} }
}, },
"country-codes-list": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/country-codes-list/-/country-codes-list-2.0.0.tgz",
"integrity": "sha512-KZqq/LBdCD76hQCa6nOx0bA/nIjYly1OtV8+Bbt/4SW+mJEqGk7oZHjUj7PRrV0gXJJKs6Tv2cIntFdofBByvA=="
},
"create-error-class": { "create-error-class": {
"version": "3.0.2", "version": "3.0.2",
"resolved": "https://registry.npmjs.org/create-error-class/-/create-error-class-3.0.2.tgz", "resolved": "https://registry.npmjs.org/create-error-class/-/create-error-class-3.0.2.tgz",
@ -20358,11 +20002,6 @@
"resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-10.7.3.tgz", "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-10.7.3.tgz",
"integrity": "sha512-tzcUFauisWKNHaRkN4Wjl/ZA07gENAjFl3J/c480dprkGTg5EQstgaNFqBfUqCq54kZRIEcreTsAgF/m2quD7A==" "integrity": "sha512-tzcUFauisWKNHaRkN4Wjl/ZA07gENAjFl3J/c480dprkGTg5EQstgaNFqBfUqCq54kZRIEcreTsAgF/m2quD7A=="
}, },
"hoek": {
"version": "6.1.3",
"resolved": "https://registry.npmjs.org/hoek/-/hoek-6.1.3.tgz",
"integrity": "sha512-YXXAAhmF9zpQbC7LEcREFtXfGq5K1fmd+4PHkBq8NUqmzW3G+Dq10bI/i0KucLRwss3YYFQ0fSfoxBZYiGUqtQ=="
},
"hookable": { "hookable": {
"version": "5.5.3", "version": "5.5.3",
"resolved": "https://registry.npmjs.org/hookable/-/hookable-5.5.3.tgz", "resolved": "https://registry.npmjs.org/hookable/-/hookable-5.5.3.tgz",
@ -23607,8 +23246,7 @@
"prettier": { "prettier": {
"version": "3.6.2", "version": "3.6.2",
"resolved": "https://registry.npmjs.org/prettier/-/prettier-3.6.2.tgz", "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.6.2.tgz",
"integrity": "sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ==", "integrity": "sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ=="
"dev": true
}, },
"prettier-linter-helpers": { "prettier-linter-helpers": {
"version": "1.0.0", "version": "1.0.0",
@ -24243,9 +23881,9 @@
} }
}, },
"sealious": { "sealious": {
"version": "0.21.20", "version": "0.21.30",
"resolved": "https://registry.npmjs.org/sealious/-/sealious-0.21.20.tgz", "resolved": "https://registry.npmjs.org/sealious/-/sealious-0.21.30.tgz",
"integrity": "sha512-O4ac6jHkL3tP8UcN/3ybmOHMSo17IRaAFt5/FDixw+6upcQw8QeXuQgf7DR8gKdmNbNCiWLjqGoksw6GeQFWgg==", "integrity": "sha512-EWmqqFpDdgMvBmqAnaoX3FN2TmWdEgA1MgCUoQNB0iwUSl5m2Ghpd3W3eoM4H0Nr6bTr1ogJaOsAZJJFlIdc0Q==",
"requires": { "requires": {
"@koa/router": "^12.0.1", "@koa/router": "^12.0.1",
"@sealcode/file-manager": "^1.0.1", "@sealcode/file-manager": "^1.0.1",
@ -24267,12 +23905,12 @@
"@types/object-hash": "^1.3.3", "@types/object-hash": "^1.3.3",
"@types/sanitize-html": "^2.11.0", "@types/sanitize-html": "^2.11.0",
"@types/uuid": "^8.3.0", "@types/uuid": "^8.3.0",
"boom": "^7.3.0",
"chalk": "^4.1.0", "chalk": "^4.1.0",
"clone": "^1.0.2", "clone": "^1.0.2",
"color": "latest", "color": "latest",
"color-hash": "^1.0.3", "color-hash": "^1.0.3",
"commonmark": "^0.31.0", "commonmark": "^0.31.0",
"country-codes-list": "^2.0.0",
"cron": "^2.1.0", "cron": "^2.1.0",
"csv-stringify": "^6.4.5", "csv-stringify": "^6.4.5",
"deepmerge": "^4.2.2", "deepmerge": "^4.2.2",

View File

@ -20,7 +20,7 @@
"test:ui": "npm run test -- --ui", "test:ui": "npm run test -- --ui",
"test-ci": "TESTS_RUN_IN_DOCKER=true PW_TEST_CONNECT_WS_ENDPOINT=ws://playwright:3000/ npx playwright test", "test-ci": "TESTS_RUN_IN_DOCKER=true PW_TEST_CONNECT_WS_ENDPOINT=ws://playwright:3000/ npx playwright test",
"prepare": "husky", "prepare": "husky",
"lint-css": "stylelint \"**/*.css\" --config ./.stylelintrc.json", "lint-css": "stylelint \"src/**/*.css\" --config ./.stylelintrc.json",
"lint-css-fix": "npm run lint-css -- --fix", "lint-css-fix": "npm run lint-css -- --fix",
"lint-css-report": "npm run --silent lint-css -- --formatter json --output-file .stylelint-result.json", "lint-css-report": "npm run --silent lint-css -- --formatter json --output-file .stylelint-result.json",
"lint-js": "eslint src", "lint-js": "eslint src",
@ -86,11 +86,10 @@
"@hotwired/turbo": "^8.0.2", "@hotwired/turbo": "^8.0.2",
"@koa/router": "^12.0.1", "@koa/router": "^12.0.1",
"@sealcode/add-to-head": "^1.0.0", "@sealcode/add-to-head": "^1.0.0",
"@sealcode/crud-ui": "^0.0.18",
"@sealcode/file-manager": "^1.0.2", "@sealcode/file-manager": "^1.0.2",
"@sealcode/jdd": "^0.8.0", "@sealcode/jdd": "^0.8.1",
"@sealcode/jdd-editor": "^0.2.1", "@sealcode/jdd-editor": "^0.2.4",
"@sealcode/sealgen": "^0.19.0", "@sealcode/sealgen": "^0.19.6",
"@sealcode/simplemde": "^1.12.1", "@sealcode/simplemde": "^1.12.1",
"@sealcode/sortable": "^0.0.1", "@sealcode/sortable": "^0.0.1",
"@sealcode/ts-predicates": "^0.6.2", "@sealcode/ts-predicates": "^0.6.2",
@ -117,7 +116,7 @@
"nyc": "^17.1.0", "nyc": "^17.1.0",
"object-path": "^0.11.8", "object-path": "^0.11.8",
"qs": "^6.12.0", "qs": "^6.12.0",
"sealious": "^0.21.20", "sealious": "^0.21.30",
"slug": "^9.1.0", "slug": "^9.1.0",
"stimulus": "^3.2.2", "stimulus": "^3.2.2",
"tempstream": "^0.4.6", "tempstream": "^0.4.6",

View File

@ -16,14 +16,14 @@ export default async function PasswordResetTemplate(
const username = matching_users.items[0]?.get("username"); const username = matching_users.items[0]?.get("username");
const context = new app.Context();
return EmailTemplates.Simple(app, { return EmailTemplates.Simple(app, {
subject: app.i18n("password_reset_email_subject", [app.manifest.name]), subject: context.i18n`[${app.manifest.name}] Password reset request`,
to: `${String(username)}<${email_address}>`, to: `${String(username)}<${email_address}>`,
text: ` text: `Hello, ${username}. Someone requested a password reset on your account on ${app.manifest.name}. If it was you, use the link below to change the password. Otherwise, ignore this message.`,
${app.i18n("password_reset_email_text", [app.manifest.name, username])}`,
buttons: [ buttons: [
{ {
text: app.i18n("password_reset_cta"), text: context.i18n`Change password`,
href: `${app.manifest.base_url}/confirm-password-reset?token=${token}&email=${email_address}`, href: `${app.manifest.base_url}/confirm-password-reset?token=${token}&email=${email_address}`,
}, },
], ],

View File

@ -5,14 +5,14 @@ export default async function RegistrationIntentTemplate(
app: App, app: App,
{ email_address, token }: { email_address: string; token: string } { email_address, token }: { email_address: string; token: string }
) { ) {
const context = new app.Context();
return EmailTemplates.Simple(app, { return EmailTemplates.Simple(app, {
subject: app.i18n("registration_intent_email_subject", [app.manifest.name]), subject: context.i18n`Finish creating your ${app.manifest.name} account`,
to: email_address, to: email_address,
text: ` text: `To finish setting up your account, click the following link:`,
${app.i18n("registration_intent_email_text", [app.manifest.name])}`,
buttons: [ buttons: [
{ {
text: app.i18n("registration_intent_cta"), text: context.i18n`To finish setting up your account, click the following link:`,
href: `${app.manifest.base_url}/account/confirm-registration-email?token=${token}&email=${email_address}`, href: `${app.manifest.base_url}/account/confirm-registration-email?token=${token}&email=${email_address}`,
}, },
], ],

View File

@ -37,18 +37,16 @@ export class Roles extends Policy {
async checkerFunction(context: Context) { async checkerFunction(context: Context) {
if (context.user_id === null) { if (context.user_id === null) {
return Policy.deny(context.app.i18n("policy_logged_in_deny")); return Policy.deny(context.i18n`You are not logged in`);
} }
const matching_roles_count = await this.countMatchingRoles(context); const matching_roles_count = await this.countMatchingRoles(context);
return matching_roles_count > 0 return matching_roles_count > 0
? Policy.allow( ? Policy.allow(
context.app.i18n("policy_roles_allow", [ context.i18n`You are assigned to one of these roles: ${this.allowed_roles.join(", ")}`
this.allowed_roles.join(", "),
])
) )
: Policy.deny( : Policy.deny(
context.app.i18n("policy_roles_deny", [this.allowed_roles.join(", ")]) context.i18n`You are not assigned to one of these roles: ${this.allowed_roles.join(", ")}`
); );
} }
} }

View File

@ -215,6 +215,11 @@
padding: 8px; padding: 8px;
flex-grow: 1; flex-grow: 1;
background-color: var(--color-brand-canvas); background-color: var(--color-brand-canvas);
&[disabled] {
background-color: var(--color-brand-canvas-09);
cursor: not-allowed;
}
} }
} }

View File

@ -20,9 +20,12 @@ export const NavbarLinksCRUDEditShape = fieldsToShape(fields);
export default new (class NavbarLinksCRUDEditForm extends Form<typeof fields, void> { export default new (class NavbarLinksCRUDEditForm extends Form<typeof fields, void> {
defaultSuccessMessage = "Formularz wypełniony poprawnie"; defaultSuccessMessage = "Formularz wypełniony poprawnie";
fields = fields; getFields = () => fields;
controls = [new Controls.FormHeader("Edit NavbarLinks"), ...NavbarLinksFormControls]; getControls = () => [
new Controls.FormHeader("Edit NavbarLinks"),
...NavbarLinksFormControls,
];
async getID(ctx: Context): Promise<string> { async getID(ctx: Context): Promise<string> {
// trying to automatically guess which param is the one that represents the ID // trying to automatically guess which param is the one that represents the ID

View File

@ -21,9 +21,9 @@ export const NavbarLinksCRUDCreateShape = fieldsToShape(fields);
export default new (class NavbarLinksCRUDCreateForm extends Form<typeof fields, void> { export default new (class NavbarLinksCRUDCreateForm extends Form<typeof fields, void> {
defaultSuccessMessage = "Formularz wypełniony poprawnie"; defaultSuccessMessage = "Formularz wypełniony poprawnie";
fields = fields; getFields = () => fields;
controls = [ getControls = () => [
new Controls.FormHeader("Create NavbarLinks"), new Controls.FormHeader("Create NavbarLinks"),
...NavbarLinksFormControls, ...NavbarLinksFormControls,
]; ];

View File

@ -20,9 +20,9 @@ export const PagesCRUDEditShape = fieldsToShape(fields);
export default new (class PagesCRUDEditForm extends Form<typeof fields, void> { export default new (class PagesCRUDEditForm extends Form<typeof fields, void> {
defaultSuccessMessage = "Formularz wypełniony poprawnie"; defaultSuccessMessage = "Formularz wypełniony poprawnie";
fields = fields; getFields = () => fields;
controls = [new Controls.FormHeader("Edit Pages"), ...PagesFormControls]; getControls = () => [new Controls.FormHeader("Edit Pages"), ...PagesFormControls];
async getID(ctx: Context): Promise<string> { async getID(ctx: Context): Promise<string> {
const param_name = "id"; const param_name = "id";

View File

@ -21,9 +21,9 @@ export const PagesCRUDCreateShape = fieldsToShape(fields);
export default new (class PagesCRUDCreateForm extends Form<typeof fields, void> { export default new (class PagesCRUDCreateForm extends Form<typeof fields, void> {
defaultSuccessMessage = "Formularz wypełniony poprawnie"; defaultSuccessMessage = "Formularz wypełniony poprawnie";
fields = fields; getFields = () => fields;
controls = [new Controls.FormHeader("Create Pages"), ...PagesFormControls]; getControls = () => [new Controls.FormHeader("Create Pages"), ...PagesFormControls];
async onSubmit(ctx: Context) { async onSubmit(ctx: Context) {
const data = await this.getParsedValues(ctx); const data = await this.getParsedValues(ctx);

View File

@ -16,9 +16,9 @@ export const ResetPasswordShape = fieldsToShape(fields);
export default new (class ResetPasswordForm extends Form<typeof fields, void> { export default new (class ResetPasswordForm extends Form<typeof fields, void> {
defaultSuccessMessage = "Formularz wypełniony poprawnie"; defaultSuccessMessage = "Formularz wypełniony poprawnie";
fields = fields; getFields = () => fields;
controls = [ getControls = () => [
new Controls.HTML("decoration", /* HTML */ `<h1>Change password</h1>`), new Controls.HTML("decoration", /* HTML */ `<h1>Change password</h1>`),
fields.password.getControl(), fields.password.getControl(),
]; ];

View File

@ -19,9 +19,9 @@ export const LoginShape = fieldsToShape(fields);
export default new (class LoginForm extends Form<typeof fields, void> { export default new (class LoginForm extends Form<typeof fields, void> {
defaultSuccessMessage = "Logged in"; defaultSuccessMessage = "Logged in";
fields = fields; getFields = () => fields;
controls = [ getControls = () => [
new Controls.FormHeader(`Log in`), new Controls.FormHeader(`Log in`),
new Controls.SimpleInput(fields.username, { new Controls.SimpleInput(fields.username, {
label: "Username:", label: "Username:",

View File

@ -22,9 +22,9 @@ export const SignInShape = fieldsToShape(fields);
export default new (class SignInForm extends Form<typeof fields, void> { export default new (class SignInForm extends Form<typeof fields, void> {
defaultSuccessMessage = "Formularz wypełniony poprawnie"; defaultSuccessMessage = "Formularz wypełniony poprawnie";
fields = fields; getFields = () => fields;
controls = [ getControls = () => [
new Controls.SimpleInput(fields.username, { label: "Username:", type: "text" }), new Controls.SimpleInput(fields.username, { label: "Username:", type: "text" }),
new Controls.SimpleInput(fields.password, { new Controls.SimpleInput(fields.password, {
label: "Password:", label: "Password:",

View File

@ -16,20 +16,16 @@ th {
} }
thead th { thead th {
background-color: #ddd; background-color: var(--color-brand-text-bg-08);
border-style: solid; border-style: solid;
border-width: 1px 0; border-width: 1px 0;
border-color: #777; border-color: var(--color-brand-text-bg-04);
padding: 9px 7px; padding: 9px 7px;
font-size: 14px; font-size: 14px;
} }
tr {
transition: background-color 100ms;
}
tr:hover { tr:hover {
background-color: #ccc !important; background-color: var(--color-brand-text-bg-07) !important;
} }
td { td {

View File

@ -7,11 +7,64 @@ import * as dgram from "dgram";
import * as http from "http"; import * as http from "http";
import * as fs from "fs/promises"; import * as fs from "fs/promises";
import { MongoClient } from "mongodb"; import { MongoClient } from "mongodb";
import { MONGO_PORT, MONGO_HOST } from "../src/back/config.js"; import {
MONGO_PORT,
MONGO_HOST,
MAILCATCHER_API_PORT,
MAILCATCHER_SMTP_PORT,
} from "../src/back/config.js";
export class MailcatcherMessage {
id: number;
sender: string;
recipients: string[];
subject: string;
size: string;
created_at: string;
constructor({
id,
sender,
recipients,
subject,
size,
created_at,
}: {
id: number;
sender: string;
recipients: string[];
subject: string;
size: string;
created_at: string;
}) {
this.id = id;
this.sender = sender;
this.recipients = recipients;
this.subject = subject;
this.size = size;
this.created_at = created_at;
}
async getBody(format: "html" | "plain" | "source") {
return (await fetch(`${mailcatcher_url}/messages/${this.id}.${format}`)).text();
}
async getURLs(): Promise<string[]> {
const url_regex =
/https?:\/\/[a-z0-9.]+(:[0-9]+)\/[a-zA-Z0-9.\/!@#$%^&*()?\-=]+/g;
const body = await this.getBody("plain");
return Array.from(body.matchAll(url_regex)).map((e) => e[0]);
}
}
export type MailcatcherAPI = {
getLatestMessage: () => Promise<MailcatcherMessage>;
};
type TestFixtures = { type TestFixtures = {
backend: { url: string; env: Record<string, string> }; backend: { url: string; env: Record<string, string> };
setMarkdownValue: (field_name: string, value: string) => Promise<void>; setMarkdownValue: (field_name: string, value: string) => Promise<void>;
email: MailcatcherAPI;
}; };
const c8 = "./node_modules/c8/bin/c8.js"; const c8 = "./node_modules/c8/bin/c8.js";
@ -19,6 +72,8 @@ const app_host = process.env.TESTS_RUN_IN_DOCKER
? "test" // the docker name ? "test" // the docker name
: "172.17.0.1"; // ip to access localhost from within docker (playwright always runs in docker) : "172.17.0.1"; // ip to access localhost from within docker (playwright always runs in docker)
const mailcatcher_url = `http://${app_host}:${MAILCATCHER_API_PORT}`;
export async function waitForHttpPort({ export async function waitForHttpPort({
port, port,
host = app_host, host = app_host,
@ -100,7 +155,10 @@ export const test = base.extend<TestFixtures>({
...(process.env.TESTS_RUN_IN_DOCKER ...(process.env.TESTS_RUN_IN_DOCKER
? { MEILISEARCH_HOST: `http://meilisearch:7700` } ? { MEILISEARCH_HOST: `http://meilisearch:7700` }
: {}), : {}),
MAILCATCHER_HOST: app_host,
MAILCATCHER_SMTP_PORT: String(MAILCATCHER_SMTP_PORT),
SEALIOUS_KILLSWITCH_PORT: `${killswitch_port}`, SEALIOUS_KILLSWITCH_PORT: `${killswitch_port}`,
SEALIOUS_BASE_URL: `http://${app_host}:${port}`,
}; };
const backendProcess = spawn( const backendProcess = spawn(
@ -167,6 +225,19 @@ export const test = base.extend<TestFixtures>({
} }
}); });
}, },
email: ({}, use) => {
async function getLatestMessage() {
const all_messages = (await (
await fetch(`${mailcatcher_url}/messages`)
).json()) as Record<string, unknown>[];
return new MailcatcherMessage(all_messages.at(-1) as any);
}
async function getURLsFromLatestMessage() {}
return use({
getLatestMessage,
});
},
}); });
export { expect } from "@playwright/test"; export { expect } from "@playwright/test";