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

9
frontend/node_modules/@poppinss/macroable/LICENSE.md generated vendored Normal file
View File

@@ -0,0 +1,9 @@
# The MIT License
Copyright 2022 Harminder Virk, contributors
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the 'Software'), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

162
frontend/node_modules/@poppinss/macroable/README.md generated vendored Normal file
View File

@@ -0,0 +1,162 @@
# @poppinss/macroable
> Extend classes from outside in using Macros and getters
[![gh-workflow-image]][gh-workflow-url] [![typescript-image]][typescript-url] [![npm-image]][npm-url] [![license-image]][license-url]
Macroable offers a simple API for adding properties and getters to the class prototype. You might not even need this package, if you are happy writing `Object.defineProperty` calls yourself.
## Usage
Install the package from npm packages registry as follows.
```sh
npm i @poppinss/macroable
# yarn lovers
yarn add @poppinss/macroable
```
And import the `Macroable` class.
```ts
import Macroable from '@poppinss/macroable'
export class Route extends Macroable {}
```
Now, you can add properties to the Route class from outside-in. This is usually needed, when you want the consumer of your classes to be able to extend them by adding custom properties.
## Macros
Getters are added to the class prototype directly.
```ts
Route.macro('head', function (uri, callback) {
return this.route(['HEAD'], uri, callback)
})
```
And now, you can will be use the `head` method from an instance of the `Route` class.
```ts
const route = new Route()
route.head('/', () => {})
```
Adding a macro is same as writing the following code in JavaScript.
```ts
Route.prototype.head = function () {
}
```
## Instance properties
Since, macros are defined on the prototype of the class and therefore they loose the `this` context when destructured from the class instance. For example:
```ts
HttpContext.macro('getUser', function (this: HttpContext) {
return this.auth.user
})
const { getUser } = ctx
getUser() // ❌ Error: Cannot read property auth of undefined
```
In order to fix this issue, the properties that can be destructured must be defined as instance properties on the class.
```ts
HttpContext.instanceProperty('getUser', function (this: HttpContext) {
return this.auth.user
})
const { getUser } = ctx
getUser() // ✅ Works fine
```
## Getters
Getters are added to the class prototype using the `Object.defineProperty`. The implementation of a getter is always a function.
```ts
Route.getter('version', function () {
return 'v1'
})
```
And now access the version as follows.
```ts
const route = new Route()
route.version // v1
```
Adding a getter is same as writing the following code in JavaScript.
```ts
Object.defineProperty(Route.prototype, 'version', {
get() {
const value = callback()
return value
},
configurable: false,
enumerable: false,
})
```
## Singleton getters
Singleton getters are also defined on the class prototype. However, their values are cached after the first access.
```ts
const singleton = true
Mysql.getter('version', function () {
return this.config.driver.split('-')[1]
}, singleton)
```
Adding a singleton getter is same as writing the following code in JavaScript.
```ts
Object.defineProperty(Mysql.prototype, 'version', {
get() {
const value = callback()
// Cache value on the class instance
Object.defineProperty(this, 'version', {
configurable: false,
enumerable: false,
value: value,
writable: false,
})
return value
},
configurable: false,
enumerable: false,
})
```
## TypeScript types
You will have to use [module augmentation](https://www.typescriptlang.org/docs/handbook/declaration-merging.html#module-augmentation) in order to define the types for the dynamically added properties.
## Contributing
One of our primary goals is to have a vibrant community of users and contributors who believes in the principles of the framework.
We encourage you to read the [contribution guide](https://github.com/poppinss/.github/blob/main/docs/CONTRIBUTING.md) before contributing to the framework.
## Code of Conduct
In order to ensure that the community is welcoming to all, please review and abide by the [Code of Conduct](https://github.com/poppinss/.github/blob/main/docs/CODE_OF_CONDUCT.md).
## License
Poppinss macroable is open-sourced software licensed under the [MIT license](LICENSE.md).
[gh-workflow-image]: https://img.shields.io/github/actions/workflow/status/poppinss/macroable/checks.yml?style=for-the-badge
[gh-workflow-url]: https://github.com/poppinss/macroable/actions/workflows/checks.yml "Github action"
[typescript-image]: https://img.shields.io/badge/Typescript-294E80.svg?style=for-the-badge&logo=typescript
[typescript-url]: "typescript"
[npm-image]: https://img.shields.io/npm/v/@poppinss/macroable.svg?style=for-the-badge&logo=npm
[npm-url]: https://npmjs.org/package/@poppinss/macroable 'npm'
[license-image]: https://img.shields.io/npm/l/@poppinss/macroable?color=blueviolet&style=for-the-badge
[license-url]: LICENSE.md 'license'

View File

@@ -0,0 +1,121 @@
/**
* Abstract class that adds capabilities for extending classes from outside-in,
* in the form of macros, instance properties, and getters.
*
* @example
* ```ts
* class User extends Macroable {
* name: string
* constructor(name: string) {
* super()
* this.name = name
* }
* }
*
* // Add a macro
* User.macro('greet', function() {
* return `Hello, ${this.name}`
* })
*
* // Add a getter
* User.getter('upperName', function() {
* return this.name.toUpperCase()
* })
*
* const user = new User('John')
* user.greet() // "Hello, John"
* user.upperName // "JOHN"
* ```
*/
export default abstract class Macroable {
/**
* Set of instance properties that will be added to each instance during construction.
* Each entry contains a key and value pair representing the property name and its value.
*/
protected static instanceMacros: Set<{
key: string | symbol | number;
value: unknown;
}>;
/**
* Adds a macro (property or method) to the class prototype.
* Macros are standard properties that get added to the class prototype,
* making them available on all instances of the class.
*
* @param name - The name of the property or method to add
* @param value - The value to assign to the property or method
*
* @example
* ```ts
* // Add a property macro
* MyClass.macro('version', '1.0.0')
*
* // Add a method macro
* MyClass.macro('greet', function() {
* return 'Hello!'
* })
*
* const instance = new MyClass()
* instance.version // "1.0.0"
* instance.greet() // "Hello!"
* ```
*/
static macro<T extends {
new (...args: any[]): any;
}, K extends keyof InstanceType<T>>(this: T, name: K, value: InstanceType<T>[K]): void;
/**
* Adds an instance property that will be assigned to each instance during construction.
* Unlike macros which are added to the prototype, instance properties are unique to each instance.
*
* @param name - The name of the property to add to instances
* @param value - The value to assign to the property on each instance
*
* @example
* ```ts
* // Add an instance method
* MyClass.instanceProperty('save', function() {
* console.log('Saving...', this.id)
* })
*
* const { save } = new MyClass()
* save()
* ```
*/
static instanceProperty<T extends {
new (...args: any[]): any;
}, K extends keyof InstanceType<T>>(this: T, name: K, value: InstanceType<T>[K]): void;
/**
* Adds a getter property to the class prototype using Object.defineProperty.
* Getters are computed properties that are evaluated each time they are accessed,
* unless the singleton flag is enabled.
*
* @param name - The name of the getter property
* @param accumulator - Function that computes and returns the property value
* @param singleton - If true, the getter value is cached after first access
*
* @example
* ```ts
* // Add a regular getter
* MyClass.getter('timestamp', function() {
* return Date.now()
* })
*
* // Add a singleton getter (cached after first access)
* MyClass.getter('config', function() {
* return loadConfig()
* }, true)
*
* const instance = new MyClass()
* instance.timestamp // Computed each time
* instance.config // Computed once, then cached
* ```
*/
static getter<T extends {
new (...args: any[]): any;
}, K extends keyof InstanceType<T>>(this: T, name: K, accumulator: () => InstanceType<T>[K], singleton?: boolean): void;
/**
* Constructor that applies all registered instance properties to the new instance.
* This method iterates through the instanceMacros set and assigns each property
* to the instance, binding functions to the instance context.
*/
constructor();
}

View File

@@ -0,0 +1,124 @@
// index.ts
var Macroable = class {
/**
* Set of instance properties that will be added to each instance during construction.
* Each entry contains a key and value pair representing the property name and its value.
*/
static instanceMacros = /* @__PURE__ */ new Set();
/**
* Adds a macro (property or method) to the class prototype.
* Macros are standard properties that get added to the class prototype,
* making them available on all instances of the class.
*
* @param name - The name of the property or method to add
* @param value - The value to assign to the property or method
*
* @example
* ```ts
* // Add a property macro
* MyClass.macro('version', '1.0.0')
*
* // Add a method macro
* MyClass.macro('greet', function() {
* return 'Hello!'
* })
*
* const instance = new MyClass()
* instance.version // "1.0.0"
* instance.greet() // "Hello!"
* ```
*/
static macro(name, value) {
this.prototype[name] = value;
}
/**
* Adds an instance property that will be assigned to each instance during construction.
* Unlike macros which are added to the prototype, instance properties are unique to each instance.
*
* @param name - The name of the property to add to instances
* @param value - The value to assign to the property on each instance
*
* @example
* ```ts
* // Add an instance method
* MyClass.instanceProperty('save', function() {
* console.log('Saving...', this.id)
* })
*
* const { save } = new MyClass()
* save()
* ```
*/
static instanceProperty(name, value) {
const self = this;
if (!self.hasOwnProperty("instanceMacros")) {
const inheritedProperties = self.instanceMacros;
Object.defineProperty(self, "instanceMacros", {
value: new Set(inheritedProperties),
configurable: true,
enumerable: true,
writable: true
});
}
self.instanceMacros.add({ key: name, value });
}
/**
* Adds a getter property to the class prototype using Object.defineProperty.
* Getters are computed properties that are evaluated each time they are accessed,
* unless the singleton flag is enabled.
*
* @param name - The name of the getter property
* @param accumulator - Function that computes and returns the property value
* @param singleton - If true, the getter value is cached after first access
*
* @example
* ```ts
* // Add a regular getter
* MyClass.getter('timestamp', function() {
* return Date.now()
* })
*
* // Add a singleton getter (cached after first access)
* MyClass.getter('config', function() {
* return loadConfig()
* }, true)
*
* const instance = new MyClass()
* instance.timestamp // Computed each time
* instance.config // Computed once, then cached
* ```
*/
static getter(name, accumulator, singleton = false) {
Object.defineProperty(this.prototype, name, {
get() {
const value = accumulator.call(this);
if (singleton) {
Object.defineProperty(this, name, {
configurable: false,
enumerable: false,
value,
writable: false
});
}
return value;
},
configurable: true,
enumerable: false
});
}
/**
* Constructor that applies all registered instance properties to the new instance.
* This method iterates through the instanceMacros set and assigns each property
* to the instance, binding functions to the instance context.
*/
constructor() {
const self = this;
const Constructor = this.constructor;
Constructor.instanceMacros.forEach(({ key, value }) => {
self[key] = typeof value === "function" ? value.bind(this) : value;
});
}
};
export {
Macroable as default
};

109
frontend/node_modules/@poppinss/macroable/package.json generated vendored Normal file
View File

@@ -0,0 +1,109 @@
{
"name": "@poppinss/macroable",
"version": "1.1.0",
"description": "Extend classes from outside in using Macros and getters",
"main": "build/index.js",
"type": "module",
"files": [
"build",
"!build/bin",
"!build/tests"
],
"exports": {
".": "./build/index.js"
},
"scripts": {
"pretest": "npm run lint",
"test": "c8 npm run quick:test",
"lint": "eslint",
"format": "prettier --write .",
"typecheck": "tsc --noEmit",
"precompile": "npm run lint",
"compile": "tsup-node && tsc --emitDeclarationOnly --declaration",
"build": "npm run compile",
"version": "npm run build",
"prepublishOnly": "npm run build",
"release": "release-it",
"quick:test": "node --import=@poppinss/ts-exec --enable-source-maps bin/test.ts"
},
"keywords": [
"macroable"
],
"author": "virk,poppinss",
"license": "MIT",
"devDependencies": {
"@adonisjs/eslint-config": "^3.0.0-next.0",
"@adonisjs/prettier-config": "^1.4.5",
"@adonisjs/tsconfig": "^2.0.0-next.0",
"@japa/assert": "^4.0.1",
"@japa/expect-type": "^2.0.3",
"@japa/runner": "^4.2.0",
"@poppinss/ts-exec": "^1.4.0",
"@release-it/conventional-changelog": "^10.0.1",
"@swc/core": "^1.12.9",
"@types/node": "^24.0.10",
"c8": "^10.1.3",
"eslint": "^9.30.1",
"prettier": "^3.6.2",
"release-it": "^19.0.3",
"tsup": "^8.5.0",
"typescript": "^5.8.3"
},
"repository": {
"type": "git",
"url": "git+https://github.com/poppinss/macroable.git"
},
"bugs": {
"url": "https://github.com/poppinss/macroable/issues"
},
"homepage": "https://github.com/poppinss/macroable#readme",
"publishConfig": {
"access": "public",
"provenance": true
},
"tsup": {
"entry": [
"./index.ts"
],
"outDir": "./build",
"clean": true,
"format": "esm",
"dts": false,
"sourcemap": false,
"target": "esnext"
},
"release-it": {
"git": {
"requireCleanWorkingDir": true,
"requireUpstream": true,
"commitMessage": "chore(release): ${version}",
"tagAnnotation": "v${version}",
"push": true,
"tagName": "v${version}"
},
"github": {
"release": true
},
"npm": {
"publish": true,
"skipChecks": true
},
"plugins": {
"@release-it/conventional-changelog": {
"preset": {
"name": "angular"
}
}
}
},
"c8": {
"reporter": [
"text",
"html"
],
"exclude": [
"tests/**"
]
},
"prettier": "@adonisjs/prettier-config"
}