feat: Reinitialize frontend with SvelteKit and TypeScript

- Delete old Vite+Svelte frontend
- Initialize new SvelteKit project with TypeScript
- Configure Tailwind CSS v4 + DaisyUI
- Implement JWT authentication with auto-refresh
- Create login page with form validation (Zod)
- Add protected route guards
- Update Docker configuration for single-stage build
- Add E2E tests with Playwright (6/11 passing)
- Fix Svelte 5 reactivity with $state() runes

Known issues:
- 5 E2E tests failing (timing/async issues)
- Token refresh implementation needs debugging
- Validation error display timing
This commit is contained in:
2026-02-17 16:19:59 -05:00
parent 54df6018f5
commit de2d83092e
28274 changed files with 3816354 additions and 90 deletions

View File

@@ -0,0 +1,72 @@
import HTMLElement from '../html-element/HTMLElement.js';
import * as PropertySymbol from '../../PropertySymbol.js';
import DocumentFragment from '../document-fragment/DocumentFragment.js';
import Node from '../node/Node.js';
import ShadowRoot from '../shadow-root/ShadowRoot.js';
/**
* HTML Template Element.
*
* Reference:
* https://developer.mozilla.org/en-US/docs/Web/API/HTMLTemplateElement.
*/
export default class HTMLTemplateElement extends HTMLElement {
cloneNode: (deep?: boolean) => HTMLTemplateElement;
[PropertySymbol.content]: DocumentFragment;
/**
* Returns content.
*
* @returns Content.
*/
get content(): DocumentFragment;
/**
* @override
*/
get innerHTML(): string;
/**
* @override
*/
set innerHTML(html: string);
/**
* @override
*/
get firstChild(): Node;
/**
* @override
*/
get lastChild(): Node;
/**
* @deprecated
* @override
*/
getInnerHTML(_options?: {
includeShadowRoots?: boolean;
}): string;
/**
* @override
*/
getHTML(_options?: {
serializableShadowRoots?: boolean;
shadowRoots?: ShadowRoot[];
}): string;
/**
* @override
*/
[PropertySymbol.appendChild](node: Node, disableValidations?: boolean): Node;
/**
* @override
*/
[PropertySymbol.removeChild](node: Node): Node;
/**
* @override
*/
[PropertySymbol.insertBefore](newNode: Node, referenceNode: Node, disableValidations?: boolean): Node;
/**
* @override
*/
[PropertySymbol.replaceChild](newChild: Node, oldChild: Node): Node;
/**
* @override
*/
[PropertySymbol.cloneNode](deep?: boolean): HTMLTemplateElement;
}
//# sourceMappingURL=HTMLTemplateElement.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"HTMLTemplateElement.d.ts","sourceRoot":"","sources":["../../../src/nodes/html-template-element/HTMLTemplateElement.ts"],"names":[],"mappings":"AAAA,OAAO,WAAW,MAAM,gCAAgC,CAAC;AACzD,OAAO,KAAK,cAAc,MAAM,yBAAyB,CAAC;AAC1D,OAAO,gBAAgB,MAAM,0CAA0C,CAAC;AACxE,OAAO,IAAI,MAAM,iBAAiB,CAAC;AACnC,OAAO,UAAU,MAAM,8BAA8B,CAAC;AAItD;;;;;GAKG;AACH,MAAM,CAAC,OAAO,OAAO,mBAAoB,SAAQ,WAAW;IAE5C,SAAS,EAAE,CAAC,IAAI,CAAC,EAAE,OAAO,KAAK,mBAAmB,CAAC;IAG3D,CAAC,cAAc,CAAC,OAAO,CAAC,EAAE,gBAAgB,CACY;IAE7D;;;;OAIG;IACH,IAAW,OAAO,IAAI,gBAAgB,CAErC;IAED;;OAEG;IACH,IAAoB,SAAS,IAAI,MAAM,CAEtC;IAED;;OAEG;IACH,IAAoB,SAAS,CAAC,IAAI,EAAE,MAAM,EASzC;IAED;;OAEG;IACH,IAAoB,UAAU,IAAI,IAAI,CAErC;IAED;;OAEG;IACH,IAAoB,SAAS,IAAI,IAAI,CAEpC;IAED;;;OAGG;IACa,YAAY,CAAC,QAAQ,CAAC,EAAE;QAAE,kBAAkB,CAAC,EAAE,OAAO,CAAA;KAAE,GAAG,MAAM;IAejF;;OAEG;IACa,OAAO,CAAC,QAAQ,CAAC,EAAE;QAClC,uBAAuB,CAAC,EAAE,OAAO,CAAC;QAClC,WAAW,CAAC,EAAE,UAAU,EAAE,CAAC;KAC3B,GAAG,MAAM;IAeV;;OAEG;IACa,CAAC,cAAc,CAAC,WAAW,CAAC,CAAC,IAAI,EAAE,IAAI,EAAE,kBAAkB,UAAQ,GAAG,IAAI;IAI1F;;OAEG;IACa,CAAC,cAAc,CAAC,WAAW,CAAC,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI;IAI9D;;OAEG;IACa,CAAC,cAAc,CAAC,YAAY,CAAC,CAC5C,OAAO,EAAE,IAAI,EACb,aAAa,EAAE,IAAI,EACnB,kBAAkB,UAAQ,GACxB,IAAI;IAQP;;OAEG;IACa,CAAC,cAAc,CAAC,YAAY,CAAC,CAAC,QAAQ,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,GAAG,IAAI;IAInF;;OAEG;IACa,CAAC,cAAc,CAAC,SAAS,CAAC,CAAC,IAAI,UAAQ,GAAG,mBAAmB;CAK7E"}

