diff --git a/README.md b/README.md index b99f6bc2..ea6d596a 100644 --- a/README.md +++ b/README.md @@ -8,6 +8,12 @@ Client side React SDK [Read the docs](packages/react-sdk/README.md) +## Vue SDK (beta) + +Client side Vue SDK + +[Read the docs](packages/vue-sdk/README.md) + ## Browser SDK Browser SDK for use in non-React web applications diff --git a/packages/eslint-config/base.js b/packages/eslint-config/base.js index 107ee2ac..af741e34 100644 --- a/packages/eslint-config/base.js +++ b/packages/eslint-config/base.js @@ -7,6 +7,7 @@ const globals = require("globals"); const tsPlugin = require("@typescript-eslint/eslint-plugin"); const tsParser = require("@typescript-eslint/parser"); const prettierConfig = require("eslint-config-prettier"); +const vuePlugin = require("eslint-plugin-vue"); module.exports = [ { @@ -22,6 +23,7 @@ module.exports = [ "**/*.jsx", "**/*.ts", "**/*.tsx", + "**/*.vue", ], plugins: { import: importsPlugin, @@ -104,6 +106,7 @@ module.exports = [ files: ["**/*.ts", "**/*.tsx"], plugins: { "@typescript-eslint": tsPlugin, + vue: vuePlugin, }, languageOptions: { parser: tsParser, @@ -154,6 +157,7 @@ module.exports = [ "**/*.jsx", "**/*.ts", "**/*.tsx", + "**/*.vue", ], rules: { ...prettierConfig.rules, diff --git a/packages/vue-sdk/.prettierignore b/packages/vue-sdk/.prettierignore new file mode 100644 index 00000000..5a0ae0bb --- /dev/null +++ b/packages/vue-sdk/.prettierignore @@ -0,0 +1,3 @@ +dist +eslint-report.json +dev diff --git a/packages/vue-sdk/README.md b/packages/vue-sdk/README.md new file mode 100644 index 00000000..4bdb409f --- /dev/null +++ b/packages/vue-sdk/README.md @@ -0,0 +1,395 @@ +# Bucket Vue SDK (beta) + +Vue client side library for [Bucket.co](https://bucket.co) + +Bucket supports feature toggling, tracking feature usage, requesting feedback on features and remotely configuring features. + +The Bucket Vue SDK comes with the same built-in toolbar as the browser SDK which appears on `localhost` by default. + +## Install + +Install via npm: + +```shell +npm i @bucketco/vue-sdk +``` + +## Get started + +### 1. Wrap your application with the `BucketProvider` + +```vue + + + + + +``` + +### 2. Use `useFeature(key)` to get feature status + +```vue + + + +``` + +## Setting `user` and `company` + +Bucket determines which features are active for a given `user`, `company`, or `otherContext`. +You pass these to the `BucketProvider` as props. + +If you supply `user` or `company` objects, they must include at least the `id` property otherwise they will be ignored in their entirety. +In addition to the `id`, you must also supply anything additional that you want to be able to evaluate feature targeting rules against. +Attributes which are not properties of the `user` or `company` can be supplied using the `otherContext` prop. + +Attributes cannot be nested (multiple levels) and must be either strings, numbers or booleans. +A number of special attributes exist: + +- `name` -- display name for `user`/`company`, +- `email` -- the email of the user, +- `avatar` -- the URL for `user`/`company` avatar image. + +```vue + +``` + +To retrieve features along with their targeting information, use `useFeature(key: string)` hook (described in a section below). + +Note that accessing `isEnabled` on the object returned by `useFeature()` automatically +generates a `check` event. + +## Remote config + +Remote config is a dynamic and flexible approach to configuring feature behavior outside of your app – without needing to re-deploy it. + +Similar to `isEnabled`, each feature accessed using the `useFeature()` hook, has a `config` property. This configuration is managed from within Bucket. It is managed similar to the way access to features is managed, but instead of the +binary `isEnabled` you can have multiple configuration values which are given to different user/companies. + +### Get started with Remote config + +```ts +const { + isEnabled, + config: { key, payload }, +} = useFeature("huddles"); + +// isEnabled: true, +// key: "gpt-3.5", +// payload: { maxTokens: 10000, model: "gpt-3.5-beta1" } +``` + +`key` is mandatory for a config, but if a feature has no config or no config value was matched against the context, the `key` will be `undefined`. Make sure to check against this case when trying to use the configuration in your application. `payload` is an optional JSON value for arbitrary configuration needs. + +Note that, similar to `isEnabled`, accessing `config` on the object returned by `useFeature()` automatically +generates a `check` event. + +## `` component + +The `` initializes the Bucket SDK, fetches features and starts listening for automated feedback survey events. The component can be configured using a number of props: + +- `publishableKey` is used to connect the provider to an _environment_ on Bucket. Find your `publishableKey` under [environment settings](https://app.bucket.co/envs/current/settings/app-environments) in Bucket, +- `company`, `user` and `otherContext` make up the _context_ that is used to determine if a feature is enabled or not. `company` and `user` contexts are automatically transmitted to Bucket servers so the Bucket app can show you which companies have access to which features etc. + > [!Note] + > If you specify `company` and/or `user` they must have at least the `id` property, otherwise they will be ignored in their entirety. You should also supply anything additional you want to be able to evaluate feature targeting against, +- `fallbackFeatures`: A list of strings which specify which features to consider enabled if the SDK is unable to fetch features. Can be provided in two formats: + + ```ts + // Simple array of feature keys + fallbackFeatures={["feature1", "feature2"]} + + // Or with configuration overrides + fallbackFeatures: { + "feature1": true, // just enable the feature + "feature2": { // enable with configuration + key: "variant-a", + payload: { + limit: 100, + mode: "test" + } + } + } + ``` + +- `timeoutMs`: Timeout in milliseconds when fetching features from the server, +- `staleWhileRevalidate`: If set to `true`, stale features will be returned while refetching features in the background, +- `expireTimeMs`: If set, features will be cached between page loads for this duration (in milliseconds), +- `staleTimeMs`: Maximum time (in milliseconds) that stale features will be returned if `staleWhileRevalidate` is true and new features cannot be fetched. + +- `enableTracking`: Set to `false` to stop sending tracking events and user/company updates to Bucket. Useful when you're impersonating a user (defaults to `true`), +- `apiBaseUrl`: Optional base URL for the Bucket API. Use this to override the default API endpoint, +- `appBaseUrl`: Optional base URL for the Bucket application. Use this to override the default app URL, +- `sseBaseUrl`: Optional base URL for Server-Sent Events. Use this to override the default SSE endpoint, +- `debug`: Set to `true` to enable debug logging to the console, +- `toolbar`: Optional [configuration](https://docs.bucket.co/supported-languages/browser-sdk/globals#toolbaroptions) for the Bucket toolbar, +- `feedback`: Optional configuration for feedback collection + +### Loading states + +BucketProvider lets you define a template to be shown while BucketProvider is inititalizing: + +```vue + +``` + +If you want more control over loading screens, `useIsLoading()` returns a Ref which you can use to customize the loading experience. + +## Hooks + +### `useFeature()` + +Returns the state of a given feature for the current context. The composable provides type-safe access to feature flags and their configurations. + +```vue + + + +``` + +### `useTrack()` + +`useTrack()` lets you send custom events to Bucket. Use this whenever a user _uses_ a feature. + +```vue + + + +``` + +### `useRequestFeedback()` + +Returns a function that lets you open up a dialog to ask for feedback on a specific feature. This is useful for collecting targeted feedback about specific features. + +See [Automated Feedback Surveys](https://docs.bucket.co/product-handbook/live-satisfaction) for how to do this automatically, without code. + +When using the `useRequestFeedback` you must pass the feature key to `requestFeedback`. +The example below shows how to use `position` to ensure the popover appears next to the "Give feedback!" button. + +```vue + + + +``` + +See the [Feedback Documentation](https://github.com/bucketco/bucket-javascript-sdk/blob/main/packages/browser-sdk/FEEDBACK.md#manual-feedback-collection) for more information on `requestFeedback` options. + +### `useSendFeedback()` + +Returns a function that lets you send feedback to Bucket. This is useful if you've manually collected feedback through your own UI and want to send it to Bucket. + +```vue + + + +``` + +### `useUpdateUser()`, `useUpdateCompany()` and `useUpdateOtherContext()` + +These composables return functions that let you update the attributes for the currently set user, company, or other context. Updates to user/company are stored remotely and affect feature targeting, while "other" context updates only affect the current session. + +```vue + + + +``` + +Note: To change the `user.id` or `company.id`, you need to update the props passed to `BucketProvider` instead of using these composables. + +### `useClient()` + +Returns the `BucketClient` used by the `BucketProvider`. The client offers more functionality that +is not directly accessible through the other composables. + +```vue + + + +``` + +### `useIsLoading()` + +Returns a `Ref` to indicate if Bucket has finished loading. + +## Content Security Policy (CSP) + +See [CSP](https://github.com/bucketco/bucket-javascript-sdk/blob/main/packages/browser-sdk/README.md#content-security-policy-csp) for info on using Bucket React SDK with CSP + +## License + +MIT License + +Copyright (c) 2025 Bucket ApS diff --git a/packages/vue-sdk/dev/plain/App.vue b/packages/vue-sdk/dev/plain/App.vue new file mode 100644 index 00000000..5210efad --- /dev/null +++ b/packages/vue-sdk/dev/plain/App.vue @@ -0,0 +1,37 @@ + + + diff --git a/packages/vue-sdk/dev/plain/components/MissingKeyMessage.vue b/packages/vue-sdk/dev/plain/components/MissingKeyMessage.vue new file mode 100644 index 00000000..96e9b429 --- /dev/null +++ b/packages/vue-sdk/dev/plain/components/MissingKeyMessage.vue @@ -0,0 +1,24 @@ + + + diff --git a/packages/vue-sdk/dev/plain/components/RequestFeedback.vue b/packages/vue-sdk/dev/plain/components/RequestFeedback.vue new file mode 100644 index 00000000..80b37c5b --- /dev/null +++ b/packages/vue-sdk/dev/plain/components/RequestFeedback.vue @@ -0,0 +1,58 @@ + + + diff --git a/packages/vue-sdk/dev/plain/components/Section.vue b/packages/vue-sdk/dev/plain/components/Section.vue new file mode 100644 index 00000000..d43bb00d --- /dev/null +++ b/packages/vue-sdk/dev/plain/components/Section.vue @@ -0,0 +1,22 @@ + + diff --git a/packages/vue-sdk/dev/plain/components/StartHuddleButton.vue b/packages/vue-sdk/dev/plain/components/StartHuddleButton.vue new file mode 100644 index 00000000..c1a0ce98 --- /dev/null +++ b/packages/vue-sdk/dev/plain/components/StartHuddleButton.vue @@ -0,0 +1,36 @@ + + diff --git a/packages/vue-sdk/dev/plain/components/Track.vue b/packages/vue-sdk/dev/plain/components/Track.vue new file mode 100644 index 00000000..5d7e46cb --- /dev/null +++ b/packages/vue-sdk/dev/plain/components/Track.vue @@ -0,0 +1,15 @@ + + + diff --git a/packages/vue-sdk/dev/plain/env.d.ts b/packages/vue-sdk/dev/plain/env.d.ts new file mode 100644 index 00000000..16e2e3d3 --- /dev/null +++ b/packages/vue-sdk/dev/plain/env.d.ts @@ -0,0 +1,9 @@ +/// + +interface ImportMetaEnv { + readonly VITE_PUBLISHABLE_KEY: string; +} + +interface ImportMeta { + readonly env: ImportMetaEnv; +} diff --git a/packages/vue-sdk/dev/plain/index.html b/packages/vue-sdk/dev/plain/index.html new file mode 100644 index 00000000..b7f608d0 --- /dev/null +++ b/packages/vue-sdk/dev/plain/index.html @@ -0,0 +1,14 @@ + + + + + + Bucket Vue SDK playground + + + +
+ + + + diff --git a/packages/vue-sdk/dev/plain/index.ts b/packages/vue-sdk/dev/plain/index.ts new file mode 100644 index 00000000..7b326841 --- /dev/null +++ b/packages/vue-sdk/dev/plain/index.ts @@ -0,0 +1,10 @@ +import { createApp } from "vue"; + +import App from "./App.vue"; + +const el = document.getElementById("app"); + +if (el) { + const app = createApp(App); + app.mount(el); +} diff --git a/packages/vue-sdk/eslint.config.js b/packages/vue-sdk/eslint.config.js new file mode 100644 index 00000000..97f9de87 --- /dev/null +++ b/packages/vue-sdk/eslint.config.js @@ -0,0 +1,54 @@ +const base = require("@bucketco/eslint-config"); +const importsPlugin = require("eslint-plugin-import"); +const vuePlugin = require("eslint-plugin-vue"); +const vueParser = require("vue-eslint-parser"); + +module.exports = [ + ...base, + { + ignores: ["dist/"], + }, + { + // Vue files + files: ["**/*.vue"], + plugins: { + vue: vuePlugin, + import: importsPlugin, + }, + languageOptions: { + parser: vueParser, + parserOptions: { + ecmaVersion: "latest", + sourceType: "module", + ecmaFeatures: { + jsx: true, + }, + parser: { + ts: require("@typescript-eslint/parser"), + }, + }, + }, + settings: { + "import/resolver": { + typescript: { + alwaysTryTypes: true, + project: "./tsconfig.eslint.json", + }, + }, + }, + rules: { + ...vuePlugin.configs.recommended.rules, + ...vuePlugin.configs["vue3-recommended"].rules, + + // Vue specific rules + "vue/multi-word-component-names": "off", + "vue/no-unused-vars": "warn", + "vue/require-default-prop": "off", + "vue/require-explicit-emits": "off", + "vue/no-v-html": "off", + + // Import rules for Vue files + "import/no-unresolved": "off", // Disable for now since we're using TypeScript resolver + }, + }, +]; diff --git a/packages/vue-sdk/package.json b/packages/vue-sdk/package.json new file mode 100644 index 00000000..f5fb6a66 --- /dev/null +++ b/packages/vue-sdk/package.json @@ -0,0 +1,65 @@ +{ + "name": "@bucketco/vue-sdk", + "version": "0.0.1", + "license": "MIT", + "repository": { + "type": "git", + "url": "https://github.com/bucketco/bucket-javascript-sdk.git" + }, + "publishConfig": { + "access": "public" + }, + "scripts": { + "dev": "vite", + "build": "tsc --project tsconfig.build.json && vite build", + "test": "vitest -c vite.config.mjs", + "test:ci": "vitest run -c vite.config.mjs --reporter=default --reporter=junit --outputFile=junit.xml", + "coverage": "vitest run --coverage", + "lint": "eslint .", + "lint:ci": "eslint --output-file eslint-report.json --format json .", + "prettier": "prettier --check .", + "format": "yarn lint --fix && yarn prettier --write", + "preversion": "yarn lint && yarn prettier && yarn vitest run -c vite.config.mjs && yarn build" + }, + "files": [ + "dist" + ], + "main": "./dist/bucket-vue-sdk.umd.js", + "types": "./dist/index.d.ts", + "exports": { + ".": { + "import": "./dist/bucket-vue-sdk.mjs", + "require": "./dist/bucket-vue-sdk.umd.js", + "types": "./dist/index.d.ts" + } + }, + "dependencies": { + "@bucketco/browser-sdk": "3.2.0", + "canonical-json": "^0.2.0" + }, + "peerDependencies": { + "vue": "^3.0.0" + }, + "devDependencies": { + "@bucketco/eslint-config": "workspace:^", + "@bucketco/tsconfig": "workspace:^", + "@types/jsdom": "^21.1.6", + "@types/node": "^22.12.0", + "@vitejs/plugin-vue": "^5.2.4", + "@vue/test-utils": "^2.3.2", + "eslint": "^9.21.0", + "eslint-plugin-vue": "^9.28.0", + "jsdom": "^24.1.0", + "msw": "^2.3.5", + "prettier": "^3.5.2", + "rollup": "^4.2.0", + "rollup-preserve-directives": "^1.1.2", + "ts-node": "^10.9.2", + "typescript": "^5.7.3", + "vite": "^5.0.13", + "vite-plugin-dts": "^4.5.4", + "vitest": "^2.0.4", + "vue": "^3.5.16", + "vue-eslint-parser": "^9.4.2" + } +} diff --git a/packages/vue-sdk/src/index.ts b/packages/vue-sdk/src/index.ts new file mode 100644 index 00000000..b8f83be4 --- /dev/null +++ b/packages/vue-sdk/src/index.ts @@ -0,0 +1,413 @@ +import canonicalJson from "canonical-json"; +import { + App, + defineComponent, + inject, + InjectionKey, + onBeforeUnmount, + provide, + Ref, + ref, + type SetupContext, + shallowRef, + watch, +} from "vue"; + +import { + BucketClient, + BucketContext, + CheckEvent, + CompanyContext, + InitOptions, + RawFeatures, + RequestFeedbackData, + TrackEvent, + UnassignedFeedback, + UserContext, +} from "@bucketco/browser-sdk"; + +import { version } from "../package.json"; + +export type { + CheckEvent, + CompanyContext, + RawFeatures, + TrackEvent, + UserContext, +}; + +export type EmptyFeatureRemoteConfig = { key: undefined; payload: undefined }; + +export type FeatureType = { + config?: { + payload: any; + }; +}; + +export type FeatureRemoteConfig = + | { + key: string; + payload: any; + } + | EmptyFeatureRemoteConfig; + +export interface Feature< + TConfig extends FeatureType["config"] = EmptyFeatureRemoteConfig, +> { + key: string; + isEnabled: Ref; + isLoading: Ref; + config: ({ key: string } & TConfig) | EmptyFeatureRemoteConfig; + track(): Promise | undefined; + requestFeedback: (opts: RequestFeedbackOptions) => void; +} + +// eslint-disable-next-line @typescript-eslint/no-empty-object-type +export interface Features {} + +export type TypedFeatures = keyof Features extends never + ? Record + : { + [TypedFeatureKey in keyof Features]: Features[TypedFeatureKey] extends FeatureType + ? Feature + : Feature; + }; + +export type FeatureKey = keyof TypedFeatures; + +const SDK_VERSION = `vue-sdk/${version}`; + +interface ProviderContextType { + client: Ref; + isLoading: Ref; + updatedCount: Ref; + provider: boolean; +} + +const ProviderSymbol: InjectionKey = + Symbol("BucketProvider"); + +export type BucketProps = BucketContext & + InitOptions & { + debug?: boolean; + newBucketClient?: ( + ...args: ConstructorParameters + ) => BucketClient; + }; + +export const BucketProvider = defineComponent({ + name: "BucketProvider", + props: { + publishableKey: { type: String, required: true }, + user: { type: Object as () => UserContext | undefined, default: undefined }, + company: { + type: Object as () => CompanyContext | undefined, + default: undefined, + }, + otherContext: { + type: Object as () => Record | undefined, + default: undefined, + }, + loadingComponent: { type: null as any, default: undefined }, + debug: { type: Boolean, default: false }, + newBucketClient: { + type: Function as unknown as () => BucketProps["newBucketClient"], + default: undefined, + }, + }, + setup(props: BucketProps, { slots }: SetupContext) { + const featuresLoading = ref(true); + const updatedCount = ref(0); + + function updateClient() { + const cnext = ( + props.newBucketClient ?? ((...args) => new BucketClient(...args)) + )({ + ...props, + logger: props.debug ? console : undefined, + sdkVersion: SDK_VERSION, + }); + featuresLoading.value = true; + cnext + .initialize() + .catch((e) => cnext.logger.error("failed to initialize client", e)) + .finally(() => { + featuresLoading.value = false; + }); + + return cnext; + } + + watch( + () => + canonicalJson( + // canonicalJson doesn't handle `undefined` values, so we stringify/parse to remove them + JSON.parse( + JSON.stringify({ + user: props.user, + company: props.company, + otherContext: props.otherContext, + }), + ), + ), + () => { + clientRef.value = updateClient(); + }, + ); + + const clientRef = shallowRef(updateClient()); + + const context = { + isLoading: featuresLoading, + updatedCount: updatedCount, + client: clientRef, + provider: true, + } satisfies ProviderContextType; + + provide(ProviderSymbol, context); + + return () => + featuresLoading.value && typeof slots.loading !== "undefined" + ? slots.loading() + : slots.default?.(); + }, +}); + +export type RequestFeedbackOptions = Omit< + RequestFeedbackData, + "featureKey" | "featureId" +>; + +export function useFeature(key: TKey) { + const client = useClient(); + const ctx = injectSafe(); + + const track = () => client?.value.track(key); + const requestFeedback = (opts: RequestFeedbackOptions) => + client.value.requestFeedback({ ...opts, featureKey: key }); + + function getFeature() { + const f = client.value.getFeature(key); + return { + isEnabled: f.isEnabled, + config: f.config, + track, + requestFeedback, + key, + isLoading: ctx.isLoading, + }; + } + + const feature = ref(getFeature()); + + function updateFeature() { + feature.value = getFeature(); + } + + client.value.on("featuresUpdated", updateFeature); + onBeforeUnmount(() => { + client.value.off("featuresUpdated", updateFeature); + }); + + return feature; +} + +/** + * Vue composable for tracking custom events. + * + * This composable returns a function that can be used to track custom events + * with the Bucket SDK. + * + * @example + * ```ts + * import { useTrack } from '@bucketco/vue-sdk'; + * + * const track = useTrack(); + * + * // Track a custom event + * track('button_clicked', { buttonName: 'Start Huddle' }); + * ``` + * + * @returns A function that tracks an event. The function accepts: + * - `eventName`: The name of the event to track. + * - `attributes`: (Optional) Additional attributes to associate with the event. + */ +export function useTrack() { + const client = useClient(); + return (eventName: string, attributes?: Record | null) => + client?.value.track(eventName, attributes); +} + +/** + * Vue composable for requesting user feedback. + * + * This composable returns a function that can be used to trigger the feedback + * collection flow with the Bucket SDK. You can use this to prompt users for + * feedback at any point in your application. + * + * @example + * ```ts + * import { useRequestFeedback } from '@bucketco/vue-sdk'; + * + * const requestFeedback = useRequestFeedback(); + * + * // Request feedback from the user + * requestFeedback({ + * prompt: "How was your experience?", + * metadata: { page: "dashboard" } + * }); + * ``` + * + * @returns A function that requests feedback from the user. The function accepts: + * - `options`: An object containing feedback request options. + */ +export function useRequestFeedback() { + const client = useClient(); + return (options: RequestFeedbackData) => + client?.value.requestFeedback(options); +} + +/** + * Vue composable for sending feedback. + * + * This composable returns a function that can be used to send feedback to the + * Bucket SDK. You can use this to send feedback from your application. + * + * @example + * ```ts + * import { useSendFeedback } from '@bucketco/vue-sdk'; + * + * const sendFeedback = useSendFeedback(); + * + * // Send feedback from the user + * sendFeedback({ + * feedback: "I love this feature!", + * metadata: { page: "dashboard" } + * }); + * ``` + * + * @returns A function that sends feedback to the Bucket SDK. The function accepts: + * - `options`: An object containing feedback options. + */ +export function useSendFeedback() { + const client = useClient(); + return (opts: UnassignedFeedback) => client?.value.feedback(opts); +} + +/** + * Vue composable for updating the user context. + * + * This composable returns a function that can be used to update the user context + * with the Bucket SDK. You can use this to update the user context at any point + * in your application. + * + * @example + * ```ts + * import { useUpdateUser } from '@bucketco/vue-sdk'; + * + * const updateUser = useUpdateUser(); + * + * // Update the user context + * updateUser({ id: "123", name: "John Doe" }); + * ``` + * + * @returns A function that updates the user context. The function accepts: + * - `opts`: An object containing the user context to update. + */ +export function useUpdateUser() { + const client = useClient(); + return (opts: { [key: string]: string | number | undefined }) => + client?.value.updateUser(opts); +} + +/** + * Vue composable for updating the company context. + * + * This composable returns a function that can be used to update the company + * context with the Bucket SDK. You can use this to update the company context + * at any point in your application. + * + * @example + * ```ts + * import { useUpdateCompany } from '@bucketco/vue-sdk'; + * + * const updateCompany = useUpdateCompany(); + * + * // Update the company context + * updateCompany({ id: "123", name: "Acme Inc." }); + * ``` + * + * @returns A function that updates the company context. The function accepts: + * - `opts`: An object containing the company context to update. + */ +export function useUpdateCompany() { + const client = useClient(); + return (opts: { [key: string]: string | number | undefined }) => + client?.value.updateCompany(opts); +} + +/** + * Vue composable for updating the other context. + * + * This composable returns a function that can be used to update the other + * context with the Bucket SDK. You can use this to update the other context + * at any point in your application. + * + * @example + * ```ts + * import { useUpdateOtherContext } from '@bucketco/vue-sdk'; + * + * const updateOtherContext = useUpdateOtherContext(); + * + * // Update the other context + * updateOtherContext({ id: "123", name: "Acme Inc." }); + * ``` + * + * @returns A function that updates the other context. The function accepts: + * - `opts`: An object containing the other context to update. + */ +export function useUpdateOtherContext() { + const client = useClient(); + return (opts: { [key: string]: string | number | undefined }) => + client?.value.updateOtherContext(opts); +} + +/** + * Vue composable for getting the Bucket client. + * + * This composable returns the Bucket client. You can use this to get the Bucket + * client at any point in your application. + * + * @returns The Bucket client. + */ +export function useClient() { + const ctx = injectSafe(); + return ctx.client; +} + +/** + * Vue composable for checking if the Bucket client is loading. + * + * This composable returns a boolean value that indicates whether the Bucket client is loading. + * You can use this to check if the Bucket client is loading at any point in your application. + */ +export function useIsLoading() { + const ctx = injectSafe(); + return ctx.isLoading; +} + +function injectSafe() { + const ctx = inject(ProviderSymbol); + if (!ctx?.provider) { + throw new Error( + `BucketProvider is missing. Please ensure your component is wrapped with a BucketProvider.`, + ); + } + return ctx; +} + +export default { + install(app: App, _options?: BucketProps) { + app.component("BucketProvider", BucketProvider); + }, +}; diff --git a/packages/vue-sdk/src/types.d.ts b/packages/vue-sdk/src/types.d.ts new file mode 100644 index 00000000..59f438a8 --- /dev/null +++ b/packages/vue-sdk/src/types.d.ts @@ -0,0 +1 @@ +declare module "canonical-json"; diff --git a/packages/vue-sdk/test/usage.test.ts b/packages/vue-sdk/test/usage.test.ts new file mode 100644 index 00000000..5907b5f9 --- /dev/null +++ b/packages/vue-sdk/test/usage.test.ts @@ -0,0 +1,52 @@ +import { mount } from "@vue/test-utils"; +import { describe, expect, test, vi } from "vitest"; +import { defineComponent, h, nextTick } from "vue"; + +import { BucketProvider, useClient } from "../src"; + +const fakeClient = { + initialize: vi.fn().mockResolvedValue(undefined), + stop: vi.fn(), + on: vi.fn(), +}; + +function getProvider() { + return { + props: { + publishableKey: "key", + newBucketClient: () => fakeClient, + }, + }; +} + +describe("BucketProvider", () => { + test("provides the client", async () => { + const Child = defineComponent({ + setup() { + const client = useClient(); + return { client }; + }, + template: "
", + }); + + const wrapper = mount(BucketProvider, { + ...getProvider(), + slots: { default: () => h(Child) }, + }); + + await nextTick(); + expect(wrapper.findComponent(Child).vm.client).toStrictEqual(fakeClient); + }); + + test("throws without provider", () => { + const Comp = defineComponent({ + setup() { + return () => { + useClient(); + }; + }, + }); + + expect(() => mount(Comp)).toThrow(); + }); +}); diff --git a/packages/vue-sdk/tsconfig.build.json b/packages/vue-sdk/tsconfig.build.json new file mode 100644 index 00000000..b90fc83e --- /dev/null +++ b/packages/vue-sdk/tsconfig.build.json @@ -0,0 +1,4 @@ +{ + "extends": "./tsconfig.json", + "include": ["src"] +} diff --git a/packages/vue-sdk/tsconfig.eslint.json b/packages/vue-sdk/tsconfig.eslint.json new file mode 100644 index 00000000..fc6f6fd3 --- /dev/null +++ b/packages/vue-sdk/tsconfig.eslint.json @@ -0,0 +1,4 @@ +{ + "extends": "./tsconfig.json", + "include": ["./src", "./test", "./dev", "./*.ts"] +} diff --git a/packages/vue-sdk/tsconfig.json b/packages/vue-sdk/tsconfig.json new file mode 100644 index 00000000..464bdb25 --- /dev/null +++ b/packages/vue-sdk/tsconfig.json @@ -0,0 +1,11 @@ +{ + "extends": "@bucketco/tsconfig/library", + "compilerOptions": { + "lib": [], + "outDir": "./dist/", + "declarationDir": "./dist/types", + "declarationMap": true + }, + "include": ["src"], + "typeRoots": ["./node_modules/@types"] +} diff --git a/packages/vue-sdk/typedoc.json b/packages/vue-sdk/typedoc.json new file mode 100644 index 00000000..ca164def --- /dev/null +++ b/packages/vue-sdk/typedoc.json @@ -0,0 +1,4 @@ +{ + "tsconfig": "tsconfig.build.json", + "entryPoints": ["src/index.ts"] +} diff --git a/packages/vue-sdk/vite.config.mjs b/packages/vue-sdk/vite.config.mjs new file mode 100644 index 00000000..14d44f69 --- /dev/null +++ b/packages/vue-sdk/vite.config.mjs @@ -0,0 +1,45 @@ +import { resolve } from "path"; +import vue from "@vitejs/plugin-vue"; +import preserveDirectives from "rollup-preserve-directives"; +import { defineConfig } from "vite"; +import dts from "vite-plugin-dts"; + +export default defineConfig({ + test: { + environment: "jsdom", + }, + optimizeDeps: { + include: ["@bucketco/browser-sdk"], + }, + resolve: { + alias: { + vue: "vue/dist/vue.esm-bundler.js", + }, + }, + plugins: [ + vue(), + dts({ insertTypesEntry: true, exclude: ["dev"] }), + preserveDirectives(), + ], + build: { + exclude: ["**/node_modules/**", "test/e2e/**", "dev"], + sourcemap: true, + lib: { + entry: resolve(__dirname, "src/index.ts"), + name: "BucketVueSDK", + fileName: "bucket-vue-sdk", + formats: ["es", "umd"], + }, + rollupOptions: { + external: ["vue"], + output: { + globals: { + vue: "Vue", + }, + }, + }, + }, + server: { + open: "/dev/plain/index.html", + }, +}); diff --git a/vitest.workspace.js b/vitest.workspace.js index 8bc5a4eb..aa4e89e8 100644 --- a/vitest.workspace.js +++ b/vitest.workspace.js @@ -6,5 +6,6 @@ export default defineWorkspace([ "./packages/openfeature-node-provider/vite.config.js", "./packages/node-sdk/vite.config.js", "./packages/react-sdk/vite.config.mjs", + "./packages/vue-sdk/vite.config.mjs", "./packages/cli/vite.config.js", ]); diff --git a/yarn.lock b/yarn.lock index 6f542f57..4d14bc76 100644 --- a/yarn.lock +++ b/yarn.lock @@ -893,6 +893,37 @@ __metadata: languageName: unknown linkType: soft +"@bucketco/vue-sdk@workspace:packages/vue-sdk": + version: 0.0.0-use.local + resolution: "@bucketco/vue-sdk@workspace:packages/vue-sdk" + dependencies: + "@bucketco/browser-sdk": "npm:3.2.0" + "@bucketco/eslint-config": "workspace:^" + "@bucketco/tsconfig": "workspace:^" + "@types/jsdom": "npm:^21.1.6" + "@types/node": "npm:^22.12.0" + "@vitejs/plugin-vue": "npm:^5.2.4" + "@vue/test-utils": "npm:^2.3.2" + canonical-json: "npm:^0.2.0" + eslint: "npm:^9.21.0" + eslint-plugin-vue: "npm:^9.28.0" + jsdom: "npm:^24.1.0" + msw: "npm:^2.3.5" + prettier: "npm:^3.5.2" + rollup: "npm:^4.2.0" + rollup-preserve-directives: "npm:^1.1.2" + ts-node: "npm:^10.9.2" + typescript: "npm:^5.7.3" + vite: "npm:^5.0.13" + vite-plugin-dts: "npm:^4.5.4" + vitest: "npm:^2.0.4" + vue: "npm:^3.5.16" + vue-eslint-parser: "npm:^9.4.2" + peerDependencies: + vue: ^3.0.0 + languageName: unknown + linkType: soft + "@bundled-es-modules/cookie@npm:^2.0.0": version: 2.0.0 resolution: "@bundled-es-modules/cookie@npm:2.0.0" @@ -2341,6 +2372,17 @@ __metadata: languageName: node linkType: hard +"@microsoft/api-extractor-model@npm:7.30.6": + version: 7.30.6 + resolution: "@microsoft/api-extractor-model@npm:7.30.6" + dependencies: + "@microsoft/tsdoc": "npm:~0.15.1" + "@microsoft/tsdoc-config": "npm:~0.17.1" + "@rushstack/node-core-library": "npm:5.13.1" + checksum: 10c0/a2f6d01302f9e97e3100eb338e66ea2efd63742f81863cf69b616dbd2804ac47a1f988b6e5b8e2a836fb9f0be39eba3972d68c3654bfadd54339efb56d1c0643 + languageName: node + linkType: hard + "@microsoft/api-extractor@npm:7.43.0": version: 7.43.0 resolution: "@microsoft/api-extractor@npm:7.43.0" @@ -2387,6 +2429,29 @@ __metadata: languageName: node linkType: hard +"@microsoft/api-extractor@npm:^7.50.1": + version: 7.52.8 + resolution: "@microsoft/api-extractor@npm:7.52.8" + dependencies: + "@microsoft/api-extractor-model": "npm:7.30.6" + "@microsoft/tsdoc": "npm:~0.15.1" + "@microsoft/tsdoc-config": "npm:~0.17.1" + "@rushstack/node-core-library": "npm:5.13.1" + "@rushstack/rig-package": "npm:0.5.3" + "@rushstack/terminal": "npm:0.15.3" + "@rushstack/ts-command-line": "npm:5.0.1" + lodash: "npm:~4.17.15" + minimatch: "npm:~3.0.3" + resolve: "npm:~1.22.1" + semver: "npm:~7.5.4" + source-map: "npm:~0.6.1" + typescript: "npm:5.8.2" + bin: + api-extractor: bin/api-extractor + checksum: 10c0/42f4335ebf27c7fa819a858378062d774e130dda109f001825d49fd284430c62ea9eb703a8c49a9dd8e3a607bbf19ba4457548353282673e7429e0e6d01b325b + languageName: node + linkType: hard + "@microsoft/tsdoc-config@npm:~0.16.1": version: 0.16.2 resolution: "@microsoft/tsdoc-config@npm:0.16.2" @@ -2411,6 +2476,18 @@ __metadata: languageName: node linkType: hard +"@microsoft/tsdoc-config@npm:~0.17.1": + version: 0.17.1 + resolution: "@microsoft/tsdoc-config@npm:0.17.1" + dependencies: + "@microsoft/tsdoc": "npm:0.15.1" + ajv: "npm:~8.12.0" + jju: "npm:~1.4.0" + resolve: "npm:~1.22.2" + checksum: 10c0/a686355796f492f27af17e2a17d615221309caf4d9f9047a5a8f17f8625c467c4c81e2a7923ddafd71b892631d5e5013c4b8cc49c5867d3cc1d260fd90c1413d + languageName: node + linkType: hard + "@microsoft/tsdoc@npm:0.14.2": version: 0.14.2 resolution: "@microsoft/tsdoc@npm:0.14.2" @@ -2425,6 +2502,13 @@ __metadata: languageName: node linkType: hard +"@microsoft/tsdoc@npm:0.15.1, @microsoft/tsdoc@npm:~0.15.1": + version: 0.15.1 + resolution: "@microsoft/tsdoc@npm:0.15.1" + checksum: 10c0/09948691fac56c45a0d1920de478d66a30371a325bd81addc92eea5654d95106ce173c440fea1a1bd5bb95b3a544b6d4def7bb0b5a846c05d043575d8369a20c + languageName: node + linkType: hard + "@mswjs/interceptors@npm:^0.29.0": version: 0.29.1 resolution: "@mswjs/interceptors@npm:0.29.1" @@ -2951,6 +3035,13 @@ __metadata: languageName: node linkType: hard +"@one-ini/wasm@npm:0.1.1": + version: 0.1.1 + resolution: "@one-ini/wasm@npm:0.1.1" + checksum: 10c0/54700e055037f1a63bfcc86d24822203b25759598c2c3e295d1435130a449108aebc119c9c2e467744767dbe0b6ab47a182c61aa1071ba7368f5e20ab197ba65 + languageName: node + linkType: hard + "@open-draft/deferred-promise@npm:^2.2.0": version: 2.2.0 resolution: "@open-draft/deferred-promise@npm:2.2.0" @@ -3060,6 +3151,22 @@ __metadata: languageName: node linkType: hard +"@rollup/pluginutils@npm:^5.1.4": + version: 5.2.0 + resolution: "@rollup/pluginutils@npm:5.2.0" + dependencies: + "@types/estree": "npm:^1.0.0" + estree-walker: "npm:^2.0.2" + picomatch: "npm:^4.0.2" + peerDependencies: + rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0 + peerDependenciesMeta: + rollup: + optional: true + checksum: 10c0/794890d512751451bcc06aa112366ef47ea8f9125dac49b1abf72ff8b079518b09359de9c60a013b33266541634e765ae61839c749fae0edb59a463418665c55 + languageName: node + linkType: hard + "@rollup/rollup-android-arm-eabi@npm:4.21.3": version: 4.21.3 resolution: "@rollup/rollup-android-arm-eabi@npm:4.21.3" @@ -3478,6 +3585,27 @@ __metadata: languageName: node linkType: hard +"@rushstack/node-core-library@npm:5.13.1": + version: 5.13.1 + resolution: "@rushstack/node-core-library@npm:5.13.1" + dependencies: + ajv: "npm:~8.13.0" + ajv-draft-04: "npm:~1.0.0" + ajv-formats: "npm:~3.0.1" + fs-extra: "npm:~11.3.0" + import-lazy: "npm:~4.0.0" + jju: "npm:~1.4.0" + resolve: "npm:~1.22.1" + semver: "npm:~7.5.4" + peerDependencies: + "@types/node": "*" + peerDependenciesMeta: + "@types/node": + optional: true + checksum: 10c0/e3d31c876390040235e0aae9e458a6b7214cb4385fd743adb49b8408911e7d662761d745276d4ff10c09a9b47b55a3a01690c4800f4b775d82b7c991b3de25d2 + languageName: node + linkType: hard + "@rushstack/node-core-library@npm:5.5.0": version: 5.5.0 resolution: "@rushstack/node-core-library@npm:5.5.0" @@ -3509,6 +3637,16 @@ __metadata: languageName: node linkType: hard +"@rushstack/rig-package@npm:0.5.3": + version: 0.5.3 + resolution: "@rushstack/rig-package@npm:0.5.3" + dependencies: + resolve: "npm:~1.22.1" + strip-json-comments: "npm:~3.1.1" + checksum: 10c0/ef0b0115b60007f965b875f671019ac7fc26592f6bf7d7b40fa8c68e8dc37e9f7dcda3b5533b489ebf04d28a182dc60987bfd365a8d4173c73d482b270647741 + languageName: node + linkType: hard + "@rushstack/terminal@npm:0.10.0": version: 0.10.0 resolution: "@rushstack/terminal@npm:0.10.0" @@ -3539,6 +3677,21 @@ __metadata: languageName: node linkType: hard +"@rushstack/terminal@npm:0.15.3": + version: 0.15.3 + resolution: "@rushstack/terminal@npm:0.15.3" + dependencies: + "@rushstack/node-core-library": "npm:5.13.1" + supports-color: "npm:~8.1.1" + peerDependencies: + "@types/node": "*" + peerDependenciesMeta: + "@types/node": + optional: true + checksum: 10c0/3e8be5168aea2224261fce071808948d63790fa9d9fb2dfb2a659e616b4b9ce513ebc4cf211d528322987b75fc83482e8e0a7c1e262077e271ef887a5b56f5aa + languageName: node + linkType: hard + "@rushstack/ts-command-line@npm:4.19.1": version: 4.19.1 resolution: "@rushstack/ts-command-line@npm:4.19.1" @@ -3563,6 +3716,18 @@ __metadata: languageName: node linkType: hard +"@rushstack/ts-command-line@npm:5.0.1": + version: 5.0.1 + resolution: "@rushstack/ts-command-line@npm:5.0.1" + dependencies: + "@rushstack/terminal": "npm:0.15.3" + "@types/argparse": "npm:1.0.38" + argparse: "npm:~1.0.9" + string-argv: "npm:~0.3.1" + checksum: 10c0/9f4ffe63d5eaa9bda2b026c68e62a99f6c1d6d8ad3cc7a4247d6cd90f2fdf038ca9e950911f8035f9cb408a54abcd049ba5435206f63f98fb8df484488debd83 + languageName: node + linkType: hard + "@shikijs/engine-oniguruma@npm:^1.24.2": version: 1.24.2 resolution: "@shikijs/engine-oniguruma@npm:1.24.2" @@ -4327,6 +4492,16 @@ __metadata: languageName: node linkType: hard +"@vitejs/plugin-vue@npm:^5.2.4": + version: 5.2.4 + resolution: "@vitejs/plugin-vue@npm:5.2.4" + peerDependencies: + vite: ^5.0.0 || ^6.0.0 + vue: ^3.2.25 + checksum: 10c0/9559224f178daf35e3a665410d09089b0ce7c0402981f8757481c24c22f29df377f96cc6161d92f74d16c37c6e32ac19fea99086f75338ad6ceb9b5ee8375509 + languageName: node + linkType: hard + "@vitest/coverage-v8@npm:^2.0.4": version: 2.1.9 resolution: "@vitest/coverage-v8@npm:2.1.9" @@ -4622,6 +4797,15 @@ __metadata: languageName: node linkType: hard +"@volar/language-core@npm:2.4.14, @volar/language-core@npm:~2.4.11": + version: 2.4.14 + resolution: "@volar/language-core@npm:2.4.14" + dependencies: + "@volar/source-map": "npm:2.4.14" + checksum: 10c0/ac375e88cf7bad7eb94eb48750eeb37a237378c5ebafd8c0ea764c39fee2a69d9195468c19fbbeeeaa4a205b966e83f732004ab52df1d72206c30dcea2a1b623 + languageName: node + linkType: hard + "@volar/source-map@npm:1.11.1, @volar/source-map@npm:~1.11.1": version: 1.11.1 resolution: "@volar/source-map@npm:1.11.1" @@ -4647,6 +4831,13 @@ __metadata: languageName: node linkType: hard +"@volar/source-map@npm:2.4.14": + version: 2.4.14 + resolution: "@volar/source-map@npm:2.4.14" + checksum: 10c0/b8c0c83e5796b92a5087749e4db5d894edf61775c3912f4bd0bbe45a237441a78e1502e433d3cb25feef1c63f01e7a5d51ea417dfb6b352b3e898f707c64c972 + languageName: node + linkType: hard + "@volar/typescript@npm:^2.3.4": version: 2.3.4 resolution: "@volar/typescript@npm:2.3.4" @@ -4658,6 +4849,17 @@ __metadata: languageName: node linkType: hard +"@volar/typescript@npm:^2.4.11": + version: 2.4.14 + resolution: "@volar/typescript@npm:2.4.14" + dependencies: + "@volar/language-core": "npm:2.4.14" + path-browserify: "npm:^1.0.1" + vscode-uri: "npm:^3.0.8" + checksum: 10c0/bdbe2375cc99b1acfc29c718c30240b888a41cf32b413a24425ea666552d65fec32de20dda14c522e2ec626dcaf2f6f55ba1c9dc1d2c5a5727fe7e2ea87857d3 + languageName: node + linkType: hard + "@volar/typescript@npm:~1.11.1": version: 1.11.1 resolution: "@volar/typescript@npm:1.11.1" @@ -4703,6 +4905,29 @@ __metadata: languageName: node linkType: hard +"@vue/compiler-core@npm:3.5.16": + version: 3.5.16 + resolution: "@vue/compiler-core@npm:3.5.16" + dependencies: + "@babel/parser": "npm:^7.27.2" + "@vue/shared": "npm:3.5.16" + entities: "npm:^4.5.0" + estree-walker: "npm:^2.0.2" + source-map-js: "npm:^1.2.1" + checksum: 10c0/1a6f1446320467eac382c9ee567bd6017a61d374eebe48cbf948badb13e14beb0f96645e2cb8c4bfff565aa4948f1d836352bea511e5f3322c51cc5921caf42a + languageName: node + linkType: hard + +"@vue/compiler-dom@npm:3.5.16, @vue/compiler-dom@npm:^3.5.0": + version: 3.5.16 + resolution: "@vue/compiler-dom@npm:3.5.16" + dependencies: + "@vue/compiler-core": "npm:3.5.16" + "@vue/shared": "npm:3.5.16" + checksum: 10c0/e3ed5b50977cbb240abc2b8a71497254810e433a2e4a5eb254900c46abc6494b99df7e69ae79d7122c29c2e1cc4605c5b4925bf280e83e4f918098194b2894cf + languageName: node + linkType: hard + "@vue/compiler-dom@npm:^3.3.0": version: 3.3.4 resolution: "@vue/compiler-dom@npm:3.3.4" @@ -4723,6 +4948,43 @@ __metadata: languageName: node linkType: hard +"@vue/compiler-sfc@npm:3.5.16": + version: 3.5.16 + resolution: "@vue/compiler-sfc@npm:3.5.16" + dependencies: + "@babel/parser": "npm:^7.27.2" + "@vue/compiler-core": "npm:3.5.16" + "@vue/compiler-dom": "npm:3.5.16" + "@vue/compiler-ssr": "npm:3.5.16" + "@vue/shared": "npm:3.5.16" + estree-walker: "npm:^2.0.2" + magic-string: "npm:^0.30.17" + postcss: "npm:^8.5.3" + source-map-js: "npm:^1.2.1" + checksum: 10c0/b9614aadde2c85f87fac3ee6f6b31209cec294c9b7c7aeb23d0dc92bdb7a0ee7ec6dc6d11f2bbc7403c19b4eb8df5d3dc9ae915e8cd74d77c50024608cabc02b + languageName: node + linkType: hard + +"@vue/compiler-ssr@npm:3.5.16": + version: 3.5.16 + resolution: "@vue/compiler-ssr@npm:3.5.16" + dependencies: + "@vue/compiler-dom": "npm:3.5.16" + "@vue/shared": "npm:3.5.16" + checksum: 10c0/e2f0e652981ded459f7bf1c9821d34332207e01b43db819281f632bdc0e7b8518c485019e65e010724f86acf520c715ae4b35cb717d2c0ad0f7cfacf83933df6 + languageName: node + linkType: hard + +"@vue/compiler-vue2@npm:^2.7.16": + version: 2.7.16 + resolution: "@vue/compiler-vue2@npm:2.7.16" + dependencies: + de-indent: "npm:^1.0.2" + he: "npm:^1.2.0" + checksum: 10c0/c76c3fad770b9a7da40b314116cc9da173da20e5fd68785c8ed8dd8a87d02f239545fa296e16552e040ec86b47bfb18283b39447b250c2e76e479bd6ae475bb3 + languageName: node + linkType: hard + "@vue/language-core@npm:1.8.27, @vue/language-core@npm:^1.8.27": version: 1.8.27 resolution: "@vue/language-core@npm:1.8.27" @@ -4765,6 +5027,70 @@ __metadata: languageName: node linkType: hard +"@vue/language-core@npm:2.2.0": + version: 2.2.0 + resolution: "@vue/language-core@npm:2.2.0" + dependencies: + "@volar/language-core": "npm:~2.4.11" + "@vue/compiler-dom": "npm:^3.5.0" + "@vue/compiler-vue2": "npm:^2.7.16" + "@vue/shared": "npm:^3.5.0" + alien-signals: "npm:^0.4.9" + minimatch: "npm:^9.0.3" + muggle-string: "npm:^0.4.1" + path-browserify: "npm:^1.0.1" + peerDependencies: + typescript: "*" + peerDependenciesMeta: + typescript: + optional: true + checksum: 10c0/1c44cc4067266bbc825af358a867aed455963a08c160cd9df9a47571fd917a87d9de9bdea6149877e0c8309a6cf39f263e7cf2fbadeceba47a5a158f392151b2 + languageName: node + linkType: hard + +"@vue/reactivity@npm:3.5.16": + version: 3.5.16 + resolution: "@vue/reactivity@npm:3.5.16" + dependencies: + "@vue/shared": "npm:3.5.16" + checksum: 10c0/88e8ff0b62518dac6db5adf7b130ec7e389ef5133c861223aa7ec89d310ee4fbc4cde42a53873187d98a8a113c507e41c366c3a3249c6714dfb5d1b47d409402 + languageName: node + linkType: hard + +"@vue/runtime-core@npm:3.5.16": + version: 3.5.16 + resolution: "@vue/runtime-core@npm:3.5.16" + dependencies: + "@vue/reactivity": "npm:3.5.16" + "@vue/shared": "npm:3.5.16" + checksum: 10c0/8695a37049020a789b77c3ada3f4bb595b1149644d8c98e42c37889c863fa4bad5a2c8afa105ce1adf767d0e5f7e7869def7a9864dc18bce1c79877f3006246a + languageName: node + linkType: hard + +"@vue/runtime-dom@npm:3.5.16": + version: 3.5.16 + resolution: "@vue/runtime-dom@npm:3.5.16" + dependencies: + "@vue/reactivity": "npm:3.5.16" + "@vue/runtime-core": "npm:3.5.16" + "@vue/shared": "npm:3.5.16" + csstype: "npm:^3.1.3" + checksum: 10c0/3e18a6c80b51fde47efa65b8da4cd3876ac49a295bf8e2f26755db97fde413248d72697e288085e90f882c9e14731f6aa0eb2b8f85e7e169e4cfe519c2df4e76 + languageName: node + linkType: hard + +"@vue/server-renderer@npm:3.5.16": + version: 3.5.16 + resolution: "@vue/server-renderer@npm:3.5.16" + dependencies: + "@vue/compiler-ssr": "npm:3.5.16" + "@vue/shared": "npm:3.5.16" + peerDependencies: + vue: 3.5.16 + checksum: 10c0/c6adccf54caf8bac495cf53cd41ae804eeee8257b5f30c611ff5bcb7741c2488b7c9126fe5857b93753742cba62be43fbe8db1be155b8f3f90b256d2f7a39236 + languageName: node + linkType: hard + "@vue/shared@npm:3.3.4, @vue/shared@npm:^3.3.0": version: 3.3.4 resolution: "@vue/shared@npm:3.3.4" @@ -4779,6 +5105,23 @@ __metadata: languageName: node linkType: hard +"@vue/shared@npm:3.5.16, @vue/shared@npm:^3.5.0": + version: 3.5.16 + resolution: "@vue/shared@npm:3.5.16" + checksum: 10c0/242ecc41f4c4e8f7f5d8714d715f4a78e31ead988da47cb369b88bd2f53aacc0f1db8c15dfac726e2a3ebe1104689bddd65c5c349ca5097e6657b2af2098c2f7 + languageName: node + linkType: hard + +"@vue/test-utils@npm:^2.3.2": + version: 2.4.6 + resolution: "@vue/test-utils@npm:2.4.6" + dependencies: + js-beautify: "npm:^1.14.9" + vue-component-type-helpers: "npm:^2.0.0" + checksum: 10c0/37fa46cb6b98f90affb2faf5aa41422617bbd23ff35bc714d08035334e593ae31d18757d5ae688f778dd8b4c28de431601c0b9b7ca17fc1b55f1401a5577375e + languageName: node + linkType: hard + "@webassemblyjs/ast@npm:1.12.1, @webassemblyjs/ast@npm:^1.12.1": version: 1.12.1 resolution: "@webassemblyjs/ast@npm:1.12.1" @@ -5249,6 +5592,13 @@ __metadata: languageName: node linkType: hard +"alien-signals@npm:^0.4.9": + version: 0.4.14 + resolution: "alien-signals@npm:0.4.14" + checksum: 10c0/5abb3377bcaf6b3819e950084b3ebd022ad90210105afb450c89dc347e80e28da441bf34858a57ea122abe7603e552ddbad80dc597c8f02a0a5206c5fb9c20cb + languageName: node + linkType: hard + "ansi-colors@npm:^4.1.1": version: 4.1.3 resolution: "ansi-colors@npm:4.1.3" @@ -5829,6 +6179,13 @@ __metadata: languageName: node linkType: hard +"boolbase@npm:^1.0.0": + version: 1.0.0 + resolution: "boolbase@npm:1.0.0" + checksum: 10c0/e4b53deb4f2b85c52be0e21a273f2045c7b6a6ea002b0e139c744cb6f95e9ec044439a52883b0d74dedd1ff3da55ed140cfdddfed7fb0cccbed373de5dce1bcf + languageName: node + linkType: hard + "brace-expansion@npm:^1.1.7": version: 1.1.11 resolution: "brace-expansion@npm:1.1.11" @@ -6180,6 +6537,15 @@ __metadata: languageName: node linkType: hard +"canonical-json@npm:^0.2.0": + version: 0.2.0 + resolution: "canonical-json@npm:0.2.0" + bin: + canonical-json: canonical-json.js + checksum: 10c0/6764e0671bf0227523eeebc872f8cf14d544f0cf02b4c4512e87ebd0504fc74762193db0cc6ee2ba97f1217fc77834c03afdb108417b3c5782636858f7948040 + languageName: node + linkType: hard + "chai@npm:^4.3.10": version: 4.4.1 resolution: "chai@npm:4.4.1" @@ -6594,6 +6960,30 @@ __metadata: languageName: node linkType: hard +"confbox@npm:^0.1.8": + version: 0.1.8 + resolution: "confbox@npm:0.1.8" + checksum: 10c0/fc2c68d97cb54d885b10b63e45bd8da83a8a71459d3ecf1825143dd4c7f9f1b696b3283e07d9d12a144c1301c2ebc7842380bdf0014e55acc4ae1c9550102418 + languageName: node + linkType: hard + +"confbox@npm:^0.2.1": + version: 0.2.2 + resolution: "confbox@npm:0.2.2" + checksum: 10c0/7c246588d533d31e8cdf66cb4701dff6de60f9be77ab54c0d0338e7988750ac56863cc0aca1b3f2046f45ff223a765d3e5d4977a7674485afcd37b6edf3fd129 + languageName: node + linkType: hard + +"config-chain@npm:^1.1.13": + version: 1.1.13 + resolution: "config-chain@npm:1.1.13" + dependencies: + ini: "npm:^1.3.4" + proto-list: "npm:~1.2.1" + checksum: 10c0/39d1df18739d7088736cc75695e98d7087aea43646351b028dfabd5508d79cf6ef4c5bcd90471f52cd87ae470d1c5490c0a8c1a292fbe6ee9ff688061ea0963e + languageName: node + linkType: hard + "console-control-strings@npm:^1.1.0": version: 1.1.0 resolution: "console-control-strings@npm:1.1.0" @@ -6854,7 +7244,7 @@ __metadata: languageName: node linkType: hard -"csstype@npm:^3.0.2": +"csstype@npm:^3.0.2, csstype@npm:^3.1.3": version: 3.1.3 resolution: "csstype@npm:3.1.3" checksum: 10c0/80c089d6f7e0c5b2bd83cf0539ab41474198579584fa10d86d0cafe0642202343cbc119e076a0b1aece191989477081415d66c9fefbf3c957fc2fc4b7009f248 @@ -7353,6 +7743,20 @@ __metadata: languageName: node linkType: hard +"editorconfig@npm:^1.0.4": + version: 1.0.4 + resolution: "editorconfig@npm:1.0.4" + dependencies: + "@one-ini/wasm": "npm:0.1.1" + commander: "npm:^10.0.0" + minimatch: "npm:9.0.1" + semver: "npm:^7.5.3" + bin: + editorconfig: bin/editorconfig + checksum: 10c0/ed6985959d7b34a56e1c09bef118758c81c969489b768d152c93689fce8403b0452462e934f665febaba3478eebc0fd41c0a36100783eaadf6d926c4abc87a3d + languageName: node + linkType: hard + "ee-first@npm:1.1.1": version: 1.1.1 resolution: "ee-first@npm:1.1.1" @@ -8437,6 +8841,24 @@ __metadata: languageName: node linkType: hard +"eslint-plugin-vue@npm:^9.28.0": + version: 9.33.0 + resolution: "eslint-plugin-vue@npm:9.33.0" + dependencies: + "@eslint-community/eslint-utils": "npm:^4.4.0" + globals: "npm:^13.24.0" + natural-compare: "npm:^1.4.0" + nth-check: "npm:^2.1.1" + postcss-selector-parser: "npm:^6.0.15" + semver: "npm:^7.6.3" + vue-eslint-parser: "npm:^9.4.3" + xml-name-validator: "npm:^4.0.0" + peerDependencies: + eslint: ^6.2.0 || ^7.0.0 || ^8.0.0 || ^9.0.0 + checksum: 10c0/2f5ee967158fc345ec3f2076835e6a9d706c4bbb7dc4c3806ad8db81133d73128fbd402f71b3adf8ae53e5e4a0a1aba32e44eb757544901a6a62021a1ccad92e + languageName: node + linkType: hard + "eslint-scope@npm:5.1.1": version: 5.1.1 resolution: "eslint-scope@npm:5.1.1" @@ -8447,7 +8869,7 @@ __metadata: languageName: node linkType: hard -"eslint-scope@npm:^7.2.2": +"eslint-scope@npm:^7.1.1, eslint-scope@npm:^7.2.2": version: 7.2.2 resolution: "eslint-scope@npm:7.2.2" dependencies: @@ -8596,7 +9018,7 @@ __metadata: languageName: node linkType: hard -"espree@npm:^9.6.0, espree@npm:^9.6.1": +"espree@npm:^9.3.1, espree@npm:^9.6.0, espree@npm:^9.6.1": version: 9.6.1 resolution: "espree@npm:9.6.1" dependencies: @@ -8617,21 +9039,21 @@ __metadata: languageName: node linkType: hard -"esquery@npm:^1.4.2": - version: 1.5.0 - resolution: "esquery@npm:1.5.0" +"esquery@npm:^1.4.0, esquery@npm:^1.5.0": + version: 1.6.0 + resolution: "esquery@npm:1.6.0" dependencies: estraverse: "npm:^5.1.0" - checksum: 10c0/a084bd049d954cc88ac69df30534043fb2aee5555b56246493f42f27d1e168f00d9e5d4192e46f10290d312dc30dc7d58994d61a609c579c1219d636996f9213 + checksum: 10c0/cb9065ec605f9da7a76ca6dadb0619dfb611e37a81e318732977d90fab50a256b95fee2d925fba7c2f3f0523aa16f91587246693bc09bc34d5a59575fe6e93d2 languageName: node linkType: hard -"esquery@npm:^1.5.0": - version: 1.6.0 - resolution: "esquery@npm:1.6.0" +"esquery@npm:^1.4.2": + version: 1.5.0 + resolution: "esquery@npm:1.5.0" dependencies: estraverse: "npm:^5.1.0" - checksum: 10c0/cb9065ec605f9da7a76ca6dadb0619dfb611e37a81e318732977d90fab50a256b95fee2d925fba7c2f3f0523aa16f91587246693bc09bc34d5a59575fe6e93d2 + checksum: 10c0/a084bd049d954cc88ac69df30534043fb2aee5555b56246493f42f27d1e168f00d9e5d4192e46f10290d312dc30dc7d58994d61a609c579c1219d636996f9213 languageName: node linkType: hard @@ -8789,6 +9211,13 @@ __metadata: languageName: node linkType: hard +"exsolve@npm:^1.0.1": + version: 1.0.5 + resolution: "exsolve@npm:1.0.5" + checksum: 10c0/0e845843951e8e7f190d26648259b3d584990933ea68a3c8ec984e826d4fb3731681f7f2569252b4fe619db1d67b0859abe0ef694cb2edb454343bd44bcdce59 + languageName: node + linkType: hard + "external-editor@npm:^3.0.3, external-editor@npm:^3.1.0": version: 3.1.0 resolution: "external-editor@npm:3.1.0" @@ -9146,6 +9575,17 @@ __metadata: languageName: node linkType: hard +"fs-extra@npm:~11.3.0": + version: 11.3.0 + resolution: "fs-extra@npm:11.3.0" + dependencies: + graceful-fs: "npm:^4.2.0" + jsonfile: "npm:^6.0.1" + universalify: "npm:^2.0.0" + checksum: 10c0/5f95e996186ff45463059feb115a22fb048bdaf7e487ecee8a8646c78ed8fdca63630e3077d4c16ce677051f5e60d3355a06f3cd61f3ca43f48cc58822a44d0a + languageName: node + linkType: hard + "fs-extra@npm:~7.0.1": version: 7.0.1 resolution: "fs-extra@npm:7.0.1" @@ -9602,6 +10042,22 @@ __metadata: languageName: node linkType: hard +"glob@npm:^10.4.2": + version: 10.4.5 + resolution: "glob@npm:10.4.5" + dependencies: + foreground-child: "npm:^3.1.0" + jackspeak: "npm:^3.1.2" + minimatch: "npm:^9.0.4" + minipass: "npm:^7.1.2" + package-json-from-dist: "npm:^1.0.0" + path-scurry: "npm:^1.11.1" + bin: + glob: dist/esm/bin.mjs + checksum: 10c0/19a9759ea77b8e3ca0a43c2f07ecddc2ad46216b786bb8f993c445aee80d345925a21e5280c7b7c6c59e860a0154b84e4b2b60321fea92cd3c56b4a7489f160e + languageName: node + linkType: hard + "glob@npm:^7.0.0, glob@npm:^7.1.4": version: 7.2.3 resolution: "glob@npm:7.2.3" @@ -9671,6 +10127,15 @@ __metadata: languageName: node linkType: hard +"globals@npm:^13.24.0": + version: 13.24.0 + resolution: "globals@npm:13.24.0" + dependencies: + type-fest: "npm:^0.20.2" + checksum: 10c0/d3c11aeea898eb83d5ec7a99508600fbe8f83d2cf00cbb77f873dbf2bcb39428eff1b538e4915c993d8a3b3473fa71eeebfe22c9bb3a3003d1e26b1f2c8a42cd + languageName: node + linkType: hard + "globals@npm:^14.0.0": version: 14.0.0 resolution: "globals@npm:14.0.0" @@ -10251,7 +10716,7 @@ __metadata: languageName: node linkType: hard -"ini@npm:^1.3.2, ini@npm:^1.3.8": +"ini@npm:^1.3.2, ini@npm:^1.3.4, ini@npm:^1.3.8": version: 1.3.8 resolution: "ini@npm:1.3.8" checksum: 10c0/ec93838d2328b619532e4f1ff05df7909760b6f66d9c9e2ded11e5c1897d6f2f9980c54dd638f88654b00919ce31e827040631eab0a3969e4d1abefa0719516a @@ -11206,6 +11671,23 @@ __metadata: languageName: node linkType: hard +"js-beautify@npm:^1.14.9": + version: 1.15.4 + resolution: "js-beautify@npm:1.15.4" + dependencies: + config-chain: "npm:^1.1.13" + editorconfig: "npm:^1.0.4" + glob: "npm:^10.4.2" + js-cookie: "npm:^3.0.5" + nopt: "npm:^7.2.1" + bin: + css-beautify: js/bin/css-beautify.js + html-beautify: js/bin/html-beautify.js + js-beautify: js/bin/js-beautify.js + checksum: 10c0/300386f648579feacda98640742e8db50d4504bc896673af8bc784a5864585abf89ad8d1f257f2cfd4e3da951e0e4d1f027aa3c21537edb920bd498a0e27bd86 + languageName: node + linkType: hard + "js-cookie@npm:^3.0.5": version: 3.0.5 resolution: "js-cookie@npm:3.0.5" @@ -11680,6 +12162,17 @@ __metadata: languageName: node linkType: hard +"local-pkg@npm:^1.0.0": + version: 1.1.1 + resolution: "local-pkg@npm:1.1.1" + dependencies: + mlly: "npm:^1.7.4" + pkg-types: "npm:^2.0.1" + quansync: "npm:^0.2.8" + checksum: 10c0/fe8f9d0443fb066c3f28a4c89d587dd7cba3ab02645cd16598f8d5f30968acf60af1b0ec2d6ad768475ec9f52baad124f31a93d2fbc034f645bcc02bf3a84882 + languageName: node + linkType: hard + "locate-path@npm:^2.0.0": version: 2.0.0 resolution: "locate-path@npm:2.0.0" @@ -12165,6 +12658,15 @@ __metadata: languageName: node linkType: hard +"minimatch@npm:9.0.1": + version: 9.0.1 + resolution: "minimatch@npm:9.0.1" + dependencies: + brace-expansion: "npm:^2.0.1" + checksum: 10c0/aa043eb8822210b39888a5d0d28df0017b365af5add9bd522f180d2a6962de1cbbf1bdeacdb1b17f410dc3336bc8d76fb1d3e814cdc65d00c2f68e01f0010096 + languageName: node + linkType: hard + "minimatch@npm:9.0.3, minimatch@npm:^9.0.3": version: 9.0.3 resolution: "minimatch@npm:9.0.3" @@ -12395,6 +12897,18 @@ __metadata: languageName: node linkType: hard +"mlly@npm:^1.7.4": + version: 1.7.4 + resolution: "mlly@npm:1.7.4" + dependencies: + acorn: "npm:^8.14.0" + pathe: "npm:^2.0.1" + pkg-types: "npm:^1.3.0" + ufo: "npm:^1.5.4" + checksum: 10c0/69e738218a13d6365caf930e0ab4e2b848b84eec261597df9788cefb9930f3e40667be9cb58a4718834ba5f97a6efeef31d3b5a95f4388143fd4e0d0deff72ff + languageName: node + linkType: hard + "modify-values@npm:^1.0.1": version: 1.0.1 resolution: "modify-values@npm:1.0.1" @@ -12494,7 +13008,7 @@ __metadata: languageName: node linkType: hard -"muggle-string@npm:^0.4.0": +"muggle-string@npm:^0.4.0, muggle-string@npm:^0.4.1": version: 0.4.1 resolution: "muggle-string@npm:0.4.1" checksum: 10c0/e914b63e24cd23f97e18376ec47e4ba3aa24365e4776212b666add2e47bb158003212980d732c49abf3719568900af7861873844a6e2d3a7ca7e86952c0e99e9 @@ -12764,7 +13278,7 @@ __metadata: languageName: node linkType: hard -"nopt@npm:^7.0.0": +"nopt@npm:^7.0.0, nopt@npm:^7.2.1": version: 7.2.1 resolution: "nopt@npm:7.2.1" dependencies: @@ -13009,6 +13523,15 @@ __metadata: languageName: node linkType: hard +"nth-check@npm:^2.1.1": + version: 2.1.1 + resolution: "nth-check@npm:2.1.1" + dependencies: + boolbase: "npm:^1.0.0" + checksum: 10c0/5fee7ff309727763689cfad844d979aedd2204a817fbaaf0e1603794a7c20db28548d7b024692f953557df6ce4a0ee4ae46cd8ebd9b36cfb300b9226b567c479 + languageName: node + linkType: hard + "nwsapi@npm:^2.2.10": version: 2.2.10 resolution: "nwsapi@npm:2.2.10" @@ -13832,7 +14355,7 @@ __metadata: languageName: node linkType: hard -"pathe@npm:^2.0.3": +"pathe@npm:^2.0.1, pathe@npm:^2.0.3": version: 2.0.3 resolution: "pathe@npm:2.0.3" checksum: 10c0/c118dc5a8b5c4166011b2b70608762e260085180bb9e33e80a50dcdb1e78c010b1624f4280c492c92b05fc276715a4c357d1f9edc570f8f1b3d90b6839ebaca1 @@ -13950,6 +14473,28 @@ __metadata: languageName: node linkType: hard +"pkg-types@npm:^1.3.0": + version: 1.3.1 + resolution: "pkg-types@npm:1.3.1" + dependencies: + confbox: "npm:^0.1.8" + mlly: "npm:^1.7.4" + pathe: "npm:^2.0.1" + checksum: 10c0/19e6cb8b66dcc66c89f2344aecfa47f2431c988cfa3366bdfdcfb1dd6695f87dcce37fbd90fe9d1605e2f4440b77f391e83c23255347c35cf84e7fd774d7fcea + languageName: node + linkType: hard + +"pkg-types@npm:^2.0.1": + version: 2.1.0 + resolution: "pkg-types@npm:2.1.0" + dependencies: + confbox: "npm:^0.2.1" + exsolve: "npm:^1.0.1" + pathe: "npm:^2.0.3" + checksum: 10c0/7729d0a2367ba0aa2caf0f84a6ff0b73b13f4e9a3d62c229ddfa6d45d1f3898f590acdbaa64d779d56737d4ebea2d085961efd59094b8adf8baa34d829599b75 + languageName: node + linkType: hard + "playwright-core@npm:1.49.1": version: 1.49.1 resolution: "playwright-core@npm:1.49.1" @@ -14429,6 +14974,16 @@ __metadata: languageName: node linkType: hard +"postcss-selector-parser@npm:^6.0.15": + version: 6.1.2 + resolution: "postcss-selector-parser@npm:6.1.2" + dependencies: + cssesc: "npm:^3.0.0" + util-deprecate: "npm:^1.0.2" + checksum: 10c0/523196a6bd8cf660bdf537ad95abd79e546d54180f9afb165a4ab3e651ac705d0f8b8ce6b3164fb9e3279ce482c5f751a69eb2d3a1e8eb0fd5e82294fb3ef13e + languageName: node + linkType: hard + "postcss-value-parser@npm:^4.0.0, postcss-value-parser@npm:^4.2.0": version: 4.2.0 resolution: "postcss-value-parser@npm:4.2.0" @@ -14601,6 +15156,13 @@ __metadata: languageName: node linkType: hard +"proto-list@npm:~1.2.1": + version: 1.2.4 + resolution: "proto-list@npm:1.2.4" + checksum: 10c0/b9179f99394ec8a68b8afc817690185f3b03933f7b46ce2e22c1930dc84b60d09f5ad222beab4e59e58c6c039c7f7fcf620397235ef441a356f31f9744010e12 + languageName: node + linkType: hard + "protocols@npm:^2.0.0, protocols@npm:^2.0.1": version: 2.0.1 resolution: "protocols@npm:2.0.1" @@ -14678,6 +15240,13 @@ __metadata: languageName: node linkType: hard +"quansync@npm:^0.2.8": + version: 0.2.10 + resolution: "quansync@npm:0.2.10" + checksum: 10c0/f86f1d644f812a3a7c42de79eb401c47a5a67af82a9adff8a8afb159325e03e00f77cebbf42af6340a0bd47bd0c1fbe999e7caf7e1bbb30d7acb00c8729b7530 + languageName: node + linkType: hard + "querystringify@npm:^2.1.1": version: 2.2.0 resolution: "querystringify@npm:2.2.0" @@ -15710,6 +16279,15 @@ __metadata: languageName: node linkType: hard +"semver@npm:^7.3.6": + version: 7.7.2 + resolution: "semver@npm:7.7.2" + bin: + semver: bin/semver.js + checksum: 10c0/aca305edfbf2383c22571cb7714f48cadc7ac95371b4b52362fb8eeffdfbc0de0669368b82b2b15978f8848f01d7114da65697e56cd8c37b0dab8c58e543f9ea + languageName: node + linkType: hard + "semver@npm:^7.6.3": version: 7.7.1 resolution: "semver@npm:7.7.1" @@ -17379,6 +17957,16 @@ __metadata: languageName: node linkType: hard +"typescript@npm:5.8.2": + version: 5.8.2 + resolution: "typescript@npm:5.8.2" + bin: + tsc: bin/tsc + tsserver: bin/tsserver + checksum: 10c0/5c4f6fbf1c6389b6928fe7b8fcd5dc73bb2d58cd4e3883f1d774ed5bd83b151cbac6b7ecf11723de56d4676daeba8713894b1e9af56174f2f9780ae7848ec3c6 + languageName: node + linkType: hard + "typescript@npm:>=3 < 6": version: 5.4.5 resolution: "typescript@npm:5.4.5" @@ -17419,6 +18007,16 @@ __metadata: languageName: node linkType: hard +"typescript@patch:typescript@npm%3A5.8.2#optional!builtin": + version: 5.8.2 + resolution: "typescript@patch:typescript@npm%3A5.8.2#optional!builtin::version=5.8.2&hash=5adc0c" + bin: + tsc: bin/tsc + tsserver: bin/tsserver + checksum: 10c0/8a6cd29dfb59bd5a978407b93ae0edb530ee9376a5b95a42ad057a6f80ffb0c410489ccd6fe48d1d0dfad6e8adf5d62d3874bbd251f488ae30e11a1ce6dabd28 + languageName: node + linkType: hard + "typescript@patch:typescript@npm%3A>=3 < 6#optional!builtin": version: 5.4.5 resolution: "typescript@patch:typescript@npm%3A5.4.5#optional!builtin::version=5.4.5&hash=5adc0c" @@ -17463,6 +18061,13 @@ __metadata: languageName: node linkType: hard +"ufo@npm:^1.5.4": + version: 1.6.1 + resolution: "ufo@npm:1.6.1" + checksum: 10c0/5a9f041e5945fba7c189d5410508cbcbefef80b253ed29aa2e1f8a2b86f4bd51af44ee18d4485e6d3468c92be9bf4a42e3a2b72dcaf27ce39ce947ec994f1e6b + languageName: node + linkType: hard + "uglify-js@npm:^3.1.4": version: 3.17.4 resolution: "uglify-js@npm:3.17.4" @@ -17820,6 +18425,29 @@ __metadata: languageName: node linkType: hard +"vite-plugin-dts@npm:^4.5.4": + version: 4.5.4 + resolution: "vite-plugin-dts@npm:4.5.4" + dependencies: + "@microsoft/api-extractor": "npm:^7.50.1" + "@rollup/pluginutils": "npm:^5.1.4" + "@volar/typescript": "npm:^2.4.11" + "@vue/language-core": "npm:2.2.0" + compare-versions: "npm:^6.1.1" + debug: "npm:^4.4.0" + kolorist: "npm:^1.8.0" + local-pkg: "npm:^1.0.0" + magic-string: "npm:^0.30.17" + peerDependencies: + typescript: "*" + vite: "*" + peerDependenciesMeta: + vite: + optional: true + checksum: 10c0/5fcb7f3739d115f36195a692c0e9f9fca4e504bbbbabe29e71ee06630dd05ea2920169371e80e548eb4779d2eca14107277497838d7df588d53e1fadf84be861 + languageName: node + linkType: hard + "vite-plugin-dts@npm:~3.9.1": version: 3.9.1 resolution: "vite-plugin-dts@npm:3.9.1" @@ -18099,6 +18727,30 @@ __metadata: languageName: node linkType: hard +"vue-component-type-helpers@npm:^2.0.0": + version: 2.2.10 + resolution: "vue-component-type-helpers@npm:2.2.10" + checksum: 10c0/f4d2219941a6bb987dc813e5e132fa9f8880163efc73faa6871713241dae0358cbfb6ecbee3b7e6e2ef65c02e5b5a8204c6e44c4a7d213499957e4d36f8c99c7 + languageName: node + linkType: hard + +"vue-eslint-parser@npm:^9.4.2, vue-eslint-parser@npm:^9.4.3": + version: 9.4.3 + resolution: "vue-eslint-parser@npm:9.4.3" + dependencies: + debug: "npm:^4.3.4" + eslint-scope: "npm:^7.1.1" + eslint-visitor-keys: "npm:^3.3.0" + espree: "npm:^9.3.1" + esquery: "npm:^1.4.0" + lodash: "npm:^4.17.21" + semver: "npm:^7.3.6" + peerDependencies: + eslint: ">=6.0.0" + checksum: 10c0/128be5988de025b5abd676a91c3e92af68288a5da1c20b2ff848fe90e040c04b2222a03b5d8048cf4a5e0b667a8addfb6f6e6565860d4afb5190c4cc42d05578 + languageName: node + linkType: hard + "vue-template-compiler@npm:^2.7.14": version: 2.7.14 resolution: "vue-template-compiler@npm:2.7.14" @@ -18139,6 +18791,24 @@ __metadata: languageName: node linkType: hard +"vue@npm:^3.5.16": + version: 3.5.16 + resolution: "vue@npm:3.5.16" + dependencies: + "@vue/compiler-dom": "npm:3.5.16" + "@vue/compiler-sfc": "npm:3.5.16" + "@vue/runtime-dom": "npm:3.5.16" + "@vue/server-renderer": "npm:3.5.16" + "@vue/shared": "npm:3.5.16" + peerDependencies: + typescript: "*" + peerDependenciesMeta: + typescript: + optional: true + checksum: 10c0/dbc2edacd5fd1eaa6683579e9561960cdc735a0210238e2ce3a2570efbfe24b8a242592fe4c1d2e8e167650077592f36b5056711e70584d9339ff5cb6ef724f6 + languageName: node + linkType: hard + "w3c-xmlserializer@npm:^5.0.0": version: 5.0.0 resolution: "w3c-xmlserializer@npm:5.0.0" @@ -18615,6 +19285,13 @@ __metadata: languageName: node linkType: hard +"xml-name-validator@npm:^4.0.0": + version: 4.0.0 + resolution: "xml-name-validator@npm:4.0.0" + checksum: 10c0/c1bfa219d64e56fee265b2bd31b2fcecefc063ee802da1e73bad1f21d7afd89b943c9e2c97af2942f60b1ad46f915a4c81e00039c7d398b53cf410e29d3c30bd + languageName: node + linkType: hard + "xml-name-validator@npm:^5.0.0": version: 5.0.0 resolution: "xml-name-validator@npm:5.0.0"