Add svelte as a view engine to swaf #33

Merged
ashpie merged 97 commits from svelte into develop 2021-11-09 19:31:22 +01:00
15 changed files with 2184 additions and 3123 deletions
Showing only changes of commit e7695b7027 - Show all commits

View File

@ -25,25 +25,23 @@
"release": "yarn build && yarn lint && yarn test && cd dist && yarn publish" "release": "yarn build && yarn lint && yarn test && cd dist && yarn publish"
}, },
"devDependencies": { "devDependencies": {
"@rollup/plugin-commonjs": "^18.0.0", "@rollup/plugin-commonjs": "^21.0.1",
"@rollup/plugin-node-resolve": "^11.2.0", "@rollup/plugin-node-resolve": "^13.0.6",
"@sveltejs/eslint-config": "sveltejs/eslint-config", "@sveltejs/eslint-config": "sveltejs/eslint-config",
"@tsconfig/svelte": "^1.0.10", "@tsconfig/svelte": "^2.0.1",
"@types/compression": "^1.7.0", "@types/compression": "^1.7.0",
"@types/config": "^0.0.38", "@types/config": "^0.0.40",
"@types/connect-flash": "^0.0.36", "@types/connect-flash": "^0.0.37",
"@types/cookie": "^0.4.0", "@types/cookie": "^0.4.0",
"@types/cookie-parser": "^1.4.2", "@types/cookie-parser": "^1.4.2",
"@types/express": "^4.17.6", "@types/express": "^4.17.6",
"@types/express-session": "^1.17.0", "@types/express-session": "^1.17.0",
"@types/feather-icons": "^4.7.0", "@types/feather-icons": "^4.7.0",
"@types/formidable": "^1.0.31", "@types/formidable": "^2.0.0",
"@types/geoip-lite": "^1.1.31", "@types/geoip-lite": "^1.1.31",
"@types/jest": "^26.0.4", "@types/jest": "^27.0.2",
"@types/mjml": "^4.0.4", "@types/mjml": "^4.0.4",
"@types/mysql": "^2.15.10", "@types/mysql": "^2.15.10",
"@types/nanoid": "^2.1.0",
"@types/node-fetch": "^2.5.7",
"@types/nodemailer": "^6.4.0", "@types/nodemailer": "^6.4.0",
"@types/nunjucks": "^3.1.3", "@types/nunjucks": "^3.1.3",
"@types/on-finished": "^2.3.1", "@types/on-finished": "^2.3.1",
@ -51,23 +49,23 @@
"@types/require-from-string": "^1.2.0", "@types/require-from-string": "^1.2.0",
"@types/supertest": "^2.0.10", "@types/supertest": "^2.0.10",
"@types/uuid": "^8.0.0", "@types/uuid": "^8.0.0",
"@types/ws": "^7.2.4", "@types/ws": "^8.2.0",
"@typescript-eslint/eslint-plugin": "^4.2.0", "@typescript-eslint/eslint-plugin": "^5.3.0",
"@typescript-eslint/parser": "^4.2.0", "@typescript-eslint/parser": "^5.3.0",
"chokidar": "^3.5.1", "chokidar": "^3.5.1",
"clear-module": "^4.1.1", "clear-module": "^4.1.1",
"concurrently": "^6.0.0", "concurrently": "^6.0.0",
"eslint": "^7.9.0", "eslint": "^8.2.0",
"eslint-plugin-import": "^2.22.1", "eslint-plugin-import": "^2.22.1",
"eslint-plugin-node": "^11.1.0", "eslint-plugin-node": "^11.1.0",
"eslint-plugin-simple-import-sort": "^7.0.0", "eslint-plugin-simple-import-sort": "^7.0.0",
"eslint-plugin-svelte3": "^3.1.2", "eslint-plugin-svelte3": "^3.1.2",
"feather-icons": "^4.28.0", "feather-icons": "^4.28.0",
"jest": "^26.1.0", "jest": "^27.3.1",
"jest-resolve": "^26.6.2", "jest-resolve": "^27.3.1",
"jest-ts-webcompat-resolver": "^1.0.0", "jest-ts-webcompat-resolver": "^1.0.0",
"maildev": "^1.1.0", "maildev": "^1.1.0",
"node-fetch": "^2.6.0", "node-fetch": "^3.0.0",
"nodemon": "^2.0.6", "nodemon": "^2.0.6",
"normalize.css": "^8.0.1", "normalize.css": "^8.0.1",
"require-from-string": "^2.0.2", "require-from-string": "^2.0.2",
@ -80,13 +78,13 @@
"sass": "^1.32.12", "sass": "^1.32.12",
"supertest": "^6.0.0", "supertest": "^6.0.0",
"svelte": "^3.35.0", "svelte": "^3.35.0",
"svelte-check": "^1.2.3", "svelte-check": "^2.2.8",
"svelte-preprocess": "4.6.9", "svelte-preprocess": "4.6.9",
"ts-jest": "^26.1.1", "ts-jest": "^27.0.7",
"typescript": "^4.0.2" "typescript": "^4.0.2"
}, },
"dependencies": { "dependencies": {
"argon2": "^0.27.0", "argon2": "^0.28.2",
"compression": "^1.7.4", "compression": "^1.7.4",
"config": "^3.3.1", "config": "^3.3.1",
"connect-flash": "^0.1.1", "connect-flash": "^0.1.1",
@ -94,7 +92,7 @@
"cookie-parser": "^1.4.5", "cookie-parser": "^1.4.5",
"express": "^4.17.1", "express": "^4.17.1",
"express-session": "^1.17.1", "express-session": "^1.17.1",
"formidable": "^1.2.2", "formidable": "^2.0.1",
"geoip-lite": "^1.4.2", "geoip-lite": "^1.4.2",
"mjml": "^4.6.2", "mjml": "^4.6.2",
"mysql": "^2.18.1", "mysql": "^2.18.1",
@ -103,9 +101,9 @@
"nunjucks": "^3.2.1", "nunjucks": "^3.2.1",
"on-finished": "^2.3.0", "on-finished": "^2.3.0",
"redis": "^3.0.2", "redis": "^3.0.2",
"ts-node": "^9.0.0", "ts-node": "^10.4.0",
"tslog": "^3.0.1", "tslog": "^3.0.1",
"uuid": "^8.0.0", "uuid": "^8.0.0",
"ws": "^7.2.3" "ws": "^8.2.3"
} }
} }