View File

@@ -0,0 +1,111 @@
import HTMLElement from '../html-element/HTMLElement.js';
import * as PropertySymbol from '../../PropertySymbol.js';
import HTMLSerializer from '../../html-serializer/HTMLSerializer.js';
import HTMLParser from '../../html-parser/HTMLParser.js';
/**
* HTML Template Element.
*
* Reference:
* https://developer.mozilla.org/en-US/docs/Web/API/HTMLTemplateElement.
*/
export default class HTMLTemplateElement extends HTMLElement {
// Internal properties
[PropertySymbol.content] = this[PropertySymbol.ownerDocument].createDocumentFragment();
/**
* Returns content.
*
* @returns Content.
*/
get content() {
return this[PropertySymbol.content];
}
/**
* @override
*/
get innerHTML() {
return this.getHTML();
}
/**
* @override
*/
set innerHTML(html) {
const content = this[PropertySymbol.content];
const childNodes = content[PropertySymbol.nodeArray];
while (childNodes.length) {
content.removeChild(childNodes[0]);
}
new HTMLParser(this[PropertySymbol.window]).parse(html, this[PropertySymbol.content]);
}
/**
* @override
*/
get firstChild() {
return this[PropertySymbol.content].firstChild;
}
/**
* @override
*/
get lastChild() {
return this[PropertySymbol.content].lastChild;
}
/**
* @deprecated
* @override
*/
getInnerHTML(_options) {
const serializer = new HTMLSerializer();
// Options should be ignored as shadow roots should not be serialized for HTMLTemplateElement.
const content = this[PropertySymbol.content];
let html = '';
for (const node of content[PropertySymbol.nodeArray]) {
html += serializer.serializeToString(node);
}
return html;
}
/**
* @override
*/
getHTML(_options) {
const serializer = new HTMLSerializer();
// Options should be ignored as shadow roots should not be serialized for HTMLTemplateElement.
const content = this[PropertySymbol.content];
let html = '';
for (const node of content[PropertySymbol.nodeArray]) {
html += serializer.serializeToString(node);
}
return html;
}
/**
* @override
*/
[PropertySymbol.appendChild](node, disableValidations = false) {
return this[PropertySymbol.content][PropertySymbol.appendChild](node, disableValidations);
}
/**
* @override
*/
[PropertySymbol.removeChild](node) {
return this[PropertySymbol.content][PropertySymbol.removeChild](node);
}
/**
* @override
*/
[PropertySymbol.insertBefore](newNode, referenceNode, disableValidations = false) {
return this[PropertySymbol.content][PropertySymbol.insertBefore](newNode, referenceNode, disableValidations);
}
/**
* @override
*/
[PropertySymbol.replaceChild](newChild, oldChild) {
return this[PropertySymbol.content][PropertySymbol.replaceChild](newChild, oldChild);
}
/**
* @override
*/
[PropertySymbol.cloneNode](deep = false) {
const clone = super[PropertySymbol.cloneNode](deep);
clone[PropertySymbol.content] = this[PropertySymbol.content].cloneNode(deep);
return clone;
}
}
//# sourceMappingURL=HTMLTemplateElement.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"HTMLTemplateElement.js","sourceRoot":"","sources":["../../../src/nodes/html-template-element/HTMLTemplateElement.ts"],"names":[],"mappings":"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"}