commit 18eaa2daaa3cd8236983915f29830f2698ed55eb Author: Mathias Beaulieu-Duncan Date: Mon Jun 23 17:25:57 2025 -0400 initial commit diff --git a/.gitea/workflows/publish.yaml b/.gitea/workflows/publish.yaml new file mode 100644 index 0000000..713bcef --- /dev/null +++ b/.gitea/workflows/publish.yaml @@ -0,0 +1,44 @@ +name: Publish to npm + +on: + release: + types: [published] + +jobs: + publish: + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: 20 + registry-url: 'https://registry.npmjs.org/' + + - name: Install dependencies + run: npm ci + + - name: Run type check + run: npm run type-check + + - name: Build library + run: npm run build + + - name: Determine npm tag + id: determine_tag + run: | + IS_PRERELEASE=${{ github.event.release.prerelease }} + VERSION=$(node -p "require('./package.json').version") + if [[ "$VERSION" =~ -(alpha|beta|rc|dev) ]]; then + echo "NPM_TAG=dev" >> $GITHUB_OUTPUT + else + echo "NPM_TAG=latest" >> $GITHUB_OUTPUT + fi + + - name: Publish to npm + run: npm publish --access public --tag ${{ steps.determine_tag.outputs.NPM_TAG }} + env: + NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..a547bf3 --- /dev/null +++ b/.gitignore @@ -0,0 +1,24 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +dist +dist-ssr +*.local + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +.DS_Store +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 0000000..a7cea0b --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,3 @@ +{ + "recommendations": ["Vue.volar"] +} diff --git a/README.md b/README.md new file mode 100644 index 0000000..eaeac09 --- /dev/null +++ b/README.md @@ -0,0 +1,324 @@ +# @openharbor/vue-data + +A Vue 3 Composition API library for simplified data management with CQRS backends, powered by a flexible builder pattern. This library helps you effortlessly connect your Vue components to backend services using a POST-centric interaction model, providing reactive data, loading states, and robust error handling. + +## Features + +* **Vue 3 Composition API:** Fully integrated with Vue's reactivity system. +* **CQRS-Oriented:** Designed for backends that use POST requests for both queries and commands. +* **Flexible Data Source Builders:** Configure data fetching and command execution with a fluent API. +* **Reactive State Management:** Automatically tracks `data`/`items`, `total`, `loading` status, and `error` states. +* **Pluggable Commands:** Easily define domain-specific commands (e.g., `AddProduct`, `RemoveProduct`, `UpdateProductDetails`, `PlaceOrder`). +* **Standardized Error Handling:** Consistent approach to backend error messages and validation errors. + +--- + +## Installation + +To use this library in your Vue 3 project, you need to install it via npm or Yarn. Remember that `vue` is a peer dependency, so ensure you have Vue 3 installed in your project. + +```bash +# Using npm +npm install @openharbor/vue-data + +# Using Yarn +yarn add @openharbor/vue-data +``` + +## Usage + +The library provides three main composables: `useHttpDataSource`, `useSingleDataSource`, and `useListDataSource`, each tailored for different data interaction patterns. + +### Core Concepts + +* **Query Criteria (`IQueryCriteria`):** An object defining the parameters for your data requests (e.g., filters, pagination, sorting). +* **Models (`TModel`):** The shape of the data objects you are fetching or sending as commands. +* **Commands (`ICommand`):** The data payload sent to your backend for actions (e.g., `AddProductCommand`, `RemoveProductCommand`, `UpdateProductDetailsCommand`). +* **`keyResolver`:** A function `(model: TModel) => TModel[keyof TModel]` that extracts a unique identifier (like an `id`) from your model. This is crucial for `useSingleDataSource` and for certain command resolution scenarios. +* **`autoFetch`:** A boolean option to automatically trigger a `read` operation when the component mounts or when `criteria` changes. + +### `useHttpDataSource` + +This is the most generic data source composable. It's suitable for a wide range of querying and commanding needs where the structure isn't strictly a single item or a traditional list. + +```typescript +// Example: src/views/MyGenericDataComponent.vue + + + +``` + +### `useSingleDataSource` + +Best for managing a single entity (e.g., editing a product details page, displaying a user profile). It requires a `keyResolver` and can easily set up common CQRS commands for a single entity. + +```typescript +// Example: src/views/ProductDetailComponent.vue + + + +``` + +### `useListDataSource` + +Ideal for displaying collections of data, such as tables, grids, or paginated lists. It functions as a semantic wrapper around `useHttpDataSource` for clarity. + +```typescript +// Example: src/views/ProductListingComponent.vue + + + +``` diff --git a/index.html b/index.html new file mode 100644 index 0000000..dde16aa --- /dev/null +++ b/index.html @@ -0,0 +1,13 @@ + + + + + + + Vite + Vue + TS + + +
+ + + diff --git a/package.json b/package.json new file mode 100644 index 0000000..47e6188 --- /dev/null +++ b/package.json @@ -0,0 +1,47 @@ +{ + "name": "@openharbor/vue-data", + "author": "Open Harbor", + "private": false, + "license": "MIT", + "version": "1.0.0", + "description": "Vue 3 Composition API implementation for OpenHarbor data management.", + "type": "module", + "main": "./dist/vue-openharbor-data.umd.cjs", + "module": "./dist/vue-openharbor-data.js", + "types": "./dist/index.d.ts", + "exports": { + ".": { + "types": "./dist/index.d.ts", + "import": "./dist/vue-openharbor-data.js", + "require": "./dist/vue-openharbor-data.umd.cjs" + } + }, + "files": [ + "dist" + ], + "scripts": { + "dev": "vite", + "build": "vite build", + "preview": "vite preview", + "type-check": "vue-tsc --noEmit --composite false" + }, + "peerDependenciesMeta": { + "vue": { + "optional": false + } + }, + "peerDependencies": { + "vue": "^3.4.0" + }, + "devDependencies": { + "@tsconfig/node20": "^20.1.6", + "@types/node": "^24.0.3", + "@vitejs/plugin-vue": "^5.2.3", + "@vue/tsconfig": "^0.7.0", + "typescript": "~5.8.3", + "vite": "^6.3.5", + "vue": "^3.5.13", + "vue-tsc": "^2.2.8" + }, + "packageManager": "yarn@1.22.22+sha1.ac34549e6aa8e7ead463a7407e1c7390f61a6610" +} diff --git a/src/composables/index.ts b/src/composables/index.ts new file mode 100644 index 0000000..e69de29 diff --git a/src/composables/use-http-data-source.ts b/src/composables/use-http-data-source.ts new file mode 100644 index 0000000..cb5866b --- /dev/null +++ b/src/composables/use-http-data-source.ts @@ -0,0 +1,157 @@ +// src/composables/use-http-data-source.ts + +import { ref, readonly, watch, type Ref } from 'vue'; +import { + type IQueryCriteria, + type ICommand, + type IQueryExecutionResult, + type IQueryExecutionGroupResult, + type IDataSourceError, + type IDataSourceOptions, + type IResolveCommandModelEvent +} from '../core/types'; +import { HttpDataSourceBuilder } from '../core/http-data-source-builder.ts'; + + +export interface UseHttpDataSourceOptions { + queryUrl?: string; + queryHandler?: (query: TQuery) => Promise & IQueryExecutionGroupResult>; + beforeRead?: (query: IQueryCriteria) => Promise; + defaultCriteria?: TQuery; + + keyResolver?: (model: TModel) => TModel[keyof TModel]; + + commands?: { + [name: string]: { + url?: string; + handler?: (command: any) => Promise; + resolveCommandModel?: (event: IResolveCommandModelEvent) => Promise; + beforeCommand?: (command: any) => Promise; + }; + }; + + autoFetch?: boolean; +} + +export function useHttpDataSource( + options: UseHttpDataSourceOptions +) { + const data: Ref = ref(null); + const total: Ref = ref(null); + const loading = ref(false); + const error: Ref = ref(null); + + const criteria: Ref = ref(options.defaultCriteria || {} as TQuery) as Ref; + + const builder = new HttpDataSourceBuilder(); + + if (options.keyResolver) { + builder.keyResolver(options.keyResolver); + } + if (options.defaultCriteria) { + builder.defaultCriteria(options.defaultCriteria); + } + if (options.beforeRead) { + builder.beforeRead(options.beforeRead); + } + + if (options.queryUrl) { + builder.queryUrl(options.queryUrl); + } else if (options.queryHandler) { + builder.queryHandler(options.queryHandler); + } else { + console.warn("useHttpDataSource: No queryUrl or queryHandler provided. Data will not be fetched."); + } + + if (options.commands) { + for (const name in options.commands) { + if (Object.prototype.hasOwnProperty.call(options.commands, name)) { + const commandOptions = options.commands[name]; + if (commandOptions.handler) { + builder.addCommandByCallback(name, commandOptions.handler, commandOptions.resolveCommandModel); + } else if (commandOptions.url) { + builder.addCommandByUrl(name, commandOptions.url, commandOptions.resolveCommandModel, commandOptions.beforeCommand); + } + } + } + } + + const dataSourceOptions: IDataSourceOptions = builder.createOptions(); + + const _read = async (query?: TQuery) => { + loading.value = true; + error.value = null; + data.value = null; + total.value = null; + + try { + const finalQuery = query || criteria.value; + const result = await dataSourceOptions.transport.query.adapter.handle(finalQuery); + data.value = result.items; + total.value = result.total; + } catch (e: any) { + error.value = e as IDataSourceError; + console.error("Data source query failed:", e); + } finally { + loading.value = false; + } + }; + + const read = async (overrideQuery?: TQuery) => { + if (overrideQuery) { + criteria.value = overrideQuery; + } + await _read(criteria.value); + }; + + const executeCommand = async (commandName: string, commandData: any): Promise => { + loading.value = true; + error.value = null; + + try { + const commandAdapter = dataSourceOptions.transport.commands[commandName]; + if (!commandAdapter) { + throw new Error(`Command "${commandName}" is not defined for this data source.`); + } + + let finalCommandData = commandData; + if (commandAdapter.resolveCommandModel) { + const modelToResolveFrom = options.keyResolver && data.value && data.value.length > 0 + ? data.value.find(item => options.keyResolver!(item) === options.keyResolver!(commandData)) + : null; + + finalCommandData = await commandAdapter.resolveCommandModel({ + model: modelToResolveFrom || commandData, + data: commandData + }); + } + + const result = await commandAdapter.adapter.handle(finalCommandData); + return result; + } catch (e: any) { + error.value = e as IDataSourceError; + console.error(`Data source command '${commandName}' failed:`, e); + throw e; + } finally { + loading.value = false; + } + }; + + if (options.autoFetch) { + watch(criteria, async () => { + await _read(); + }, { immediate: true, deep: true }); + } + + return { + data: readonly(data), + total: readonly(total), + loading: readonly(loading), + error: readonly(error), + + criteria, + + read, + executeCommand, + }; +} diff --git a/src/composables/use-list-data-source.ts b/src/composables/use-list-data-source.ts new file mode 100644 index 0000000..252abca --- /dev/null +++ b/src/composables/use-list-data-source.ts @@ -0,0 +1,45 @@ +import { + type IQueryCriteria, + type ICommand, + type IQueryExecutionResult, + type IQueryExecutionGroupResult, + type IResolveCommandModelEvent +} from '../core/types'; +import { useHttpDataSource } from './use-http-data-source.ts'; + + +export interface UseListDataSourceOptions { + queryUrl?: string; + queryHandler?: (query: TQuery) => Promise & IQueryExecutionGroupResult>; + beforeRead?: (query: IQueryCriteria) => Promise; + defaultCriteria?: TQuery; + + keyResolver?: (model: TModel) => TModel[keyof TModel]; + + commands?: { + [name: string]: { + url?: string; + handler?: (command: any) => Promise; + resolveCommandModel?: (event: IResolveCommandModelEvent) => Promise; + beforeCommand?: (command: any) => Promise; + }; + }; + + autoFetch?: boolean; +} + +export function useListDataSource( + options: UseListDataSourceOptions +) { + const { data, total, loading, error, criteria, read, executeCommand } = useHttpDataSource(options); + + return { + items: data, + total, + loading, + error, + criteria, + read, + executeCommand, + }; +} diff --git a/src/composables/use-single-data-source.ts b/src/composables/use-single-data-source.ts new file mode 100644 index 0000000..79bed4f --- /dev/null +++ b/src/composables/use-single-data-source.ts @@ -0,0 +1,169 @@ +// src/composables/use-single-data-source.ts + +import { ref, readonly, watch, type Ref } from 'vue'; +import { + type IQueryCriteria, + type ICommand, + type IQueryExecutionResult, + type IDataSourceError, + type IResolveCommandModelEvent, + type IDataSourceOptions, + type IQueryExecutionGroupResult +} from '../core/types'; +import { SingleDataSourceBuilder } from '../core/single-data-source-builder'; + + +export interface UseSingleDataSourceOptions { + queryUrl?: string; + queryHandler?: (query: TQuery) => Promise & IQueryExecutionGroupResult>; + beforeRead?: (query: IQueryCriteria) => Promise; + defaultCriteria?: TQuery; + + keyResolver: (model: TModel) => TModel[keyof TModel]; + + commands?: { + [name: string]: { + url?: string; + handler?: (command: any) => Promise; + resolveCommandModel?: (event: IResolveCommandModelEvent) => Promise; + beforeCommand?: (command: any) => Promise; + }; + }; + + addStandardRestCommands?: { + route: string; + }; + + autoFetch?: boolean; +} + +export function useSingleDataSource( + options: UseSingleDataSourceOptions +) { + const data: Ref = ref(null); + const loading = ref(false); + const error: Ref = ref(null); + + const criteria: Ref = ref(options.defaultCriteria || {} as TQuery) as Ref; + + const builder = new SingleDataSourceBuilder(); + + if (!options.keyResolver) { + throw new Error("useSingleDataSource: 'keyResolver' is mandatory for single data source operations."); + } + builder.keyResolver(options.keyResolver); + + if (options.defaultCriteria) { + builder.defaultCriteria(options.defaultCriteria); + } + if (options.beforeRead) { + builder.beforeRead(options.beforeRead); + } + + if (options.queryUrl) { + builder.queryUrl(options.queryUrl); + } else if (options.queryHandler) { + builder.queryHandler(options.queryHandler); + } else { + console.warn("useSingleDataSource: No queryUrl or queryHandler provided. Data will not be fetched."); + } + + if (options.addStandardRestCommands) { + builder.addStandardRestCommands(options.addStandardRestCommands.route); + } + + if (options.commands) { + for (const name in options.commands) { + if (Object.prototype.hasOwnProperty.call(options.commands, name)) { + const commandOptions = options.commands[name]; + if (commandOptions.handler) { + builder.addCommandByCallback(name, commandOptions.handler, commandOptions.resolveCommandModel); + } else if (commandOptions.url) { + builder.addCommandByUrl(name, commandOptions.url, commandOptions.resolveCommandModel, commandOptions.beforeCommand); + } + } + } + } + + const dataSourceOptions: IDataSourceOptions = builder.createOptions(); + + const _read = async (query?: TQuery) => { + loading.value = true; + error.value = null; + data.value = null; + + try { + const finalQuery = query || criteria.value; + const result = await dataSourceOptions.transport.query.adapter.handle(finalQuery); + data.value = result.items && result.items.length > 0 ? result.items[0] : null; + } catch (e: any) { + error.value = e as IDataSourceError; + console.error("Single data source query failed:", e); + } finally { + loading.value = false; + } + }; + + const read = async (overrideQuery?: TQuery) => { + if (overrideQuery) { + criteria.value = overrideQuery; + } + await _read(criteria.value); + }; + + const executeCommand = async (commandName: string, commandData: any): Promise => { + loading.value = true; + error.value = null; + + try { + const commandAdapter = dataSourceOptions.transport.commands[commandName]; + if (!commandAdapter) { + throw new Error(`Command "${commandName}" is not defined for this data source.`); + } + + let finalCommandData = commandData; + if (commandAdapter.resolveCommandModel) { + let modelToResolveFrom: TModel | null = null; + + modelToResolveFrom = data.value; + + finalCommandData = await commandAdapter.resolveCommandModel({ + model: modelToResolveFrom || commandData, + data: commandData + }); + } + + const result = await commandAdapter.adapter.handle(finalCommandData); + if (commandName === 'create' || commandName === 'update') { + data.value = result; + } + if (commandName === 'delete') { + data.value = null; + } + return result; + } catch (e: any) { + error.value = e as IDataSourceError; + console.error(`Single data source command '${commandName}' failed:`, e); + throw e; + } finally { + loading.value = false; + } + }; + + if (options.autoFetch) { + watch(criteria, async () => { + await _read(); + }, { immediate: true, deep: true }); + } + + return { + data: readonly(data), + loading: readonly(loading), + error: readonly(error), + + criteria, + + read, + executeCommand, + }; +} diff --git a/src/core/base-datasource-builder.ts b/src/core/base-datasource-builder.ts new file mode 100644 index 0000000..d68093a --- /dev/null +++ b/src/core/base-datasource-builder.ts @@ -0,0 +1,101 @@ +// src/core/base-datasource-builder.ts + +import { httpClient } from './http-client'; +import { + type IQueryCriteria, + type IDataSourceCommandAdapterOptions, + type IResolveCommandModelEvent, + type IDataSourceOptions, + type IDataSourceTransportOptions, + type IDataSourceError +} from './types'; + +export abstract class BaseDataSourceBuilder { + protected _commands: { [key: string]: IDataSourceCommandAdapterOptions; } = {}; + protected _keyResolver?: (model: TModel) => TModel[keyof TModel]; + protected _defaultCriteria!: IQueryCriteria; + + protected constructor() { } + + protected createTransport(): IDataSourceTransportOptions { + return { + query: {} as any, + commands: this._commands + }; + } + + public keyResolver(resolver: (model: TModel) => TModel[keyof TModel]) { + this._keyResolver = resolver; + return this; + } + + public createOptions(): IDataSourceOptions { // <--- CHANGED FROM 'protected' to 'public' + return { + resolveIdField: this._keyResolver, + defaultCriteria: this._defaultCriteria, + transport: this.createTransport() + }; + } + + protected _handleErrorPipe(error: any): IDataSourceError { + if (error && (error.type === 'message' || error.type === 'validation')) { + return error as IDataSourceError; + } + return { + type: 'message', + message: 'UNEXPECTED_ERROR_MESSAGE', + originalError: error, + statusCode: 0 + }; + } + + public addCommandByCallback( + name: string, + commandHandler: (command: TCommand) => Promise, + resolveCommandModel?: (event: IResolveCommandModelEvent) => Promise + ) { + const handleWrapper = async (command: TCommand) => { + try { + return await commandHandler(command); + } catch (e) { + throw this._handleErrorPipe(e); + } + }; + + this._commands[name] = { + adapter: { + handle: handleWrapper + }, + resolveCommandModel: resolveCommandModel + }; + + return this; + } + + public addCommandByUrl( + name: string, + url: string, + resolveCommandModel?: (event: IResolveCommandModelEvent) => Promise, + beforeCommand?: (command: TCommand) => Promise + ) { + const handleWrapper = async (command: TCommand) => { + const finalBeforeCommand = beforeCommand || (_ => Promise.resolve(command)); + const processedCommand = await finalBeforeCommand(command); + + try { + return await httpClient.post(url, processedCommand); + } catch (e) { + throw this._handleErrorPipe(e); + } + }; + + this._commands[name] = { + adapter: { + handle: handleWrapper + }, + resolveCommandModel: resolveCommandModel + }; + + return this; + } +} diff --git a/src/core/http-client.ts b/src/core/http-client.ts new file mode 100644 index 0000000..ddb5758 --- /dev/null +++ b/src/core/http-client.ts @@ -0,0 +1,97 @@ +export interface HttpError { + type: 'message' | 'validation'; + message?: string; + errors?: { [key: string]: string[] }; + statusCode?: number; + originalError?: any; +} + +export const httpClient = { + async post(url: string, data: any): Promise { + try { + const response = await fetch(url, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify(data), + }); + + if (!response.ok) { + let errorData: any = null; + try { + errorData = await response.json(); + } catch (parseError) { + errorData = await response.text(); + } + + throw this._handleHttpError(response.status, errorData); + } + + if (response.status === 204 || response.headers.get('content-length') === '0') { + return undefined as TResponse; + } + + return await response.json() as TResponse; + + } catch (error: any) { + if (error && typeof error.type === 'string' && (error.type === 'message' || error.type === 'validation')) { + throw error; + } else { + throw { + type: 'message', + message: 'NETWORK_ERROR_MESSAGE', + originalError: error, + statusCode: 0 + } as HttpError; + } + } + }, + + _handleHttpError(status: number, errorBody: any): HttpError { + if (status === 500) { + return { + type: 'message', + message: 'UNEXPECTED_ERROR_MESSAGE', + statusCode: status, + originalError: errorBody + }; + } + + if (status === 400) { + if (errorBody && errorBody.errors) { + return { + type: 'validation', + errors: errorBody.errors, + statusCode: status, + originalError: errorBody + }; + } + + if (typeof errorBody === 'object' && (errorBody.Message || errorBody.message)) { + return { + type: 'message', + message: errorBody.Message || errorBody.message, + statusCode: status, + originalError: errorBody + }; + } + } + + if (typeof errorBody === 'string') { + return { + type: 'message', + message: errorBody, + statusCode: status, + originalError: errorBody + }; + } + + return { + type: 'message', + message: 'UNEXPECTED_ERROR_MESSAGE', + statusCode: status, + originalError: errorBody + }; + } +}; diff --git a/src/core/http-data-source-builder.ts b/src/core/http-data-source-builder.ts new file mode 100644 index 0000000..af9b2b6 --- /dev/null +++ b/src/core/http-data-source-builder.ts @@ -0,0 +1,60 @@ +import { httpClient } from './http-client'; +import { + type IQueryCriteria, + type IQueryExecutionGroupResult, + type IQueryExecutionResult, + type IDataSourceQueryAdapterOptions, +} from './types'; +import { BaseDataSourceBuilder } from './base-datasource-builder'; + +export class HttpDataSourceBuilder extends BaseDataSourceBuilder +{ + private _beforeRead?: (query: IQueryCriteria) => Promise; + protected _query!: IDataSourceQueryAdapterOptions; + + constructor() { + super(); + } + + protected createTransport() { + const baseTransport = super.createTransport(); + baseTransport.query = this._query; + return baseTransport; + } + + public beforeRead(beforeRead: (query: IQueryCriteria) => Promise) { + this._beforeRead = beforeRead; + return this; + } + + public queryUrl(url: string) { + this._query = { + adapter: { + handle: async (query: IQueryCriteria) => { + const finalBeforeRead = this._beforeRead || (() => Promise.resolve(query as TQuery)); + const finalQuery = await finalBeforeRead(query); + return httpClient.post & IQueryExecutionGroupResult>(url, finalQuery); + } + } + }; + return this; + } + + public queryHandler(queryHandler: (query: TQuery) => Promise & IQueryExecutionGroupResult>) { + this._query = { + adapter: { + handle: async (query: TQuery) => { + const finalBeforeRead = this._beforeRead || (() => Promise.resolve(query as TQuery)); + const finalQuery = await finalBeforeRead(query); + return queryHandler(finalQuery); + } + } + }; + return this; + } + + public defaultCriteria(criteria: IQueryCriteria) { + this._defaultCriteria = criteria; + return this; + } +} diff --git a/src/core/list-data-source-builder.ts b/src/core/list-data-source-builder.ts new file mode 100644 index 0000000..97cb2f2 --- /dev/null +++ b/src/core/list-data-source-builder.ts @@ -0,0 +1,8 @@ +import { HttpDataSourceBuilder } from './http-data-source-builder.ts'; +import { type IQueryCriteria, type ICommand } from './types'; + +export class ListDataSourceBuilder extends HttpDataSourceBuilder { + constructor() { + super(); + } +} diff --git a/src/core/single-data-source-builder.ts b/src/core/single-data-source-builder.ts new file mode 100644 index 0000000..f2a7586 --- /dev/null +++ b/src/core/single-data-source-builder.ts @@ -0,0 +1,35 @@ +// src/core/single-datasource-builder.ts (REVISED - RxJS compatible and delete data fix) + +import { HttpDataSourceBuilder } from './http-data-source-builder.ts'; +import { type IQueryCriteria, type ICommand } from './types'; +import { httpClient } from './http-client'; + +export class SingleDataSourceBuilder extends HttpDataSourceBuilder +{ + constructor() { + super(); + } + + public addStandardRestCommands(route: string) { + if (!this._keyResolver) { + console.warn("A key resolver is recommended for standard commands to help identify models."); + } + + this.addCommandByCallback( + 'create', + (command: TModel) => httpClient.post(route, command) + ); + + this.addCommandByCallback( + 'update', + (command: TModel) => httpClient.post(route, command) + ); + + this.addCommandByCallback( + 'delete', + (command: TModel) => httpClient.post(route, command) + ); + + return this; + } +} diff --git a/src/core/types.ts b/src/core/types.ts new file mode 100644 index 0000000..5749d83 --- /dev/null +++ b/src/core/types.ts @@ -0,0 +1,63 @@ +export interface IQueryCriteria { + [key: string]: any; +} + +export interface ICommand { + [key: string]: any; +} + +export interface IQueryExecutionResult { + items: TModel[]; + total: number; +} + +export interface IQueryExecutionGroupResult { } + +export interface IDataSourceErrorMessage { + type: 'message'; + message: string; + statusCode?: number; + originalError?: any; +} + +export interface IDataSourceValidationError { + type: 'validation'; + errors: { [key: string]: string[] }; + statusCode?: number; + originalError?: any; +} + +export type IDataSourceError = IDataSourceErrorMessage | IDataSourceValidationError; + +export interface IResolveCommandModelEvent { + model: TModel; + data: any; +} + +export interface IDataSourceCommandAdapterOptions { + adapter: { + handle: (command: any) => Promise; + }; + resolveCommandModel?: (event: IResolveCommandModelEvent) => Promise; +} + +export interface IDataSourceQueryAdapterOptions { + adapter: { + handle: (query: TQuery) => Promise & IQueryExecutionGroupResult>; + }; +} + +export interface IDataSourceTransportOptions { + query: IDataSourceQueryAdapterOptions; + commands: { [key: string]: IDataSourceCommandAdapterOptions }; +} + +export interface IDataSourceOptions { + resolveIdField?: (model: TModel) => TModel[keyof TModel]; + defaultCriteria?: IQueryCriteria; + transport: IDataSourceTransportOptions; +} + +export interface IDataSource { + read(query?: TQuery): Promise & IQueryExecutionGroupResult>; +} diff --git a/src/index.ts b/src/index.ts new file mode 100644 index 0000000..e69de29 diff --git a/src/style.css b/src/style.css new file mode 100644 index 0000000..f691315 --- /dev/null +++ b/src/style.css @@ -0,0 +1,79 @@ +:root { + font-family: system-ui, Avenir, Helvetica, Arial, sans-serif; + line-height: 1.5; + font-weight: 400; + + color-scheme: light dark; + color: rgba(255, 255, 255, 0.87); + background-color: #242424; + + font-synthesis: none; + text-rendering: optimizeLegibility; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +a { + font-weight: 500; + color: #646cff; + text-decoration: inherit; +} +a:hover { + color: #535bf2; +} + +body { + margin: 0; + display: flex; + place-items: center; + min-width: 320px; + min-height: 100vh; +} + +h1 { + font-size: 3.2em; + line-height: 1.1; +} + +button { + border-radius: 8px; + border: 1px solid transparent; + padding: 0.6em 1.2em; + font-size: 1em; + font-weight: 500; + font-family: inherit; + background-color: #1a1a1a; + cursor: pointer; + transition: border-color 0.25s; +} +button:hover { + border-color: #646cff; +} +button:focus, +button:focus-visible { + outline: 4px auto -webkit-focus-ring-color; +} + +.card { + padding: 2em; +} + +#app { + max-width: 1280px; + margin: 0 auto; + padding: 2rem; + text-align: center; +} + +@media (prefers-color-scheme: light) { + :root { + color: #213547; + background-color: #ffffff; + } + a:hover { + color: #747bff; + } + button { + background-color: #f9f9f9; + } +} diff --git a/src/vite-env.d.ts b/src/vite-env.d.ts new file mode 100644 index 0000000..11f02fe --- /dev/null +++ b/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..8e9b449 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,32 @@ +{ + "extends": "@vue/tsconfig/tsconfig.dom.json", + "compilerOptions": { + "composite": true, + "baseUrl": ".", + "paths": { + "@/*": ["./src/*"] + }, + + "target": "ESNext", + "module": "ESNext", + "lib": ["esnext", "dom"], + + "moduleResolution": "node", + "allowSyntheticDefaultImports": true, + "esModuleInterop": true, + + "declaration": true, + "declarationDir": "./dist", + "emitDeclarationOnly": false, + + "strict": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "noImplicitReturns": true, // Good practice + "noFallthroughCasesInSwitch": true, + "forceConsistentCasingInFileNames": true, + "skipLibCheck": true, + }, + "include": ["src/**/*.ts", "src/**/*.tsx", "src/**/*.vue", "vite.config.ts"], + "exclude": ["node_modules", "dist"] +} diff --git a/vite.config.ts b/vite.config.ts new file mode 100644 index 0000000..7eceaee --- /dev/null +++ b/vite.config.ts @@ -0,0 +1,33 @@ +import { defineConfig } from 'vite'; +import vue from '@vitejs/plugin-vue'; + +import { fileURLToPath, URL } from 'node:url'; +import { resolve } from 'path'; + +export default defineConfig({ + plugins: [ + vue(), + ], + resolve: { + alias: { + '@': fileURLToPath(new URL('./src', import.meta.url)) + } + }, + build: { + lib: { + entry: resolve(__dirname, 'src/index.ts'), + name: 'VueOpenHarborData', + fileName: (format) => `vue-openharbor-data.${format}.js`, + }, + rollupOptions: { + + external: ['vue', '@openharbor/data'], + output: { + globals: { + vue: 'Vue', + '@openharbor/data': 'OpenHarborData', + }, + }, + }, + }, +}); diff --git a/yarn.lock b/yarn.lock new file mode 100644 index 0000000..4aee91c --- /dev/null +++ b/yarn.lock @@ -0,0 +1,629 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@babel/helper-string-parser@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz#54da796097ab19ce67ed9f88b47bb2ec49367687" + integrity sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA== + +"@babel/helper-validator-identifier@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.27.1.tgz#a7054dcc145a967dd4dc8fee845a57c1316c9df8" + integrity sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow== + +"@babel/parser@^7.27.5": + version "7.27.5" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.27.5.tgz#ed22f871f110aa285a6fd934a0efed621d118826" + integrity sha512-OsQd175SxWkGlzbny8J3K8TnnDD0N3lrIUtB92xwyRpzaenGZhxDvxN/JgU00U3CDZNj9tPuDJ5H0WS4Nt3vKg== + dependencies: + "@babel/types" "^7.27.3" + +"@babel/types@^7.27.3": + version "7.27.6" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.27.6.tgz#a434ca7add514d4e646c80f7375c0aa2befc5535" + integrity sha512-ETyHEk2VHHvl9b9jZP5IHPavHYk57EhanlRRuae9XCpb/j5bDCbPPMOBfCWhnl/7EDJz0jEMCi/RhccCE8r1+Q== + dependencies: + "@babel/helper-string-parser" "^7.27.1" + "@babel/helper-validator-identifier" "^7.27.1" + +"@esbuild/aix-ppc64@0.25.5": + version "0.25.5" + resolved "https://registry.yarnpkg.com/@esbuild/aix-ppc64/-/aix-ppc64-0.25.5.tgz#4e0f91776c2b340e75558f60552195f6fad09f18" + integrity sha512-9o3TMmpmftaCMepOdA5k/yDw8SfInyzWWTjYTFCX3kPSDJMROQTb8jg+h9Cnwnmm1vOzvxN7gIfB5V2ewpjtGA== + +"@esbuild/android-arm64@0.25.5": + version "0.25.5" + resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.25.5.tgz#bc766407f1718923f6b8079c8c61bf86ac3a6a4f" + integrity sha512-VGzGhj4lJO+TVGV1v8ntCZWJktV7SGCs3Pn1GRWI1SBFtRALoomm8k5E9Pmwg3HOAal2VDc2F9+PM/rEY6oIDg== + +"@esbuild/android-arm@0.25.5": + version "0.25.5" + resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.25.5.tgz#4290d6d3407bae3883ad2cded1081a234473ce26" + integrity sha512-AdJKSPeEHgi7/ZhuIPtcQKr5RQdo6OO2IL87JkianiMYMPbCtot9fxPbrMiBADOWWm3T2si9stAiVsGbTQFkbA== + +"@esbuild/android-x64@0.25.5": + version "0.25.5" + resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.25.5.tgz#40c11d9cbca4f2406548c8a9895d321bc3b35eff" + integrity sha512-D2GyJT1kjvO//drbRT3Hib9XPwQeWd9vZoBJn+bu/lVsOZ13cqNdDeqIF/xQ5/VmWvMduP6AmXvylO/PIc2isw== + +"@esbuild/darwin-arm64@0.25.5": + version "0.25.5" + resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.25.5.tgz#49d8bf8b1df95f759ac81eb1d0736018006d7e34" + integrity sha512-GtaBgammVvdF7aPIgH2jxMDdivezgFu6iKpmT+48+F8Hhg5J/sfnDieg0aeG/jfSvkYQU2/pceFPDKlqZzwnfQ== + +"@esbuild/darwin-x64@0.25.5": + version "0.25.5" + resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.25.5.tgz#e27a5d92a14886ef1d492fd50fc61a2d4d87e418" + integrity sha512-1iT4FVL0dJ76/q1wd7XDsXrSW+oLoquptvh4CLR4kITDtqi2e/xwXwdCVH8hVHU43wgJdsq7Gxuzcs6Iq/7bxQ== + +"@esbuild/freebsd-arm64@0.25.5": + version "0.25.5" + resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.5.tgz#97cede59d638840ca104e605cdb9f1b118ba0b1c" + integrity sha512-nk4tGP3JThz4La38Uy/gzyXtpkPW8zSAmoUhK9xKKXdBCzKODMc2adkB2+8om9BDYugz+uGV7sLmpTYzvmz6Sw== + +"@esbuild/freebsd-x64@0.25.5": + version "0.25.5" + resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.25.5.tgz#71c77812042a1a8190c3d581e140d15b876b9c6f" + integrity sha512-PrikaNjiXdR2laW6OIjlbeuCPrPaAl0IwPIaRv+SMV8CiM8i2LqVUHFC1+8eORgWyY7yhQY+2U2fA55mBzReaw== + +"@esbuild/linux-arm64@0.25.5": + version "0.25.5" + resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.25.5.tgz#f7b7c8f97eff8ffd2e47f6c67eb5c9765f2181b8" + integrity sha512-Z9kfb1v6ZlGbWj8EJk9T6czVEjjq2ntSYLY2cw6pAZl4oKtfgQuS4HOq41M/BcoLPzrUbNd+R4BXFyH//nHxVg== + +"@esbuild/linux-arm@0.25.5": + version "0.25.5" + resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.25.5.tgz#2a0be71b6cd8201fa559aea45598dffabc05d911" + integrity sha512-cPzojwW2okgh7ZlRpcBEtsX7WBuqbLrNXqLU89GxWbNt6uIg78ET82qifUy3W6OVww6ZWobWub5oqZOVtwolfw== + +"@esbuild/linux-ia32@0.25.5": + version "0.25.5" + resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.25.5.tgz#763414463cd9ea6fa1f96555d2762f9f84c61783" + integrity sha512-sQ7l00M8bSv36GLV95BVAdhJ2QsIbCuCjh/uYrWiMQSUuV+LpXwIqhgJDcvMTj+VsQmqAHL2yYaasENvJ7CDKA== + +"@esbuild/linux-loong64@0.25.5": + version "0.25.5" + resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.25.5.tgz#428cf2213ff786a502a52c96cf29d1fcf1eb8506" + integrity sha512-0ur7ae16hDUC4OL5iEnDb0tZHDxYmuQyhKhsPBV8f99f6Z9KQM02g33f93rNH5A30agMS46u2HP6qTdEt6Q1kg== + +"@esbuild/linux-mips64el@0.25.5": + version "0.25.5" + resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.25.5.tgz#5cbcc7fd841b4cd53358afd33527cd394e325d96" + integrity sha512-kB/66P1OsHO5zLz0i6X0RxlQ+3cu0mkxS3TKFvkb5lin6uwZ/ttOkP3Z8lfR9mJOBk14ZwZ9182SIIWFGNmqmg== + +"@esbuild/linux-ppc64@0.25.5": + version "0.25.5" + resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.25.5.tgz#0d954ab39ce4f5e50f00c4f8c4fd38f976c13ad9" + integrity sha512-UZCmJ7r9X2fe2D6jBmkLBMQetXPXIsZjQJCjgwpVDz+YMcS6oFR27alkgGv3Oqkv07bxdvw7fyB71/olceJhkQ== + +"@esbuild/linux-riscv64@0.25.5": + version "0.25.5" + resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.25.5.tgz#0e7dd30730505abd8088321e8497e94b547bfb1e" + integrity sha512-kTxwu4mLyeOlsVIFPfQo+fQJAV9mh24xL+y+Bm6ej067sYANjyEw1dNHmvoqxJUCMnkBdKpvOn0Ahql6+4VyeA== + +"@esbuild/linux-s390x@0.25.5": + version "0.25.5" + resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.25.5.tgz#5669af81327a398a336d7e40e320b5bbd6e6e72d" + integrity sha512-K2dSKTKfmdh78uJ3NcWFiqyRrimfdinS5ErLSn3vluHNeHVnBAFWC8a4X5N+7FgVE1EjXS1QDZbpqZBjfrqMTQ== + +"@esbuild/linux-x64@0.25.5": + version "0.25.5" + resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.25.5.tgz#b2357dd153aa49038967ddc1ffd90c68a9d2a0d4" + integrity sha512-uhj8N2obKTE6pSZ+aMUbqq+1nXxNjZIIjCjGLfsWvVpy7gKCOL6rsY1MhRh9zLtUtAI7vpgLMK6DxjO8Qm9lJw== + +"@esbuild/netbsd-arm64@0.25.5": + version "0.25.5" + resolved "https://registry.yarnpkg.com/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.5.tgz#53b4dfb8fe1cee93777c9e366893bd3daa6ba63d" + integrity sha512-pwHtMP9viAy1oHPvgxtOv+OkduK5ugofNTVDilIzBLpoWAM16r7b/mxBvfpuQDpRQFMfuVr5aLcn4yveGvBZvw== + +"@esbuild/netbsd-x64@0.25.5": + version "0.25.5" + resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.25.5.tgz#a0206f6314ce7dc8713b7732703d0f58de1d1e79" + integrity sha512-WOb5fKrvVTRMfWFNCroYWWklbnXH0Q5rZppjq0vQIdlsQKuw6mdSihwSo4RV/YdQ5UCKKvBy7/0ZZYLBZKIbwQ== + +"@esbuild/openbsd-arm64@0.25.5": + version "0.25.5" + resolved "https://registry.yarnpkg.com/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.5.tgz#2a796c87c44e8de78001d808c77d948a21ec22fd" + integrity sha512-7A208+uQKgTxHd0G0uqZO8UjK2R0DDb4fDmERtARjSHWxqMTye4Erz4zZafx7Di9Cv+lNHYuncAkiGFySoD+Mw== + +"@esbuild/openbsd-x64@0.25.5": + version "0.25.5" + resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.25.5.tgz#28d0cd8909b7fa3953af998f2b2ed34f576728f0" + integrity sha512-G4hE405ErTWraiZ8UiSoesH8DaCsMm0Cay4fsFWOOUcz8b8rC6uCvnagr+gnioEjWn0wC+o1/TAHt+It+MpIMg== + +"@esbuild/sunos-x64@0.25.5": + version "0.25.5" + resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.25.5.tgz#a28164f5b997e8247d407e36c90d3fd5ddbe0dc5" + integrity sha512-l+azKShMy7FxzY0Rj4RCt5VD/q8mG/e+mDivgspo+yL8zW7qEwctQ6YqKX34DTEleFAvCIUviCFX1SDZRSyMQA== + +"@esbuild/win32-arm64@0.25.5": + version "0.25.5" + resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.25.5.tgz#6eadbead38e8bd12f633a5190e45eff80e24007e" + integrity sha512-O2S7SNZzdcFG7eFKgvwUEZ2VG9D/sn/eIiz8XRZ1Q/DO5a3s76Xv0mdBzVM5j5R639lXQmPmSo0iRpHqUUrsxw== + +"@esbuild/win32-ia32@0.25.5": + version "0.25.5" + resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.25.5.tgz#bab6288005482f9ed2adb9ded7e88eba9a62cc0d" + integrity sha512-onOJ02pqs9h1iMJ1PQphR+VZv8qBMQ77Klcsqv9CNW2w6yLqoURLcgERAIurY6QE63bbLuqgP9ATqajFLK5AMQ== + +"@esbuild/win32-x64@0.25.5": + version "0.25.5" + resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.25.5.tgz#7fc114af5f6563f19f73324b5d5ff36ece0803d1" + integrity sha512-TXv6YnJ8ZMVdX+SXWVBo/0p8LTcrUYngpWjvm91TMjjBQii7Oz11Lw5lbDV5Y0TzuhSJHwiH4hEtC1I42mMS0g== + +"@jridgewell/sourcemap-codec@^1.5.0": + version "1.5.0" + resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz#3188bcb273a414b0d215fd22a58540b989b9409a" + integrity sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ== + +"@rollup/rollup-android-arm-eabi@4.44.0": + version "4.44.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.44.0.tgz#a3e4e4b2baf0bade6918cf5135c3ef7eee653196" + integrity sha512-xEiEE5oDW6tK4jXCAyliuntGR+amEMO7HLtdSshVuhFnKTYoeYMyXQK7pLouAJJj5KHdwdn87bfHAR2nSdNAUA== + +"@rollup/rollup-android-arm64@4.44.0": + version "4.44.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.44.0.tgz#63566b0e76c62d4f96d44448f38a290562280200" + integrity sha512-uNSk/TgvMbskcHxXYHzqwiyBlJ/lGcv8DaUfcnNwict8ba9GTTNxfn3/FAoFZYgkaXXAdrAA+SLyKplyi349Jw== + +"@rollup/rollup-darwin-arm64@4.44.0": + version "4.44.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.44.0.tgz#60a51a61b22b1f4fdf97b4adf5f0f447f492759d" + integrity sha512-VGF3wy0Eq1gcEIkSCr8Ke03CWT+Pm2yveKLaDvq51pPpZza3JX/ClxXOCmTYYq3us5MvEuNRTaeyFThCKRQhOA== + +"@rollup/rollup-darwin-x64@4.44.0": + version "4.44.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.44.0.tgz#bfe3059440f7032de11e749ece868cd7f232e609" + integrity sha512-fBkyrDhwquRvrTxSGH/qqt3/T0w5Rg0L7ZIDypvBPc1/gzjJle6acCpZ36blwuwcKD/u6oCE/sRWlUAcxLWQbQ== + +"@rollup/rollup-freebsd-arm64@4.44.0": + version "4.44.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.44.0.tgz#d5d4c6cd3b8acb7493b76227d8b2b4a2d732a37b" + integrity sha512-u5AZzdQJYJXByB8giQ+r4VyfZP+walV+xHWdaFx/1VxsOn6eWJhK2Vl2eElvDJFKQBo/hcYIBg/jaKS8ZmKeNQ== + +"@rollup/rollup-freebsd-x64@4.44.0": + version "4.44.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.44.0.tgz#cb4e1547b572cd0144c5fbd6c4a0edfed5fe6024" + integrity sha512-qC0kS48c/s3EtdArkimctY7h3nHicQeEUdjJzYVJYR3ct3kWSafmn6jkNCA8InbUdge6PVx6keqjk5lVGJf99g== + +"@rollup/rollup-linux-arm-gnueabihf@4.44.0": + version "4.44.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.44.0.tgz#feb81bd086f6a469777f75bec07e1bdf93352e69" + integrity sha512-x+e/Z9H0RAWckn4V2OZZl6EmV0L2diuX3QB0uM1r6BvhUIv6xBPL5mrAX2E3e8N8rEHVPwFfz/ETUbV4oW9+lQ== + +"@rollup/rollup-linux-arm-musleabihf@4.44.0": + version "4.44.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.44.0.tgz#68bff1c6620c155c9d8f5ee6a83c46eb50486f18" + integrity sha512-1exwiBFf4PU/8HvI8s80icyCcnAIB86MCBdst51fwFmH5dyeoWVPVgmQPcKrMtBQ0W5pAs7jBCWuRXgEpRzSCg== + +"@rollup/rollup-linux-arm64-gnu@4.44.0": + version "4.44.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.44.0.tgz#dbc5036a85e3ca3349887c8bdbebcfd011e460b0" + integrity sha512-ZTR2mxBHb4tK4wGf9b8SYg0Y6KQPjGpR4UWwTFdnmjB4qRtoATZ5dWn3KsDwGa5Z2ZBOE7K52L36J9LueKBdOQ== + +"@rollup/rollup-linux-arm64-musl@4.44.0": + version "4.44.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.44.0.tgz#72efc633aa0b93531bdfc69d70bcafa88e6152fc" + integrity sha512-GFWfAhVhWGd4r6UxmnKRTBwP1qmModHtd5gkraeW2G490BpFOZkFtem8yuX2NyafIP/mGpRJgTJ2PwohQkUY/Q== + +"@rollup/rollup-linux-loongarch64-gnu@4.44.0": + version "4.44.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.44.0.tgz#9b6a49afde86c8f57ca11efdf8fd8d7c52048817" + integrity sha512-xw+FTGcov/ejdusVOqKgMGW3c4+AgqrfvzWEVXcNP6zq2ue+lsYUgJ+5Rtn/OTJf7e2CbgTFvzLW2j0YAtj0Gg== + +"@rollup/rollup-linux-powerpc64le-gnu@4.44.0": + version "4.44.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.44.0.tgz#93cb96073efab0cdbf419c8dfc44b5e2bd815139" + integrity sha512-bKGibTr9IdF0zr21kMvkZT4K6NV+jjRnBoVMt2uNMG0BYWm3qOVmYnXKzx7UhwrviKnmK46IKMByMgvpdQlyJQ== + +"@rollup/rollup-linux-riscv64-gnu@4.44.0": + version "4.44.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.44.0.tgz#028708f73c8130ae924e5c3755de50fe93687249" + integrity sha512-vV3cL48U5kDaKZtXrti12YRa7TyxgKAIDoYdqSIOMOFBXqFj2XbChHAtXquEn2+n78ciFgr4KIqEbydEGPxXgA== + +"@rollup/rollup-linux-riscv64-musl@4.44.0": + version "4.44.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.44.0.tgz#878bfb158b2cf6671b7611fd58e5c80d9144ac6c" + integrity sha512-TDKO8KlHJuvTEdfw5YYFBjhFts2TR0VpZsnLLSYmB7AaohJhM8ctDSdDnUGq77hUh4m/djRafw+9zQpkOanE2Q== + +"@rollup/rollup-linux-s390x-gnu@4.44.0": + version "4.44.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.44.0.tgz#59b4ebb2129d34b7807ed8c462ff0baaefca9ad4" + integrity sha512-8541GEyktXaw4lvnGp9m84KENcxInhAt6vPWJ9RodsB/iGjHoMB2Pp5MVBCiKIRxrxzJhGCxmNzdu+oDQ7kwRA== + +"@rollup/rollup-linux-x64-gnu@4.44.0": + version "4.44.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.44.0.tgz#597d40f60d4b15bedbbacf2491a69c5b67a58e93" + integrity sha512-iUVJc3c0o8l9Sa/qlDL2Z9UP92UZZW1+EmQ4xfjTc1akr0iUFZNfxrXJ/R1T90h/ILm9iXEY6+iPrmYB3pXKjw== + +"@rollup/rollup-linux-x64-musl@4.44.0": + version "4.44.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.44.0.tgz#0a062d6fee35ec4fbb607b2a9d933a9372ccf63a" + integrity sha512-PQUobbhLTQT5yz/SPg116VJBgz+XOtXt8D1ck+sfJJhuEsMj2jSej5yTdp8CvWBSceu+WW+ibVL6dm0ptG5fcA== + +"@rollup/rollup-win32-arm64-msvc@4.44.0": + version "4.44.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.44.0.tgz#41ffab489857987c75385b0fc8cccf97f7e69d0a" + integrity sha512-M0CpcHf8TWn+4oTxJfh7LQuTuaYeXGbk0eageVjQCKzYLsajWS/lFC94qlRqOlyC2KvRT90ZrfXULYmukeIy7w== + +"@rollup/rollup-win32-ia32-msvc@4.44.0": + version "4.44.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.44.0.tgz#d9fb61d98eedfa52720b6ed9f31442b3ef4b839f" + integrity sha512-3XJ0NQtMAXTWFW8FqZKcw3gOQwBtVWP/u8TpHP3CRPXD7Pd6s8lLdH3sHWh8vqKCyyiI8xW5ltJScQmBU9j7WA== + +"@rollup/rollup-win32-x64-msvc@4.44.0": + version "4.44.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.44.0.tgz#a36e79b6ccece1533f777a1bca1f89c13f0c5f62" + integrity sha512-Q2Mgwt+D8hd5FIPUuPDsvPR7Bguza6yTkJxspDGkZj7tBRn2y4KSWYuIXpftFSjBra76TbKerCV7rgFPQrn+wQ== + +"@tsconfig/node20@^20.1.6": + version "20.1.6" + resolved "https://registry.yarnpkg.com/@tsconfig/node20/-/node20-20.1.6.tgz#cdf11db8322e1c245d5a4bb2e398239c82ae78b2" + integrity sha512-sz+Hqx9zwZDpZIV871WSbUzSqNIsXzghZydypnfgzPKLltVJfkINfUeTct31n/tTSa9ZE1ZOfKdRre1uHHquYQ== + +"@types/estree@1.0.8": + version "1.0.8" + resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.8.tgz#958b91c991b1867ced318bedea0e215ee050726e" + integrity sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w== + +"@types/node@^24.0.3": + version "24.0.3" + resolved "https://registry.yarnpkg.com/@types/node/-/node-24.0.3.tgz#f935910f3eece3a3a2f8be86b96ba833dc286cab" + integrity sha512-R4I/kzCYAdRLzfiCabn9hxWfbuHS573x+r0dJMkkzThEa7pbrcDWK+9zu3e7aBOouf+rQAciqPFMnxwr0aWgKg== + dependencies: + undici-types "~7.8.0" + +"@vitejs/plugin-vue@^5.2.3": + version "5.2.4" + resolved "https://registry.yarnpkg.com/@vitejs/plugin-vue/-/plugin-vue-5.2.4.tgz#9e8a512eb174bfc2a333ba959bbf9de428d89ad8" + integrity sha512-7Yx/SXSOcQq5HiiV3orevHUFn+pmMB4cgbEkDYgnkUWb0WfeQ/wa2yFv6D5ICiCQOVpjA7vYDXrC7AGO8yjDHA== + +"@volar/language-core@2.4.14", "@volar/language-core@~2.4.11": + version "2.4.14" + resolved "https://registry.yarnpkg.com/@volar/language-core/-/language-core-2.4.14.tgz#dac7573014d4f3bafb186cb16888ffea5698be71" + integrity sha512-X6beusV0DvuVseaOEy7GoagS4rYHgDHnTrdOj5jeUb49fW5ceQyP9Ej5rBhqgz2wJggl+2fDbbojq1XKaxDi6w== + dependencies: + "@volar/source-map" "2.4.14" + +"@volar/source-map@2.4.14": + version "2.4.14" + resolved "https://registry.yarnpkg.com/@volar/source-map/-/source-map-2.4.14.tgz#cdcecd533c2e767449b2414cc22327d2bda7ef95" + integrity sha512-5TeKKMh7Sfxo8021cJfmBzcjfY1SsXsPMMjMvjY7ivesdnybqqS+GxGAoXHAOUawQTwtdUxgP65Im+dEmvWtYQ== + +"@volar/typescript@~2.4.11": + version "2.4.14" + resolved "https://registry.yarnpkg.com/@volar/typescript/-/typescript-2.4.14.tgz#b99a1025dd6a8b751e96627ebcb0739ceed0e5f1" + integrity sha512-p8Z6f/bZM3/HyCdRNFZOEEzts51uV8WHeN8Tnfnm2EBv6FDB2TQLzfVx7aJvnl8ofKAOnS64B2O8bImBFaauRw== + dependencies: + "@volar/language-core" "2.4.14" + path-browserify "^1.0.1" + vscode-uri "^3.0.8" + +"@vue/compiler-core@3.5.17": + version "3.5.17" + resolved "https://registry.yarnpkg.com/@vue/compiler-core/-/compiler-core-3.5.17.tgz#23d291bd01b863da3ef2e26e7db84d8e01a9b4c5" + integrity sha512-Xe+AittLbAyV0pabcN7cP7/BenRBNcteM4aSDCtRvGw0d9OL+HG1u/XHLY/kt1q4fyMeZYXyIYrsHuPSiDPosA== + dependencies: + "@babel/parser" "^7.27.5" + "@vue/shared" "3.5.17" + entities "^4.5.0" + estree-walker "^2.0.2" + source-map-js "^1.2.1" + +"@vue/compiler-dom@3.5.17", "@vue/compiler-dom@^3.5.0": + version "3.5.17" + resolved "https://registry.yarnpkg.com/@vue/compiler-dom/-/compiler-dom-3.5.17.tgz#7bc19a20e23b670243a64b47ce3a890239b870be" + integrity sha512-+2UgfLKoaNLhgfhV5Ihnk6wB4ljyW1/7wUIog2puUqajiC29Lp5R/IKDdkebh9jTbTogTbsgB+OY9cEWzG95JQ== + dependencies: + "@vue/compiler-core" "3.5.17" + "@vue/shared" "3.5.17" + +"@vue/compiler-sfc@3.5.17": + version "3.5.17" + resolved "https://registry.yarnpkg.com/@vue/compiler-sfc/-/compiler-sfc-3.5.17.tgz#c518871276e26593612bdab36f3f5bcd053b13bf" + integrity sha512-rQQxbRJMgTqwRugtjw0cnyQv9cP4/4BxWfTdRBkqsTfLOHWykLzbOc3C4GGzAmdMDxhzU/1Ija5bTjMVrddqww== + dependencies: + "@babel/parser" "^7.27.5" + "@vue/compiler-core" "3.5.17" + "@vue/compiler-dom" "3.5.17" + "@vue/compiler-ssr" "3.5.17" + "@vue/shared" "3.5.17" + estree-walker "^2.0.2" + magic-string "^0.30.17" + postcss "^8.5.6" + source-map-js "^1.2.1" + +"@vue/compiler-ssr@3.5.17": + version "3.5.17" + resolved "https://registry.yarnpkg.com/@vue/compiler-ssr/-/compiler-ssr-3.5.17.tgz#14ba3b7bba6e0e1fd02002316263165a5d1046c7" + integrity sha512-hkDbA0Q20ZzGgpj5uZjb9rBzQtIHLS78mMilwrlpWk2Ep37DYntUz0PonQ6kr113vfOEdM+zTBuJDaceNIW0tQ== + dependencies: + "@vue/compiler-dom" "3.5.17" + "@vue/shared" "3.5.17" + +"@vue/compiler-vue2@^2.7.16": + version "2.7.16" + resolved "https://registry.yarnpkg.com/@vue/compiler-vue2/-/compiler-vue2-2.7.16.tgz#2ba837cbd3f1b33c2bc865fbe1a3b53fb611e249" + integrity sha512-qYC3Psj9S/mfu9uVi5WvNZIzq+xnXMhOwbTFKKDD7b1lhpnn71jXSFdTQ+WsIEk0ONCd7VV2IMm7ONl6tbQ86A== + dependencies: + de-indent "^1.0.2" + he "^1.2.0" + +"@vue/language-core@2.2.10": + version "2.2.10" + resolved "https://registry.yarnpkg.com/@vue/language-core/-/language-core-2.2.10.tgz#5ae1e71a4e16dd59d1e4bac167f4b9c8c04d9f17" + integrity sha512-+yNoYx6XIKuAO8Mqh1vGytu8jkFEOH5C8iOv3i8Z/65A7x9iAOXA97Q+PqZ3nlm2lxf5rOJuIGI/wDtx/riNYw== + dependencies: + "@volar/language-core" "~2.4.11" + "@vue/compiler-dom" "^3.5.0" + "@vue/compiler-vue2" "^2.7.16" + "@vue/shared" "^3.5.0" + alien-signals "^1.0.3" + minimatch "^9.0.3" + muggle-string "^0.4.1" + path-browserify "^1.0.1" + +"@vue/reactivity@3.5.17": + version "3.5.17" + resolved "https://registry.yarnpkg.com/@vue/reactivity/-/reactivity-3.5.17.tgz#169b5dcf96c7f23788e5ed9745ec8a7227f2125e" + integrity sha512-l/rmw2STIscWi7SNJp708FK4Kofs97zc/5aEPQh4bOsReD/8ICuBcEmS7KGwDj5ODQLYWVN2lNibKJL1z5b+Lw== + dependencies: + "@vue/shared" "3.5.17" + +"@vue/runtime-core@3.5.17": + version "3.5.17" + resolved "https://registry.yarnpkg.com/@vue/runtime-core/-/runtime-core-3.5.17.tgz#b17bd41e13011e85e9b1025545292d43f5512730" + integrity sha512-QQLXa20dHg1R0ri4bjKeGFKEkJA7MMBxrKo2G+gJikmumRS7PTD4BOU9FKrDQWMKowz7frJJGqBffYMgQYS96Q== + dependencies: + "@vue/reactivity" "3.5.17" + "@vue/shared" "3.5.17" + +"@vue/runtime-dom@3.5.17": + version "3.5.17" + resolved "https://registry.yarnpkg.com/@vue/runtime-dom/-/runtime-dom-3.5.17.tgz#8e325e29cd03097fe179032fc8df384a426fc83a" + integrity sha512-8El0M60TcwZ1QMz4/os2MdlQECgGoVHPuLnQBU3m9h3gdNRW9xRmI8iLS4t/22OQlOE6aJvNNlBiCzPHur4H9g== + dependencies: + "@vue/reactivity" "3.5.17" + "@vue/runtime-core" "3.5.17" + "@vue/shared" "3.5.17" + csstype "^3.1.3" + +"@vue/server-renderer@3.5.17": + version "3.5.17" + resolved "https://registry.yarnpkg.com/@vue/server-renderer/-/server-renderer-3.5.17.tgz#9b8fd6a40a3d55322509fafe78ac841ede649fbe" + integrity sha512-BOHhm8HalujY6lmC3DbqF6uXN/K00uWiEeF22LfEsm9Q93XeJ/plHTepGwf6tqFcF7GA5oGSSAAUock3VvzaCA== + dependencies: + "@vue/compiler-ssr" "3.5.17" + "@vue/shared" "3.5.17" + +"@vue/shared@3.5.17", "@vue/shared@^3.5.0": + version "3.5.17" + resolved "https://registry.yarnpkg.com/@vue/shared/-/shared-3.5.17.tgz#e8b3a41f0be76499882a89e8ed40d86a70fa4b70" + integrity sha512-CabR+UN630VnsJO/jHWYBC1YVXyMq94KKp6iF5MQgZJs5I8cmjw6oVMO1oDbtBkENSHSSn/UadWlW/OAgdmKrg== + +"@vue/tsconfig@^0.7.0": + version "0.7.0" + resolved "https://registry.yarnpkg.com/@vue/tsconfig/-/tsconfig-0.7.0.tgz#67044c847b7a137b8cbfd6b23104c36dbaf80d1d" + integrity sha512-ku2uNz5MaZ9IerPPUyOHzyjhXoX2kVJaVf7hL315DC17vS6IiZRmmCPfggNbU16QTvM80+uYYy3eYJB59WCtvg== + +alien-signals@^1.0.3: + version "1.0.13" + resolved "https://registry.yarnpkg.com/alien-signals/-/alien-signals-1.0.13.tgz#8d6db73462f742ee6b89671fbd8c37d0b1727a7e" + integrity sha512-OGj9yyTnJEttvzhTUWuscOvtqxq5vrhF7vL9oS0xJ2mK0ItPYP1/y+vCFebfxoEyAz0++1AIwJ5CMr+Fk3nDmg== + +balanced-match@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" + integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== + +brace-expansion@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.0.2.tgz#54fc53237a613d854c7bd37463aad17df87214e7" + integrity sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ== + dependencies: + balanced-match "^1.0.0" + +csstype@^3.1.3: + version "3.1.3" + resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.1.3.tgz#d80ff294d114fb0e6ac500fbf85b60137d7eff81" + integrity sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw== + +de-indent@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/de-indent/-/de-indent-1.0.2.tgz#b2038e846dc33baa5796128d0804b455b8c1e21d" + integrity sha512-e/1zu3xH5MQryN2zdVaF0OrdNLUbvWxzMbi+iNA6Bky7l1RoP8a2fIbRocyHclXt/arDrrR6lL3TqFD9pMQTsg== + +entities@^4.5.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/entities/-/entities-4.5.0.tgz#5d268ea5e7113ec74c4d033b79ea5a35a488fb48" + integrity sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw== + +esbuild@^0.25.0: + version "0.25.5" + resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.25.5.tgz#71075054993fdfae76c66586f9b9c1f8d7edd430" + integrity sha512-P8OtKZRv/5J5hhz0cUAdu/cLuPIKXpQl1R9pZtvmHWQvrAUVd0UNIPT4IB4W3rNOqVO0rlqHmCIbSwxh/c9yUQ== + optionalDependencies: + "@esbuild/aix-ppc64" "0.25.5" + "@esbuild/android-arm" "0.25.5" + "@esbuild/android-arm64" "0.25.5" + "@esbuild/android-x64" "0.25.5" + "@esbuild/darwin-arm64" "0.25.5" + "@esbuild/darwin-x64" "0.25.5" + "@esbuild/freebsd-arm64" "0.25.5" + "@esbuild/freebsd-x64" "0.25.5" + "@esbuild/linux-arm" "0.25.5" + "@esbuild/linux-arm64" "0.25.5" + "@esbuild/linux-ia32" "0.25.5" + "@esbuild/linux-loong64" "0.25.5" + "@esbuild/linux-mips64el" "0.25.5" + "@esbuild/linux-ppc64" "0.25.5" + "@esbuild/linux-riscv64" "0.25.5" + "@esbuild/linux-s390x" "0.25.5" + "@esbuild/linux-x64" "0.25.5" + "@esbuild/netbsd-arm64" "0.25.5" + "@esbuild/netbsd-x64" "0.25.5" + "@esbuild/openbsd-arm64" "0.25.5" + "@esbuild/openbsd-x64" "0.25.5" + "@esbuild/sunos-x64" "0.25.5" + "@esbuild/win32-arm64" "0.25.5" + "@esbuild/win32-ia32" "0.25.5" + "@esbuild/win32-x64" "0.25.5" + +estree-walker@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-2.0.2.tgz#52f010178c2a4c117a7757cfe942adb7d2da4cac" + integrity sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w== + +fdir@^6.4.4: + version "6.4.6" + resolved "https://registry.yarnpkg.com/fdir/-/fdir-6.4.6.tgz#2b268c0232697063111bbf3f64810a2a741ba281" + integrity sha512-hiFoqpyZcfNm1yc4u8oWCf9A2c4D3QjCrks3zmoVKVxpQRzmPNar1hUJcBG2RQHvEVGDN+Jm81ZheVLAQMK6+w== + +fsevents@~2.3.2, fsevents@~2.3.3: + version "2.3.3" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6" + integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw== + +he@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" + integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== + +magic-string@^0.30.17: + version "0.30.17" + resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.30.17.tgz#450a449673d2460e5bbcfba9a61916a1714c7453" + integrity sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA== + dependencies: + "@jridgewell/sourcemap-codec" "^1.5.0" + +minimatch@^9.0.3: + version "9.0.5" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.5.tgz#d74f9dd6b57d83d8e98cfb82133b03978bc929e5" + integrity sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow== + dependencies: + brace-expansion "^2.0.1" + +muggle-string@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/muggle-string/-/muggle-string-0.4.1.tgz#3b366bd43b32f809dc20659534dd30e7c8a0d328" + integrity sha512-VNTrAak/KhO2i8dqqnqnAHOa3cYBwXEZe9h+D5h/1ZqFSTEFHdM65lR7RoIqq3tBBYavsOXV84NoHXZ0AkPyqQ== + +nanoid@^3.3.11: + version "3.3.11" + resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.11.tgz#4f4f112cefbe303202f2199838128936266d185b" + integrity sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w== + +path-browserify@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/path-browserify/-/path-browserify-1.0.1.tgz#d98454a9c3753d5790860f16f68867b9e46be1fd" + integrity sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g== + +picocolors@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.1.1.tgz#3d321af3eab939b083c8f929a1d12cda81c26b6b" + integrity sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA== + +picomatch@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-4.0.2.tgz#77c742931e8f3b8820946c76cd0c1f13730d1dab" + integrity sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg== + +postcss@^8.5.3, postcss@^8.5.6: + version "8.5.6" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.5.6.tgz#2825006615a619b4f62a9e7426cc120b349a8f3c" + integrity sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg== + dependencies: + nanoid "^3.3.11" + picocolors "^1.1.1" + source-map-js "^1.2.1" + +rollup@^4.34.9: + version "4.44.0" + resolved "https://registry.yarnpkg.com/rollup/-/rollup-4.44.0.tgz#0e10b98339b306edad1e612f1e5590a79aef521c" + integrity sha512-qHcdEzLCiktQIfwBq420pn2dP+30uzqYxv9ETm91wdt2R9AFcWfjNAmje4NWlnCIQ5RMTzVf0ZyisOKqHR6RwA== + dependencies: + "@types/estree" "1.0.8" + optionalDependencies: + "@rollup/rollup-android-arm-eabi" "4.44.0" + "@rollup/rollup-android-arm64" "4.44.0" + "@rollup/rollup-darwin-arm64" "4.44.0" + "@rollup/rollup-darwin-x64" "4.44.0" + "@rollup/rollup-freebsd-arm64" "4.44.0" + "@rollup/rollup-freebsd-x64" "4.44.0" + "@rollup/rollup-linux-arm-gnueabihf" "4.44.0" + "@rollup/rollup-linux-arm-musleabihf" "4.44.0" + "@rollup/rollup-linux-arm64-gnu" "4.44.0" + "@rollup/rollup-linux-arm64-musl" "4.44.0" + "@rollup/rollup-linux-loongarch64-gnu" "4.44.0" + "@rollup/rollup-linux-powerpc64le-gnu" "4.44.0" + "@rollup/rollup-linux-riscv64-gnu" "4.44.0" + "@rollup/rollup-linux-riscv64-musl" "4.44.0" + "@rollup/rollup-linux-s390x-gnu" "4.44.0" + "@rollup/rollup-linux-x64-gnu" "4.44.0" + "@rollup/rollup-linux-x64-musl" "4.44.0" + "@rollup/rollup-win32-arm64-msvc" "4.44.0" + "@rollup/rollup-win32-ia32-msvc" "4.44.0" + "@rollup/rollup-win32-x64-msvc" "4.44.0" + fsevents "~2.3.2" + +source-map-js@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.2.1.tgz#1ce5650fddd87abc099eda37dcff024c2667ae46" + integrity sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA== + +tinyglobby@^0.2.13: + version "0.2.14" + resolved "https://registry.yarnpkg.com/tinyglobby/-/tinyglobby-0.2.14.tgz#5280b0cf3f972b050e74ae88406c0a6a58f4079d" + integrity sha512-tX5e7OM1HnYr2+a2C/4V0htOcSQcoSTH9KgJnVvNm5zm/cyEWKJ7j7YutsH9CxMdtOkkLFy2AHrMci9IM8IPZQ== + dependencies: + fdir "^6.4.4" + picomatch "^4.0.2" + +typescript@~5.8.3: + version "5.8.3" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.8.3.tgz#92f8a3e5e3cf497356f4178c34cd65a7f5e8440e" + integrity sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ== + +undici-types@~7.8.0: + version "7.8.0" + resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-7.8.0.tgz#de00b85b710c54122e44fbfd911f8d70174cd294" + integrity sha512-9UJ2xGDvQ43tYyVMpuHlsgApydB8ZKfVYTsLDhXkFL/6gfkp+U8xTGdh8pMJv1SpZna0zxG1DwsKZsreLbXBxw== + +vite@^6.3.5: + version "6.3.5" + resolved "https://registry.yarnpkg.com/vite/-/vite-6.3.5.tgz#fec73879013c9c0128c8d284504c6d19410d12a3" + integrity sha512-cZn6NDFE7wdTpINgs++ZJ4N49W2vRp8LCKrn3Ob1kYNtOo21vfDoaV5GzBfLU4MovSAB8uNRm4jgzVQZ+mBzPQ== + dependencies: + esbuild "^0.25.0" + fdir "^6.4.4" + picomatch "^4.0.2" + postcss "^8.5.3" + rollup "^4.34.9" + tinyglobby "^0.2.13" + optionalDependencies: + fsevents "~2.3.3" + +vscode-uri@^3.0.8: + version "3.1.0" + resolved "https://registry.yarnpkg.com/vscode-uri/-/vscode-uri-3.1.0.tgz#dd09ec5a66a38b5c3fffc774015713496d14e09c" + integrity sha512-/BpdSx+yCQGnCvecbyXdxHDkuk55/G3xwnC0GqY4gmQ3j+A+g8kzzgB4Nk/SINjqn6+waqw3EgbVF2QKExkRxQ== + +vue-tsc@^2.2.8: + version "2.2.10" + resolved "https://registry.yarnpkg.com/vue-tsc/-/vue-tsc-2.2.10.tgz#7b51a666cb90788884efd0caedc69fc1fc9c5b78" + integrity sha512-jWZ1xSaNbabEV3whpIDMbjVSVawjAyW+x1n3JeGQo7S0uv2n9F/JMgWW90tGWNFRKya4YwKMZgCtr0vRAM7DeQ== + dependencies: + "@volar/typescript" "~2.4.11" + "@vue/language-core" "2.2.10" + +vue@^3.5.13: + version "3.5.17" + resolved "https://registry.yarnpkg.com/vue/-/vue-3.5.17.tgz#ea8a6a45abb2b0620e7d479319ce8434b55650cf" + integrity sha512-LbHV3xPN9BeljML+Xctq4lbz2lVHCR6DtbpTf5XIO6gugpXUN49j2QQPcMj086r9+AkJ0FfUT8xjulKKBkkr9g== + dependencies: + "@vue/compiler-dom" "3.5.17" + "@vue/compiler-sfc" "3.5.17" + "@vue/runtime-dom" "3.5.17" + "@vue/server-renderer" "3.5.17" + "@vue/shared" "3.5.17"