View File

@ -1,11 +1,11 @@
import {NextFunction, Request, Response} from "express"; import {NextFunction, Request, Response} from "express";
import Formidable from "formidable"; import IncomingForm from "formidable/Formidable.js";
import {FileError, ValidationBag} from "./db/Validator.js"; import {FileError, ValidationBag} from "./db/Validator.js";
import Middleware from "./Middleware.js"; import Middleware from "./Middleware.js";
export default abstract class FileUploadMiddleware extends Middleware { export default abstract class FileUploadMiddleware extends Middleware {
protected abstract makeForm(): Formidable; protected abstract makeForm(): IncomingForm;
protected abstract getDefaultField(): string; protected abstract getDefaultField(): string;
@ -23,7 +23,7 @@ export default abstract class FileUploadMiddleware extends Middleware {
resolve(); resolve();
}); });
}); });
} catch (e) { } catch (e: any) {
const bag = new ValidationBag(); const bag = new ValidationBag();
const fileError = new FileError(e); const fileError = new FileError(e);
fileError.thingName = this.getDefaultField(); fileError.thingName = this.getDefaultField();

View File

@ -58,14 +58,26 @@ export default class TestApp extends Application {
private readonly addr: string; private readonly addr: string;
private readonly port: number; private readonly port: number;
public constructor(version: string, addr: string, port: number, ignoreCommandLine: boolean = false) { public constructor(
version: string,
addr: string,
port: number,
ignoreCommandLine: boolean = false,
private readonly approvalMode: boolean,
) {
super(version, ignoreCommandLine); super(version, ignoreCommandLine);
this.addr = addr; this.addr = addr;
this.port = port; this.port = port;
} }
protected getMigrations(): MigrationType<Migration>[] { protected getMigrations(): MigrationType<Migration>[] {
return [...MIGRATIONS, AddApprovedFieldToUsersTableMigration]; const migrations = [...MIGRATIONS];
if (this.approvalMode) {
migrations.push(AddApprovedFieldToUsersTableMigration);
}
return migrations;
} }
protected async init(): Promise<void> { protected async init(): Promise<void> {

View File

@ -67,8 +67,8 @@ export async function listFilesRecursively(dir: string): Promise<string[]> {
export async function doesFileExist(file: string): Promise<boolean> { export async function doesFileExist(file: string): Promise<boolean> {
try { try {
await fs.stat(file); await fs.stat(file);
} catch (err) { } catch (err: any) {
if (err.code === 'ENOENT') { if (err?.code === 'ENOENT') {
return false; return false;
} else { } else {
throw err; throw err;

View File

@ -10,7 +10,7 @@
const setRoutes = Routing.R.setRoutes; const setRoutes = Routing.R.setRoutes;
const setPublicUrl = Routing.R.setPublicUrl; const setPublicUrl = Routing.R.setPublicUrl;
import * as stores from '/js/stores.js'; import * as stores from '/js/stores.js';
const localStore = stores.s.locals; const localStore = stores.l;
const localMap = %locals%; const localMap = %locals%;
localStore.set((key, args) => { localStore.set((key, args) => {

View File

@ -48,7 +48,7 @@ export default class MailComponent extends ApplicationComponent {
try { try {
await util.promisify(transporter.verify)(); await util.promisify(transporter.verify)();
this.transporter = transporter; this.transporter = transporter;
} catch (e) { } catch (e: any) {
throw new MailError('Connection to mail service unsuccessful.', e); throw new MailError('Connection to mail service unsuccessful.', e);
} }

View File

@ -3,7 +3,7 @@ import cookie from "cookie";
import cookieParser from "cookie-parser"; import cookieParser from "cookie-parser";
import {Express, Request} from "express"; import {Express, Request} from "express";
import {Session} from "express-session"; import {Session} from "express-session";
import WebSocket from "ws"; import {WebSocketServer} from "ws";
import Application from "../Application.js"; import Application from "../Application.js";
import ApplicationComponent from "../ApplicationComponent.js"; import ApplicationComponent from "../ApplicationComponent.js";
@ -14,7 +14,7 @@ import FrontendToolsComponent from "./FrontendToolsComponent.js";
import RedisComponent from "./RedisComponent.js"; import RedisComponent from "./RedisComponent.js";
export default class WebSocketServerComponent extends ApplicationComponent { export default class WebSocketServerComponent extends ApplicationComponent {
private wss?: WebSocket.Server; private wss?: WebSocketServer;
public async init(): Promise<void> { public async init(): Promise<void> {
const app = this.getApp(); const app = this.getApp();
@ -32,7 +32,7 @@ export default class WebSocketServerComponent extends ApplicationComponent {
const app = this.getApp(); const app = this.getApp();
const listeners: { [p: string]: WebSocketListener<Application> } = app.getWebSocketListeners(); const listeners: { [p: string]: WebSocketListener<Application> } = app.getWebSocketListeners();
this.wss = new WebSocket.Server({ this.wss = new WebSocketServer({
server: app.as(ExpressAppComponent).getServer(), server: app.as(ExpressAppComponent).getServer(),
}, () => { }, () => {
logger.info(`Websocket server started over webserver.`); logger.info(`Websocket server started over webserver.`);

View File

@ -183,7 +183,7 @@ export default class MysqlConnectionManager {
try { try {
const result = await query('SELECT id FROM migrations ORDER BY id DESC LIMIT 1'); const result = await query('SELECT id FROM migrations ORDER BY id DESC LIMIT 1');
currentVersion = Number(result.results[0]?.id); currentVersion = Number(result.results[0]?.id);
} catch (e) { } catch (e: any) {
if (e.code === 'ECONNREFUSED' || e.code !== 'ER_NO_SUCH_TABLE') { if (e.code === 'ECONNREFUSED' || e.code !== 'ER_NO_SUCH_TABLE') {
throw new Error('Cannot run migrations: ' + e.code); throw new Error('Cannot run migrations: ' + e.code);
} }

View File

@ -61,7 +61,7 @@ export default class Validator<V> {
if (result instanceof Promise) { if (result instanceof Promise) {
result = await result; result = await result;
} }
} catch (e) { } catch (e: any) {
throw new ServerError(`An error occurred while validating ${thingName} with value "${value}".`, e); throw new ServerError(`An error occurred while validating ${thingName} with value "${value}".`, e);
} }

View File

@ -17,7 +17,13 @@ import TestApp from "./TestApp.js";
const packageJson = JSON.parse((await fs.readFile('package.json')).toString()); const packageJson = JSON.parse((await fs.readFile('package.json')).toString());
const app = new TestApp(packageJson.version, config.get<string>('app.listen_addr'), config.get<number>('app.port')); const app = new TestApp(
packageJson.version,
config.get<string>('app.listen_addr'),
config.get<number>('app.port'),
false,
true,
);
await app.start(); await app.start();
})().catch(err => { })().catch(err => {
logger.error(err); logger.error(err);

View File

@ -8,7 +8,7 @@ export default class CreateMigrationsTable extends Migration {
public async shouldRun(currentVersion: number): Promise<boolean> { public async shouldRun(currentVersion: number): Promise<boolean> {
try { try {
await query('SELECT 1 FROM migrations LIMIT 1'); await query('SELECT 1 FROM migrations LIMIT 1');
} catch (e) { } catch (e: any) {
if (e.code !== 'ER_NO_SUCH_TABLE') { if (e.code !== 'ER_NO_SUCH_TABLE') {
return false; return false;
} }

View File

@ -25,7 +25,7 @@ useApp(async (addr, port) => {
await super.init(); await super.init();
} }
}('test', addr, port, true); }('test', addr, port, true, false);
}); });
describe('Test CSRF protection', () => { describe('Test CSRF protection', () => {

View File

@ -8,7 +8,7 @@ import {setupMailServer, teardownMailServer} from "./_mail_server.js";
export default function useApp<T extends TestApp>(appSupplier: AppSupplier<T>): () => T { export default function useApp<T extends TestApp>(appSupplier: AppSupplier<T>): () => T {
let app: T; let app: T;
beforeAll(async (done) => { beforeAll(async () => {
await MysqlConnectionManager.prepare(); await MysqlConnectionManager.prepare();
await MysqlConnectionManager.query('DROP DATABASE IF EXISTS ' + config.get<string>('mysql.database')); await MysqlConnectionManager.query('DROP DATABASE IF EXISTS ' + config.get<string>('mysql.database'));
await MysqlConnectionManager.endPool(); await MysqlConnectionManager.endPool();
@ -17,10 +17,9 @@ export default function useApp<T extends TestApp>(appSupplier: AppSupplier<T>):
app = await appSupplier('127.0.0.1', 8966); app = await appSupplier('127.0.0.1', 8966);
await app.start(); await app.start();
done();
}); });
afterAll(async (done) => { afterAll(async () => {
const errors = []; const errors = [];
try { try {
@ -36,7 +35,6 @@ export default function useApp<T extends TestApp>(appSupplier: AppSupplier<T>):
} }
if (errors.length > 0) throw errors; if (errors.length > 0) throw errors;
done();
}); });
return () => app; return () => app;

View File

@ -85,16 +85,12 @@ export function authAppProvider(withUsername: boolean = true, approvalMode: bool
} }
protected getMigrations(): MigrationType<Migration>[] { protected getMigrations(): MigrationType<Migration>[] {
let migrations = withUsername ? const migrations = withUsername ?
super.getMigrations() : super.getMigrations() :
super.getMigrations().filter(m => m !== AddNameToUsersMigration); super.getMigrations().filter(m => m !== AddNameToUsersMigration);
migrations = approvalMode ?
[...migrations, AddApprovedFieldToUsersTableMigration] :
migrations;
return migrations; return migrations;
} }
}('test', addr, port, true); }('test', addr, port, true, approvalMode);
}; };
} }

5199
yarn.lock

File diff suppressed because it is too large Load Diff