├── .eslintignore ├── .eslintrc.js ├── .github └── workflows │ ├── node.js.yml │ └── pull-request.yml ├── .gitignore ├── .npmignore ├── .prettierignore ├── .prettierrc.json ├── LICENSE ├── README.md ├── package.json ├── pnpm-lock.yaml ├── src ├── attributes.ts ├── database.ts ├── index.ts ├── model.ts └── plugins │ └── Date │ ├── DateType.ts │ └── index.ts ├── test ├── Cases.spec.ts ├── Database.spec.ts ├── Model.spec.ts └── unit │ ├── AttrField.spec.ts │ ├── BooleanField.spec.ts │ ├── DateField.spec.ts │ ├── NumberField.spec.ts │ ├── PrimaryKey.spec.ts │ ├── StringField.spec.ts │ ├── UidField.spec.ts │ └── relationships │ ├── BelongsToField.spec.ts │ ├── BelongsToManyField.spec.ts │ ├── HasManyByField.spec.ts │ ├── HasManyField.spec.ts │ ├── HasManyThroughField.spec.ts │ ├── HasOneField.spec.ts │ ├── MorphManyField.spec.ts │ ├── MorphOneField.spec.ts │ ├── MorphToField.spec.ts │ ├── MorphToManyField.spec.ts │ └── fixtures │ ├── Profile.ts │ └── User.ts ├── tsconfig.json └── vitest.config.ts /.eslintignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | dist 3 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | // http://eslint.org/docs/user-guide/configuring 2 | module.exports = { 3 | root: true, 4 | parserOptions: { 5 | parser: "@typescript-eslint/parser", 6 | ecmaVersion: "latest", 7 | }, 8 | env: { 9 | node: true, 10 | }, 11 | // https://github.com/airbnb/javascript 12 | extends: ["eslint:recommended", "plugin:@typescript-eslint/recommended", "prettier"], 13 | plugins: ["@typescript-eslint", "unused-imports", "sort-imports-es6-autofix", "prettier"], 14 | settings: { 15 | "import/resolver": { 16 | typescript: { 17 | project: ".", 18 | }, 19 | }, 20 | }, 21 | rules: { 22 | // https://github.com/typescript-eslint/typescript-eslint/tree/main/packages/eslint-plugin/docs/rules 23 | "@typescript-eslint/ban-types": "off", 24 | "@typescript-eslint/no-explicit-any": "off", 25 | "@typescript-eslint/no-empty-function": "off", 26 | "@typescript-eslint/no-empty-interface": "off", 27 | "@typescript-eslint/explicit-function-return-type": "off", 28 | "@typescript-eslint/consistent-type-imports": "error", 29 | "@typescript-eslint/lines-between-class-members": [ 30 | "error", 31 | "always", 32 | { 33 | exceptAfterOverload: true, 34 | exceptAfterSingleLine: true, 35 | }, 36 | ], 37 | 38 | // http://eslint.org/docs/rules/ 39 | "no-empty-pattern": "off", 40 | "newline-before-return": "error", 41 | curly: "error", 42 | "eol-last": ["error", "always"], 43 | "no-alert": process.env.NODE_ENV === "production" ? "error" : "off", 44 | "no-console": process.env.NODE_ENV === "production" ? "error" : "off", 45 | "no-debugger": process.env.NODE_ENV === "production" ? "error" : "off", 46 | "newline-after-var": ["error", "always"], 47 | "one-var": ["error", "never"], 48 | "padded-blocks": [ 49 | "error", 50 | { 51 | classes: "never", 52 | blocks: "never", 53 | }, 54 | ], 55 | quotes: [ 56 | "error", 57 | "double", 58 | { 59 | allowTemplateLiterals: true, 60 | }, 61 | ], 62 | "no-multiple-empty-lines": ["error", { max: 1, maxBOF: 0, maxEOF: 0 }], 63 | "padding-line-between-statements": [ 64 | "error", 65 | { blankLine: "always", prev: "*", next: "export" }, 66 | { blankLine: "never", prev: ["let", "const"], next: ["let", "const"] }, 67 | { blankLine: "always", prev: "cjs-import", next: ["let", "const"] }, 68 | { blankLine: "never", prev: "cjs-import", next: "cjs-import" }, 69 | { blankLine: "always", prev: "block-like", next: "*" }, 70 | { blankLine: "always", prev: "*", next: "block-like" }, 71 | ], 72 | 73 | // https://github.com/marudor/eslint-plugin-sort-imports-es6-autofix 74 | "sort-imports-es6-autofix/sort-imports-es6": [ 75 | "error", 76 | { 77 | ignoreCase: true, 78 | ignoreMemberSort: false, 79 | memberSyntaxSortOrder: ["none", "all", "multiple", "single"], 80 | }, 81 | ], 82 | 83 | // https://github.com/sweepline/eslint-plugin-unused-imports 84 | "unused-imports/no-unused-imports-ts": "error", 85 | }, 86 | ignorePatterns: ["dist"], 87 | }; 88 | -------------------------------------------------------------------------------- /.github/workflows/node.js.yml: -------------------------------------------------------------------------------- 1 | name: Node.js CI 2 | 3 | on: 4 | push: 5 | branches: [ master ] 6 | 7 | jobs: 8 | build: 9 | name: Build and Publish 10 | runs-on: ubuntu-latest 11 | 12 | steps: 13 | - uses: actions/checkout@v3 14 | - uses: pnpm/action-setup@v2 15 | with: 16 | version: 7.11.0 17 | - uses: actions/setup-node@v3 18 | with: 19 | node-version: 16 20 | cache: "pnpm" 21 | 22 | - name: Install Dependencies 23 | run: pnpm install 24 | 25 | - name: Build 26 | run: pnpm build 27 | 28 | - name: Publish 29 | uses: JS-DevTools/npm-publish@v1 30 | with: 31 | token: ${{ secrets.NPM_AUTH_TOKEN }} 32 | check-version: false 33 | -------------------------------------------------------------------------------- /.github/workflows/pull-request.yml: -------------------------------------------------------------------------------- 1 | name: Node.js CI 2 | 3 | on: 4 | pull_request: 5 | branches: [ master ] 6 | 7 | jobs: 8 | test: 9 | name: Testing 10 | runs-on: ubuntu-latest 11 | 12 | steps: 13 | - uses: actions/checkout@v3 14 | - uses: pnpm/action-setup@v2 15 | with: 16 | version: 7.11.0 17 | - uses: actions/setup-node@v3 18 | with: 19 | node-version: 16 20 | cache: "pnpm" 21 | 22 | - name: Install Dependencies 23 | run: pnpm install 24 | 25 | - name: Run Tests 26 | run: pnpm test 27 | 28 | - name: Save Code Linting Report 29 | run: pnpm lint:report 30 | continue-on-error: true 31 | 32 | - name: Annotate Code Linting Results 33 | uses: ataylorme/eslint-annotate-action@1.1.2 34 | with: 35 | repo-token: "${{ secrets.GITHUB_TOKEN }}" 36 | report-json: "eslint_report.json" 37 | 38 | - name: Upload ESLint report 39 | uses: actions/upload-artifact@v1 40 | with: 41 | name: eslint_report.json 42 | path: eslint_report.json 43 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | .vscode 3 | coverage 4 | dist 5 | node_modules 6 | .DS_Store 7 | yarn.lock 8 | package-lock.json 9 | eslint_report.json 10 | *.txt 11 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | .github 2 | .idea 3 | .vscode 4 | .eslintignore 5 | .eslintrc.js 6 | coverage 7 | src 8 | test 9 | tsconfig.json 10 | .DS_Store 11 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | dist 2 | -------------------------------------------------------------------------------- /.prettierrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "printWidth": 100, 3 | "tabWidth": 4, 4 | "trailingComma": "es5" 5 | } 6 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 Michalis Giannas 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # vuex-orm-decorators 2 | 3 | Decorator Syntax for Vuex ORM `v0.36` for better type safety and a better experience. 4 | 5 | ![NPM](https://img.shields.io/npm/l/vuex-orm-decorators.svg) ![GitHub issues](https://img.shields.io/github/issues/TiBianMod/vuex-orm-decorators.svg) ![Snyk Vulnerabilities for GitHub Repo](https://img.shields.io/snyk/vulnerabilities/github/TiBianMod/vuex-orm-decorators.svg) ![](https://img.shields.io/badge/types-Typescript-blue.svg) 6 | 7 | --- 8 | 9 | :fire: **Quick note before start using this package** 10 | * [Pinia](https://github.com/vuejs/pinia) is the new official state management library for [Vue](https://github.com/vuejs/core) 11 | * [Vuex](https://github.com/vuejs/vuex) and [Vuex ORM](https://github.com/vuex-orm/vuex-orm) considered deprecated!!! 12 | * If you need to use Vuex ORM, please make use of [Vuex ORM Next](https://github.com/vuex-orm/vuex-orm-next) 13 | * This is the next iteration of Vuex ORM 14 | * New documentation is ongoing and can be found at https://next.vuex-orm.org 15 | 16 | --- 17 | 18 | Typescript Decorators to simplify Vuex ORM integration in typescript projects. If you are using 19 | the [vue-module-decorators](https://github.com/championswimmer/vuex-module-decorators) 20 | or [vue-property-decorator](https://github.com/kaorun343/vue-property-decorator) packages then this will allow you to 21 | use the Vuex ORM plugin in the same way. 22 | 23 | Using the decorators allows better type safety in your projects by allowing you to create conventional Typescript 24 | properties, and annotate them as fields for a better experience. Intellisense in Visual Studio Code just works with the 25 | annotations, where it doesn't in the vanilla plugin without boilerplate. 26 | 27 | This documentation isn't supposed to be a replacement for the Vuex ORM documentation, if you are unfamiliar with the 28 | concepts of Vuex ORM then check out their [documentation](https://vuex-orm.org/guide/prologue/what-is-vuex-orm.html). I 29 | have linked to relevant guide pages in their documentation throughout this documentation. 30 | 31 | ##### Contribute 32 | 33 | If you have improvements or contributions to make, I will happily check and merge in pull requests. 34 | 35 | # Setup 36 | 37 | ### Installation 38 | 39 | First install the version of vuex you want to use, Vuex ORM Decorators works with vuex 3 and vuex 4. 40 | 41 | You can install Vuex ORM Decorators via NPM or Yarn 42 | 43 | ### NPM 44 | 45 | ```console 46 | npm install @vuex-orm/core@^0.36 47 | npm install vuex-orm-decorators -D 48 | ``` 49 | 50 | ### pnpm 51 | 52 | ```console 53 | pnpm add @vuex-orm/core@^0.36 54 | pnpm add vuex-orm-decorators -D 55 | ``` 56 | 57 | ### Yarn 58 | 59 | ```console 60 | yarn add @vuex-orm/core@^0.36 61 | yarn add vuex-orm-decorators -D 62 | ``` 63 | 64 | This package targets es2015, if you need to target es5 then you will need to get VUE-CLI to transpile this package. 65 | 66 | ### Auto Model Registration 67 | 68 | Models can automatically register themselves in the database. To do so, instead of installing 69 | the [Vuex ORM Database](https://vuex-orm.org/guide/prologue/getting-started.html#register-models-to-vuex), install the 70 | wrapper provided by this library as follows: 71 | 72 | ### vue 2 with vuex v3 73 | 74 | ```typescript 75 | import Vue from 'vue'; 76 | import Vuex from 'vuex'; 77 | import { ORMDatabase } from 'vuex-orm-decorators' 78 | 79 | Vue.use(Vuex); 80 | 81 | export default new Vuex.Store({ 82 | plugins: [ 83 | ORMDatabase.install({ namespace: 'Models' }) 84 | ] 85 | }); 86 | ``` 87 | 88 | ### vue 3 with vuex v4 89 | 90 | ```typescript 91 | import { createStore } from 'vuex'; 92 | import { ORMDatabase } from 'vuex-orm-decorators'; 93 | 94 | export default createStore({ 95 | plugins: [ 96 | ORMDatabase.install({ namespace: 'Models' }) 97 | ] 98 | }); 99 | ``` 100 | 101 | When you use a model it registers itself in the database automatically if it has not already. If you do not want auto 102 | registered models, simply install the vanilla database and register them as you would normally. 103 | 104 | ### Typescript 105 | 106 | 1. Set `ExperimentalDecorators` to true. 107 | 2. Set `importHelpers: true` in `tsconfig.json`. 108 | 3. Set `emitHelpers: true` in `tsconfig.json` (only required in typescript 2) 109 | 110 | ### Nuxt.js 111 | 112 | Add the following to the nuxt.config.js to transpile the library 113 | 114 | ```javascript 115 | { 116 | build: { 117 | transpile: ['vuex-orm-decorators'] 118 | } 119 | } 120 | ``` 121 | 122 | If you want to register models automatically do not install Vuex ORM Database, just export plugin from store/index.js 123 | 124 | ```javascript 125 | import { ORMDatabase } from 'vuex-orm-decorators' 126 | 127 | export const plugins = [ORMDatabase.install({ namespace: 'Models' })] 128 | ``` 129 | 130 | # Usage 131 | 132 | ### Basic Usage 133 | 134 | Out of the box a Vuex ORM Model is defined as: 135 | 136 | ```typescript 137 | import { Model } from '@vuex-orm/core'; 138 | 139 | class User extends Model { 140 | 141 | static entity = 'users'; 142 | 143 | static fields() { 144 | return { 145 | id: this.attr(undefined), 146 | name: this.attr('') 147 | }; 148 | } 149 | 150 | } 151 | ``` 152 | 153 | The defined fields don't gain type checking by Typescript in this way because they are never defined as properties of 154 | the model class. With this decorator library though it allows you to write the same in the following way to achieve type 155 | checking on your queried models: 156 | 157 | ```typescript 158 | import { Model } from '@vuex-orm/core'; 159 | import { NumberField, OrmModel, StringField } from 'vuex-orm-decorators'; 160 | 161 | @OrmModel('users') 162 | class User extends Model { 163 | 164 | @NumberField() id!: number; 165 | 166 | @StringField() name!: string; 167 | 168 | } 169 | ``` 170 | 171 | ### Getters 172 | 173 | To create a fully reactive getter/computed, simply add your getters to the model class: 174 | 175 | ```typescript 176 | import { Model } from '@vuex-orm/core'; 177 | import { NumberField, OrmModel, StringField } from 'vuex-orm-decorators'; 178 | 179 | @OrmModel('users') 180 | class User extends Model { 181 | 182 | @NumberField() id!: number; 183 | 184 | @StringField() name!: string; 185 | 186 | get lowerName() { 187 | return this.name.toLowerCase(); 188 | } 189 | 190 | } 191 | ``` 192 | 193 | ### Mutators 194 | 195 | You can pass a closure to the 2nd argument of `@AttrField`, `@StringField`, `@NumberField`, `@DateField`, 196 | and `@BooleanField` decorator. The closure takes the corresponding value as an argument, and you can modify the value 197 | however you want: 198 | 199 | ```typescript 200 | import { Model } from '@vuex-orm/core'; 201 | import { OrmModel, StringField } from 'vuex-orm-decorators'; 202 | 203 | @OrmModel('users') 204 | class User extends Model { 205 | 206 | @StringField(null, (name) => { 207 | return name.toLowerCase(); 208 | }) name!: string; 209 | 210 | } 211 | ``` 212 | 213 | ### Default Values 214 | 215 | If undefined the default values for the `@AttrField`, `@StringField`, `@NumberField`, `@DateField`, and `@BooleanField` 216 | decorator will be: 217 | 218 | ```typescript 219 | @OrmModel('users') 220 | class User extends Model { 221 | 222 | // Default value: '' 223 | @AttrField() email!: string; 224 | 225 | // Default value: '' 226 | @StringField() name!: string; 227 | 228 | // Default value: 0 229 | @NumberField() age!: number; 230 | 231 | // Default value: false 232 | @BooleanField() active!: boolean; 233 | 234 | // Default value: null 235 | // if can parse the date, then Date instance will be returned 236 | @DateField() created_at!: Date; 237 | 238 | } 239 | ``` 240 | 241 | If you want to set the field as `nullable`, pass a `null` value as default value, this will also set the `isNullable` 242 | Type to `true`: 243 | 244 | ```typescript 245 | @OrmModel('users') 246 | class User extends Model { 247 | 248 | // Default value: null, isNullable: true 249 | @AttrField(null) email!: string; 250 | 251 | // Default value: null, isNullable: true 252 | @StringField(null) name!: string; 253 | 254 | // Default value: null, isNullable: true 255 | @NumberField(null) age!: number; 256 | 257 | // Default value: null, isNullable: true 258 | @BooleanField(null) active!: boolean; 259 | 260 | // Default value: null, isNullable: true 261 | @DateField(null) deleted_at!: Date; 262 | 263 | } 264 | ``` 265 | 266 | ### Setting a Primary Key 267 | 268 | Rather than setting a [primary key](https://vuex-orm.org/guide/model/defining-models.html#primary-key) by setting the 269 | static property `primaryKey` with the magic string name of the property you want to be the primary key, you can simply 270 | annotate the property with the `@PrimaryKey` decorator as follows: 271 | 272 | > No need using `@PrimaryKey` decorator on property `id`. Property `id` is by default the `primaryKey`. 273 | 274 | ```typescript 275 | import { Model } from '@vuex-orm/core'; 276 | import { NumberField, OrmModel, PrimaryKey, StringField } from 'vuex-orm-decorators'; 277 | 278 | @OrmModel('users') 279 | class User extends Model { 280 | 281 | @PrimaryKey() 282 | @NumberField() uuid!: number; 283 | 284 | @StringField() name!: string; 285 | 286 | } 287 | ``` 288 | 289 | In this example the property `uuid` replaces the default `id` property as the primary key. 290 | 291 | You can also define a composite primary key by annotating several properties with the `@PrimaryKey` decorator as follows: 292 | 293 | ```typescript 294 | import { Model } from '@vuex-orm/core'; 295 | import { OrmModel, PrimaryKey, StringField } from 'vuex-orm-decorators'; 296 | 297 | @OrmModel('users') 298 | class User extends Model { 299 | 300 | @PrimaryKey() 301 | @StringField() public id!: string; 302 | 303 | @PrimaryKey() 304 | @StringField() public voteId!: string; 305 | 306 | } 307 | ``` 308 | 309 | ### Single Table Inheritance 310 | 311 | If your model extends a base model, then STI inheritance needs to be used. The base entity name needs to be provided as 312 | the second argument to the ORMModel decorator and as third argument provide the discriminator fields: 313 | 314 | > Person : Base Entity 315 | 316 | ```typescript 317 | @OrmModel('persons') 318 | class Person extends Model { 319 | 320 | @NumberField() id!: number; 321 | 322 | @StringField() name!: string; 323 | 324 | } 325 | ``` 326 | 327 | > Teenager extends Person 328 | 329 | ```typescript 330 | @OrmModel('teenagers', 'persons', { 331 | PERSON: Person, 332 | TEENAGER: Teenager 333 | }) 334 | class Teenager extends Person { 335 | 336 | @StringField() school!: string; 337 | 338 | } 339 | ``` 340 | 341 | > Adult extends Person 342 | 343 | ```typescript 344 | @OrmModel('adults', 'persons', { 345 | PERSON: Person, 346 | ADULT: Adult 347 | }) 348 | class Adult extends Person { 349 | 350 | @StringField() job!: string; 351 | 352 | } 353 | ``` 354 | 355 | > Now, you can create mixed types of records at once. 356 | 357 | ```typescript 358 | Person.insert({ 359 | data: [ 360 | { type: 'PERSON', id: 1, name: 'John Doe' }, 361 | { type: 'TEENAGER', id: 2, name: 'Jane Doe', school: '22nd Best School' }, 362 | { type: 'ADULT', id: 3, name: 'Jane Roe', job: 'Software Engineer' } 363 | ] 364 | }); 365 | ``` 366 | 367 | ##### Discriminator Field Override 368 | 369 | > You may define a `static typeKey` on the base entity of your hierarchy if you want to change the default discriminator field name: 370 | 371 | ```typescript 372 | @OrmModel('persons') 373 | class Person extends Model { 374 | 375 | /** 376 | * The discriminator key to be used for the model when inheritance is used. 377 | */ 378 | static typeKey = 'PERSON'; 379 | 380 | @NumberField() id!: number; 381 | 382 | @StringField() name!: string; 383 | 384 | } 385 | ``` 386 | 387 | # Decorators 388 | 389 | * `@PrimaryKey` sets field as [Primary Key](https://vuex-orm.org/guide/model/defining-models.html#primary-key) to be 390 | used for the model. 391 | * `@UidField` creates a [UID Type](https://vuex-orm.org/guide/model/defining-models.html#uid-type) field 392 | * `@AttrField` creates a [Generic Type](https://vuex-orm.org/guide/model/defining-models.html#generic-type) field 393 | * `@DateField` creates a [Date](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date) 394 | instance field 395 | 396 | ### Primitive Types 397 | 398 | Like the Vuex ORM library, you can create primitive fields using the following decorators: 399 | 400 | * `@StringField` creates a [string](https://vuex-orm.org/guide/model/defining-models.html#primitive-types) field 401 | * `@NumberField` creates a [number](https://vuex-orm.org/guide/model/defining-models.html#primitive-types) field 402 | * `@BooleanField` creates a [boolean](https://vuex-orm.org/guide/model/defining-models.html#primitive-types) field 403 | 404 | ### Creating Relationships 405 | 406 | You can create all relationships defined in the Vuex ORM library. All the relationship decorators take the exact same 407 | arguments as the vanilla Vuex ORM library static functions. 408 | 409 | * `@HasManyField` creates a [HasMany](https://vuex-orm.org/guide/model/relationships.html#one-to-many) relationship 410 | field 411 | 412 | * `@HasOneField` creates a [HasOne](https://vuex-orm.org/guide/model/relationships.html#one-to-one) relationship field 413 | 414 | * `@BelongsToField` creates a [BelongsTo](https://vuex-orm.org/guide/model/relationships.html#one-to-one-inverse) 415 | relationship field 416 | 417 | * `@HasManyByField` creates a [HasManyBy](https://vuex-orm.org/guide/model/relationships.html#has-many-by) relationship 418 | field 419 | 420 | * `@HasManyThroughField` creates 421 | a [HasManyThrough](https://vuex-orm.org/guide/model/relationships.html#has-many-through) relationship field 422 | 423 | * `@BelongsToManyField` creates a [BelongsToMany](https://vuex-orm.org/guide/model/relationships.html#many-to-many) 424 | relationship field 425 | 426 | * `@MorphOneField` creates a [MorphOne](https://vuex-orm.org/guide/model/relationships.html#one-to-one-polymorphic) 427 | relationship field 428 | 429 | * `@MorphToField` creates a [MorphTo](https://vuex-orm.org/guide/model/relationships.html#one-to-one-polymorphic) 430 | relationship field 431 | 432 | * `@MorphManyField` creates a [MorphMany](https://vuex-orm.org/guide/model/relationships.html#one-to-many-polymorphic) 433 | relationship field 434 | 435 | * `@MorphToManyField` creates 436 | a [MorphToMany](https://vuex-orm.org/guide/model/relationships.html#many-to-many-polymorphic) relationship field 437 | 438 | * `@MorphedByManyField` creates 439 | a [MorphedByMany](https://vuex-orm.org/guide/model/relationships.html#defining-the-inverse-of-the-relationship-2) 440 | relationship field 441 | 442 | ## License 443 | 444 | Vuex ORM Decorators is open-sourced software licensed under the [MIT License](./LICENSE). 445 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vuex-orm-decorators", 3 | "version": "2.0.3", 4 | "description": "Simple Typescript decorators to improve the vuex-orm experience in Typescript by introducing typed property access.", 5 | "main": "dist/index.js", 6 | "types": "dist/types/index.d.ts", 7 | "typings": "dist/types/index.d.ts", 8 | "scripts": { 9 | "build": "pnpm lint && pnpm test && tsc --rootDir src && rm -rf dist/types/plugins", 10 | "cleanup": "rm -rf {coverage,dist,node_modules}", 11 | "lint": "eslint . --ext .ts", 12 | "lint:report": "pnpm lint --output-file eslint_report.json --format json", 13 | "test": "VITE_CJS_IGNORE_WARNING=true vitest run", 14 | "test:watch": "VITE_CJS_IGNORE_WARNING=true vitest watch", 15 | "test:coverage": "vitest run --coverage" 16 | }, 17 | "keywords": [ 18 | "vue", 19 | "vuex", 20 | "vuex-orm", 21 | "typescript", 22 | "decorators", 23 | "ES2015" 24 | ], 25 | "repository": { 26 | "type": "git", 27 | "url": "git@github.com:TiBianMod/vuex-orm-decorators.git" 28 | }, 29 | "author": "TiBianMod ", 30 | "license": "MIT", 31 | "devDependencies": { 32 | "@typescript-eslint/eslint-plugin": "^7.12.0", 33 | "@typescript-eslint/parser": "^7.12.0", 34 | "@vitest/coverage-v8": "^1.6.0", 35 | "@vuex-orm/core": "^0.36.4", 36 | "eslint": "^8.57.0", 37 | "eslint-config-prettier": "^9.1.0", 38 | "eslint-plugin-prettier": "^5.1.3", 39 | "eslint-plugin-sort-imports-es6-autofix": "^0.6.0", 40 | "eslint-plugin-unused-imports": "^3.2.0", 41 | "prettier": "^3.3.1", 42 | "tslib": "^2.6.3", 43 | "typescript": "^5.4.5", 44 | "vitest": "^1.6.0", 45 | "vue": "^3.4.27", 46 | "vuex": "^4.1.0" 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /pnpm-lock.yaml: -------------------------------------------------------------------------------- 1 | lockfileVersion: '9.0' 2 | 3 | settings: 4 | autoInstallPeers: true 5 | excludeLinksFromLockfile: false 6 | 7 | importers: 8 | 9 | .: 10 | devDependencies: 11 | '@typescript-eslint/eslint-plugin': 12 | specifier: ^7.12.0 13 | version: 7.12.0(@typescript-eslint/parser@7.12.0(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0)(typescript@5.4.5) 14 | '@typescript-eslint/parser': 15 | specifier: ^7.12.0 16 | version: 7.12.0(eslint@8.57.0)(typescript@5.4.5) 17 | '@vitest/coverage-v8': 18 | specifier: ^1.6.0 19 | version: 1.6.0(vitest@1.6.0(@types/node@20.8.3)) 20 | '@vuex-orm/core': 21 | specifier: ^0.36.4 22 | version: 0.36.4(vuex@4.1.0(vue@3.4.27(typescript@5.4.5))) 23 | eslint: 24 | specifier: ^8.57.0 25 | version: 8.57.0 26 | eslint-config-prettier: 27 | specifier: ^9.1.0 28 | version: 9.1.0(eslint@8.57.0) 29 | eslint-plugin-prettier: 30 | specifier: ^5.1.3 31 | version: 5.1.3(eslint-config-prettier@9.1.0(eslint@8.57.0))(eslint@8.57.0)(prettier@3.3.1) 32 | eslint-plugin-sort-imports-es6-autofix: 33 | specifier: ^0.6.0 34 | version: 0.6.0(eslint@8.57.0) 35 | eslint-plugin-unused-imports: 36 | specifier: ^3.2.0 37 | version: 3.2.0(@typescript-eslint/eslint-plugin@7.12.0(@typescript-eslint/parser@7.12.0(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0) 38 | prettier: 39 | specifier: ^3.3.1 40 | version: 3.3.1 41 | tslib: 42 | specifier: ^2.6.3 43 | version: 2.6.3 44 | typescript: 45 | specifier: ^5.4.5 46 | version: 5.4.5 47 | vitest: 48 | specifier: ^1.6.0 49 | version: 1.6.0(@types/node@20.8.3) 50 | vue: 51 | specifier: ^3.4.27 52 | version: 3.4.27(typescript@5.4.5) 53 | vuex: 54 | specifier: ^4.1.0 55 | version: 4.1.0(vue@3.4.27(typescript@5.4.5)) 56 | 57 | packages: 58 | 59 | '@aashutoshrathi/word-wrap@1.2.6': 60 | resolution: {integrity: sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==} 61 | engines: {node: '>=0.10.0'} 62 | 63 | '@ampproject/remapping@2.2.1': 64 | resolution: {integrity: sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==} 65 | engines: {node: '>=6.0.0'} 66 | 67 | '@babel/helper-string-parser@7.24.7': 68 | resolution: {integrity: sha512-7MbVt6xrwFQbunH2DNQsAP5sTGxfqQtErvBIvIMi6EQnbgUOuVYanvREcmFrOPhoXBrTtjhhP+lW+o5UfK+tDg==} 69 | engines: {node: '>=6.9.0'} 70 | 71 | '@babel/helper-validator-identifier@7.24.7': 72 | resolution: {integrity: sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w==} 73 | engines: {node: '>=6.9.0'} 74 | 75 | '@babel/parser@7.24.7': 76 | resolution: {integrity: sha512-9uUYRm6OqQrCqQdG1iCBwBPZgN8ciDBro2nIOFaiRz1/BCxaI7CNvQbDHvsArAC7Tw9Hda/B3U+6ui9u4HWXPw==} 77 | engines: {node: '>=6.0.0'} 78 | hasBin: true 79 | 80 | '@babel/types@7.24.7': 81 | resolution: {integrity: sha512-XEFXSlxiG5td2EJRe8vOmRbaXVgfcBlszKujvVmWIK/UpywWljQCfzAv3RQCGujWQ1RD4YYWEAqDXfuJiy8f5Q==} 82 | engines: {node: '>=6.9.0'} 83 | 84 | '@bcoe/v8-coverage@0.2.3': 85 | resolution: {integrity: sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==} 86 | 87 | '@esbuild/aix-ppc64@0.20.2': 88 | resolution: {integrity: sha512-D+EBOJHXdNZcLJRBkhENNG8Wji2kgc9AZ9KiPr1JuZjsNtyHzrsfLRrY0tk2H2aoFu6RANO1y1iPPUCDYWkb5g==} 89 | engines: {node: '>=12'} 90 | cpu: [ppc64] 91 | os: [aix] 92 | 93 | '@esbuild/android-arm64@0.20.2': 94 | resolution: {integrity: sha512-mRzjLacRtl/tWU0SvD8lUEwb61yP9cqQo6noDZP/O8VkwafSYwZ4yWy24kan8jE/IMERpYncRt2dw438LP3Xmg==} 95 | engines: {node: '>=12'} 96 | cpu: [arm64] 97 | os: [android] 98 | 99 | '@esbuild/android-arm@0.20.2': 100 | resolution: {integrity: sha512-t98Ra6pw2VaDhqNWO2Oph2LXbz/EJcnLmKLGBJwEwXX/JAN83Fym1rU8l0JUWK6HkIbWONCSSatf4sf2NBRx/w==} 101 | engines: {node: '>=12'} 102 | cpu: [arm] 103 | os: [android] 104 | 105 | '@esbuild/android-x64@0.20.2': 106 | resolution: {integrity: sha512-btzExgV+/lMGDDa194CcUQm53ncxzeBrWJcncOBxuC6ndBkKxnHdFJn86mCIgTELsooUmwUm9FkhSp5HYu00Rg==} 107 | engines: {node: '>=12'} 108 | cpu: [x64] 109 | os: [android] 110 | 111 | '@esbuild/darwin-arm64@0.20.2': 112 | resolution: {integrity: sha512-4J6IRT+10J3aJH3l1yzEg9y3wkTDgDk7TSDFX+wKFiWjqWp/iCfLIYzGyasx9l0SAFPT1HwSCR+0w/h1ES/MjA==} 113 | engines: {node: '>=12'} 114 | cpu: [arm64] 115 | os: [darwin] 116 | 117 | '@esbuild/darwin-x64@0.20.2': 118 | resolution: {integrity: sha512-tBcXp9KNphnNH0dfhv8KYkZhjc+H3XBkF5DKtswJblV7KlT9EI2+jeA8DgBjp908WEuYll6pF+UStUCfEpdysA==} 119 | engines: {node: '>=12'} 120 | cpu: [x64] 121 | os: [darwin] 122 | 123 | '@esbuild/freebsd-arm64@0.20.2': 124 | resolution: {integrity: sha512-d3qI41G4SuLiCGCFGUrKsSeTXyWG6yem1KcGZVS+3FYlYhtNoNgYrWcvkOoaqMhwXSMrZRl69ArHsGJ9mYdbbw==} 125 | engines: {node: '>=12'} 126 | cpu: [arm64] 127 | os: [freebsd] 128 | 129 | '@esbuild/freebsd-x64@0.20.2': 130 | resolution: {integrity: sha512-d+DipyvHRuqEeM5zDivKV1KuXn9WeRX6vqSqIDgwIfPQtwMP4jaDsQsDncjTDDsExT4lR/91OLjRo8bmC1e+Cw==} 131 | engines: {node: '>=12'} 132 | cpu: [x64] 133 | os: [freebsd] 134 | 135 | '@esbuild/linux-arm64@0.20.2': 136 | resolution: {integrity: sha512-9pb6rBjGvTFNira2FLIWqDk/uaf42sSyLE8j1rnUpuzsODBq7FvpwHYZxQ/It/8b+QOS1RYfqgGFNLRI+qlq2A==} 137 | engines: {node: '>=12'} 138 | cpu: [arm64] 139 | os: [linux] 140 | 141 | '@esbuild/linux-arm@0.20.2': 142 | resolution: {integrity: sha512-VhLPeR8HTMPccbuWWcEUD1Az68TqaTYyj6nfE4QByZIQEQVWBB8vup8PpR7y1QHL3CpcF6xd5WVBU/+SBEvGTg==} 143 | engines: {node: '>=12'} 144 | cpu: [arm] 145 | os: [linux] 146 | 147 | '@esbuild/linux-ia32@0.20.2': 148 | resolution: {integrity: sha512-o10utieEkNPFDZFQm9CoP7Tvb33UutoJqg3qKf1PWVeeJhJw0Q347PxMvBgVVFgouYLGIhFYG0UGdBumROyiig==} 149 | engines: {node: '>=12'} 150 | cpu: [ia32] 151 | os: [linux] 152 | 153 | '@esbuild/linux-loong64@0.20.2': 154 | resolution: {integrity: sha512-PR7sp6R/UC4CFVomVINKJ80pMFlfDfMQMYynX7t1tNTeivQ6XdX5r2XovMmha/VjR1YN/HgHWsVcTRIMkymrgQ==} 155 | engines: {node: '>=12'} 156 | cpu: [loong64] 157 | os: [linux] 158 | 159 | '@esbuild/linux-mips64el@0.20.2': 160 | resolution: {integrity: sha512-4BlTqeutE/KnOiTG5Y6Sb/Hw6hsBOZapOVF6njAESHInhlQAghVVZL1ZpIctBOoTFbQyGW+LsVYZ8lSSB3wkjA==} 161 | engines: {node: '>=12'} 162 | cpu: [mips64el] 163 | os: [linux] 164 | 165 | '@esbuild/linux-ppc64@0.20.2': 166 | resolution: {integrity: sha512-rD3KsaDprDcfajSKdn25ooz5J5/fWBylaaXkuotBDGnMnDP1Uv5DLAN/45qfnf3JDYyJv/ytGHQaziHUdyzaAg==} 167 | engines: {node: '>=12'} 168 | cpu: [ppc64] 169 | os: [linux] 170 | 171 | '@esbuild/linux-riscv64@0.20.2': 172 | resolution: {integrity: sha512-snwmBKacKmwTMmhLlz/3aH1Q9T8v45bKYGE3j26TsaOVtjIag4wLfWSiZykXzXuE1kbCE+zJRmwp+ZbIHinnVg==} 173 | engines: {node: '>=12'} 174 | cpu: [riscv64] 175 | os: [linux] 176 | 177 | '@esbuild/linux-s390x@0.20.2': 178 | resolution: {integrity: sha512-wcWISOobRWNm3cezm5HOZcYz1sKoHLd8VL1dl309DiixxVFoFe/o8HnwuIwn6sXre88Nwj+VwZUvJf4AFxkyrQ==} 179 | engines: {node: '>=12'} 180 | cpu: [s390x] 181 | os: [linux] 182 | 183 | '@esbuild/linux-x64@0.20.2': 184 | resolution: {integrity: sha512-1MdwI6OOTsfQfek8sLwgyjOXAu+wKhLEoaOLTjbijk6E2WONYpH9ZU2mNtR+lZ2B4uwr+usqGuVfFT9tMtGvGw==} 185 | engines: {node: '>=12'} 186 | cpu: [x64] 187 | os: [linux] 188 | 189 | '@esbuild/netbsd-x64@0.20.2': 190 | resolution: {integrity: sha512-K8/DhBxcVQkzYc43yJXDSyjlFeHQJBiowJ0uVL6Tor3jGQfSGHNNJcWxNbOI8v5k82prYqzPuwkzHt3J1T1iZQ==} 191 | engines: {node: '>=12'} 192 | cpu: [x64] 193 | os: [netbsd] 194 | 195 | '@esbuild/openbsd-x64@0.20.2': 196 | resolution: {integrity: sha512-eMpKlV0SThJmmJgiVyN9jTPJ2VBPquf6Kt/nAoo6DgHAoN57K15ZghiHaMvqjCye/uU4X5u3YSMgVBI1h3vKrQ==} 197 | engines: {node: '>=12'} 198 | cpu: [x64] 199 | os: [openbsd] 200 | 201 | '@esbuild/sunos-x64@0.20.2': 202 | resolution: {integrity: sha512-2UyFtRC6cXLyejf/YEld4Hajo7UHILetzE1vsRcGL3earZEW77JxrFjH4Ez2qaTiEfMgAXxfAZCm1fvM/G/o8w==} 203 | engines: {node: '>=12'} 204 | cpu: [x64] 205 | os: [sunos] 206 | 207 | '@esbuild/win32-arm64@0.20.2': 208 | resolution: {integrity: sha512-GRibxoawM9ZCnDxnP3usoUDO9vUkpAxIIZ6GQI+IlVmr5kP3zUq+l17xELTHMWTWzjxa2guPNyrpq1GWmPvcGQ==} 209 | engines: {node: '>=12'} 210 | cpu: [arm64] 211 | os: [win32] 212 | 213 | '@esbuild/win32-ia32@0.20.2': 214 | resolution: {integrity: sha512-HfLOfn9YWmkSKRQqovpnITazdtquEW8/SoHW7pWpuEeguaZI4QnCRW6b+oZTztdBnZOS2hqJ6im/D5cPzBTTlQ==} 215 | engines: {node: '>=12'} 216 | cpu: [ia32] 217 | os: [win32] 218 | 219 | '@esbuild/win32-x64@0.20.2': 220 | resolution: {integrity: sha512-N49X4lJX27+l9jbLKSqZ6bKNjzQvHaT8IIFUy+YIqmXQdjYCToGWwOItDrfby14c78aDd5NHQl29xingXfCdLQ==} 221 | engines: {node: '>=12'} 222 | cpu: [x64] 223 | os: [win32] 224 | 225 | '@eslint-community/eslint-utils@4.4.0': 226 | resolution: {integrity: sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==} 227 | engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} 228 | peerDependencies: 229 | eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 230 | 231 | '@eslint-community/regexpp@4.10.1': 232 | resolution: {integrity: sha512-Zm2NGpWELsQAD1xsJzGQpYfvICSsFkEpU0jxBjfdC6uNEWXcHnfs9hScFWtXVDVl+rBQJGrl4g1vcKIejpH9dA==} 233 | engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} 234 | 235 | '@eslint-community/regexpp@4.9.1': 236 | resolution: {integrity: sha512-Y27x+MBLjXa+0JWDhykM3+JE+il3kHKAEqabfEWq3SDhZjLYb6/BHL/JKFnH3fe207JaXkyDo685Oc2Glt6ifA==} 237 | engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} 238 | 239 | '@eslint/eslintrc@2.1.4': 240 | resolution: {integrity: sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==} 241 | engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} 242 | 243 | '@eslint/js@8.57.0': 244 | resolution: {integrity: sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==} 245 | engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} 246 | 247 | '@humanwhocodes/config-array@0.11.14': 248 | resolution: {integrity: sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==} 249 | engines: {node: '>=10.10.0'} 250 | 251 | '@humanwhocodes/module-importer@1.0.1': 252 | resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==} 253 | engines: {node: '>=12.22'} 254 | 255 | '@humanwhocodes/object-schema@2.0.3': 256 | resolution: {integrity: sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==} 257 | 258 | '@istanbuljs/schema@0.1.3': 259 | resolution: {integrity: sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==} 260 | engines: {node: '>=8'} 261 | 262 | '@jest/schemas@29.6.3': 263 | resolution: {integrity: sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==} 264 | engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} 265 | 266 | '@jridgewell/gen-mapping@0.3.3': 267 | resolution: {integrity: sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==} 268 | engines: {node: '>=6.0.0'} 269 | 270 | '@jridgewell/resolve-uri@3.1.1': 271 | resolution: {integrity: sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==} 272 | engines: {node: '>=6.0.0'} 273 | 274 | '@jridgewell/set-array@1.1.2': 275 | resolution: {integrity: sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==} 276 | engines: {node: '>=6.0.0'} 277 | 278 | '@jridgewell/sourcemap-codec@1.4.15': 279 | resolution: {integrity: sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==} 280 | 281 | '@jridgewell/trace-mapping@0.3.19': 282 | resolution: {integrity: sha512-kf37QtfW+Hwx/buWGMPcR60iF9ziHa6r/CZJIHbmcm4+0qrXiVdxegAH0F6yddEVQ7zdkjcGCgCzUu+BcbhQxw==} 283 | 284 | '@jridgewell/trace-mapping@0.3.25': 285 | resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==} 286 | 287 | '@nodelib/fs.scandir@2.1.5': 288 | resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} 289 | engines: {node: '>= 8'} 290 | 291 | '@nodelib/fs.stat@2.0.5': 292 | resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} 293 | engines: {node: '>= 8'} 294 | 295 | '@nodelib/fs.walk@1.2.8': 296 | resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} 297 | engines: {node: '>= 8'} 298 | 299 | '@pkgr/core@0.1.1': 300 | resolution: {integrity: sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA==} 301 | engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0} 302 | 303 | '@rollup/rollup-android-arm-eabi@4.18.0': 304 | resolution: {integrity: sha512-Tya6xypR10giZV1XzxmH5wr25VcZSncG0pZIjfePT0OVBvqNEurzValetGNarVrGiq66EBVAFn15iYX4w6FKgQ==} 305 | cpu: [arm] 306 | os: [android] 307 | 308 | '@rollup/rollup-android-arm64@4.18.0': 309 | resolution: {integrity: sha512-avCea0RAP03lTsDhEyfy+hpfr85KfyTctMADqHVhLAF3MlIkq83CP8UfAHUssgXTYd+6er6PaAhx/QGv4L1EiA==} 310 | cpu: [arm64] 311 | os: [android] 312 | 313 | '@rollup/rollup-darwin-arm64@4.18.0': 314 | resolution: {integrity: sha512-IWfdwU7KDSm07Ty0PuA/W2JYoZ4iTj3TUQjkVsO/6U+4I1jN5lcR71ZEvRh52sDOERdnNhhHU57UITXz5jC1/w==} 315 | cpu: [arm64] 316 | os: [darwin] 317 | 318 | '@rollup/rollup-darwin-x64@4.18.0': 319 | resolution: {integrity: sha512-n2LMsUz7Ynu7DoQrSQkBf8iNrjOGyPLrdSg802vk6XT3FtsgX6JbE8IHRvposskFm9SNxzkLYGSq9QdpLYpRNA==} 320 | cpu: [x64] 321 | os: [darwin] 322 | 323 | '@rollup/rollup-linux-arm-gnueabihf@4.18.0': 324 | resolution: {integrity: sha512-C/zbRYRXFjWvz9Z4haRxcTdnkPt1BtCkz+7RtBSuNmKzMzp3ZxdM28Mpccn6pt28/UWUCTXa+b0Mx1k3g6NOMA==} 325 | cpu: [arm] 326 | os: [linux] 327 | 328 | '@rollup/rollup-linux-arm-musleabihf@4.18.0': 329 | resolution: {integrity: sha512-l3m9ewPgjQSXrUMHg93vt0hYCGnrMOcUpTz6FLtbwljo2HluS4zTXFy2571YQbisTnfTKPZ01u/ukJdQTLGh9A==} 330 | cpu: [arm] 331 | os: [linux] 332 | 333 | '@rollup/rollup-linux-arm64-gnu@4.18.0': 334 | resolution: {integrity: sha512-rJ5D47d8WD7J+7STKdCUAgmQk49xuFrRi9pZkWoRD1UeSMakbcepWXPF8ycChBoAqs1pb2wzvbY6Q33WmN2ftw==} 335 | cpu: [arm64] 336 | os: [linux] 337 | 338 | '@rollup/rollup-linux-arm64-musl@4.18.0': 339 | resolution: {integrity: sha512-be6Yx37b24ZwxQ+wOQXXLZqpq4jTckJhtGlWGZs68TgdKXJgw54lUUoFYrg6Zs/kjzAQwEwYbp8JxZVzZLRepQ==} 340 | cpu: [arm64] 341 | os: [linux] 342 | 343 | '@rollup/rollup-linux-powerpc64le-gnu@4.18.0': 344 | resolution: {integrity: sha512-hNVMQK+qrA9Todu9+wqrXOHxFiD5YmdEi3paj6vP02Kx1hjd2LLYR2eaN7DsEshg09+9uzWi2W18MJDlG0cxJA==} 345 | cpu: [ppc64] 346 | os: [linux] 347 | 348 | '@rollup/rollup-linux-riscv64-gnu@4.18.0': 349 | resolution: {integrity: sha512-ROCM7i+m1NfdrsmvwSzoxp9HFtmKGHEqu5NNDiZWQtXLA8S5HBCkVvKAxJ8U+CVctHwV2Gb5VUaK7UAkzhDjlg==} 350 | cpu: [riscv64] 351 | os: [linux] 352 | 353 | '@rollup/rollup-linux-s390x-gnu@4.18.0': 354 | resolution: {integrity: sha512-0UyyRHyDN42QL+NbqevXIIUnKA47A+45WyasO+y2bGJ1mhQrfrtXUpTxCOrfxCR4esV3/RLYyucGVPiUsO8xjg==} 355 | cpu: [s390x] 356 | os: [linux] 357 | 358 | '@rollup/rollup-linux-x64-gnu@4.18.0': 359 | resolution: {integrity: sha512-xuglR2rBVHA5UsI8h8UbX4VJ470PtGCf5Vpswh7p2ukaqBGFTnsfzxUBetoWBWymHMxbIG0Cmx7Y9qDZzr648w==} 360 | cpu: [x64] 361 | os: [linux] 362 | 363 | '@rollup/rollup-linux-x64-musl@4.18.0': 364 | resolution: {integrity: sha512-LKaqQL9osY/ir2geuLVvRRs+utWUNilzdE90TpyoX0eNqPzWjRm14oMEE+YLve4k/NAqCdPkGYDaDF5Sw+xBfg==} 365 | cpu: [x64] 366 | os: [linux] 367 | 368 | '@rollup/rollup-win32-arm64-msvc@4.18.0': 369 | resolution: {integrity: sha512-7J6TkZQFGo9qBKH0pk2cEVSRhJbL6MtfWxth7Y5YmZs57Pi+4x6c2dStAUvaQkHQLnEQv1jzBUW43GvZW8OFqA==} 370 | cpu: [arm64] 371 | os: [win32] 372 | 373 | '@rollup/rollup-win32-ia32-msvc@4.18.0': 374 | resolution: {integrity: sha512-Txjh+IxBPbkUB9+SXZMpv+b/vnTEtFyfWZgJ6iyCmt2tdx0OF5WhFowLmnh8ENGNpfUlUZkdI//4IEmhwPieNg==} 375 | cpu: [ia32] 376 | os: [win32] 377 | 378 | '@rollup/rollup-win32-x64-msvc@4.18.0': 379 | resolution: {integrity: sha512-UOo5FdvOL0+eIVTgS4tIdbW+TtnBLWg1YBCcU2KWM7nuNwRz9bksDX1bekJJCpu25N1DVWaCwnT39dVQxzqS8g==} 380 | cpu: [x64] 381 | os: [win32] 382 | 383 | '@sinclair/typebox@0.27.8': 384 | resolution: {integrity: sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==} 385 | 386 | '@types/estree@1.0.5': 387 | resolution: {integrity: sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==} 388 | 389 | '@types/node@20.8.3': 390 | resolution: {integrity: sha512-jxiZQFpb+NlH5kjW49vXxvxTjeeqlbsnTAdBTKpzEdPs9itay7MscYXz3Fo9VYFEsfQ6LJFitHad3faerLAjCw==} 391 | 392 | '@typescript-eslint/eslint-plugin@7.12.0': 393 | resolution: {integrity: sha512-7F91fcbuDf/d3S8o21+r3ZncGIke/+eWk0EpO21LXhDfLahriZF9CGj4fbAetEjlaBdjdSm9a6VeXbpbT6Z40Q==} 394 | engines: {node: ^18.18.0 || >=20.0.0} 395 | peerDependencies: 396 | '@typescript-eslint/parser': ^7.0.0 397 | eslint: ^8.56.0 398 | typescript: '*' 399 | peerDependenciesMeta: 400 | typescript: 401 | optional: true 402 | 403 | '@typescript-eslint/parser@7.12.0': 404 | resolution: {integrity: sha512-dm/J2UDY3oV3TKius2OUZIFHsomQmpHtsV0FTh1WO8EKgHLQ1QCADUqscPgTpU+ih1e21FQSRjXckHn3txn6kQ==} 405 | engines: {node: ^18.18.0 || >=20.0.0} 406 | peerDependencies: 407 | eslint: ^8.56.0 408 | typescript: '*' 409 | peerDependenciesMeta: 410 | typescript: 411 | optional: true 412 | 413 | '@typescript-eslint/scope-manager@7.12.0': 414 | resolution: {integrity: sha512-itF1pTnN6F3unPak+kutH9raIkL3lhH1YRPGgt7QQOh43DQKVJXmWkpb+vpc/TiDHs6RSd9CTbDsc/Y+Ygq7kg==} 415 | engines: {node: ^18.18.0 || >=20.0.0} 416 | 417 | '@typescript-eslint/type-utils@7.12.0': 418 | resolution: {integrity: sha512-lib96tyRtMhLxwauDWUp/uW3FMhLA6D0rJ8T7HmH7x23Gk1Gwwu8UZ94NMXBvOELn6flSPiBrCKlehkiXyaqwA==} 419 | engines: {node: ^18.18.0 || >=20.0.0} 420 | peerDependencies: 421 | eslint: ^8.56.0 422 | typescript: '*' 423 | peerDependenciesMeta: 424 | typescript: 425 | optional: true 426 | 427 | '@typescript-eslint/types@7.12.0': 428 | resolution: {integrity: sha512-o+0Te6eWp2ppKY3mLCU+YA9pVJxhUJE15FV7kxuD9jgwIAa+w/ycGJBMrYDTpVGUM/tgpa9SeMOugSabWFq7bg==} 429 | engines: {node: ^18.18.0 || >=20.0.0} 430 | 431 | '@typescript-eslint/typescript-estree@7.12.0': 432 | resolution: {integrity: sha512-5bwqLsWBULv1h6pn7cMW5dXX/Y2amRqLaKqsASVwbBHMZSnHqE/HN4vT4fE0aFsiwxYvr98kqOWh1a8ZKXalCQ==} 433 | engines: {node: ^18.18.0 || >=20.0.0} 434 | peerDependencies: 435 | typescript: '*' 436 | peerDependenciesMeta: 437 | typescript: 438 | optional: true 439 | 440 | '@typescript-eslint/utils@7.12.0': 441 | resolution: {integrity: sha512-Y6hhwxwDx41HNpjuYswYp6gDbkiZ8Hin9Bf5aJQn1bpTs3afYY4GX+MPYxma8jtoIV2GRwTM/UJm/2uGCVv+DQ==} 442 | engines: {node: ^18.18.0 || >=20.0.0} 443 | peerDependencies: 444 | eslint: ^8.56.0 445 | 446 | '@typescript-eslint/visitor-keys@7.12.0': 447 | resolution: {integrity: sha512-uZk7DevrQLL3vSnfFl5bj4sL75qC9D6EdjemIdbtkuUmIheWpuiiylSY01JxJE7+zGrOWDZrp1WxOuDntvKrHQ==} 448 | engines: {node: ^18.18.0 || >=20.0.0} 449 | 450 | '@ungap/structured-clone@1.2.0': 451 | resolution: {integrity: sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==} 452 | 453 | '@vitest/coverage-v8@1.6.0': 454 | resolution: {integrity: sha512-KvapcbMY/8GYIG0rlwwOKCVNRc0OL20rrhFkg/CHNzncV03TE2XWvO5w9uZYoxNiMEBacAJt3unSOiZ7svePew==} 455 | peerDependencies: 456 | vitest: 1.6.0 457 | 458 | '@vitest/expect@1.6.0': 459 | resolution: {integrity: sha512-ixEvFVQjycy/oNgHjqsL6AZCDduC+tflRluaHIzKIsdbzkLn2U/iBnVeJwB6HsIjQBdfMR8Z0tRxKUsvFJEeWQ==} 460 | 461 | '@vitest/runner@1.6.0': 462 | resolution: {integrity: sha512-P4xgwPjwesuBiHisAVz/LSSZtDjOTPYZVmNAnpHHSR6ONrf8eCJOFRvUwdHn30F5M1fxhqtl7QZQUk2dprIXAg==} 463 | 464 | '@vitest/snapshot@1.6.0': 465 | resolution: {integrity: sha512-+Hx43f8Chus+DCmygqqfetcAZrDJwvTj0ymqjQq4CvmpKFSTVteEOBzCusu1x2tt4OJcvBflyHUE0DZSLgEMtQ==} 466 | 467 | '@vitest/spy@1.6.0': 468 | resolution: {integrity: sha512-leUTap6B/cqi/bQkXUu6bQV5TZPx7pmMBKBQiI0rJA8c3pB56ZsaTbREnF7CJfmvAS4V2cXIBAh/3rVwrrCYgw==} 469 | 470 | '@vitest/utils@1.6.0': 471 | resolution: {integrity: sha512-21cPiuGMoMZwiOHa2i4LXkMkMkCGzA+MVFV70jRwHo95dL4x/ts5GZhML1QWuy7yfp3WzK3lRvZi3JnXTYqrBw==} 472 | 473 | '@vue/compiler-core@3.4.27': 474 | resolution: {integrity: sha512-E+RyqY24KnyDXsCuQrI+mlcdW3ALND6U7Gqa/+bVwbcpcR3BRRIckFoz7Qyd4TTlnugtwuI7YgjbvsLmxb+yvg==} 475 | 476 | '@vue/compiler-dom@3.4.27': 477 | resolution: {integrity: sha512-kUTvochG/oVgE1w5ViSr3KUBh9X7CWirebA3bezTbB5ZKBQZwR2Mwj9uoSKRMFcz4gSMzzLXBPD6KpCLb9nvWw==} 478 | 479 | '@vue/compiler-sfc@3.4.27': 480 | resolution: {integrity: sha512-nDwntUEADssW8e0rrmE0+OrONwmRlegDA1pD6QhVeXxjIytV03yDqTey9SBDiALsvAd5U4ZrEKbMyVXhX6mCGA==} 481 | 482 | '@vue/compiler-ssr@3.4.27': 483 | resolution: {integrity: sha512-CVRzSJIltzMG5FcidsW0jKNQnNRYC8bT21VegyMMtHmhW3UOI7knmUehzswXLrExDLE6lQCZdrhD4ogI7c+vuw==} 484 | 485 | '@vue/devtools-api@6.5.0': 486 | resolution: {integrity: sha512-o9KfBeaBmCKl10usN4crU53fYtC1r7jJwdGKjPT24t348rHxgfpZ0xL3Xm/gLUYnc0oTp8LAmrxOeLyu6tbk2Q==} 487 | 488 | '@vue/reactivity@3.4.27': 489 | resolution: {integrity: sha512-kK0g4NknW6JX2yySLpsm2jlunZJl2/RJGZ0H9ddHdfBVHcNzxmQ0sS0b09ipmBoQpY8JM2KmUw+a6sO8Zo+zIA==} 490 | 491 | '@vue/runtime-core@3.4.27': 492 | resolution: {integrity: sha512-7aYA9GEbOOdviqVvcuweTLe5Za4qBZkUY7SvET6vE8kyypxVgaT1ixHLg4urtOlrApdgcdgHoTZCUuTGap/5WA==} 493 | 494 | '@vue/runtime-dom@3.4.27': 495 | resolution: {integrity: sha512-ScOmP70/3NPM+TW9hvVAz6VWWtZJqkbdf7w6ySsws+EsqtHvkhxaWLecrTorFxsawelM5Ys9FnDEMt6BPBDS0Q==} 496 | 497 | '@vue/server-renderer@3.4.27': 498 | resolution: {integrity: sha512-dlAMEuvmeA3rJsOMJ2J1kXU7o7pOxgsNHVr9K8hB3ImIkSuBrIdy0vF66h8gf8Tuinf1TK3mPAz2+2sqyf3KzA==} 499 | peerDependencies: 500 | vue: 3.4.27 501 | 502 | '@vue/shared@3.4.27': 503 | resolution: {integrity: sha512-DL3NmY2OFlqmYYrzp39yi3LDkKxa5vZVwxWdQ3rG0ekuWscHraeIbnI8t+aZK7qhYqEqWKTUdijadunb9pnrgA==} 504 | 505 | '@vuex-orm/core@0.36.4': 506 | resolution: {integrity: sha512-Wkq1G+FtcEQ4LbhEZUZalhuErb2nY2nuBo2UeGVpbVKkMss5piJhw7bt5TpWecDNmIUc2BzaenDDqm08AAe7Hw==} 507 | peerDependencies: 508 | vuex: '>=3.1.0' 509 | 510 | acorn-jsx@5.3.2: 511 | resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} 512 | peerDependencies: 513 | acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 514 | 515 | acorn-walk@8.3.2: 516 | resolution: {integrity: sha512-cjkyv4OtNCIeqhHrfS81QWXoCBPExR/J62oyEqepVw8WaQeSqpW2uhuLPh1m9eWhDuOo/jUXVTlifvesOWp/4A==} 517 | engines: {node: '>=0.4.0'} 518 | 519 | acorn@8.10.0: 520 | resolution: {integrity: sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==} 521 | engines: {node: '>=0.4.0'} 522 | hasBin: true 523 | 524 | ajv@6.12.6: 525 | resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} 526 | 527 | ansi-regex@5.0.1: 528 | resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} 529 | engines: {node: '>=8'} 530 | 531 | ansi-styles@4.3.0: 532 | resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} 533 | engines: {node: '>=8'} 534 | 535 | ansi-styles@5.2.0: 536 | resolution: {integrity: sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==} 537 | engines: {node: '>=10'} 538 | 539 | argparse@2.0.1: 540 | resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} 541 | 542 | array-union@2.1.0: 543 | resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==} 544 | engines: {node: '>=8'} 545 | 546 | assertion-error@1.1.0: 547 | resolution: {integrity: sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==} 548 | 549 | balanced-match@1.0.2: 550 | resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} 551 | 552 | brace-expansion@1.1.11: 553 | resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} 554 | 555 | brace-expansion@2.0.1: 556 | resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==} 557 | 558 | braces@3.0.2: 559 | resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==} 560 | engines: {node: '>=8'} 561 | 562 | cac@6.7.14: 563 | resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==} 564 | engines: {node: '>=8'} 565 | 566 | callsites@3.1.0: 567 | resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} 568 | engines: {node: '>=6'} 569 | 570 | chai@4.3.10: 571 | resolution: {integrity: sha512-0UXG04VuVbruMUYbJ6JctvH0YnC/4q3/AkT18q4NaITo91CUm0liMS9VqzT9vZhVQ/1eqPanMWjBM+Juhfb/9g==} 572 | engines: {node: '>=4'} 573 | 574 | chalk@4.1.2: 575 | resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} 576 | engines: {node: '>=10'} 577 | 578 | check-error@1.0.3: 579 | resolution: {integrity: sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg==} 580 | 581 | color-convert@2.0.1: 582 | resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} 583 | engines: {node: '>=7.0.0'} 584 | 585 | color-name@1.1.4: 586 | resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} 587 | 588 | concat-map@0.0.1: 589 | resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} 590 | 591 | cross-spawn@7.0.3: 592 | resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} 593 | engines: {node: '>= 8'} 594 | 595 | csstype@3.1.3: 596 | resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==} 597 | 598 | debug@4.3.4: 599 | resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==} 600 | engines: {node: '>=6.0'} 601 | peerDependencies: 602 | supports-color: '*' 603 | peerDependenciesMeta: 604 | supports-color: 605 | optional: true 606 | 607 | deep-eql@4.1.3: 608 | resolution: {integrity: sha512-WaEtAOpRA1MQ0eohqZjpGD8zdI0Ovsm8mmFhaDN8dvDZzyoUMcYDnf5Y6iu7HTXxf8JDS23qWa4a+hKCDyOPzw==} 609 | engines: {node: '>=6'} 610 | 611 | deep-is@0.1.4: 612 | resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} 613 | 614 | diff-sequences@29.6.3: 615 | resolution: {integrity: sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==} 616 | engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} 617 | 618 | dir-glob@3.0.1: 619 | resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==} 620 | engines: {node: '>=8'} 621 | 622 | doctrine@3.0.0: 623 | resolution: {integrity: sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==} 624 | engines: {node: '>=6.0.0'} 625 | 626 | entities@4.5.0: 627 | resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==} 628 | engines: {node: '>=0.12'} 629 | 630 | esbuild@0.20.2: 631 | resolution: {integrity: sha512-WdOOppmUNU+IbZ0PaDiTst80zjnrOkyJNHoKupIcVyU8Lvla3Ugx94VzkQ32Ijqd7UhHJy75gNWDMUekcrSJ6g==} 632 | engines: {node: '>=12'} 633 | hasBin: true 634 | 635 | escape-string-regexp@4.0.0: 636 | resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} 637 | engines: {node: '>=10'} 638 | 639 | eslint-config-prettier@9.1.0: 640 | resolution: {integrity: sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==} 641 | hasBin: true 642 | peerDependencies: 643 | eslint: '>=7.0.0' 644 | 645 | eslint-plugin-prettier@5.1.3: 646 | resolution: {integrity: sha512-C9GCVAs4Eq7ZC/XFQHITLiHJxQngdtraXaM+LoUFoFp/lHNl2Zn8f3WQbe9HvTBBQ9YnKFB0/2Ajdqwo5D1EAw==} 647 | engines: {node: ^14.18.0 || >=16.0.0} 648 | peerDependencies: 649 | '@types/eslint': '>=8.0.0' 650 | eslint: '>=8.0.0' 651 | eslint-config-prettier: '*' 652 | prettier: '>=3.0.0' 653 | peerDependenciesMeta: 654 | '@types/eslint': 655 | optional: true 656 | eslint-config-prettier: 657 | optional: true 658 | 659 | eslint-plugin-sort-imports-es6-autofix@0.6.0: 660 | resolution: {integrity: sha512-2NVaBGF9NN+727Fyq+jJYihdIeegjXeUUrZED9Q8FVB8MsV3YQEyXG96GVnXqWt0pmn7xfCZOZf3uKnIhBrfeQ==} 661 | peerDependencies: 662 | eslint: '>=7.7.0' 663 | 664 | eslint-plugin-unused-imports@3.2.0: 665 | resolution: {integrity: sha512-6uXyn6xdINEpxE1MtDjxQsyXB37lfyO2yKGVVgtD7WEWQGORSOZjgrD6hBhvGv4/SO+TOlS+UnC6JppRqbuwGQ==} 666 | engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} 667 | peerDependencies: 668 | '@typescript-eslint/eslint-plugin': 6 - 7 669 | eslint: '8' 670 | peerDependenciesMeta: 671 | '@typescript-eslint/eslint-plugin': 672 | optional: true 673 | 674 | eslint-rule-composer@0.3.0: 675 | resolution: {integrity: sha512-bt+Sh8CtDmn2OajxvNO+BX7Wn4CIWMpTRm3MaiKPCQcnnlm0CS2mhui6QaoeQugs+3Kj2ESKEEGJUdVafwhiCg==} 676 | engines: {node: '>=4.0.0'} 677 | 678 | eslint-scope@7.2.2: 679 | resolution: {integrity: sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==} 680 | engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} 681 | 682 | eslint-visitor-keys@3.4.3: 683 | resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==} 684 | engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} 685 | 686 | eslint@8.57.0: 687 | resolution: {integrity: sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==} 688 | engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} 689 | hasBin: true 690 | 691 | espree@9.6.1: 692 | resolution: {integrity: sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==} 693 | engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} 694 | 695 | esquery@1.5.0: 696 | resolution: {integrity: sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==} 697 | engines: {node: '>=0.10'} 698 | 699 | esrecurse@4.3.0: 700 | resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==} 701 | engines: {node: '>=4.0'} 702 | 703 | estraverse@5.3.0: 704 | resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} 705 | engines: {node: '>=4.0'} 706 | 707 | estree-walker@2.0.2: 708 | resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==} 709 | 710 | estree-walker@3.0.3: 711 | resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==} 712 | 713 | esutils@2.0.3: 714 | resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} 715 | engines: {node: '>=0.10.0'} 716 | 717 | execa@8.0.1: 718 | resolution: {integrity: sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==} 719 | engines: {node: '>=16.17'} 720 | 721 | fast-deep-equal@3.1.3: 722 | resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} 723 | 724 | fast-diff@1.3.0: 725 | resolution: {integrity: sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==} 726 | 727 | fast-glob@3.3.1: 728 | resolution: {integrity: sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg==} 729 | engines: {node: '>=8.6.0'} 730 | 731 | fast-json-stable-stringify@2.1.0: 732 | resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} 733 | 734 | fast-levenshtein@2.0.6: 735 | resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} 736 | 737 | fastq@1.15.0: 738 | resolution: {integrity: sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==} 739 | 740 | file-entry-cache@6.0.1: 741 | resolution: {integrity: sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==} 742 | engines: {node: ^10.12.0 || >=12.0.0} 743 | 744 | fill-range@7.0.1: 745 | resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==} 746 | engines: {node: '>=8'} 747 | 748 | find-up@5.0.0: 749 | resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} 750 | engines: {node: '>=10'} 751 | 752 | flat-cache@3.1.1: 753 | resolution: {integrity: sha512-/qM2b3LUIaIgviBQovTLvijfyOQXPtSRnRK26ksj2J7rzPIecePUIpJsZ4T02Qg+xiAEKIs5K8dsHEd+VaKa/Q==} 754 | engines: {node: '>=12.0.0'} 755 | 756 | flatted@3.2.9: 757 | resolution: {integrity: sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ==} 758 | 759 | fs.realpath@1.0.0: 760 | resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} 761 | 762 | fsevents@2.3.3: 763 | resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} 764 | engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} 765 | os: [darwin] 766 | 767 | get-func-name@2.0.2: 768 | resolution: {integrity: sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==} 769 | 770 | get-stream@8.0.1: 771 | resolution: {integrity: sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==} 772 | engines: {node: '>=16'} 773 | 774 | glob-parent@5.1.2: 775 | resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} 776 | engines: {node: '>= 6'} 777 | 778 | glob-parent@6.0.2: 779 | resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} 780 | engines: {node: '>=10.13.0'} 781 | 782 | glob@7.2.3: 783 | resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} 784 | deprecated: Glob versions prior to v9 are no longer supported 785 | 786 | globals@13.23.0: 787 | resolution: {integrity: sha512-XAmF0RjlrjY23MA51q3HltdlGxUpXPvg0GioKiD9X6HD28iMjo2dKC8Vqwm7lne4GNr78+RHTfliktR6ZH09wA==} 788 | engines: {node: '>=8'} 789 | 790 | globby@11.1.0: 791 | resolution: {integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==} 792 | engines: {node: '>=10'} 793 | 794 | graphemer@1.4.0: 795 | resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==} 796 | 797 | has-flag@4.0.0: 798 | resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} 799 | engines: {node: '>=8'} 800 | 801 | html-escaper@2.0.2: 802 | resolution: {integrity: sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==} 803 | 804 | human-signals@5.0.0: 805 | resolution: {integrity: sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==} 806 | engines: {node: '>=16.17.0'} 807 | 808 | ignore@5.2.4: 809 | resolution: {integrity: sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==} 810 | engines: {node: '>= 4'} 811 | 812 | ignore@5.3.1: 813 | resolution: {integrity: sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==} 814 | engines: {node: '>= 4'} 815 | 816 | import-fresh@3.3.0: 817 | resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==} 818 | engines: {node: '>=6'} 819 | 820 | imurmurhash@0.1.4: 821 | resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} 822 | engines: {node: '>=0.8.19'} 823 | 824 | inflight@1.0.6: 825 | resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} 826 | deprecated: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful. 827 | 828 | inherits@2.0.4: 829 | resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} 830 | 831 | is-extglob@2.1.1: 832 | resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} 833 | engines: {node: '>=0.10.0'} 834 | 835 | is-glob@4.0.3: 836 | resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} 837 | engines: {node: '>=0.10.0'} 838 | 839 | is-number@7.0.0: 840 | resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} 841 | engines: {node: '>=0.12.0'} 842 | 843 | is-path-inside@3.0.3: 844 | resolution: {integrity: sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==} 845 | engines: {node: '>=8'} 846 | 847 | is-stream@3.0.0: 848 | resolution: {integrity: sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==} 849 | engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} 850 | 851 | isexe@2.0.0: 852 | resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} 853 | 854 | istanbul-lib-coverage@3.2.2: 855 | resolution: {integrity: sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==} 856 | engines: {node: '>=8'} 857 | 858 | istanbul-lib-report@3.0.1: 859 | resolution: {integrity: sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==} 860 | engines: {node: '>=10'} 861 | 862 | istanbul-lib-source-maps@5.0.4: 863 | resolution: {integrity: sha512-wHOoEsNJTVltaJp8eVkm8w+GVkVNHT2YDYo53YdzQEL2gWm1hBX5cGFR9hQJtuGLebidVX7et3+dmDZrmclduw==} 864 | engines: {node: '>=10'} 865 | 866 | istanbul-reports@3.1.6: 867 | resolution: {integrity: sha512-TLgnMkKg3iTDsQ9PbPTdpfAK2DzjF9mqUG7RMgcQl8oFjad8ob4laGxv5XV5U9MAfx8D6tSJiUyuAwzLicaxlg==} 868 | engines: {node: '>=8'} 869 | 870 | js-tokens@9.0.0: 871 | resolution: {integrity: sha512-WriZw1luRMlmV3LGJaR6QOJjWwgLUTf89OwT2lUOyjX2dJGBwgmIkbcz+7WFZjrZM635JOIR517++e/67CP9dQ==} 872 | 873 | js-yaml@4.1.0: 874 | resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} 875 | hasBin: true 876 | 877 | json-buffer@3.0.1: 878 | resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==} 879 | 880 | json-schema-traverse@0.4.1: 881 | resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} 882 | 883 | json-stable-stringify-without-jsonify@1.0.1: 884 | resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} 885 | 886 | jsonc-parser@3.2.0: 887 | resolution: {integrity: sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==} 888 | 889 | keyv@4.5.4: 890 | resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} 891 | 892 | levn@0.4.1: 893 | resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} 894 | engines: {node: '>= 0.8.0'} 895 | 896 | local-pkg@0.5.0: 897 | resolution: {integrity: sha512-ok6z3qlYyCDS4ZEU27HaU6x/xZa9Whf8jD4ptH5UZTQYZVYeb9bnZ3ojVhiJNLiXK1Hfc0GNbLXcmZ5plLDDBg==} 898 | engines: {node: '>=14'} 899 | 900 | locate-path@6.0.0: 901 | resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} 902 | engines: {node: '>=10'} 903 | 904 | lodash.merge@4.6.2: 905 | resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} 906 | 907 | loupe@2.3.6: 908 | resolution: {integrity: sha512-RaPMZKiMy8/JruncMU5Bt6na1eftNoo++R4Y+N2FrxkDVTrGvcyzFTsaGif4QTeKESheMGegbhw6iUAq+5A8zA==} 909 | deprecated: Please upgrade to 2.3.7 which fixes GHSA-4q6p-r6v2-jvc5 910 | 911 | loupe@2.3.7: 912 | resolution: {integrity: sha512-zSMINGVYkdpYSOBmLi0D1Uo7JU9nVdQKrHxC8eYlV+9YKK9WePqAlL7lSlorG/U2Fw1w0hTBmaa/jrQ3UbPHtA==} 913 | 914 | lru-cache@6.0.0: 915 | resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==} 916 | engines: {node: '>=10'} 917 | 918 | magic-string@0.30.10: 919 | resolution: {integrity: sha512-iIRwTIf0QKV3UAnYK4PU8uiEc4SRh5jX0mwpIwETPpHdhVM4f53RSwS/vXvN1JhGX+Cs7B8qIq3d6AH49O5fAQ==} 920 | 921 | magicast@0.3.4: 922 | resolution: {integrity: sha512-TyDF/Pn36bBji9rWKHlZe+PZb6Mx5V8IHCSxk7X4aljM4e/vyDvZZYwHewdVaqiA0nb3ghfHU/6AUpDxWoER2Q==} 923 | 924 | make-dir@4.0.0: 925 | resolution: {integrity: sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==} 926 | engines: {node: '>=10'} 927 | 928 | merge-stream@2.0.0: 929 | resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} 930 | 931 | merge2@1.4.1: 932 | resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} 933 | engines: {node: '>= 8'} 934 | 935 | micromatch@4.0.5: 936 | resolution: {integrity: sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==} 937 | engines: {node: '>=8.6'} 938 | 939 | mimic-fn@4.0.0: 940 | resolution: {integrity: sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==} 941 | engines: {node: '>=12'} 942 | 943 | minimatch@3.1.2: 944 | resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} 945 | 946 | minimatch@9.0.4: 947 | resolution: {integrity: sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==} 948 | engines: {node: '>=16 || 14 >=14.17'} 949 | 950 | mlly@1.4.2: 951 | resolution: {integrity: sha512-i/Ykufi2t1EZ6NaPLdfnZk2AX8cs0d+mTzVKuPfqPKPatxLApaBoxJQ9x1/uckXtrS/U5oisPMDkNs0yQTaBRg==} 952 | 953 | ms@2.1.2: 954 | resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} 955 | 956 | nanoid@3.3.7: 957 | resolution: {integrity: sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==} 958 | engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} 959 | hasBin: true 960 | 961 | natural-compare@1.4.0: 962 | resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} 963 | 964 | normalizr@3.6.2: 965 | resolution: {integrity: sha512-30qCybsBaCBciotorvuOZTCGEg2AXrJfADMT2Kk/lvpIAcipHdK0zc33nNtwKzyfQAqIJXAcqET6YgflYUgsoQ==} 966 | 967 | npm-run-path@5.1.0: 968 | resolution: {integrity: sha512-sJOdmRGrY2sjNTRMbSvluQqg+8X7ZK61yvzBEIDhz4f8z1TZFYABsqjjCBd/0PUNE9M6QDgHJXQkGUEm7Q+l9Q==} 969 | engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} 970 | 971 | once@1.4.0: 972 | resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} 973 | 974 | onetime@6.0.0: 975 | resolution: {integrity: sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==} 976 | engines: {node: '>=12'} 977 | 978 | optionator@0.9.3: 979 | resolution: {integrity: sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==} 980 | engines: {node: '>= 0.8.0'} 981 | 982 | p-limit@3.1.0: 983 | resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} 984 | engines: {node: '>=10'} 985 | 986 | p-limit@5.0.0: 987 | resolution: {integrity: sha512-/Eaoq+QyLSiXQ4lyYV23f14mZRQcXnxfHrN0vCai+ak9G0pp9iEQukIIZq5NccEvwRB8PUnZT0KsOoDCINS1qQ==} 988 | engines: {node: '>=18'} 989 | 990 | p-locate@5.0.0: 991 | resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} 992 | engines: {node: '>=10'} 993 | 994 | parent-module@1.0.1: 995 | resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} 996 | engines: {node: '>=6'} 997 | 998 | path-exists@4.0.0: 999 | resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} 1000 | engines: {node: '>=8'} 1001 | 1002 | path-is-absolute@1.0.1: 1003 | resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} 1004 | engines: {node: '>=0.10.0'} 1005 | 1006 | path-key@3.1.1: 1007 | resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} 1008 | engines: {node: '>=8'} 1009 | 1010 | path-key@4.0.0: 1011 | resolution: {integrity: sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==} 1012 | engines: {node: '>=12'} 1013 | 1014 | path-type@4.0.0: 1015 | resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} 1016 | engines: {node: '>=8'} 1017 | 1018 | pathe@1.1.1: 1019 | resolution: {integrity: sha512-d+RQGp0MAYTIaDBIMmOfMwz3E+LOZnxx1HZd5R18mmCZY0QBlK0LDZfPc8FW8Ed2DlvsuE6PRjroDY+wg4+j/Q==} 1020 | 1021 | pathval@1.1.1: 1022 | resolution: {integrity: sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==} 1023 | 1024 | picocolors@1.0.0: 1025 | resolution: {integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==} 1026 | 1027 | picomatch@2.3.1: 1028 | resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} 1029 | engines: {node: '>=8.6'} 1030 | 1031 | pkg-types@1.0.3: 1032 | resolution: {integrity: sha512-nN7pYi0AQqJnoLPC9eHFQ8AcyaixBUOwvqc5TDnIKCMEE6I0y8P7OKA7fPexsXGCGxQDl/cmrLAp26LhcwxZ4A==} 1033 | 1034 | postcss@8.4.38: 1035 | resolution: {integrity: sha512-Wglpdk03BSfXkHoQa3b/oulrotAkwrlLDRSOb9D0bN86FdRyE9lppSp33aHNPgBa0JKCoB+drFLZkQoRRYae5A==} 1036 | engines: {node: ^10 || ^12 || >=14} 1037 | 1038 | prelude-ls@1.2.1: 1039 | resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} 1040 | engines: {node: '>= 0.8.0'} 1041 | 1042 | prettier-linter-helpers@1.0.0: 1043 | resolution: {integrity: sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==} 1044 | engines: {node: '>=6.0.0'} 1045 | 1046 | prettier@3.3.1: 1047 | resolution: {integrity: sha512-7CAwy5dRsxs8PHXT3twixW9/OEll8MLE0VRPCJyl7CkS6VHGPSlsVaWTiASPTyGyYRyApxlaWTzwUxVNrhcwDg==} 1048 | engines: {node: '>=14'} 1049 | hasBin: true 1050 | 1051 | pretty-format@29.7.0: 1052 | resolution: {integrity: sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==} 1053 | engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} 1054 | 1055 | punycode@2.3.0: 1056 | resolution: {integrity: sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==} 1057 | engines: {node: '>=6'} 1058 | 1059 | queue-microtask@1.2.3: 1060 | resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} 1061 | 1062 | react-is@18.2.0: 1063 | resolution: {integrity: sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==} 1064 | 1065 | resolve-from@4.0.0: 1066 | resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} 1067 | engines: {node: '>=4'} 1068 | 1069 | reusify@1.0.4: 1070 | resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} 1071 | engines: {iojs: '>=1.0.0', node: '>=0.10.0'} 1072 | 1073 | rimraf@3.0.2: 1074 | resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==} 1075 | deprecated: Rimraf versions prior to v4 are no longer supported 1076 | hasBin: true 1077 | 1078 | rollup@4.18.0: 1079 | resolution: {integrity: sha512-QmJz14PX3rzbJCN1SG4Xe/bAAX2a6NpCP8ab2vfu2GiUr8AQcr2nCV/oEO3yneFarB67zk8ShlIyWb2LGTb3Sg==} 1080 | engines: {node: '>=18.0.0', npm: '>=8.0.0'} 1081 | hasBin: true 1082 | 1083 | run-parallel@1.2.0: 1084 | resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} 1085 | 1086 | semver@7.5.4: 1087 | resolution: {integrity: sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==} 1088 | engines: {node: '>=10'} 1089 | hasBin: true 1090 | 1091 | semver@7.6.2: 1092 | resolution: {integrity: sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==} 1093 | engines: {node: '>=10'} 1094 | hasBin: true 1095 | 1096 | shebang-command@2.0.0: 1097 | resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} 1098 | engines: {node: '>=8'} 1099 | 1100 | shebang-regex@3.0.0: 1101 | resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} 1102 | engines: {node: '>=8'} 1103 | 1104 | siginfo@2.0.0: 1105 | resolution: {integrity: sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==} 1106 | 1107 | signal-exit@4.1.0: 1108 | resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} 1109 | engines: {node: '>=14'} 1110 | 1111 | slash@3.0.0: 1112 | resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} 1113 | engines: {node: '>=8'} 1114 | 1115 | source-map-js@1.2.0: 1116 | resolution: {integrity: sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==} 1117 | engines: {node: '>=0.10.0'} 1118 | 1119 | stackback@0.0.2: 1120 | resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==} 1121 | 1122 | std-env@3.7.0: 1123 | resolution: {integrity: sha512-JPbdCEQLj1w5GilpiHAx3qJvFndqybBysA3qUOnznweH4QbNYUsW/ea8QzSrnh0vNsezMMw5bcVool8lM0gwzg==} 1124 | 1125 | strip-ansi@6.0.1: 1126 | resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} 1127 | engines: {node: '>=8'} 1128 | 1129 | strip-final-newline@3.0.0: 1130 | resolution: {integrity: sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==} 1131 | engines: {node: '>=12'} 1132 | 1133 | strip-json-comments@3.1.1: 1134 | resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} 1135 | engines: {node: '>=8'} 1136 | 1137 | strip-literal@2.1.0: 1138 | resolution: {integrity: sha512-Op+UycaUt/8FbN/Z2TWPBLge3jWrP3xj10f3fnYxf052bKuS3EKs1ZQcVGjnEMdsNVAM+plXRdmjrZ/KgG3Skw==} 1139 | 1140 | supports-color@7.2.0: 1141 | resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} 1142 | engines: {node: '>=8'} 1143 | 1144 | synckit@0.8.8: 1145 | resolution: {integrity: sha512-HwOKAP7Wc5aRGYdKH+dw0PRRpbO841v2DENBtjnR5HFWoiNByAl7vrx3p0G/rCyYXQsrxqtX48TImFtPcIHSpQ==} 1146 | engines: {node: ^14.18.0 || >=16.0.0} 1147 | 1148 | test-exclude@6.0.0: 1149 | resolution: {integrity: sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==} 1150 | engines: {node: '>=8'} 1151 | 1152 | text-table@0.2.0: 1153 | resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==} 1154 | 1155 | tinybench@2.5.1: 1156 | resolution: {integrity: sha512-65NKvSuAVDP/n4CqH+a9w2kTlLReS9vhsAP06MWx+/89nMinJyB2icyl58RIcqCmIggpojIGeuJGhjU1aGMBSg==} 1157 | 1158 | tinypool@0.8.4: 1159 | resolution: {integrity: sha512-i11VH5gS6IFeLY3gMBQ00/MmLncVP7JLXOw1vlgkytLmJK7QnEr7NXf0LBdxfmNPAeyetukOk0bOYrJrFGjYJQ==} 1160 | engines: {node: '>=14.0.0'} 1161 | 1162 | tinyspy@2.2.0: 1163 | resolution: {integrity: sha512-d2eda04AN/cPOR89F7Xv5bK/jrQEhmcLFe6HFldoeO9AJtps+fqEnh486vnT/8y4bw38pSyxDcTCAq+Ks2aJTg==} 1164 | engines: {node: '>=14.0.0'} 1165 | 1166 | to-fast-properties@2.0.0: 1167 | resolution: {integrity: sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==} 1168 | engines: {node: '>=4'} 1169 | 1170 | to-regex-range@5.0.1: 1171 | resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} 1172 | engines: {node: '>=8.0'} 1173 | 1174 | ts-api-utils@1.3.0: 1175 | resolution: {integrity: sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==} 1176 | engines: {node: '>=16'} 1177 | peerDependencies: 1178 | typescript: '>=4.2.0' 1179 | 1180 | tslib@2.6.3: 1181 | resolution: {integrity: sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==} 1182 | 1183 | type-check@0.4.0: 1184 | resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} 1185 | engines: {node: '>= 0.8.0'} 1186 | 1187 | type-detect@4.0.8: 1188 | resolution: {integrity: sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==} 1189 | engines: {node: '>=4'} 1190 | 1191 | type-fest@0.20.2: 1192 | resolution: {integrity: sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==} 1193 | engines: {node: '>=10'} 1194 | 1195 | typescript@5.4.5: 1196 | resolution: {integrity: sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==} 1197 | engines: {node: '>=14.17'} 1198 | hasBin: true 1199 | 1200 | ufo@1.3.1: 1201 | resolution: {integrity: sha512-uY/99gMLIOlJPwATcMVYfqDSxUR9//AUcgZMzwfSTJPDKzA1S8mX4VLqa+fiAtveraQUBCz4FFcwVZBGbwBXIw==} 1202 | 1203 | uri-js@4.4.1: 1204 | resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} 1205 | 1206 | vite-node@1.6.0: 1207 | resolution: {integrity: sha512-de6HJgzC+TFzOu0NTC4RAIsyf/DY/ibWDYQUcuEA84EMHhcefTUGkjFHKKEJhQN4A+6I0u++kr3l36ZF2d7XRw==} 1208 | engines: {node: ^18.0.0 || >=20.0.0} 1209 | hasBin: true 1210 | 1211 | vite@5.2.13: 1212 | resolution: {integrity: sha512-SSq1noJfY9pR3I1TUENL3rQYDQCFqgD+lM6fTRAM8Nv6Lsg5hDLaXkjETVeBt+7vZBCMoibD+6IWnT2mJ+Zb/A==} 1213 | engines: {node: ^18.0.0 || >=20.0.0} 1214 | hasBin: true 1215 | peerDependencies: 1216 | '@types/node': ^18.0.0 || >=20.0.0 1217 | less: '*' 1218 | lightningcss: ^1.21.0 1219 | sass: '*' 1220 | stylus: '*' 1221 | sugarss: '*' 1222 | terser: ^5.4.0 1223 | peerDependenciesMeta: 1224 | '@types/node': 1225 | optional: true 1226 | less: 1227 | optional: true 1228 | lightningcss: 1229 | optional: true 1230 | sass: 1231 | optional: true 1232 | stylus: 1233 | optional: true 1234 | sugarss: 1235 | optional: true 1236 | terser: 1237 | optional: true 1238 | 1239 | vitest@1.6.0: 1240 | resolution: {integrity: sha512-H5r/dN06swuFnzNFhq/dnz37bPXnq8xB2xB5JOVk8K09rUtoeNN+LHWkoQ0A/i3hvbUKKcCei9KpbxqHMLhLLA==} 1241 | engines: {node: ^18.0.0 || >=20.0.0} 1242 | hasBin: true 1243 | peerDependencies: 1244 | '@edge-runtime/vm': '*' 1245 | '@types/node': ^18.0.0 || >=20.0.0 1246 | '@vitest/browser': 1.6.0 1247 | '@vitest/ui': 1.6.0 1248 | happy-dom: '*' 1249 | jsdom: '*' 1250 | peerDependenciesMeta: 1251 | '@edge-runtime/vm': 1252 | optional: true 1253 | '@types/node': 1254 | optional: true 1255 | '@vitest/browser': 1256 | optional: true 1257 | '@vitest/ui': 1258 | optional: true 1259 | happy-dom: 1260 | optional: true 1261 | jsdom: 1262 | optional: true 1263 | 1264 | vue@3.4.27: 1265 | resolution: {integrity: sha512-8s/56uK6r01r1icG/aEOHqyMVxd1bkYcSe9j8HcKtr/xTOFWvnzIVTehNW+5Yt89f+DLBe4A569pnZLS5HzAMA==} 1266 | peerDependencies: 1267 | typescript: '*' 1268 | peerDependenciesMeta: 1269 | typescript: 1270 | optional: true 1271 | 1272 | vuex@4.1.0: 1273 | resolution: {integrity: sha512-hmV6UerDrPcgbSy9ORAtNXDr9M4wlNP4pEFKye4ujJF8oqgFFuxDCdOLS3eNoRTtq5O3hoBDh9Doj1bQMYHRbQ==} 1274 | peerDependencies: 1275 | vue: ^3.2.0 1276 | 1277 | which@2.0.2: 1278 | resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} 1279 | engines: {node: '>= 8'} 1280 | hasBin: true 1281 | 1282 | why-is-node-running@2.2.2: 1283 | resolution: {integrity: sha512-6tSwToZxTOcotxHeA+qGCq1mVzKR3CwcJGmVcY+QE8SHy6TnpFnh8PAvPNHYr7EcuVeG0QSMxtYCuO1ta/G/oA==} 1284 | engines: {node: '>=8'} 1285 | hasBin: true 1286 | 1287 | wrappy@1.0.2: 1288 | resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} 1289 | 1290 | yallist@4.0.0: 1291 | resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} 1292 | 1293 | yocto-queue@0.1.0: 1294 | resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} 1295 | engines: {node: '>=10'} 1296 | 1297 | yocto-queue@1.0.0: 1298 | resolution: {integrity: sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g==} 1299 | engines: {node: '>=12.20'} 1300 | 1301 | snapshots: 1302 | 1303 | '@aashutoshrathi/word-wrap@1.2.6': {} 1304 | 1305 | '@ampproject/remapping@2.2.1': 1306 | dependencies: 1307 | '@jridgewell/gen-mapping': 0.3.3 1308 | '@jridgewell/trace-mapping': 0.3.19 1309 | 1310 | '@babel/helper-string-parser@7.24.7': {} 1311 | 1312 | '@babel/helper-validator-identifier@7.24.7': {} 1313 | 1314 | '@babel/parser@7.24.7': 1315 | dependencies: 1316 | '@babel/types': 7.24.7 1317 | 1318 | '@babel/types@7.24.7': 1319 | dependencies: 1320 | '@babel/helper-string-parser': 7.24.7 1321 | '@babel/helper-validator-identifier': 7.24.7 1322 | to-fast-properties: 2.0.0 1323 | 1324 | '@bcoe/v8-coverage@0.2.3': {} 1325 | 1326 | '@esbuild/aix-ppc64@0.20.2': 1327 | optional: true 1328 | 1329 | '@esbuild/android-arm64@0.20.2': 1330 | optional: true 1331 | 1332 | '@esbuild/android-arm@0.20.2': 1333 | optional: true 1334 | 1335 | '@esbuild/android-x64@0.20.2': 1336 | optional: true 1337 | 1338 | '@esbuild/darwin-arm64@0.20.2': 1339 | optional: true 1340 | 1341 | '@esbuild/darwin-x64@0.20.2': 1342 | optional: true 1343 | 1344 | '@esbuild/freebsd-arm64@0.20.2': 1345 | optional: true 1346 | 1347 | '@esbuild/freebsd-x64@0.20.2': 1348 | optional: true 1349 | 1350 | '@esbuild/linux-arm64@0.20.2': 1351 | optional: true 1352 | 1353 | '@esbuild/linux-arm@0.20.2': 1354 | optional: true 1355 | 1356 | '@esbuild/linux-ia32@0.20.2': 1357 | optional: true 1358 | 1359 | '@esbuild/linux-loong64@0.20.2': 1360 | optional: true 1361 | 1362 | '@esbuild/linux-mips64el@0.20.2': 1363 | optional: true 1364 | 1365 | '@esbuild/linux-ppc64@0.20.2': 1366 | optional: true 1367 | 1368 | '@esbuild/linux-riscv64@0.20.2': 1369 | optional: true 1370 | 1371 | '@esbuild/linux-s390x@0.20.2': 1372 | optional: true 1373 | 1374 | '@esbuild/linux-x64@0.20.2': 1375 | optional: true 1376 | 1377 | '@esbuild/netbsd-x64@0.20.2': 1378 | optional: true 1379 | 1380 | '@esbuild/openbsd-x64@0.20.2': 1381 | optional: true 1382 | 1383 | '@esbuild/sunos-x64@0.20.2': 1384 | optional: true 1385 | 1386 | '@esbuild/win32-arm64@0.20.2': 1387 | optional: true 1388 | 1389 | '@esbuild/win32-ia32@0.20.2': 1390 | optional: true 1391 | 1392 | '@esbuild/win32-x64@0.20.2': 1393 | optional: true 1394 | 1395 | '@eslint-community/eslint-utils@4.4.0(eslint@8.57.0)': 1396 | dependencies: 1397 | eslint: 8.57.0 1398 | eslint-visitor-keys: 3.4.3 1399 | 1400 | '@eslint-community/regexpp@4.10.1': {} 1401 | 1402 | '@eslint-community/regexpp@4.9.1': {} 1403 | 1404 | '@eslint/eslintrc@2.1.4': 1405 | dependencies: 1406 | ajv: 6.12.6 1407 | debug: 4.3.4 1408 | espree: 9.6.1 1409 | globals: 13.23.0 1410 | ignore: 5.2.4 1411 | import-fresh: 3.3.0 1412 | js-yaml: 4.1.0 1413 | minimatch: 3.1.2 1414 | strip-json-comments: 3.1.1 1415 | transitivePeerDependencies: 1416 | - supports-color 1417 | 1418 | '@eslint/js@8.57.0': {} 1419 | 1420 | '@humanwhocodes/config-array@0.11.14': 1421 | dependencies: 1422 | '@humanwhocodes/object-schema': 2.0.3 1423 | debug: 4.3.4 1424 | minimatch: 3.1.2 1425 | transitivePeerDependencies: 1426 | - supports-color 1427 | 1428 | '@humanwhocodes/module-importer@1.0.1': {} 1429 | 1430 | '@humanwhocodes/object-schema@2.0.3': {} 1431 | 1432 | '@istanbuljs/schema@0.1.3': {} 1433 | 1434 | '@jest/schemas@29.6.3': 1435 | dependencies: 1436 | '@sinclair/typebox': 0.27.8 1437 | 1438 | '@jridgewell/gen-mapping@0.3.3': 1439 | dependencies: 1440 | '@jridgewell/set-array': 1.1.2 1441 | '@jridgewell/sourcemap-codec': 1.4.15 1442 | '@jridgewell/trace-mapping': 0.3.19 1443 | 1444 | '@jridgewell/resolve-uri@3.1.1': {} 1445 | 1446 | '@jridgewell/set-array@1.1.2': {} 1447 | 1448 | '@jridgewell/sourcemap-codec@1.4.15': {} 1449 | 1450 | '@jridgewell/trace-mapping@0.3.19': 1451 | dependencies: 1452 | '@jridgewell/resolve-uri': 3.1.1 1453 | '@jridgewell/sourcemap-codec': 1.4.15 1454 | 1455 | '@jridgewell/trace-mapping@0.3.25': 1456 | dependencies: 1457 | '@jridgewell/resolve-uri': 3.1.1 1458 | '@jridgewell/sourcemap-codec': 1.4.15 1459 | 1460 | '@nodelib/fs.scandir@2.1.5': 1461 | dependencies: 1462 | '@nodelib/fs.stat': 2.0.5 1463 | run-parallel: 1.2.0 1464 | 1465 | '@nodelib/fs.stat@2.0.5': {} 1466 | 1467 | '@nodelib/fs.walk@1.2.8': 1468 | dependencies: 1469 | '@nodelib/fs.scandir': 2.1.5 1470 | fastq: 1.15.0 1471 | 1472 | '@pkgr/core@0.1.1': {} 1473 | 1474 | '@rollup/rollup-android-arm-eabi@4.18.0': 1475 | optional: true 1476 | 1477 | '@rollup/rollup-android-arm64@4.18.0': 1478 | optional: true 1479 | 1480 | '@rollup/rollup-darwin-arm64@4.18.0': 1481 | optional: true 1482 | 1483 | '@rollup/rollup-darwin-x64@4.18.0': 1484 | optional: true 1485 | 1486 | '@rollup/rollup-linux-arm-gnueabihf@4.18.0': 1487 | optional: true 1488 | 1489 | '@rollup/rollup-linux-arm-musleabihf@4.18.0': 1490 | optional: true 1491 | 1492 | '@rollup/rollup-linux-arm64-gnu@4.18.0': 1493 | optional: true 1494 | 1495 | '@rollup/rollup-linux-arm64-musl@4.18.0': 1496 | optional: true 1497 | 1498 | '@rollup/rollup-linux-powerpc64le-gnu@4.18.0': 1499 | optional: true 1500 | 1501 | '@rollup/rollup-linux-riscv64-gnu@4.18.0': 1502 | optional: true 1503 | 1504 | '@rollup/rollup-linux-s390x-gnu@4.18.0': 1505 | optional: true 1506 | 1507 | '@rollup/rollup-linux-x64-gnu@4.18.0': 1508 | optional: true 1509 | 1510 | '@rollup/rollup-linux-x64-musl@4.18.0': 1511 | optional: true 1512 | 1513 | '@rollup/rollup-win32-arm64-msvc@4.18.0': 1514 | optional: true 1515 | 1516 | '@rollup/rollup-win32-ia32-msvc@4.18.0': 1517 | optional: true 1518 | 1519 | '@rollup/rollup-win32-x64-msvc@4.18.0': 1520 | optional: true 1521 | 1522 | '@sinclair/typebox@0.27.8': {} 1523 | 1524 | '@types/estree@1.0.5': {} 1525 | 1526 | '@types/node@20.8.3': 1527 | optional: true 1528 | 1529 | '@typescript-eslint/eslint-plugin@7.12.0(@typescript-eslint/parser@7.12.0(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0)(typescript@5.4.5)': 1530 | dependencies: 1531 | '@eslint-community/regexpp': 4.10.1 1532 | '@typescript-eslint/parser': 7.12.0(eslint@8.57.0)(typescript@5.4.5) 1533 | '@typescript-eslint/scope-manager': 7.12.0 1534 | '@typescript-eslint/type-utils': 7.12.0(eslint@8.57.0)(typescript@5.4.5) 1535 | '@typescript-eslint/utils': 7.12.0(eslint@8.57.0)(typescript@5.4.5) 1536 | '@typescript-eslint/visitor-keys': 7.12.0 1537 | eslint: 8.57.0 1538 | graphemer: 1.4.0 1539 | ignore: 5.3.1 1540 | natural-compare: 1.4.0 1541 | ts-api-utils: 1.3.0(typescript@5.4.5) 1542 | optionalDependencies: 1543 | typescript: 5.4.5 1544 | transitivePeerDependencies: 1545 | - supports-color 1546 | 1547 | '@typescript-eslint/parser@7.12.0(eslint@8.57.0)(typescript@5.4.5)': 1548 | dependencies: 1549 | '@typescript-eslint/scope-manager': 7.12.0 1550 | '@typescript-eslint/types': 7.12.0 1551 | '@typescript-eslint/typescript-estree': 7.12.0(typescript@5.4.5) 1552 | '@typescript-eslint/visitor-keys': 7.12.0 1553 | debug: 4.3.4 1554 | eslint: 8.57.0 1555 | optionalDependencies: 1556 | typescript: 5.4.5 1557 | transitivePeerDependencies: 1558 | - supports-color 1559 | 1560 | '@typescript-eslint/scope-manager@7.12.0': 1561 | dependencies: 1562 | '@typescript-eslint/types': 7.12.0 1563 | '@typescript-eslint/visitor-keys': 7.12.0 1564 | 1565 | '@typescript-eslint/type-utils@7.12.0(eslint@8.57.0)(typescript@5.4.5)': 1566 | dependencies: 1567 | '@typescript-eslint/typescript-estree': 7.12.0(typescript@5.4.5) 1568 | '@typescript-eslint/utils': 7.12.0(eslint@8.57.0)(typescript@5.4.5) 1569 | debug: 4.3.4 1570 | eslint: 8.57.0 1571 | ts-api-utils: 1.3.0(typescript@5.4.5) 1572 | optionalDependencies: 1573 | typescript: 5.4.5 1574 | transitivePeerDependencies: 1575 | - supports-color 1576 | 1577 | '@typescript-eslint/types@7.12.0': {} 1578 | 1579 | '@typescript-eslint/typescript-estree@7.12.0(typescript@5.4.5)': 1580 | dependencies: 1581 | '@typescript-eslint/types': 7.12.0 1582 | '@typescript-eslint/visitor-keys': 7.12.0 1583 | debug: 4.3.4 1584 | globby: 11.1.0 1585 | is-glob: 4.0.3 1586 | minimatch: 9.0.4 1587 | semver: 7.6.2 1588 | ts-api-utils: 1.3.0(typescript@5.4.5) 1589 | optionalDependencies: 1590 | typescript: 5.4.5 1591 | transitivePeerDependencies: 1592 | - supports-color 1593 | 1594 | '@typescript-eslint/utils@7.12.0(eslint@8.57.0)(typescript@5.4.5)': 1595 | dependencies: 1596 | '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0) 1597 | '@typescript-eslint/scope-manager': 7.12.0 1598 | '@typescript-eslint/types': 7.12.0 1599 | '@typescript-eslint/typescript-estree': 7.12.0(typescript@5.4.5) 1600 | eslint: 8.57.0 1601 | transitivePeerDependencies: 1602 | - supports-color 1603 | - typescript 1604 | 1605 | '@typescript-eslint/visitor-keys@7.12.0': 1606 | dependencies: 1607 | '@typescript-eslint/types': 7.12.0 1608 | eslint-visitor-keys: 3.4.3 1609 | 1610 | '@ungap/structured-clone@1.2.0': {} 1611 | 1612 | '@vitest/coverage-v8@1.6.0(vitest@1.6.0(@types/node@20.8.3))': 1613 | dependencies: 1614 | '@ampproject/remapping': 2.2.1 1615 | '@bcoe/v8-coverage': 0.2.3 1616 | debug: 4.3.4 1617 | istanbul-lib-coverage: 3.2.2 1618 | istanbul-lib-report: 3.0.1 1619 | istanbul-lib-source-maps: 5.0.4 1620 | istanbul-reports: 3.1.6 1621 | magic-string: 0.30.10 1622 | magicast: 0.3.4 1623 | picocolors: 1.0.0 1624 | std-env: 3.7.0 1625 | strip-literal: 2.1.0 1626 | test-exclude: 6.0.0 1627 | vitest: 1.6.0(@types/node@20.8.3) 1628 | transitivePeerDependencies: 1629 | - supports-color 1630 | 1631 | '@vitest/expect@1.6.0': 1632 | dependencies: 1633 | '@vitest/spy': 1.6.0 1634 | '@vitest/utils': 1.6.0 1635 | chai: 4.3.10 1636 | 1637 | '@vitest/runner@1.6.0': 1638 | dependencies: 1639 | '@vitest/utils': 1.6.0 1640 | p-limit: 5.0.0 1641 | pathe: 1.1.1 1642 | 1643 | '@vitest/snapshot@1.6.0': 1644 | dependencies: 1645 | magic-string: 0.30.10 1646 | pathe: 1.1.1 1647 | pretty-format: 29.7.0 1648 | 1649 | '@vitest/spy@1.6.0': 1650 | dependencies: 1651 | tinyspy: 2.2.0 1652 | 1653 | '@vitest/utils@1.6.0': 1654 | dependencies: 1655 | diff-sequences: 29.6.3 1656 | estree-walker: 3.0.3 1657 | loupe: 2.3.7 1658 | pretty-format: 29.7.0 1659 | 1660 | '@vue/compiler-core@3.4.27': 1661 | dependencies: 1662 | '@babel/parser': 7.24.7 1663 | '@vue/shared': 3.4.27 1664 | entities: 4.5.0 1665 | estree-walker: 2.0.2 1666 | source-map-js: 1.2.0 1667 | 1668 | '@vue/compiler-dom@3.4.27': 1669 | dependencies: 1670 | '@vue/compiler-core': 3.4.27 1671 | '@vue/shared': 3.4.27 1672 | 1673 | '@vue/compiler-sfc@3.4.27': 1674 | dependencies: 1675 | '@babel/parser': 7.24.7 1676 | '@vue/compiler-core': 3.4.27 1677 | '@vue/compiler-dom': 3.4.27 1678 | '@vue/compiler-ssr': 3.4.27 1679 | '@vue/shared': 3.4.27 1680 | estree-walker: 2.0.2 1681 | magic-string: 0.30.10 1682 | postcss: 8.4.38 1683 | source-map-js: 1.2.0 1684 | 1685 | '@vue/compiler-ssr@3.4.27': 1686 | dependencies: 1687 | '@vue/compiler-dom': 3.4.27 1688 | '@vue/shared': 3.4.27 1689 | 1690 | '@vue/devtools-api@6.5.0': {} 1691 | 1692 | '@vue/reactivity@3.4.27': 1693 | dependencies: 1694 | '@vue/shared': 3.4.27 1695 | 1696 | '@vue/runtime-core@3.4.27': 1697 | dependencies: 1698 | '@vue/reactivity': 3.4.27 1699 | '@vue/shared': 3.4.27 1700 | 1701 | '@vue/runtime-dom@3.4.27': 1702 | dependencies: 1703 | '@vue/runtime-core': 3.4.27 1704 | '@vue/shared': 3.4.27 1705 | csstype: 3.1.3 1706 | 1707 | '@vue/server-renderer@3.4.27(vue@3.4.27(typescript@5.4.5))': 1708 | dependencies: 1709 | '@vue/compiler-ssr': 3.4.27 1710 | '@vue/shared': 3.4.27 1711 | vue: 3.4.27(typescript@5.4.5) 1712 | 1713 | '@vue/shared@3.4.27': {} 1714 | 1715 | '@vuex-orm/core@0.36.4(vuex@4.1.0(vue@3.4.27(typescript@5.4.5)))': 1716 | dependencies: 1717 | normalizr: 3.6.2 1718 | vuex: 4.1.0(vue@3.4.27(typescript@5.4.5)) 1719 | 1720 | acorn-jsx@5.3.2(acorn@8.10.0): 1721 | dependencies: 1722 | acorn: 8.10.0 1723 | 1724 | acorn-walk@8.3.2: {} 1725 | 1726 | acorn@8.10.0: {} 1727 | 1728 | ajv@6.12.6: 1729 | dependencies: 1730 | fast-deep-equal: 3.1.3 1731 | fast-json-stable-stringify: 2.1.0 1732 | json-schema-traverse: 0.4.1 1733 | uri-js: 4.4.1 1734 | 1735 | ansi-regex@5.0.1: {} 1736 | 1737 | ansi-styles@4.3.0: 1738 | dependencies: 1739 | color-convert: 2.0.1 1740 | 1741 | ansi-styles@5.2.0: {} 1742 | 1743 | argparse@2.0.1: {} 1744 | 1745 | array-union@2.1.0: {} 1746 | 1747 | assertion-error@1.1.0: {} 1748 | 1749 | balanced-match@1.0.2: {} 1750 | 1751 | brace-expansion@1.1.11: 1752 | dependencies: 1753 | balanced-match: 1.0.2 1754 | concat-map: 0.0.1 1755 | 1756 | brace-expansion@2.0.1: 1757 | dependencies: 1758 | balanced-match: 1.0.2 1759 | 1760 | braces@3.0.2: 1761 | dependencies: 1762 | fill-range: 7.0.1 1763 | 1764 | cac@6.7.14: {} 1765 | 1766 | callsites@3.1.0: {} 1767 | 1768 | chai@4.3.10: 1769 | dependencies: 1770 | assertion-error: 1.1.0 1771 | check-error: 1.0.3 1772 | deep-eql: 4.1.3 1773 | get-func-name: 2.0.2 1774 | loupe: 2.3.6 1775 | pathval: 1.1.1 1776 | type-detect: 4.0.8 1777 | 1778 | chalk@4.1.2: 1779 | dependencies: 1780 | ansi-styles: 4.3.0 1781 | supports-color: 7.2.0 1782 | 1783 | check-error@1.0.3: 1784 | dependencies: 1785 | get-func-name: 2.0.2 1786 | 1787 | color-convert@2.0.1: 1788 | dependencies: 1789 | color-name: 1.1.4 1790 | 1791 | color-name@1.1.4: {} 1792 | 1793 | concat-map@0.0.1: {} 1794 | 1795 | cross-spawn@7.0.3: 1796 | dependencies: 1797 | path-key: 3.1.1 1798 | shebang-command: 2.0.0 1799 | which: 2.0.2 1800 | 1801 | csstype@3.1.3: {} 1802 | 1803 | debug@4.3.4: 1804 | dependencies: 1805 | ms: 2.1.2 1806 | 1807 | deep-eql@4.1.3: 1808 | dependencies: 1809 | type-detect: 4.0.8 1810 | 1811 | deep-is@0.1.4: {} 1812 | 1813 | diff-sequences@29.6.3: {} 1814 | 1815 | dir-glob@3.0.1: 1816 | dependencies: 1817 | path-type: 4.0.0 1818 | 1819 | doctrine@3.0.0: 1820 | dependencies: 1821 | esutils: 2.0.3 1822 | 1823 | entities@4.5.0: {} 1824 | 1825 | esbuild@0.20.2: 1826 | optionalDependencies: 1827 | '@esbuild/aix-ppc64': 0.20.2 1828 | '@esbuild/android-arm': 0.20.2 1829 | '@esbuild/android-arm64': 0.20.2 1830 | '@esbuild/android-x64': 0.20.2 1831 | '@esbuild/darwin-arm64': 0.20.2 1832 | '@esbuild/darwin-x64': 0.20.2 1833 | '@esbuild/freebsd-arm64': 0.20.2 1834 | '@esbuild/freebsd-x64': 0.20.2 1835 | '@esbuild/linux-arm': 0.20.2 1836 | '@esbuild/linux-arm64': 0.20.2 1837 | '@esbuild/linux-ia32': 0.20.2 1838 | '@esbuild/linux-loong64': 0.20.2 1839 | '@esbuild/linux-mips64el': 0.20.2 1840 | '@esbuild/linux-ppc64': 0.20.2 1841 | '@esbuild/linux-riscv64': 0.20.2 1842 | '@esbuild/linux-s390x': 0.20.2 1843 | '@esbuild/linux-x64': 0.20.2 1844 | '@esbuild/netbsd-x64': 0.20.2 1845 | '@esbuild/openbsd-x64': 0.20.2 1846 | '@esbuild/sunos-x64': 0.20.2 1847 | '@esbuild/win32-arm64': 0.20.2 1848 | '@esbuild/win32-ia32': 0.20.2 1849 | '@esbuild/win32-x64': 0.20.2 1850 | 1851 | escape-string-regexp@4.0.0: {} 1852 | 1853 | eslint-config-prettier@9.1.0(eslint@8.57.0): 1854 | dependencies: 1855 | eslint: 8.57.0 1856 | 1857 | eslint-plugin-prettier@5.1.3(eslint-config-prettier@9.1.0(eslint@8.57.0))(eslint@8.57.0)(prettier@3.3.1): 1858 | dependencies: 1859 | eslint: 8.57.0 1860 | prettier: 3.3.1 1861 | prettier-linter-helpers: 1.0.0 1862 | synckit: 0.8.8 1863 | optionalDependencies: 1864 | eslint-config-prettier: 9.1.0(eslint@8.57.0) 1865 | 1866 | eslint-plugin-sort-imports-es6-autofix@0.6.0(eslint@8.57.0): 1867 | dependencies: 1868 | eslint: 8.57.0 1869 | 1870 | eslint-plugin-unused-imports@3.2.0(@typescript-eslint/eslint-plugin@7.12.0(@typescript-eslint/parser@7.12.0(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0): 1871 | dependencies: 1872 | eslint: 8.57.0 1873 | eslint-rule-composer: 0.3.0 1874 | optionalDependencies: 1875 | '@typescript-eslint/eslint-plugin': 7.12.0(@typescript-eslint/parser@7.12.0(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0)(typescript@5.4.5) 1876 | 1877 | eslint-rule-composer@0.3.0: {} 1878 | 1879 | eslint-scope@7.2.2: 1880 | dependencies: 1881 | esrecurse: 4.3.0 1882 | estraverse: 5.3.0 1883 | 1884 | eslint-visitor-keys@3.4.3: {} 1885 | 1886 | eslint@8.57.0: 1887 | dependencies: 1888 | '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0) 1889 | '@eslint-community/regexpp': 4.9.1 1890 | '@eslint/eslintrc': 2.1.4 1891 | '@eslint/js': 8.57.0 1892 | '@humanwhocodes/config-array': 0.11.14 1893 | '@humanwhocodes/module-importer': 1.0.1 1894 | '@nodelib/fs.walk': 1.2.8 1895 | '@ungap/structured-clone': 1.2.0 1896 | ajv: 6.12.6 1897 | chalk: 4.1.2 1898 | cross-spawn: 7.0.3 1899 | debug: 4.3.4 1900 | doctrine: 3.0.0 1901 | escape-string-regexp: 4.0.0 1902 | eslint-scope: 7.2.2 1903 | eslint-visitor-keys: 3.4.3 1904 | espree: 9.6.1 1905 | esquery: 1.5.0 1906 | esutils: 2.0.3 1907 | fast-deep-equal: 3.1.3 1908 | file-entry-cache: 6.0.1 1909 | find-up: 5.0.0 1910 | glob-parent: 6.0.2 1911 | globals: 13.23.0 1912 | graphemer: 1.4.0 1913 | ignore: 5.2.4 1914 | imurmurhash: 0.1.4 1915 | is-glob: 4.0.3 1916 | is-path-inside: 3.0.3 1917 | js-yaml: 4.1.0 1918 | json-stable-stringify-without-jsonify: 1.0.1 1919 | levn: 0.4.1 1920 | lodash.merge: 4.6.2 1921 | minimatch: 3.1.2 1922 | natural-compare: 1.4.0 1923 | optionator: 0.9.3 1924 | strip-ansi: 6.0.1 1925 | text-table: 0.2.0 1926 | transitivePeerDependencies: 1927 | - supports-color 1928 | 1929 | espree@9.6.1: 1930 | dependencies: 1931 | acorn: 8.10.0 1932 | acorn-jsx: 5.3.2(acorn@8.10.0) 1933 | eslint-visitor-keys: 3.4.3 1934 | 1935 | esquery@1.5.0: 1936 | dependencies: 1937 | estraverse: 5.3.0 1938 | 1939 | esrecurse@4.3.0: 1940 | dependencies: 1941 | estraverse: 5.3.0 1942 | 1943 | estraverse@5.3.0: {} 1944 | 1945 | estree-walker@2.0.2: {} 1946 | 1947 | estree-walker@3.0.3: 1948 | dependencies: 1949 | '@types/estree': 1.0.5 1950 | 1951 | esutils@2.0.3: {} 1952 | 1953 | execa@8.0.1: 1954 | dependencies: 1955 | cross-spawn: 7.0.3 1956 | get-stream: 8.0.1 1957 | human-signals: 5.0.0 1958 | is-stream: 3.0.0 1959 | merge-stream: 2.0.0 1960 | npm-run-path: 5.1.0 1961 | onetime: 6.0.0 1962 | signal-exit: 4.1.0 1963 | strip-final-newline: 3.0.0 1964 | 1965 | fast-deep-equal@3.1.3: {} 1966 | 1967 | fast-diff@1.3.0: {} 1968 | 1969 | fast-glob@3.3.1: 1970 | dependencies: 1971 | '@nodelib/fs.stat': 2.0.5 1972 | '@nodelib/fs.walk': 1.2.8 1973 | glob-parent: 5.1.2 1974 | merge2: 1.4.1 1975 | micromatch: 4.0.5 1976 | 1977 | fast-json-stable-stringify@2.1.0: {} 1978 | 1979 | fast-levenshtein@2.0.6: {} 1980 | 1981 | fastq@1.15.0: 1982 | dependencies: 1983 | reusify: 1.0.4 1984 | 1985 | file-entry-cache@6.0.1: 1986 | dependencies: 1987 | flat-cache: 3.1.1 1988 | 1989 | fill-range@7.0.1: 1990 | dependencies: 1991 | to-regex-range: 5.0.1 1992 | 1993 | find-up@5.0.0: 1994 | dependencies: 1995 | locate-path: 6.0.0 1996 | path-exists: 4.0.0 1997 | 1998 | flat-cache@3.1.1: 1999 | dependencies: 2000 | flatted: 3.2.9 2001 | keyv: 4.5.4 2002 | rimraf: 3.0.2 2003 | 2004 | flatted@3.2.9: {} 2005 | 2006 | fs.realpath@1.0.0: {} 2007 | 2008 | fsevents@2.3.3: 2009 | optional: true 2010 | 2011 | get-func-name@2.0.2: {} 2012 | 2013 | get-stream@8.0.1: {} 2014 | 2015 | glob-parent@5.1.2: 2016 | dependencies: 2017 | is-glob: 4.0.3 2018 | 2019 | glob-parent@6.0.2: 2020 | dependencies: 2021 | is-glob: 4.0.3 2022 | 2023 | glob@7.2.3: 2024 | dependencies: 2025 | fs.realpath: 1.0.0 2026 | inflight: 1.0.6 2027 | inherits: 2.0.4 2028 | minimatch: 3.1.2 2029 | once: 1.4.0 2030 | path-is-absolute: 1.0.1 2031 | 2032 | globals@13.23.0: 2033 | dependencies: 2034 | type-fest: 0.20.2 2035 | 2036 | globby@11.1.0: 2037 | dependencies: 2038 | array-union: 2.1.0 2039 | dir-glob: 3.0.1 2040 | fast-glob: 3.3.1 2041 | ignore: 5.2.4 2042 | merge2: 1.4.1 2043 | slash: 3.0.0 2044 | 2045 | graphemer@1.4.0: {} 2046 | 2047 | has-flag@4.0.0: {} 2048 | 2049 | html-escaper@2.0.2: {} 2050 | 2051 | human-signals@5.0.0: {} 2052 | 2053 | ignore@5.2.4: {} 2054 | 2055 | ignore@5.3.1: {} 2056 | 2057 | import-fresh@3.3.0: 2058 | dependencies: 2059 | parent-module: 1.0.1 2060 | resolve-from: 4.0.0 2061 | 2062 | imurmurhash@0.1.4: {} 2063 | 2064 | inflight@1.0.6: 2065 | dependencies: 2066 | once: 1.4.0 2067 | wrappy: 1.0.2 2068 | 2069 | inherits@2.0.4: {} 2070 | 2071 | is-extglob@2.1.1: {} 2072 | 2073 | is-glob@4.0.3: 2074 | dependencies: 2075 | is-extglob: 2.1.1 2076 | 2077 | is-number@7.0.0: {} 2078 | 2079 | is-path-inside@3.0.3: {} 2080 | 2081 | is-stream@3.0.0: {} 2082 | 2083 | isexe@2.0.0: {} 2084 | 2085 | istanbul-lib-coverage@3.2.2: {} 2086 | 2087 | istanbul-lib-report@3.0.1: 2088 | dependencies: 2089 | istanbul-lib-coverage: 3.2.2 2090 | make-dir: 4.0.0 2091 | supports-color: 7.2.0 2092 | 2093 | istanbul-lib-source-maps@5.0.4: 2094 | dependencies: 2095 | '@jridgewell/trace-mapping': 0.3.25 2096 | debug: 4.3.4 2097 | istanbul-lib-coverage: 3.2.2 2098 | transitivePeerDependencies: 2099 | - supports-color 2100 | 2101 | istanbul-reports@3.1.6: 2102 | dependencies: 2103 | html-escaper: 2.0.2 2104 | istanbul-lib-report: 3.0.1 2105 | 2106 | js-tokens@9.0.0: {} 2107 | 2108 | js-yaml@4.1.0: 2109 | dependencies: 2110 | argparse: 2.0.1 2111 | 2112 | json-buffer@3.0.1: {} 2113 | 2114 | json-schema-traverse@0.4.1: {} 2115 | 2116 | json-stable-stringify-without-jsonify@1.0.1: {} 2117 | 2118 | jsonc-parser@3.2.0: {} 2119 | 2120 | keyv@4.5.4: 2121 | dependencies: 2122 | json-buffer: 3.0.1 2123 | 2124 | levn@0.4.1: 2125 | dependencies: 2126 | prelude-ls: 1.2.1 2127 | type-check: 0.4.0 2128 | 2129 | local-pkg@0.5.0: 2130 | dependencies: 2131 | mlly: 1.4.2 2132 | pkg-types: 1.0.3 2133 | 2134 | locate-path@6.0.0: 2135 | dependencies: 2136 | p-locate: 5.0.0 2137 | 2138 | lodash.merge@4.6.2: {} 2139 | 2140 | loupe@2.3.6: 2141 | dependencies: 2142 | get-func-name: 2.0.2 2143 | 2144 | loupe@2.3.7: 2145 | dependencies: 2146 | get-func-name: 2.0.2 2147 | 2148 | lru-cache@6.0.0: 2149 | dependencies: 2150 | yallist: 4.0.0 2151 | 2152 | magic-string@0.30.10: 2153 | dependencies: 2154 | '@jridgewell/sourcemap-codec': 1.4.15 2155 | 2156 | magicast@0.3.4: 2157 | dependencies: 2158 | '@babel/parser': 7.24.7 2159 | '@babel/types': 7.24.7 2160 | source-map-js: 1.2.0 2161 | 2162 | make-dir@4.0.0: 2163 | dependencies: 2164 | semver: 7.5.4 2165 | 2166 | merge-stream@2.0.0: {} 2167 | 2168 | merge2@1.4.1: {} 2169 | 2170 | micromatch@4.0.5: 2171 | dependencies: 2172 | braces: 3.0.2 2173 | picomatch: 2.3.1 2174 | 2175 | mimic-fn@4.0.0: {} 2176 | 2177 | minimatch@3.1.2: 2178 | dependencies: 2179 | brace-expansion: 1.1.11 2180 | 2181 | minimatch@9.0.4: 2182 | dependencies: 2183 | brace-expansion: 2.0.1 2184 | 2185 | mlly@1.4.2: 2186 | dependencies: 2187 | acorn: 8.10.0 2188 | pathe: 1.1.1 2189 | pkg-types: 1.0.3 2190 | ufo: 1.3.1 2191 | 2192 | ms@2.1.2: {} 2193 | 2194 | nanoid@3.3.7: {} 2195 | 2196 | natural-compare@1.4.0: {} 2197 | 2198 | normalizr@3.6.2: {} 2199 | 2200 | npm-run-path@5.1.0: 2201 | dependencies: 2202 | path-key: 4.0.0 2203 | 2204 | once@1.4.0: 2205 | dependencies: 2206 | wrappy: 1.0.2 2207 | 2208 | onetime@6.0.0: 2209 | dependencies: 2210 | mimic-fn: 4.0.0 2211 | 2212 | optionator@0.9.3: 2213 | dependencies: 2214 | '@aashutoshrathi/word-wrap': 1.2.6 2215 | deep-is: 0.1.4 2216 | fast-levenshtein: 2.0.6 2217 | levn: 0.4.1 2218 | prelude-ls: 1.2.1 2219 | type-check: 0.4.0 2220 | 2221 | p-limit@3.1.0: 2222 | dependencies: 2223 | yocto-queue: 0.1.0 2224 | 2225 | p-limit@5.0.0: 2226 | dependencies: 2227 | yocto-queue: 1.0.0 2228 | 2229 | p-locate@5.0.0: 2230 | dependencies: 2231 | p-limit: 3.1.0 2232 | 2233 | parent-module@1.0.1: 2234 | dependencies: 2235 | callsites: 3.1.0 2236 | 2237 | path-exists@4.0.0: {} 2238 | 2239 | path-is-absolute@1.0.1: {} 2240 | 2241 | path-key@3.1.1: {} 2242 | 2243 | path-key@4.0.0: {} 2244 | 2245 | path-type@4.0.0: {} 2246 | 2247 | pathe@1.1.1: {} 2248 | 2249 | pathval@1.1.1: {} 2250 | 2251 | picocolors@1.0.0: {} 2252 | 2253 | picomatch@2.3.1: {} 2254 | 2255 | pkg-types@1.0.3: 2256 | dependencies: 2257 | jsonc-parser: 3.2.0 2258 | mlly: 1.4.2 2259 | pathe: 1.1.1 2260 | 2261 | postcss@8.4.38: 2262 | dependencies: 2263 | nanoid: 3.3.7 2264 | picocolors: 1.0.0 2265 | source-map-js: 1.2.0 2266 | 2267 | prelude-ls@1.2.1: {} 2268 | 2269 | prettier-linter-helpers@1.0.0: 2270 | dependencies: 2271 | fast-diff: 1.3.0 2272 | 2273 | prettier@3.3.1: {} 2274 | 2275 | pretty-format@29.7.0: 2276 | dependencies: 2277 | '@jest/schemas': 29.6.3 2278 | ansi-styles: 5.2.0 2279 | react-is: 18.2.0 2280 | 2281 | punycode@2.3.0: {} 2282 | 2283 | queue-microtask@1.2.3: {} 2284 | 2285 | react-is@18.2.0: {} 2286 | 2287 | resolve-from@4.0.0: {} 2288 | 2289 | reusify@1.0.4: {} 2290 | 2291 | rimraf@3.0.2: 2292 | dependencies: 2293 | glob: 7.2.3 2294 | 2295 | rollup@4.18.0: 2296 | dependencies: 2297 | '@types/estree': 1.0.5 2298 | optionalDependencies: 2299 | '@rollup/rollup-android-arm-eabi': 4.18.0 2300 | '@rollup/rollup-android-arm64': 4.18.0 2301 | '@rollup/rollup-darwin-arm64': 4.18.0 2302 | '@rollup/rollup-darwin-x64': 4.18.0 2303 | '@rollup/rollup-linux-arm-gnueabihf': 4.18.0 2304 | '@rollup/rollup-linux-arm-musleabihf': 4.18.0 2305 | '@rollup/rollup-linux-arm64-gnu': 4.18.0 2306 | '@rollup/rollup-linux-arm64-musl': 4.18.0 2307 | '@rollup/rollup-linux-powerpc64le-gnu': 4.18.0 2308 | '@rollup/rollup-linux-riscv64-gnu': 4.18.0 2309 | '@rollup/rollup-linux-s390x-gnu': 4.18.0 2310 | '@rollup/rollup-linux-x64-gnu': 4.18.0 2311 | '@rollup/rollup-linux-x64-musl': 4.18.0 2312 | '@rollup/rollup-win32-arm64-msvc': 4.18.0 2313 | '@rollup/rollup-win32-ia32-msvc': 4.18.0 2314 | '@rollup/rollup-win32-x64-msvc': 4.18.0 2315 | fsevents: 2.3.3 2316 | 2317 | run-parallel@1.2.0: 2318 | dependencies: 2319 | queue-microtask: 1.2.3 2320 | 2321 | semver@7.5.4: 2322 | dependencies: 2323 | lru-cache: 6.0.0 2324 | 2325 | semver@7.6.2: {} 2326 | 2327 | shebang-command@2.0.0: 2328 | dependencies: 2329 | shebang-regex: 3.0.0 2330 | 2331 | shebang-regex@3.0.0: {} 2332 | 2333 | siginfo@2.0.0: {} 2334 | 2335 | signal-exit@4.1.0: {} 2336 | 2337 | slash@3.0.0: {} 2338 | 2339 | source-map-js@1.2.0: {} 2340 | 2341 | stackback@0.0.2: {} 2342 | 2343 | std-env@3.7.0: {} 2344 | 2345 | strip-ansi@6.0.1: 2346 | dependencies: 2347 | ansi-regex: 5.0.1 2348 | 2349 | strip-final-newline@3.0.0: {} 2350 | 2351 | strip-json-comments@3.1.1: {} 2352 | 2353 | strip-literal@2.1.0: 2354 | dependencies: 2355 | js-tokens: 9.0.0 2356 | 2357 | supports-color@7.2.0: 2358 | dependencies: 2359 | has-flag: 4.0.0 2360 | 2361 | synckit@0.8.8: 2362 | dependencies: 2363 | '@pkgr/core': 0.1.1 2364 | tslib: 2.6.3 2365 | 2366 | test-exclude@6.0.0: 2367 | dependencies: 2368 | '@istanbuljs/schema': 0.1.3 2369 | glob: 7.2.3 2370 | minimatch: 3.1.2 2371 | 2372 | text-table@0.2.0: {} 2373 | 2374 | tinybench@2.5.1: {} 2375 | 2376 | tinypool@0.8.4: {} 2377 | 2378 | tinyspy@2.2.0: {} 2379 | 2380 | to-fast-properties@2.0.0: {} 2381 | 2382 | to-regex-range@5.0.1: 2383 | dependencies: 2384 | is-number: 7.0.0 2385 | 2386 | ts-api-utils@1.3.0(typescript@5.4.5): 2387 | dependencies: 2388 | typescript: 5.4.5 2389 | 2390 | tslib@2.6.3: {} 2391 | 2392 | type-check@0.4.0: 2393 | dependencies: 2394 | prelude-ls: 1.2.1 2395 | 2396 | type-detect@4.0.8: {} 2397 | 2398 | type-fest@0.20.2: {} 2399 | 2400 | typescript@5.4.5: {} 2401 | 2402 | ufo@1.3.1: {} 2403 | 2404 | uri-js@4.4.1: 2405 | dependencies: 2406 | punycode: 2.3.0 2407 | 2408 | vite-node@1.6.0(@types/node@20.8.3): 2409 | dependencies: 2410 | cac: 6.7.14 2411 | debug: 4.3.4 2412 | pathe: 1.1.1 2413 | picocolors: 1.0.0 2414 | vite: 5.2.13(@types/node@20.8.3) 2415 | transitivePeerDependencies: 2416 | - '@types/node' 2417 | - less 2418 | - lightningcss 2419 | - sass 2420 | - stylus 2421 | - sugarss 2422 | - supports-color 2423 | - terser 2424 | 2425 | vite@5.2.13(@types/node@20.8.3): 2426 | dependencies: 2427 | esbuild: 0.20.2 2428 | postcss: 8.4.38 2429 | rollup: 4.18.0 2430 | optionalDependencies: 2431 | '@types/node': 20.8.3 2432 | fsevents: 2.3.3 2433 | 2434 | vitest@1.6.0(@types/node@20.8.3): 2435 | dependencies: 2436 | '@vitest/expect': 1.6.0 2437 | '@vitest/runner': 1.6.0 2438 | '@vitest/snapshot': 1.6.0 2439 | '@vitest/spy': 1.6.0 2440 | '@vitest/utils': 1.6.0 2441 | acorn-walk: 8.3.2 2442 | chai: 4.3.10 2443 | debug: 4.3.4 2444 | execa: 8.0.1 2445 | local-pkg: 0.5.0 2446 | magic-string: 0.30.10 2447 | pathe: 1.1.1 2448 | picocolors: 1.0.0 2449 | std-env: 3.7.0 2450 | strip-literal: 2.1.0 2451 | tinybench: 2.5.1 2452 | tinypool: 0.8.4 2453 | vite: 5.2.13(@types/node@20.8.3) 2454 | vite-node: 1.6.0(@types/node@20.8.3) 2455 | why-is-node-running: 2.2.2 2456 | optionalDependencies: 2457 | '@types/node': 20.8.3 2458 | transitivePeerDependencies: 2459 | - less 2460 | - lightningcss 2461 | - sass 2462 | - stylus 2463 | - sugarss 2464 | - supports-color 2465 | - terser 2466 | 2467 | vue@3.4.27(typescript@5.4.5): 2468 | dependencies: 2469 | '@vue/compiler-dom': 3.4.27 2470 | '@vue/compiler-sfc': 3.4.27 2471 | '@vue/runtime-dom': 3.4.27 2472 | '@vue/server-renderer': 3.4.27(vue@3.4.27(typescript@5.4.5)) 2473 | '@vue/shared': 3.4.27 2474 | optionalDependencies: 2475 | typescript: 5.4.5 2476 | 2477 | vuex@4.1.0(vue@3.4.27(typescript@5.4.5)): 2478 | dependencies: 2479 | '@vue/devtools-api': 6.5.0 2480 | vue: 3.4.27(typescript@5.4.5) 2481 | 2482 | which@2.0.2: 2483 | dependencies: 2484 | isexe: 2.0.0 2485 | 2486 | why-is-node-running@2.2.2: 2487 | dependencies: 2488 | siginfo: 2.0.0 2489 | stackback: 0.0.2 2490 | 2491 | wrappy@1.0.2: {} 2492 | 2493 | yallist@4.0.0: {} 2494 | 2495 | yocto-queue@0.1.0: {} 2496 | 2497 | yocto-queue@1.0.0: {} 2498 | -------------------------------------------------------------------------------- /src/attributes.ts: -------------------------------------------------------------------------------- 1 | import { Model } from "@vuex-orm/core"; 2 | import type { Attribute, Type } from "@vuex-orm/core"; 3 | import type Mutator from "@vuex-orm/core/dist/src/attributes/contracts/Mutator"; 4 | 5 | const defaultValues: Record = { 6 | Attr: "", 7 | Boolean: false, 8 | String: "", 9 | Number: 0, 10 | }; 11 | 12 | interface Target { 13 | _fields: Record; 14 | fields: () => { 15 | [key: string]: Attribute; 16 | }; 17 | } 18 | 19 | /** 20 | * Adds the property as a model field 21 | */ 22 | function Field(fieldType: Attribute) { 23 | return (target: Object, propertyName: string | symbol): void => { 24 | const constructor = target.constructor as unknown as Target; 25 | const field = fieldType as Type; 26 | 27 | constructor._fields = Object.assign(constructor.fields(), constructor._fields); 28 | 29 | if (field.mutator && field.value === null) { 30 | field.value = defaultValues[field.constructor.name]; 31 | } 32 | 33 | if (field.value === undefined) { 34 | field.value = defaultValues[field.constructor.name]; 35 | } 36 | 37 | if (!field.mutator && field.value === null) { 38 | field.isNullable = true; 39 | } 40 | 41 | constructor._fields[propertyName as symbol] = field; 42 | 43 | constructor.fields = () => { 44 | return { ...constructor._fields }; 45 | }; 46 | }; 47 | } 48 | 49 | /** 50 | * Adds the property as the `primary key` of the model 51 | */ 52 | export function PrimaryKey() { 53 | return (target: any, propertyName: string | symbol): void => { 54 | const symbol = Symbol.for("vuex-orm-decorator:primary-key"); 55 | 56 | if (typeof target[symbol] === "object" && target[symbol] instanceof Array) { 57 | target[symbol].push(propertyName); 58 | } 59 | 60 | if (typeof target[symbol] === "string") { 61 | if (target[symbol] !== propertyName) { 62 | target[symbol] = [target[symbol], propertyName]; 63 | } 64 | } 65 | 66 | if (typeof target[symbol] === "undefined") { 67 | target[symbol] = propertyName; 68 | } 69 | 70 | target.constructor.primaryKey = target[symbol]; 71 | }; 72 | } 73 | 74 | /** 75 | * Adds the property as a `uid` field 76 | */ 77 | export function UidField(value?: () => string | number) { 78 | return Field(Model.uid(value)); 79 | } 80 | 81 | /** 82 | * Adds the property as a generic `attribute` field 83 | */ 84 | export function AttrField(value?: any, mutator?: Mutator) { 85 | return Field(Model.attr(value, mutator)); 86 | } 87 | 88 | /** 89 | * Adds the property as a `string` field 90 | */ 91 | export function StringField(value?: string | null, mutator?: Mutator) { 92 | return Field(Model.string(value, mutator as any)); 93 | } 94 | 95 | /** 96 | * Adds the property as a `number` field 97 | */ 98 | export function NumberField(value?: number | null, mutator?: Mutator) { 99 | return Field(Model.number(value, mutator as any)); 100 | } 101 | 102 | /** 103 | * Adds the property as a `date` field 104 | */ 105 | export function DateField(value?: Date | null, mutator?: Mutator) { 106 | // @ts-expect-error use of Date plugin 107 | return Field(Model.date(value, mutator as any)); 108 | } 109 | 110 | /** 111 | * Adds the property as a `boolean` field 112 | */ 113 | export function BooleanField(value?: boolean | null, mutator?: Mutator) { 114 | return Field(Model.boolean(value, mutator as any)); 115 | } 116 | 117 | /** 118 | * Adds the property as a `Has One` relationship field 119 | */ 120 | export function HasOneField(related: typeof Model, foreignKey: string, localKey?: string) { 121 | return Field(Model.hasOne(related, foreignKey, localKey)); 122 | } 123 | 124 | /** 125 | * Adds the property as a `Belongs To` relationship field 126 | */ 127 | export function BelongsToField(parent: typeof Model, foreignKey: string, ownerKey?: string) { 128 | return Field(Model.belongsTo(parent, foreignKey, ownerKey)); 129 | } 130 | 131 | /** 132 | * Adds the property as a `Has Many` relationship field 133 | */ 134 | export function HasManyField(related: typeof Model, foreignKey: string, localKey?: string) { 135 | return Field(Model.hasMany(related, foreignKey, localKey)); 136 | } 137 | 138 | /** 139 | * Adds the property as a `Has Many By` relationship field 140 | */ 141 | export function HasManyByField(parent: typeof Model, foreignKey: string, ownerKey?: string) { 142 | return Field(Model.hasManyBy(parent, foreignKey, ownerKey)); 143 | } 144 | 145 | /** 146 | * Adds the property as a `Has Many Through` relationship field 147 | */ 148 | export function HasManyThroughField( 149 | related: typeof Model, 150 | through: typeof Model, 151 | firstKey: string, 152 | secondKey: string, 153 | localKey?: string, 154 | secondLocalKey?: string 155 | ) { 156 | return Field( 157 | Model.hasManyThrough(related, through, firstKey, secondKey, localKey, secondLocalKey) 158 | ); 159 | } 160 | 161 | /** 162 | * Adds the property as a `Belongs To Many` relationship field 163 | */ 164 | export function BelongsToManyField( 165 | related: typeof Model, 166 | pivot: typeof Model, 167 | foreignPivotKey: string, 168 | relatedPivotKey: string, 169 | parentKey?: string, 170 | relatedKey?: string 171 | ) { 172 | return Field( 173 | Model.belongsToMany(related, pivot, foreignPivotKey, relatedPivotKey, parentKey, relatedKey) 174 | ); 175 | } 176 | 177 | /** 178 | * Adds the property as a `Morph To` relationship field 179 | */ 180 | export function MorphToField(id: string, type: string) { 181 | return Field(Model.morphTo(id, type)); 182 | } 183 | 184 | /** 185 | * Adds the property as a `Morph One` relationship field 186 | */ 187 | export function MorphOneField(related: typeof Model, id: string, type: string, localKey?: string) { 188 | return Field(Model.morphOne(related, id, type, localKey)); 189 | } 190 | 191 | /** 192 | * Adds the property as a `Morph Many` relationship field 193 | */ 194 | export function MorphManyField(related: typeof Model, id: string, type: string, localKey?: string) { 195 | return Field(Model.morphMany(related, id, type, localKey)); 196 | } 197 | 198 | /** 199 | * Adds the property as a `Morph To Many` relationship field 200 | */ 201 | export function MorphToManyField( 202 | related: typeof Model, 203 | pivot: typeof Model, 204 | relatedId: string, 205 | id: string, 206 | type: string, 207 | parentKey?: string, 208 | relatedKey?: string 209 | ) { 210 | return Field(Model.morphToMany(related, pivot, relatedId, id, type, parentKey, relatedKey)); 211 | } 212 | 213 | /** 214 | * Adds the property as a `Morphed By Many` relationship field 215 | */ 216 | export function MorphedByManyField( 217 | related: typeof Model, 218 | pivot: typeof Model, 219 | relatedId: string, 220 | id: string, 221 | type: string, 222 | parentKey?: string, 223 | relatedKey?: string 224 | ) { 225 | return Field(Model.morphedByMany(related, pivot, relatedId, id, type, parentKey, relatedKey)); 226 | } 227 | -------------------------------------------------------------------------------- /src/database.ts: -------------------------------------------------------------------------------- 1 | import { Database, install, use } from "@vuex-orm/core"; 2 | import DatePlugin from "./plugins/Date"; 3 | import type { Model } from "@vuex-orm/core"; 4 | import type { Options } from "@vuex-orm/core/dist/src/store/install"; 5 | import type { Plugin } from "vuex"; 6 | 7 | use(DatePlugin); 8 | 9 | export class ORMDatabase { 10 | private static _ormDatabase = new Database(); 11 | 12 | private static _models: (typeof Model)[] = []; 13 | 14 | public static install(options?: Options): Plugin { 15 | this._models.forEach((model) => this._ormDatabase.register(model)); 16 | 17 | const plugin = install(this._ormDatabase, options); 18 | 19 | this._models = []; 20 | 21 | return plugin; 22 | } 23 | 24 | public static registerEntity(model: typeof Model) { 25 | if (this._models.includes(model)) { 26 | return console.error( 27 | `[Vuex ORM Decorators] Unable to register Model '${model.name}'. Model '${model.name}' is already registered.` 28 | ); 29 | } 30 | 31 | this._models.push(model); 32 | } 33 | 34 | public static models() { 35 | return this._models; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | export { OrmModel } from "./model"; 2 | 3 | export { ORMDatabase } from "./database"; 4 | 5 | export { 6 | AttrField, 7 | BelongsToField, 8 | BelongsToManyField, 9 | BooleanField, 10 | DateField, 11 | HasManyByField, 12 | HasManyField, 13 | HasManyThroughField, 14 | HasOneField, 15 | MorphedByManyField, 16 | MorphManyField, 17 | MorphOneField, 18 | MorphToField, 19 | MorphToManyField, 20 | NumberField, 21 | PrimaryKey, 22 | StringField, 23 | UidField, 24 | } from "./attributes"; 25 | -------------------------------------------------------------------------------- /src/model.ts: -------------------------------------------------------------------------------- 1 | import { ORMDatabase } from "./database"; 2 | import type { Model } from "@vuex-orm/core"; 3 | 4 | export function OrmModel( 5 | entity: string, 6 | baseEntity?: string, 7 | types?: { [key: string]: typeof Model } 8 | ) { 9 | return (constructor: Model): Model => { 10 | // The name that is going be used as module name in Vuex Store. 11 | (constructor as any).entity = entity; 12 | 13 | // The reference to the base entity name if the class extends a base entity. 14 | if (baseEntity) { 15 | (constructor as any).baseEntity = baseEntity; 16 | } 17 | 18 | // The 'types mapping' used to dispatch entities based on their discriminator field. 19 | if (types && baseEntity) { 20 | ORMDatabase.models().forEach((model) => { 21 | if (model.entity === baseEntity) { 22 | const _types = Object.assign(model.types(), types); 23 | 24 | model.types = () => _types; 25 | } 26 | }); 27 | } 28 | 29 | // Register a model to Database. 30 | ORMDatabase.registerEntity(constructor as unknown as typeof Model); 31 | 32 | return constructor; 33 | }; 34 | } 35 | -------------------------------------------------------------------------------- /src/plugins/Date/DateType.ts: -------------------------------------------------------------------------------- 1 | import { Type } from "@vuex-orm/core"; 2 | import type Model from "@vuex-orm/core/dist/src/model/Model"; 3 | import type Mutator from "@vuex-orm/core/dist/src/attributes/contracts/Mutator"; 4 | import type Record from "@vuex-orm/core/dist/src/data/Record"; 5 | 6 | export default class DateType extends Type { 7 | constructor(model: typeof Model, value: Date | null, mutator?: Mutator) { 8 | super(model, value, mutator); 9 | 10 | if (!mutator && value === null) { 11 | this.nullable(); 12 | } 13 | } 14 | 15 | make(value: any, _parent: Record, key: string): Date | null { 16 | return this.mutate(this.validate(value), key); 17 | } 18 | 19 | validate(value: any): Date | number | null { 20 | if (this.isNullable && value === null) { 21 | return null; 22 | } 23 | 24 | if (typeof value === "string") { 25 | if (this.inRange(value)) { 26 | value = new Date(parseInt(value)); 27 | } 28 | 29 | if (this.mutator) { 30 | this.value = value; 31 | } else { 32 | return Date.parse(value); 33 | } 34 | } 35 | 36 | if ((value === undefined || value === null) && !this.value) { 37 | return null; 38 | } 39 | 40 | return new Date(this.value || value); 41 | } 42 | 43 | inRange(value: string): boolean { 44 | const length = parseInt(value).toString().length; 45 | 46 | return length < 15 && length > 12; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/plugins/Date/index.ts: -------------------------------------------------------------------------------- 1 | import DateType from "./DateType"; 2 | import type { Plugin } from "@vuex-orm/core/dist/src/plugins/use"; 3 | import type Mutator from "@vuex-orm/core/dist/src/attributes/contracts/Mutator"; 4 | 5 | const plugin: Plugin = { 6 | install(components: any) { 7 | components.Model.date = function (value: any, mutator?: Mutator): DateType { 8 | return new DateType(this, value, mutator); 9 | }; 10 | }, 11 | }; 12 | 13 | export default plugin; 14 | -------------------------------------------------------------------------------- /test/Cases.spec.ts: -------------------------------------------------------------------------------- 1 | import { describe, expect, it } from "vitest"; 2 | import { Model } from "@vuex-orm/core"; 3 | import { NumberField, StringField } from "@/attributes"; 4 | import { ORMDatabase } from "@/database"; 5 | import { OrmModel } from "@/model"; 6 | import { Store } from "vuex"; 7 | import type { String } from "@vuex-orm/core"; 8 | 9 | describe("Cases", () => { 10 | it("merges the properties with the `fields` method", () => { 11 | @OrmModel("users") 12 | class User extends Model { 13 | @NumberField() id!: number; 14 | 15 | @StringField() name!: string; 16 | 17 | static fields() { 18 | return { 19 | email: this.attr(""), 20 | active: this.attr(true), 21 | }; 22 | } 23 | } 24 | 25 | @OrmModel("profiles") 26 | class Profile extends Model { 27 | @NumberField() id!: number; 28 | 29 | @NumberField() user_id!: number; 30 | 31 | @NumberField() age!: number; 32 | 33 | @StringField() sex!: string; 34 | 35 | static fields() { 36 | return { 37 | user: this.belongsTo(User, "user_id"), 38 | }; 39 | } 40 | } 41 | 42 | new Store({ 43 | plugins: [ORMDatabase.install()], 44 | }); 45 | 46 | Profile.insert({ 47 | data: { 48 | id: 1, 49 | user_id: 10, 50 | age: 25, 51 | sex: "male", 52 | user: { 53 | id: 10, 54 | name: "John Doe", 55 | email: "john@doe.com", 56 | }, 57 | }, 58 | }); 59 | 60 | expect(Profile.query().with("user").first()).toEqual({ 61 | $id: "1", 62 | user: { 63 | $id: "10", 64 | email: "john@doe.com", 65 | active: true, 66 | id: 10, 67 | name: "John Doe", 68 | }, 69 | id: 1, 70 | user_id: 10, 71 | age: 25, 72 | sex: "male", 73 | }); 74 | 75 | expect(Profile.query().first()).toEqual({ 76 | $id: "1", 77 | user: null, 78 | id: 1, 79 | user_id: 10, 80 | age: 25, 81 | sex: "male", 82 | }); 83 | 84 | expect(User.query().first()).toEqual({ 85 | $id: "10", 86 | email: "john@doe.com", 87 | active: true, 88 | id: 10, 89 | name: "John Doe", 90 | }); 91 | }); 92 | 93 | it("uses default value when using mutator and null as value", () => { 94 | @OrmModel("something") 95 | class Something extends Model { 96 | @StringField(null, (value: string) => { 97 | return value.toUpperCase(); 98 | }) 99 | name!: string; 100 | } 101 | 102 | expect(new Something().name).toBe(""); 103 | expect((Something.getFields().name as String).isNullable).toBe(false); 104 | }); 105 | }); 106 | -------------------------------------------------------------------------------- /test/Database.spec.ts: -------------------------------------------------------------------------------- 1 | import { afterEach, describe, expect, it, vi } from "vitest"; 2 | import { Model } from "@vuex-orm/core"; 3 | import { ORMDatabase } from "@/database"; 4 | import { OrmModel } from "@/model"; 5 | import { Store } from "vuex"; 6 | 7 | describe("ORMDatabase", () => { 8 | let store: Store; 9 | 10 | afterEach(() => { 11 | store.$db().entities = []; 12 | }); 13 | 14 | it("can auto register a model to Database", () => { 15 | const spy = vi.spyOn(console, "warn"); 16 | 17 | @OrmModel("users") 18 | class User extends Model {} 19 | 20 | @OrmModel("admins", "users") 21 | class Admin extends User {} 22 | 23 | new User(); 24 | new Admin(); 25 | new User(); 26 | 27 | store = new Store({ 28 | plugins: [ORMDatabase.install()], 29 | }); 30 | 31 | expect(store.$db().namespace).toBe("entities"); 32 | expect(store.$db().entities).toHaveLength(2); 33 | 34 | expect(store.$db().entities[0].name).toBe("users"); 35 | expect(store.$db().entities[0].base).toBe("users"); 36 | 37 | expect(store.$db().entities[1].name).toBe("admins"); 38 | expect(store.$db().entities[1].base).toBe("users"); 39 | 40 | expect(spy).toHaveBeenCalled(); 41 | }); 42 | 43 | it("can pass options during the installation", () => { 44 | @OrmModel("persons") 45 | class Persons extends Model {} 46 | 47 | new Persons(); 48 | 49 | store = new Store({ 50 | plugins: [ORMDatabase.install({ namespace: "Models" })], 51 | }); 52 | 53 | expect(store.$db().namespace).toBe("Models"); 54 | expect(store.$db().entities).toHaveLength(1); 55 | }); 56 | 57 | it("throws a error message when the model is already registered", () => { 58 | const spy = vi.spyOn(console, "error"); 59 | 60 | @OrmModel("users") 61 | class User extends Model {} 62 | 63 | new User(); 64 | 65 | ORMDatabase.registerEntity(User); 66 | 67 | store = new Store({ 68 | plugins: [ORMDatabase.install()], 69 | }); 70 | 71 | expect(console.error).toHaveBeenLastCalledWith( 72 | "[Vuex ORM Decorators] Unable to register Model 'User'. Model 'User' is already registered." 73 | ); 74 | 75 | expect(spy).toHaveBeenCalled(); 76 | }); 77 | }); 78 | -------------------------------------------------------------------------------- /test/Model.spec.ts: -------------------------------------------------------------------------------- 1 | import { BooleanField, NumberField, StringField } from "@/attributes"; 2 | import { describe, expect, it } from "vitest"; 3 | import { Model } from "@vuex-orm/core"; 4 | import { OrmModel } from "@/model"; 5 | 6 | describe("OrmModel", () => { 7 | it("can define the name that is going be used as module name in Vuex Store", () => { 8 | @OrmModel("users") 9 | class User extends Model {} 10 | 11 | expect(User.entity).toBe("users"); 12 | }); 13 | 14 | it("can define the reference to the base entity name", () => { 15 | @OrmModel("users") 16 | class User extends Model {} 17 | 18 | @OrmModel("admins", "users") 19 | class Admin extends User {} 20 | 21 | expect(User.entity).toBe("users"); 22 | expect(User.baseEntity).toBe(undefined); 23 | 24 | expect(Admin.entity).toBe("admins"); 25 | expect(Admin.baseEntity).toBe("users"); 26 | }); 27 | 28 | it("can define the inheritance types", () => { 29 | @OrmModel("users") 30 | class User extends Model {} 31 | 32 | @OrmModel("admins", "users", { 33 | ADMIN: Admin, 34 | USER: User, 35 | }) 36 | class Admin extends User {} 37 | 38 | @OrmModel("guests", "users", { 39 | GUEST: Guest, 40 | USER: User, 41 | }) 42 | class Guest extends User {} 43 | 44 | const typeKeys = ["ADMIN", "USER", "GUEST"]; 45 | 46 | expect(Object.keys(User.types())).toHaveLength(3); 47 | expect(Object.keys(User.types())).toEqual(typeKeys); 48 | expect(User.types().USER.entity).toBe("users"); 49 | expect(User.types().ADMIN.entity).toBe("admins"); 50 | expect(User.types().GUEST.entity).toBe("guests"); 51 | 52 | expect(Object.keys(Admin.types())).toHaveLength(3); 53 | expect(Object.keys(Admin.types())).toEqual(typeKeys); 54 | expect(Admin.types().USER.entity).toBe("users"); 55 | expect(Admin.types().ADMIN.entity).toBe("admins"); 56 | expect(Admin.types().GUEST.entity).toBe("guests"); 57 | 58 | expect(Object.keys(Guest.types())).toHaveLength(3); 59 | expect(Object.keys(Guest.types())).toEqual(typeKeys); 60 | expect(Guest.types().USER.entity).toBe("users"); 61 | expect(Guest.types().ADMIN.entity).toBe("admins"); 62 | expect(Admin.types().GUEST.entity).toBe("guests"); 63 | }); 64 | 65 | it("can define the inheritance fields", () => { 66 | @OrmModel("users") 67 | class User extends Model { 68 | @NumberField() id!: number; 69 | 70 | @StringField() name!: string; 71 | 72 | @StringField() email!: string; 73 | } 74 | 75 | expect(Object.keys(User.fields())).toHaveLength(3); 76 | expect(Object.keys(User.fields())).toEqual(["id", "name", "email"]); 77 | 78 | @OrmModel("admins", "users") 79 | class Admin extends User { 80 | @NumberField() level!: number; 81 | 82 | @BooleanField() active!: boolean; 83 | } 84 | 85 | expect(Object.keys(User.fields())).toHaveLength(3); 86 | 87 | expect(Object.keys(Admin.fields())).toHaveLength(5); 88 | expect(Object.keys(Admin.fields())).toEqual(["id", "name", "email", "level", "active"]); 89 | 90 | @OrmModel("super-admins", "admins") 91 | class SuperAdmin extends Admin { 92 | @BooleanField() fullAccess!: boolean; 93 | } 94 | 95 | expect(Object.keys(User.fields())).toHaveLength(3); 96 | expect(Object.keys(Admin.fields())).toHaveLength(5); 97 | 98 | expect(Object.keys(SuperAdmin.fields())).toHaveLength(6); 99 | expect(Object.keys(SuperAdmin.fields())).toEqual([ 100 | "id", 101 | "name", 102 | "email", 103 | "level", 104 | "active", 105 | "fullAccess", 106 | ]); 107 | }); 108 | }); 109 | -------------------------------------------------------------------------------- /test/unit/AttrField.spec.ts: -------------------------------------------------------------------------------- 1 | import { Attr, Model } from "@vuex-orm/core"; 2 | import { AttrField } from "@/attributes"; 3 | import { describe, expect, it } from "vitest"; 4 | import { OrmModel } from "@/model"; 5 | 6 | describe("AttrField", () => { 7 | it("can define `attr` field", () => { 8 | @OrmModel("users") 9 | class User extends Model { 10 | @AttrField() name!: string; 11 | } 12 | 13 | expect(new User().name).toBe(""); 14 | expect(User.getFields().name).toBeInstanceOf(Attr); 15 | expect((User.getFields().name as Attr).isNullable).toBe(false); 16 | }); 17 | 18 | it("can define `attr` field with default value", () => { 19 | @OrmModel("users") 20 | class User extends Model { 21 | @AttrField("John") name!: string; 22 | } 23 | 24 | expect(new User().name).toBe("John"); 25 | expect(User.getFields().name).toBeInstanceOf(Attr); 26 | expect((User.getFields().name as Attr).isNullable).toBe(false); 27 | }); 28 | 29 | it("can define `attr` field with null value", () => { 30 | @OrmModel("users") 31 | class User extends Model { 32 | @AttrField(null) name!: string; 33 | } 34 | 35 | expect(new User().name).toBe(null); 36 | expect(User.getFields().name).toBeInstanceOf(Attr); 37 | expect((User.getFields().name as Attr).isNullable).toBe(true); 38 | }); 39 | 40 | it("can mutate the given value", () => { 41 | @OrmModel("users") 42 | class User extends Model { 43 | @AttrField("john doe", (value: string) => { 44 | return value.toUpperCase(); 45 | }) 46 | name!: string; 47 | } 48 | 49 | expect(new User().name).toBe("JOHN DOE"); 50 | expect(User.getFields().name).toBeInstanceOf(Attr); 51 | expect((User.getFields().name as Attr).isNullable).toBe(false); 52 | }); 53 | }); 54 | -------------------------------------------------------------------------------- /test/unit/BooleanField.spec.ts: -------------------------------------------------------------------------------- 1 | import { Boolean, Model } from "@vuex-orm/core"; 2 | import { BooleanField } from "@/attributes"; 3 | import { describe, expect, it } from "vitest"; 4 | import { OrmModel } from "@/model"; 5 | 6 | describe("BooleanField", () => { 7 | it("can define `boolean` field", () => { 8 | @OrmModel("users") 9 | class User extends Model { 10 | @BooleanField() active!: boolean; 11 | } 12 | 13 | expect(new User().active).toBe(false); 14 | expect(User.getFields().active).toBeInstanceOf(Boolean); 15 | expect((User.getFields().active as Boolean).isNullable).toBe(false); 16 | }); 17 | 18 | it("can define `boolean` field with default value", () => { 19 | @OrmModel("users") 20 | class User extends Model { 21 | @BooleanField(true) active!: boolean; 22 | } 23 | 24 | expect(new User().active).toBe(true); 25 | expect(User.getFields().active).toBeInstanceOf(Boolean); 26 | expect((User.getFields().active as Boolean).isNullable).toBe(false); 27 | }); 28 | 29 | it("can define `boolean` field with null value", () => { 30 | @OrmModel("users") 31 | class User extends Model { 32 | @BooleanField(null) active!: boolean; 33 | } 34 | 35 | expect(new User().active).toBe(null); 36 | expect(User.getFields().active).toBeInstanceOf(Boolean); 37 | expect((User.getFields().active as Boolean).isNullable).toBe(true); 38 | }); 39 | 40 | it("can mutate the given value", () => { 41 | @OrmModel("users") 42 | class User extends Model { 43 | @BooleanField(false, (value: boolean) => { 44 | return !value; 45 | }) 46 | active!: boolean; 47 | } 48 | 49 | expect(new User().active).toBe(true); 50 | expect(User.getFields().active).toBeInstanceOf(Boolean); 51 | expect((User.getFields().active as Boolean).isNullable).toBe(false); 52 | }); 53 | }); 54 | -------------------------------------------------------------------------------- /test/unit/DateField.spec.ts: -------------------------------------------------------------------------------- 1 | import { DateField } from "@/attributes"; 2 | import { describe, expect, it } from "vitest"; 3 | import { Model } from "@vuex-orm/core"; 4 | import { ORMDatabase } from "@/database"; 5 | import { OrmModel } from "@/model"; 6 | import { Store } from "vuex"; 7 | import DateType from "@/plugins/Date/DateType"; 8 | 9 | describe("DateField", () => { 10 | it("can define `date` field", () => { 11 | @OrmModel("users") 12 | class User extends Model { 13 | @DateField() created_at!: Date; 14 | } 15 | 16 | expect(new User().created_at).toBe(null); 17 | expect(User.getFields().created_at).toBeInstanceOf(DateType); 18 | expect((User.getFields().created_at as DateType).isNullable).toBe(false); 19 | }); 20 | 21 | it("can define `date` field with default value", () => { 22 | const defaultDate = new Date(); 23 | 24 | @OrmModel("users") 25 | class User extends Model { 26 | @DateField(defaultDate) created_at!: Date; 27 | } 28 | 29 | const user = new User(); 30 | 31 | expect(user.created_at).toBeInstanceOf(Date); 32 | expect(user.created_at.toDateString()).toEqual(defaultDate.toDateString()); 33 | expect(user.created_at.toUTCString()).toEqual(defaultDate.toUTCString()); 34 | expect(User.getFields().created_at).toBeInstanceOf(DateType); 35 | expect((User.getFields().created_at as DateType).isNullable).toBe(false); 36 | }); 37 | 38 | it("can define `date` field with null value", () => { 39 | @OrmModel("users") 40 | class User extends Model { 41 | @DateField(null) created_at!: Date; 42 | } 43 | 44 | expect(new User().created_at).toBe(null); 45 | expect(User.getFields().created_at).toBeInstanceOf(DateType); 46 | expect((User.getFields().created_at as DateType).isNullable).toBe(true); 47 | }); 48 | 49 | it("parses proper dates to date instance", () => { 50 | @OrmModel("users-2") 51 | class User extends Model { 52 | @DateField() created_at!: Date; 53 | 54 | @DateField(null) deleted_at?: Date; 55 | } 56 | 57 | new Store({ 58 | plugins: [ORMDatabase.install()], 59 | }); 60 | 61 | User.insert({ 62 | data: [ 63 | { created_at: "2020-12-30T12:35:45.000000Z" }, 64 | { 65 | created_at: "2020-11-30T11:25:35.000000Z", 66 | deleted_at: "2020-12-02T11:25:35.000000Z", 67 | }, 68 | { created_at: "2020-10-30T10:15:25.000Z" }, 69 | { 70 | created_at: "1601456715000", 71 | deleted_at: "1602666315000", 72 | }, 73 | ], 74 | }); 75 | 76 | const user_1 = User.find("$uid1"); 77 | 78 | expect(user_1?.deleted_at).toBe(null); 79 | expect(user_1?.created_at).toBeInstanceOf(Date); 80 | expect(user_1?.created_at.toDateString()).toEqual("Wed Dec 30 2020"); 81 | expect(user_1?.created_at.toUTCString()).toEqual("Wed, 30 Dec 2020 12:35:45 GMT"); 82 | 83 | const user_2 = User.find("$uid2"); 84 | 85 | expect(user_2?.created_at).toBeInstanceOf(Date); 86 | expect(user_2?.created_at.toDateString()).toEqual("Mon Nov 30 2020"); 87 | expect(user_2?.created_at.toUTCString()).toEqual("Mon, 30 Nov 2020 11:25:35 GMT"); 88 | 89 | expect(user_2?.deleted_at).toBeInstanceOf(Date); 90 | expect(user_2?.deleted_at?.toDateString()).toEqual("Wed Dec 02 2020"); 91 | expect(user_2?.deleted_at?.toUTCString()).toEqual("Wed, 02 Dec 2020 11:25:35 GMT"); 92 | 93 | const user_3 = User.find("$uid3"); 94 | 95 | expect(user_3?.deleted_at).toBe(null); 96 | expect(user_3?.created_at).toBeInstanceOf(Date); 97 | expect(user_3?.created_at.toDateString()).toEqual("Fri Oct 30 2020"); 98 | expect(user_3?.created_at.toUTCString()).toEqual("Fri, 30 Oct 2020 10:15:25 GMT"); 99 | 100 | const user_4 = User.find("$uid4"); 101 | 102 | expect(user_4?.created_at).toBeInstanceOf(Date); 103 | expect(user_4?.created_at.toDateString()).toEqual("Wed Sep 30 2020"); 104 | expect(user_4?.created_at.toUTCString()).toEqual("Wed, 30 Sep 2020 09:05:15 GMT"); 105 | 106 | expect(user_4?.deleted_at).toBeInstanceOf(Date); 107 | expect(user_4?.deleted_at?.toDateString()).toEqual("Wed Oct 14 2020"); 108 | expect(user_4?.deleted_at?.toUTCString()).toEqual("Wed, 14 Oct 2020 09:05:15 GMT"); 109 | 110 | expect(User.getFields().created_at).toBeInstanceOf(DateType); 111 | expect((User.getFields().created_at as DateType).isNullable).toBe(false); 112 | expect(User.getFields().deleted_at).toBeInstanceOf(DateType); 113 | expect((User.getFields().deleted_at as DateType).isNullable).toBe(true); 114 | }); 115 | 116 | it("returns null if property is empty", () => { 117 | @OrmModel("users-3") 118 | class User extends Model { 119 | @DateField() created_at!: Date; 120 | 121 | @DateField() deleted_at?: Date; 122 | } 123 | 124 | new Store({ 125 | plugins: [ORMDatabase.install()], 126 | }); 127 | 128 | User.insert({ 129 | data: [{ created_at: "2020-12-30T12:35:45.000000Z" }], 130 | }); 131 | 132 | const user = User.query().first(); 133 | 134 | expect(user?.deleted_at).toBe(null); 135 | expect(user?.created_at).toBeInstanceOf(Date); 136 | expect(user?.created_at.toDateString()).toEqual("Wed Dec 30 2020"); 137 | expect(user?.created_at.toUTCString()).toEqual("Wed, 30 Dec 2020 12:35:45 GMT"); 138 | expect(User.getFields().created_at).toBeInstanceOf(DateType); 139 | expect((User.getFields().deleted_at as DateType).isNullable).toBe(false); 140 | expect(User.getFields().deleted_at).toBeInstanceOf(DateType); 141 | expect((User.getFields().deleted_at as DateType).isNullable).toBe(false); 142 | }); 143 | 144 | it("can mutate the given value", () => { 145 | @OrmModel("users-4") 146 | class User extends Model { 147 | @DateField(null, (value: Date) => { 148 | const mutated = value.setDate(value.getDate() + 1); 149 | 150 | return new Date(mutated); 151 | }) 152 | created_at!: Date; 153 | } 154 | 155 | new Store({ 156 | plugins: [ORMDatabase.install()], 157 | }); 158 | 159 | User.insert({ data: { created_at: "2020-12-30T12:15:45.000Z" } }); 160 | 161 | const user = User.query().first(); 162 | 163 | expect(user?.created_at).toBeInstanceOf(Date); 164 | expect(user?.created_at.toDateString()).toEqual("Thu Dec 31 2020"); 165 | expect(User.getFields().created_at).toBeInstanceOf(DateType); 166 | expect((User.getFields().created_at as DateType).isNullable).toBe(false); 167 | }); 168 | }); 169 | -------------------------------------------------------------------------------- /test/unit/NumberField.spec.ts: -------------------------------------------------------------------------------- 1 | import { describe, expect, it } from "vitest"; 2 | import { Model, Number } from "@vuex-orm/core"; 3 | import { NumberField } from "@/attributes"; 4 | import { OrmModel } from "@/model"; 5 | 6 | describe("NumberField", () => { 7 | it("can define `number` field", () => { 8 | @OrmModel("users") 9 | class User extends Model { 10 | @NumberField() age!: number; 11 | } 12 | 13 | expect(new User().age).toBe(0); 14 | expect(User.getFields().age).toBeInstanceOf(Number); 15 | expect((User.getFields().age as Number).isNullable).toBe(false); 16 | }); 17 | 18 | it("can define `number` field with default value", () => { 19 | @OrmModel("users") 20 | class User extends Model { 21 | @NumberField(25) age!: number; 22 | } 23 | 24 | expect(new User().age).toBe(25); 25 | expect(User.getFields().age).toBeInstanceOf(Number); 26 | expect((User.getFields().age as Number).isNullable).toBe(false); 27 | }); 28 | 29 | it("can define `number` field with null value", () => { 30 | @OrmModel("users") 31 | class User extends Model { 32 | @NumberField(null) age!: number; 33 | } 34 | 35 | expect(new User().age).toBe(null); 36 | expect(User.getFields().age).toBeInstanceOf(Number); 37 | expect((User.getFields().age as Number).isNullable).toBe(true); 38 | }); 39 | 40 | it("can mutate the given value", () => { 41 | @OrmModel("users") 42 | class User extends Model { 43 | @NumberField(25, (value: number) => { 44 | return value + 1; 45 | }) 46 | age!: number; 47 | } 48 | 49 | expect(new User().age).toBe(26); 50 | expect(User.getFields().age).toBeInstanceOf(Number); 51 | expect((User.getFields().age as Number).isNullable).toBe(false); 52 | }); 53 | }); 54 | -------------------------------------------------------------------------------- /test/unit/PrimaryKey.spec.ts: -------------------------------------------------------------------------------- 1 | import { describe, expect, it, test } from "vitest"; 2 | import { Model } from "@vuex-orm/core"; 3 | import { NumberField, PrimaryKey, StringField, UidField } from "@/attributes"; 4 | import { OrmModel } from "@/model"; 5 | 6 | describe("PrimaryKey", () => { 7 | test("property id is by default the primaryKey", () => { 8 | @OrmModel("users") 9 | class User extends Model { 10 | @NumberField() id!: number; 11 | } 12 | 13 | expect(User.primaryKey).toBe("id"); 14 | }); 15 | 16 | it("sets the property as the primary key of the model", () => { 17 | @OrmModel("users") 18 | class User extends Model { 19 | @PrimaryKey() 20 | @UidField() 21 | uid!: number; 22 | } 23 | 24 | expect(User.primaryKey).not.toBe("id"); 25 | expect(User.primaryKey).toBe("uid"); 26 | }); 27 | 28 | it("supports composite key", () => { 29 | @OrmModel("users") 30 | class User extends Model { 31 | @PrimaryKey() 32 | @StringField() 33 | public userId!: string; 34 | 35 | @PrimaryKey() 36 | @StringField() 37 | public voteId!: string; 38 | } 39 | 40 | expect(User.primaryKey).toEqual(["userId", "voteId"]); 41 | }); 42 | 43 | it("supports composite key with the default(id) field", () => { 44 | @OrmModel("users") 45 | class User extends Model { 46 | @PrimaryKey() 47 | @StringField() 48 | public id!: string; 49 | 50 | @PrimaryKey() 51 | @StringField() 52 | public userId!: string; 53 | 54 | @PrimaryKey() 55 | @StringField() 56 | public voteId!: string; 57 | } 58 | 59 | expect(User.primaryKey).toEqual(["id", "userId", "voteId"]); 60 | }); 61 | }); 62 | -------------------------------------------------------------------------------- /test/unit/StringField.spec.ts: -------------------------------------------------------------------------------- 1 | import { describe, expect, it } from "vitest"; 2 | import { Model, String } from "@vuex-orm/core"; 3 | import { OrmModel } from "@/model"; 4 | import { StringField } from "@/attributes"; 5 | 6 | describe("StringField", () => { 7 | it("can define `string` field", () => { 8 | @OrmModel("users") 9 | class User extends Model { 10 | @StringField() name!: string; 11 | } 12 | 13 | expect(new User().name).toBe(""); 14 | expect(User.getFields().name).toBeInstanceOf(String); 15 | expect((User.getFields().name as String).isNullable).toBe(false); 16 | }); 17 | 18 | it("can define `string` field with default value", () => { 19 | @OrmModel("users") 20 | class User extends Model { 21 | @StringField("John Doe") name!: string; 22 | } 23 | 24 | expect(new User().name).toBe("John Doe"); 25 | expect(User.getFields().name).toBeInstanceOf(String); 26 | expect((User.getFields().name as String).isNullable).toBe(false); 27 | }); 28 | 29 | it("can define `string` field with null value", () => { 30 | @OrmModel("users") 31 | class User extends Model { 32 | @StringField(null) name!: string; 33 | } 34 | 35 | expect(new User().name).toBe(null); 36 | expect(User.getFields().name).toBeInstanceOf(String); 37 | expect((User.getFields().name as String).isNullable).toBe(true); 38 | }); 39 | 40 | it("can mutate the given value", () => { 41 | @OrmModel("users") 42 | class User extends Model { 43 | @StringField("john doe", (value: string) => { 44 | return value.toUpperCase(); 45 | }) 46 | name!: string; 47 | } 48 | 49 | expect(new User().name).toBe("JOHN DOE"); 50 | expect(User.getFields().name).toBeInstanceOf(String); 51 | expect((User.getFields().name as String).isNullable).toBe(false); 52 | }); 53 | }); 54 | -------------------------------------------------------------------------------- /test/unit/UidField.spec.ts: -------------------------------------------------------------------------------- 1 | import { describe, expect, it } from "vitest"; 2 | import { Model, Uid } from "@vuex-orm/core"; 3 | import { OrmModel } from "@/model"; 4 | import { UidField } from "@/attributes"; 5 | 6 | describe("UidField", () => { 7 | it("can define `uid` field", () => { 8 | @OrmModel("users") 9 | class User extends Model { 10 | @UidField() uid!: number; 11 | } 12 | 13 | expect(new User().uid).toBe("$uid1"); 14 | expect(User.getFields().uid).toBeInstanceOf(Uid); 15 | expect((User.getFields().uid as Uid).isNullable).toBe(false); 16 | }); 17 | 18 | it("can define `uid` field with custom value", () => { 19 | @OrmModel("users") 20 | class User extends Model { 21 | @UidField(() => "uid") uid!: number; 22 | } 23 | 24 | expect(new User().uid).toBe("uid"); 25 | expect(User.getFields().uid).toBeInstanceOf(Uid); 26 | expect((User.getFields().uid as Uid).isNullable).toBe(false); 27 | }); 28 | }); 29 | -------------------------------------------------------------------------------- /test/unit/relationships/BelongsToField.spec.ts: -------------------------------------------------------------------------------- 1 | import { BelongsTo } from "@vuex-orm/core"; 2 | import { describe, expect, it } from "vitest"; 3 | import { ORMDatabase } from "@/database"; 4 | import { Profile } from "test/unit/relationships/fixtures/Profile"; 5 | import { Store } from "vuex"; 6 | import { User } from "test/unit/relationships/fixtures/User"; 7 | 8 | describe("BelongsToField", () => { 9 | it("can define the property as a `Belongs To` relationship field", () => { 10 | new Store({ 11 | plugins: [ORMDatabase.install()], 12 | }); 13 | 14 | Profile.insert({ 15 | data: { 16 | id: 1, 17 | user_id: 10, 18 | age: 25, 19 | sex: "male", 20 | user: { 21 | id: 10, 22 | name: "John Doe", 23 | }, 24 | }, 25 | }); 26 | 27 | const field = Profile.getFields().user as BelongsTo; 28 | 29 | expect(field).toBeInstanceOf(BelongsTo); 30 | 31 | expect(field.parent).toBe(User); 32 | expect(field.foreignKey).toBe("user_id"); 33 | expect(field.ownerKey).toBe("id"); 34 | 35 | const profile = Profile.query().with("user").first(); 36 | 37 | expect(profile?.user).toEqual({ 38 | $id: "10", 39 | id: 10, 40 | name: "John Doe", 41 | profile: null, 42 | }); 43 | 44 | expect(profile?.user).toBeInstanceOf(User); 45 | expect(User.all()).toHaveLength(1); 46 | expect(Profile.all()).toHaveLength(1); 47 | }); 48 | }); 49 | -------------------------------------------------------------------------------- /test/unit/relationships/BelongsToManyField.spec.ts: -------------------------------------------------------------------------------- 1 | import { BelongsToMany, Model } from "@vuex-orm/core"; 2 | import { BelongsToManyField, NumberField, StringField } from "@/attributes"; 3 | import { describe, expect, it } from "vitest"; 4 | import { ORMDatabase } from "@/database"; 5 | import { OrmModel } from "@/model"; 6 | import { Store } from "vuex"; 7 | 8 | describe("BelongsToManyField", () => { 9 | it("can define the property as a `Belongs To Many` relationship field", () => { 10 | @OrmModel("roles") 11 | class Role extends Model { 12 | @NumberField() id!: number; 13 | 14 | @StringField() name!: string; 15 | } 16 | 17 | @OrmModel("role_users") 18 | class RoleUser extends Model { 19 | static primaryKey = ["role_id", "user_id"]; 20 | 21 | @NumberField() role_id!: number; 22 | 23 | @NumberField() user_id!: number; 24 | } 25 | 26 | @OrmModel("users") 27 | class User extends Model { 28 | @NumberField() id!: number; 29 | 30 | @StringField() name!: string; 31 | 32 | @BelongsToManyField(Role, RoleUser, "user_id", "role_id") 33 | roles!: Role[]; 34 | } 35 | 36 | new Store({ 37 | plugins: [ORMDatabase.install()], 38 | }); 39 | 40 | User.insert({ 41 | data: { 42 | id: 1, 43 | name: "John Doe", 44 | roles: [ 45 | { id: 1, name: "Admin" }, 46 | { id: 2, name: "Operator" }, 47 | ], 48 | }, 49 | }); 50 | 51 | const field = User.getFields().roles as BelongsToMany; 52 | 53 | expect(field).toBeInstanceOf(BelongsToMany); 54 | 55 | expect(field.related).toBe(Role); 56 | expect(field.pivot).toBe(RoleUser); 57 | expect(field.foreignPivotKey).toBe("user_id"); 58 | expect(field.relatedPivotKey).toBe("role_id"); 59 | expect(field.parentKey).toBe("id"); 60 | expect(field.relatedKey).toBe("id"); 61 | 62 | const user = User.query().with("roles").first(); 63 | 64 | expect(user?.roles).toEqual([ 65 | { 66 | $id: "1", 67 | id: 1, 68 | name: "Admin", 69 | pivot: { $id: "[1,1]", role_id: 1, user_id: 1 }, 70 | }, 71 | { 72 | $id: "2", 73 | id: 2, 74 | name: "Operator", 75 | pivot: { $id: "[2,1]", role_id: 2, user_id: 1 }, 76 | }, 77 | ]); 78 | 79 | expect(user?.roles[0]).toBeInstanceOf(Role); 80 | expect(Role.all()).toHaveLength(2); 81 | expect(RoleUser.all()).toHaveLength(2); 82 | expect(User.all()).toHaveLength(1); 83 | }); 84 | }); 85 | -------------------------------------------------------------------------------- /test/unit/relationships/HasManyByField.spec.ts: -------------------------------------------------------------------------------- 1 | import { AttrField, HasManyByField, NumberField, StringField } from "@/attributes"; 2 | import { describe, expect, it } from "vitest"; 3 | import { HasManyBy, Model } from "@vuex-orm/core"; 4 | import { ORMDatabase } from "@/database"; 5 | import { OrmModel } from "@/model"; 6 | import { Store } from "vuex"; 7 | 8 | describe("HasManyByField", () => { 9 | it("can define the property as a `Has Many By` relationship field", () => { 10 | @OrmModel("nodes") 11 | class Node extends Model { 12 | @NumberField() id!: number; 13 | 14 | @StringField() name!: string; 15 | } 16 | 17 | @OrmModel("clusters") 18 | class Cluster extends Model { 19 | @NumberField() id!: number; 20 | 21 | @AttrField() node_ids!: number[]; 22 | 23 | @HasManyByField(Node, "node_ids") nodes!: Node; 24 | } 25 | 26 | new Store({ 27 | plugins: [ORMDatabase.install()], 28 | }); 29 | 30 | Cluster.insert({ 31 | data: { 32 | id: 1, 33 | nodes: [ 34 | { id: 1, name: "Node 1" }, 35 | { id: 2, name: "Node 2" }, 36 | { id: 3, name: "Node 3" }, 37 | ], 38 | }, 39 | }); 40 | 41 | const field = Cluster.getFields().nodes as HasManyBy; 42 | 43 | expect(field).toBeInstanceOf(HasManyBy); 44 | 45 | expect(field.parent).toBe(Node); 46 | expect(field.foreignKey).toBe("node_ids"); 47 | expect(field.ownerKey).toBe("id"); 48 | 49 | const cluster = Cluster.query().with("nodes").first(); 50 | 51 | expect(cluster?.nodes).toEqual([ 52 | { $id: "1", id: 1, name: "Node 1" }, 53 | { $id: "2", id: 2, name: "Node 2" }, 54 | { $id: "3", id: 3, name: "Node 3" }, 55 | ]); 56 | 57 | expect(cluster?.nodes[0]).toBeInstanceOf(Node); 58 | expect(Node.all()).toHaveLength(3); 59 | expect(Cluster.all()).toHaveLength(1); 60 | }); 61 | }); 62 | -------------------------------------------------------------------------------- /test/unit/relationships/HasManyField.spec.ts: -------------------------------------------------------------------------------- 1 | import { describe, expect, it } from "vitest"; 2 | import { HasMany, Model } from "@vuex-orm/core"; 3 | import { HasManyField, NumberField, StringField } from "@/attributes"; 4 | import { ORMDatabase } from "@/database"; 5 | import { OrmModel } from "@/model"; 6 | import { Store } from "vuex"; 7 | 8 | describe("HasManyField", () => { 9 | it("can define the property as a `Has Many` relationship field", () => { 10 | @OrmModel("comments") 11 | class Comment extends Model { 12 | @NumberField() id!: number; 13 | 14 | @StringField() body!: string; 15 | 16 | @NumberField() post_id!: number; 17 | } 18 | 19 | @OrmModel("posts") 20 | class Post extends Model { 21 | @NumberField() id!: number; 22 | 23 | @StringField() title!: string; 24 | 25 | @StringField() body!: string; 26 | 27 | @HasManyField(Comment, "post_id") comments!: Comment; 28 | } 29 | 30 | new Store({ 31 | plugins: [ORMDatabase.install()], 32 | }); 33 | 34 | Post.insert({ 35 | data: { 36 | id: 1, 37 | title: "Post title", 38 | body: "Some blog...", 39 | comments: [ 40 | { id: 1, body: "Comment one", post_id: 1 }, 41 | { id: 2, body: "Comment two", post_id: 2 }, 42 | { id: 3, body: "Comment three", post_id: 1 }, 43 | { id: 4, body: "Comment four", post_id: 1 }, 44 | ], 45 | }, 46 | }); 47 | 48 | const field = Post.getFields().comments as HasMany; 49 | 50 | expect(field).toBeInstanceOf(HasMany); 51 | 52 | expect(field.related).toBe(Comment); 53 | expect(field.foreignKey).toBe("post_id"); 54 | expect(field.localKey).toBe("id"); 55 | 56 | const post = Post.query().with("comments").first(); 57 | 58 | expect(post?.comments).toEqual([ 59 | { $id: "1", id: 1, body: "Comment one", post_id: 1 }, 60 | { $id: "3", id: 3, body: "Comment three", post_id: 1 }, 61 | { $id: "4", id: 4, body: "Comment four", post_id: 1 }, 62 | ]); 63 | 64 | expect(post?.comments[0]).toBeInstanceOf(Comment); 65 | expect(Comment.all()).toHaveLength(4); 66 | expect(Post.all()).toHaveLength(1); 67 | }); 68 | }); 69 | -------------------------------------------------------------------------------- /test/unit/relationships/HasManyThroughField.spec.ts: -------------------------------------------------------------------------------- 1 | import { describe, expect, it } from "vitest"; 2 | import { HasManyThrough, Model } from "@vuex-orm/core"; 3 | import { HasManyThroughField, NumberField, StringField } from "@/attributes"; 4 | import { ORMDatabase } from "@/database"; 5 | import { OrmModel } from "@/model"; 6 | import { Store } from "vuex"; 7 | 8 | describe("HasManyThroughField", () => { 9 | it("can define the property as a `Has Many Through` relationship field", () => { 10 | @OrmModel("users") 11 | class User extends Model { 12 | @NumberField() id!: number; 13 | 14 | @StringField() name!: string; 15 | 16 | @NumberField() country_id!: number; 17 | } 18 | 19 | @OrmModel("posts") 20 | class Post extends Model { 21 | @NumberField() id!: number; 22 | 23 | @StringField() name!: string; 24 | 25 | @NumberField() user_id!: number; 26 | } 27 | 28 | @OrmModel("countries") 29 | class Country extends Model { 30 | @NumberField() id!: number; 31 | 32 | @StringField() name!: string; 33 | 34 | @HasManyThroughField(Post, User, "country_id", "user_id") 35 | posts!: Post; 36 | } 37 | 38 | new Store({ 39 | plugins: [ORMDatabase.install()], 40 | }); 41 | 42 | User.insert({ 43 | data: [ 44 | { id: 1, name: "John Doe", country_id: 1 }, 45 | { id: 2, name: "Jane Doe", country_id: 1 }, 46 | ], 47 | }); 48 | 49 | Country.insert({ 50 | data: { 51 | id: 1, 52 | name: "Big Country", 53 | posts: [ 54 | { id: 1, name: "Post one", user_id: 1 }, 55 | { id: 2, name: "Post two", user_id: 2 }, 56 | { id: 3, name: "Post three", user_id: 1 }, 57 | ], 58 | }, 59 | }); 60 | 61 | const field = Country.getFields().posts as HasManyThrough; 62 | 63 | expect(field).toBeInstanceOf(HasManyThrough); 64 | 65 | expect(field.related).toBe(Post); 66 | expect(field.through).toBe(User); 67 | expect(field.firstKey).toBe("country_id"); 68 | expect(field.secondKey).toBe("user_id"); 69 | expect(field.localKey).toBe("id"); 70 | expect(field.secondLocalKey).toBe("id"); 71 | 72 | const country = Country.query().with("posts").first(); 73 | 74 | expect(country?.posts).toEqual([ 75 | { $id: "1", id: 1, name: "Post one", user_id: 1 }, 76 | { $id: "3", id: 3, name: "Post three", user_id: 1 }, 77 | { $id: "2", id: 2, name: "Post two", user_id: 2 }, 78 | ]); 79 | 80 | expect(country?.posts[0]).toBeInstanceOf(Post); 81 | expect(User.all()).toHaveLength(2); 82 | expect(Post.all()).toHaveLength(3); 83 | expect(Country.all()).toHaveLength(1); 84 | }); 85 | }); 86 | -------------------------------------------------------------------------------- /test/unit/relationships/HasOneField.spec.ts: -------------------------------------------------------------------------------- 1 | import { describe, expect, it } from "vitest"; 2 | import { HasOne, Model } from "@vuex-orm/core"; 3 | import { HasOneField, NumberField, StringField } from "@/attributes"; 4 | import { ORMDatabase } from "@/database"; 5 | import { OrmModel } from "@/model"; 6 | import { Store } from "vuex"; 7 | 8 | describe("HasOneField", () => { 9 | it("can define the property as a `Has One` relationship field", () => { 10 | @OrmModel("profiles") 11 | class Profile extends Model { 12 | @NumberField() id!: number; 13 | 14 | @NumberField() user_id!: number; 15 | 16 | @NumberField() age!: number; 17 | 18 | @StringField() sex!: string; 19 | } 20 | 21 | @OrmModel("users") 22 | class User extends Model { 23 | @NumberField() id!: number; 24 | 25 | @StringField() name!: string; 26 | 27 | @HasOneField(Profile, "user_id") profile!: Profile; 28 | } 29 | 30 | new Store({ 31 | plugins: [ORMDatabase.install()], 32 | }); 33 | 34 | User.insert({ 35 | data: { 36 | id: 1, 37 | name: "John Doe", 38 | profile: { 39 | id: 10, 40 | user_id: 1, 41 | age: 25, 42 | sex: "male", 43 | }, 44 | }, 45 | }); 46 | 47 | const field = User.getFields().profile as HasOne; 48 | 49 | expect(field).toBeInstanceOf(HasOne); 50 | 51 | expect(field.related).toBe(Profile); 52 | expect(field.localKey).toBe("id"); 53 | expect(field.foreignKey).toBe("user_id"); 54 | 55 | const user = User.query().with("profile").first(); 56 | 57 | expect(user?.profile).toEqual({ 58 | $id: "10", 59 | id: 10, 60 | user_id: 1, 61 | age: 25, 62 | sex: "male", 63 | }); 64 | 65 | expect(user?.profile).toBeInstanceOf(Profile); 66 | expect(User.all()).toHaveLength(1); 67 | expect(Profile.all()).toHaveLength(1); 68 | }); 69 | }); 70 | -------------------------------------------------------------------------------- /test/unit/relationships/MorphManyField.spec.ts: -------------------------------------------------------------------------------- 1 | import { describe, expect, it } from "vitest"; 2 | import { Model, MorphMany } from "@vuex-orm/core"; 3 | import { MorphManyField, NumberField, StringField } from "@/attributes"; 4 | import { ORMDatabase } from "@/database"; 5 | import { OrmModel } from "@/model"; 6 | import { Store } from "vuex"; 7 | 8 | describe("MorphManyField", () => { 9 | it("can define the property as a `Morph Many` relationship field", () => { 10 | @OrmModel("comments") 11 | class Comment extends Model { 12 | @NumberField() id!: number; 13 | 14 | @StringField() body!: string; 15 | 16 | @NumberField() commentable_id!: number[]; 17 | 18 | @StringField() commentable_type!: string; 19 | } 20 | 21 | @OrmModel("posts") 22 | class Post extends Model { 23 | @NumberField() id!: number; 24 | 25 | @StringField() title!: string; 26 | 27 | @MorphManyField(Comment, "commentable_id", "commentable_type") 28 | comments!: Comment[]; 29 | } 30 | 31 | @OrmModel("videos") 32 | class Video extends Model { 33 | @NumberField() id!: number; 34 | 35 | @StringField() link!: string; 36 | 37 | @MorphManyField(Comment, "commentable_id", "commentable_type") 38 | comments!: Comment[]; 39 | } 40 | 41 | new Store({ 42 | plugins: [ORMDatabase.install()], 43 | }); 44 | 45 | Post.insert({ 46 | data: { 47 | id: 1, 48 | title: "Post title...", 49 | comments: [ 50 | { id: 1, body: "comment 1", commentable_id: 1, commentable_type: "posts" }, 51 | { id: 3, body: "comment 3", commentable_id: 1, commentable_type: "posts" }, 52 | ], 53 | }, 54 | }); 55 | 56 | Video.insert({ 57 | data: { 58 | id: 1, 59 | link: "http://example.com/video/something-nice", 60 | comments: [ 61 | { id: 2, body: "comment 2", commentable_id: 1, commentable_type: "videos" }, 62 | { id: 4, body: "comment 4", commentable_id: 1, commentable_type: "videos" }, 63 | ], 64 | }, 65 | }); 66 | 67 | [Post.getFields().comments as MorphMany, Video.getFields().comments as MorphMany].forEach( 68 | (field) => { 69 | expect(field).toBeInstanceOf(MorphMany); 70 | 71 | expect(field.related).toBe(Comment); 72 | expect(field.id).toBe("commentable_id"); 73 | expect(field.type).toBe("commentable_type"); 74 | expect(field.localKey).toBe("id"); 75 | } 76 | ); 77 | 78 | expect(Post.query().with("comments").first()?.comments).toEqual([ 79 | { 80 | $id: "1", 81 | id: 1, 82 | body: "comment 1", 83 | commentable_id: 1, 84 | commentable_type: "posts", 85 | }, 86 | { 87 | $id: "3", 88 | id: 3, 89 | body: "comment 3", 90 | commentable_id: 1, 91 | commentable_type: "posts", 92 | }, 93 | ]); 94 | 95 | expect(Video.query().with("comments").first()?.comments).toEqual([ 96 | { 97 | $id: "2", 98 | id: 2, 99 | body: "comment 2", 100 | commentable_id: 1, 101 | commentable_type: "videos", 102 | }, 103 | { 104 | $id: "4", 105 | id: 4, 106 | body: "comment 4", 107 | commentable_id: 1, 108 | commentable_type: "videos", 109 | }, 110 | ]); 111 | 112 | expect(Post.query().with("comments").first()?.comments[0]).toBeInstanceOf(Comment); 113 | expect(Video.query().with("comments").first()?.comments[0]).toBeInstanceOf(Comment); 114 | expect(Comment.all()).toHaveLength(4); 115 | expect(Post.all()).toHaveLength(1); 116 | expect(Video.all()).toHaveLength(1); 117 | }); 118 | }); 119 | -------------------------------------------------------------------------------- /test/unit/relationships/MorphOneField.spec.ts: -------------------------------------------------------------------------------- 1 | import { describe, expect, it } from "vitest"; 2 | import { Model, MorphOne } from "@vuex-orm/core"; 3 | import { MorphOneField, NumberField, StringField } from "@/attributes"; 4 | import { ORMDatabase } from "@/database"; 5 | import { OrmModel } from "@/model"; 6 | import { Store } from "vuex"; 7 | 8 | describe("MorphOneField", () => { 9 | it("can define the property as a `Morph One` relationship field", () => { 10 | @OrmModel("images") 11 | class Image extends Model { 12 | @NumberField() id!: number; 13 | 14 | @StringField() url!: string; 15 | 16 | @NumberField() imageable_id!: number; 17 | 18 | @StringField() imageable_type!: string; 19 | } 20 | 21 | @OrmModel("users") 22 | class User extends Model { 23 | @NumberField() id!: number; 24 | 25 | @StringField() name!: string; 26 | 27 | @MorphOneField(Image, "imageable_id", "imageable_type") 28 | image!: Image; 29 | } 30 | 31 | @OrmModel("posts") 32 | class Post extends Model { 33 | @NumberField() id!: number; 34 | 35 | @StringField() title!: string; 36 | 37 | @MorphOneField(Image, "imageable_id", "imageable_type") 38 | image!: Image; 39 | } 40 | 41 | new Store({ 42 | plugins: [ORMDatabase.install()], 43 | }); 44 | 45 | User.insert({ 46 | data: { 47 | id: 5, 48 | name: "John Doe", 49 | image: { 50 | id: 1, 51 | url: "http://example.com/user_image_1.png", 52 | imageable_id: 5, 53 | imageable_type: "users", 54 | }, 55 | }, 56 | }); 57 | 58 | Post.insert({ 59 | data: { 60 | id: 3, 61 | title: "Post title...", 62 | image: { 63 | id: 2, 64 | url: "http://example.com/post_image_1.png", 65 | imageable_id: 3, 66 | imageable_type: "posts", 67 | }, 68 | }, 69 | }); 70 | 71 | [User.getFields().image as MorphOne, Post.getFields().image as MorphOne].forEach( 72 | (field) => { 73 | expect(field).toBeInstanceOf(MorphOne); 74 | 75 | expect(field.related).toBe(Image); 76 | expect(field.id).toBe("imageable_id"); 77 | expect(field.type).toBe("imageable_type"); 78 | expect(field.localKey).toBe("id"); 79 | } 80 | ); 81 | 82 | expect(User.query().with("image").first()?.image).toEqual({ 83 | $id: "1", 84 | id: 1, 85 | url: "http://example.com/user_image_1.png", 86 | imageable_id: 5, 87 | imageable_type: "users", 88 | }); 89 | 90 | expect(Post.query().with("image").first()?.image).toEqual({ 91 | $id: "2", 92 | id: 2, 93 | url: "http://example.com/post_image_1.png", 94 | imageable_id: 3, 95 | imageable_type: "posts", 96 | }); 97 | 98 | expect(User.query().with("image").first()?.image).toBeInstanceOf(Image); 99 | expect(Post.query().with("image").first()?.image).toBeInstanceOf(Image); 100 | expect(Image.all()).toHaveLength(2); 101 | expect(Post.all()).toHaveLength(1); 102 | expect(User.all()).toHaveLength(1); 103 | }); 104 | }); 105 | -------------------------------------------------------------------------------- /test/unit/relationships/MorphToField.spec.ts: -------------------------------------------------------------------------------- 1 | import { describe, expect, it } from "vitest"; 2 | import { Model, MorphTo } from "@vuex-orm/core"; 3 | import { MorphOneField, MorphToField, NumberField, StringField } from "@/attributes"; 4 | import { ORMDatabase } from "@/database"; 5 | import { OrmModel } from "@/model"; 6 | import { Store } from "vuex"; 7 | 8 | describe("MorphToField", () => { 9 | it("can define the property as a `Morph To` relationship field", () => { 10 | @OrmModel("images") 11 | class Image extends Model { 12 | @NumberField() id!: number; 13 | 14 | @StringField() url!: string; 15 | 16 | @NumberField() imageable_id!: number; 17 | 18 | @StringField() imageable_type!: string; 19 | 20 | @MorphToField("imageable_id", "imageable_type") 21 | imageable!: User; 22 | } 23 | 24 | @OrmModel("users") 25 | class User extends Model { 26 | @NumberField() id!: number; 27 | 28 | @StringField() name!: string; 29 | 30 | @MorphOneField(Image, "imageable_id", "imageable_type") 31 | image!: Image; 32 | } 33 | 34 | new Store({ 35 | plugins: [ORMDatabase.install()], 36 | }); 37 | 38 | User.insert({ 39 | data: { 40 | id: 5, 41 | name: "John Doe", 42 | image: { 43 | id: 1, 44 | url: "http://example.com/user_image_1.png", 45 | imageable_id: 5, 46 | imageable_type: "users", 47 | }, 48 | }, 49 | }); 50 | 51 | const field = Image.getFields().imageable as MorphTo; 52 | 53 | expect(field).toBeInstanceOf(MorphTo); 54 | 55 | expect(field.id).toBe("imageable_id"); 56 | expect(field.type).toBe("imageable_type"); 57 | 58 | expect(Image.query().with("imageable").first()).toEqual({ 59 | $id: "1", 60 | id: 1, 61 | url: "http://example.com/user_image_1.png", 62 | imageable_id: 5, 63 | imageable_type: "users", 64 | imageable: { $id: "5", id: 5, name: "John Doe", image: null }, 65 | }); 66 | 67 | expect(Image.query().with("imageable").first()?.imageable).toBeInstanceOf(User); 68 | expect(Image.all()).toHaveLength(1); 69 | expect(User.all()).toHaveLength(1); 70 | }); 71 | }); 72 | -------------------------------------------------------------------------------- /test/unit/relationships/MorphToManyField.spec.ts: -------------------------------------------------------------------------------- 1 | import { describe, expect, it } from "vitest"; 2 | import { Model, MorphToMany } from "@vuex-orm/core"; 3 | import { MorphToManyField, NumberField, StringField } from "@/attributes"; 4 | import { ORMDatabase } from "@/database"; 5 | import { OrmModel } from "@/model"; 6 | import { Store } from "vuex"; 7 | 8 | describe("MorphToManyField", () => { 9 | it("can define the property as a `Morph To Many` relationship field", () => { 10 | @OrmModel("tags") 11 | class Tag extends Model { 12 | @NumberField() id!: number; 13 | 14 | @StringField() name!: string; 15 | } 16 | 17 | @OrmModel("taggables") 18 | class Taggable extends Model { 19 | @NumberField() id!: number; 20 | 21 | @NumberField() tag_id!: number; 22 | 23 | @NumberField() taggable_id!: number; 24 | 25 | @StringField() taggable_type!: string; 26 | } 27 | 28 | @OrmModel("posts") 29 | class Post extends Model { 30 | @NumberField() id!: number; 31 | 32 | @StringField() title!: string; 33 | 34 | @MorphToManyField(Tag, Taggable, "tag_id", "taggable_id", "taggable_type") 35 | tags!: Tag[]; 36 | } 37 | 38 | @OrmModel("videos") 39 | class Video extends Model { 40 | @NumberField() id!: number; 41 | 42 | @StringField() link!: string; 43 | 44 | @MorphToManyField(Tag, Taggable, "tag_id", "taggable_id", "taggable_type") 45 | tags!: Tag[]; 46 | } 47 | 48 | new Store({ 49 | plugins: [ORMDatabase.install()], 50 | }); 51 | 52 | Post.insert({ 53 | data: { 54 | id: 1, 55 | title: "Post title...", 56 | tags: [ 57 | { 58 | id: 1, 59 | tag_id: 1, 60 | taggable_id: 1, 61 | taggable_type: "posts", 62 | name: "typescript", 63 | }, 64 | { 65 | id: 2, 66 | tag_id: 2, 67 | taggable_id: 1, 68 | taggable_type: "posts", 69 | name: "javascript", 70 | }, 71 | ], 72 | }, 73 | }); 74 | 75 | Video.insert({ 76 | data: { 77 | id: 1, 78 | link: "http://example.com/video/something-nice", 79 | tags: [ 80 | { 81 | id: 1, 82 | tag_id: 1, 83 | taggable_id: 1, 84 | taggable_type: "videos", 85 | name: "typescript", 86 | }, 87 | { id: 3, tag_id: 3, taggable_id: 1, taggable_type: "videos", name: "php" }, 88 | ], 89 | }, 90 | }); 91 | 92 | [Post.getFields().tags as MorphToMany, Video.getFields().tags as MorphToMany].forEach( 93 | (field) => { 94 | expect(field).toBeInstanceOf(MorphToMany); 95 | 96 | expect(field.related).toBe(Tag); 97 | expect(field.pivot).toBe(Taggable); 98 | 99 | expect(field.relatedId).toBe("tag_id"); 100 | expect(field.id).toBe("taggable_id"); 101 | expect(field.type).toBe("taggable_type"); 102 | expect(field.parentKey).toBe("id"); 103 | expect(field.relatedKey).toBe("id"); 104 | } 105 | ); 106 | 107 | expect(Post.query().with("tags").first()?.tags).toEqual([ 108 | { 109 | $id: "1", 110 | id: 1, 111 | name: "typescript", 112 | pivot: { 113 | $id: "1_1_posts", 114 | id: 0, 115 | tag_id: 1, 116 | taggable_id: 1, 117 | taggable_type: "posts", 118 | }, 119 | }, 120 | { 121 | $id: "2", 122 | id: 2, 123 | name: "javascript", 124 | pivot: { 125 | $id: "1_2_posts", 126 | id: 0, 127 | tag_id: 2, 128 | taggable_id: 1, 129 | taggable_type: "posts", 130 | }, 131 | }, 132 | ]); 133 | 134 | expect(Video.query().with("tags").first()?.tags).toEqual([ 135 | { 136 | $id: "1", 137 | id: 1, 138 | name: "typescript", 139 | pivot: { 140 | $id: "1_1_videos", 141 | id: 0, 142 | tag_id: 1, 143 | taggable_id: 1, 144 | taggable_type: "videos", 145 | }, 146 | }, 147 | { 148 | $id: "3", 149 | id: 3, 150 | name: "php", 151 | pivot: { 152 | $id: "1_3_videos", 153 | id: 0, 154 | tag_id: 3, 155 | taggable_id: 1, 156 | taggable_type: "videos", 157 | }, 158 | }, 159 | ]); 160 | 161 | expect(Post.query().with("tags").first()?.tags[0]).toBeInstanceOf(Tag); 162 | expect(Video.query().with("tags").first()?.tags[0]).toBeInstanceOf(Tag); 163 | expect(Tag.all()).toHaveLength(3); 164 | expect(Taggable.all()).toHaveLength(4); 165 | expect(Post.all()).toHaveLength(1); 166 | expect(Video.all()).toHaveLength(1); 167 | }); 168 | }); 169 | -------------------------------------------------------------------------------- /test/unit/relationships/fixtures/Profile.ts: -------------------------------------------------------------------------------- 1 | import { BelongsToField, NumberField, StringField } from "@/attributes"; 2 | import { Model } from "@vuex-orm/core"; 3 | import { OrmModel } from "@/model"; 4 | import { User } from "test/unit/relationships/fixtures/User"; 5 | 6 | @OrmModel("profiles") 7 | export class Profile extends Model { 8 | @NumberField() id!: number; 9 | 10 | @NumberField() user_id!: number; 11 | 12 | @NumberField() age!: number; 13 | 14 | @StringField() sex!: string; 15 | 16 | @BelongsToField(User, "user_id") 17 | user!: User; 18 | } 19 | -------------------------------------------------------------------------------- /test/unit/relationships/fixtures/User.ts: -------------------------------------------------------------------------------- 1 | import { HasOneField, NumberField, StringField } from "@/attributes"; 2 | import { Model } from "@vuex-orm/core"; 3 | import { OrmModel } from "@/model"; 4 | import { Profile } from "test/unit/relationships/fixtures/Profile"; 5 | 6 | @OrmModel("users") 7 | export class User extends Model { 8 | @NumberField() id!: number; 9 | 10 | @StringField() name!: string; 11 | 12 | @HasOneField(Profile, "user_id") profile!: Profile; 13 | } 14 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "allowSyntheticDefaultImports": true, 4 | "baseUrl": ".", 5 | "declaration": true, 6 | "declarationDir": "dist/types", 7 | "esModuleInterop": true, 8 | "experimentalDecorators": true, 9 | "importHelpers": true, 10 | "module": "ESNext", 11 | "moduleResolution": "Node", 12 | "noImplicitAny": true, 13 | "noImplicitReturns": true, 14 | "noImplicitThis": true, 15 | "noUnusedLocals": true, 16 | "noUnusedParameters": true, 17 | "outDir": "dist", 18 | "removeComments": false, 19 | "rootDir": ".", 20 | "sourceMap": true, 21 | "sourceRoot": "src", 22 | "strict": true, 23 | "strictNullChecks": true, 24 | "target": "ES2015", 25 | "verbatimModuleSyntax": true, 26 | "lib": ["DOM", "ESNext"], 27 | "paths": { 28 | "@/*": ["src/*"], 29 | "test/*": ["test/*"] 30 | } 31 | }, 32 | "include": ["src", "test"], 33 | "exclude": ["node_modules", "test"] 34 | } 35 | -------------------------------------------------------------------------------- /vitest.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from "vitest/config"; 2 | import { resolve } from "path"; 3 | 4 | export default defineConfig({ 5 | test: { 6 | onConsoleLog: () => false, 7 | }, 8 | 9 | resolve: { 10 | alias: { 11 | "@": resolve(__dirname, "/src"), 12 | test: resolve(__dirname, "/test"), 13 | }, 14 | }, 15 | }); 16 | --------------------------------------------------------------------------------