diff --git a/package-lock.json b/package-lock.json index 0b94126..ec98ea1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,6 +8,9 @@ "name": "single-spa-vue-ts", "version": "0.1.0-alpha.5", "license": "MIT", + "dependencies": { + "vue-demi": "^0.14.10" + }, "devDependencies": { "@babel/core": "^7.22.5", "@babel/preset-env": "^7.25.3", @@ -38,7 +41,13 @@ "vue2": "npm:vue@2.7.16" }, "peerDependencies": { + "@vue/composition-api": "^1.7.2", "vue": "^2.7.0 || >=3.0.0" + }, + "peerDependenciesMeta": { + "@vue/composition-api": { + "optional": true + } } }, "node_modules/@ampproject/remapping": { @@ -345,7 +354,6 @@ "version": "7.24.8", "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.24.8.tgz", "integrity": "sha512-pO9KhhRcuUyGnJWwyEgnRJTSIZHiT+vMD0kPeD+so0l7mxkMT19g3pjY9GTnHySck/hDzq+dtW/4VgnMkippsQ==", - "dev": true, "engines": { "node": ">=6.9.0" } @@ -354,7 +362,6 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.7.tgz", "integrity": "sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w==", - "dev": true, "engines": { "node": ">=6.9.0" } @@ -414,7 +421,6 @@ "version": "7.25.3", "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.25.3.tgz", "integrity": "sha512-iLTJKDbJ4hMvFPgQwwsVoxtHyWpKKPBrxkANrSYewDPaPpT5py5yeVkgPIJ7XYXhndxJpaA3PyALSXQ7u8e/Dw==", - "dev": true, "dependencies": { "@babel/types": "^7.25.2" }, @@ -1701,7 +1707,6 @@ "version": "7.25.2", "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.25.2.tgz", "integrity": "sha512-YTnYtra7W9e6/oAZEHj0bJehPRUlLH9/fbpT5LfB0NhQXyALCRkRs3zH9v07IYhkgpqX6Z78FnuccZr/l4Fs4Q==", - "dev": true, "dependencies": { "@babel/helper-string-parser": "^7.24.8", "@babel/helper-validator-identifier": "^7.24.7", @@ -2056,8 +2061,7 @@ "node_modules/@jridgewell/sourcemap-codec": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", - "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", - "dev": true + "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==" }, "node_modules/@jridgewell/trace-mapping": { "version": "0.3.25", @@ -2857,7 +2861,6 @@ "version": "3.4.35", "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.4.35.tgz", "integrity": "sha512-gKp0zGoLnMYtw4uS/SJRRO7rsVggLjvot3mcctlMXunYNsX+aRJDqqw/lV5/gHK91nvaAAlWFgdVl020AW1Prg==", - "dev": true, "dependencies": { "@babel/parser": "^7.24.7", "@vue/shared": "3.4.35", @@ -2870,7 +2873,6 @@ "version": "3.4.35", "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.4.35.tgz", "integrity": "sha512-pWIZRL76/oE/VMhdv/ovZfmuooEni6JPG1BFe7oLk5DZRo/ImydXijoZl/4kh2406boRQ7lxTYzbZEEXEhj9NQ==", - "dev": true, "dependencies": { "@vue/compiler-core": "3.4.35", "@vue/shared": "3.4.35" @@ -2880,7 +2882,6 @@ "version": "3.4.35", "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.4.35.tgz", "integrity": "sha512-xacnRS/h/FCsjsMfxBkzjoNxyxEyKyZfBch/P4vkLRvYJwe5ChXmZZrj8Dsed/752H2Q3JE8kYu9Uyha9J6PgA==", - "dev": true, "dependencies": { "@babel/parser": "^7.24.7", "@vue/compiler-core": "3.4.35", @@ -2897,7 +2898,6 @@ "version": "3.4.35", "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.4.35.tgz", "integrity": "sha512-7iynB+0KB1AAJKk/biENTV5cRGHRdbdaD7Mx3nWcm1W8bVD6QmnH3B4AHhQQ1qZHhqFwzEzMwiytXm3PX1e60A==", - "dev": true, "dependencies": { "@vue/compiler-dom": "3.4.35", "@vue/shared": "3.4.35" @@ -2941,7 +2941,6 @@ "version": "3.4.35", "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.4.35.tgz", "integrity": "sha512-Ggtz7ZZHakriKioveJtPlStYardwQH6VCs9V13/4qjHSQb/teE30LVJNrbBVs4+aoYGtTQKJbTe4CWGxVZrvEw==", - "dev": true, "dependencies": { "@vue/shared": "3.4.35" } @@ -2950,7 +2949,6 @@ "version": "3.4.35", "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.4.35.tgz", "integrity": "sha512-D+BAjFoWwT5wtITpSxwqfWZiBClhBbR+bm0VQlWYFOadUUXFo+5wbe9ErXhLvwguPiLZdEF13QAWi2vP3ZD5tA==", - "dev": true, "dependencies": { "@vue/reactivity": "3.4.35", "@vue/shared": "3.4.35" @@ -2960,7 +2958,6 @@ "version": "3.4.35", "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.4.35.tgz", "integrity": "sha512-yGOlbos+MVhlS5NWBF2HDNgblG8e2MY3+GigHEyR/dREAluvI5tuUUgie3/9XeqhPE4LF0i2wjlduh5thnfOqw==", - "dev": true, "dependencies": { "@vue/reactivity": "3.4.35", "@vue/runtime-core": "3.4.35", @@ -2972,7 +2969,6 @@ "version": "3.4.35", "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.4.35.tgz", "integrity": "sha512-iZ0e/u9mRE4T8tNhlo0tbA+gzVkgv8r5BX6s1kRbOZqfpq14qoIvCZ5gIgraOmYkMYrSEZgkkojFPr+Nyq/Mnw==", - "dev": true, "dependencies": { "@vue/compiler-ssr": "3.4.35", "@vue/shared": "3.4.35" @@ -2984,8 +2980,7 @@ "node_modules/@vue/shared": { "version": "3.4.35", "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.4.35.tgz", - "integrity": "sha512-hvuhBYYDe+b1G8KHxsQ0diDqDMA8D9laxWZhNAjE83VZb5UDaXl9Xnz7cGdDSyiHM90qqI/CyGMcpBpiDy6VVQ==", - "dev": true + "integrity": "sha512-hvuhBYYDe+b1G8KHxsQ0diDqDMA8D9laxWZhNAjE83VZb5UDaXl9Xnz7cGdDSyiHM90qqI/CyGMcpBpiDy6VVQ==" }, "node_modules/acorn": { "version": "8.12.1", @@ -3529,8 +3524,7 @@ "node_modules/csstype": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", - "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", - "dev": true + "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==" }, "node_modules/data-urls": { "version": "5.0.0", @@ -3657,7 +3651,6 @@ "version": "4.5.0", "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", - "dev": true, "engines": { "node": ">=0.12" }, @@ -3987,8 +3980,7 @@ "node_modules/estree-walker": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", - "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", - "dev": true + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==" }, "node_modules/esutils": { "version": "2.0.3", @@ -4831,7 +4823,6 @@ "version": "0.30.11", "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.11.tgz", "integrity": "sha512-+Wri9p0QHMy+545hKww7YAu5NyzF8iomPL/RQazugQ9+Ez4Ic3mERMd8ZTX5rfK944j+560ZJi8iAwgak1Ac7A==", - "dev": true, "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.0" } @@ -4981,7 +4972,6 @@ "version": "3.3.7", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", - "dev": true, "funding": [ { "type": "github", @@ -5196,8 +5186,7 @@ "node_modules/picocolors": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.1.tgz", - "integrity": "sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==", - "dev": true + "integrity": "sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==" }, "node_modules/picomatch": { "version": "2.3.1", @@ -5215,7 +5204,6 @@ "version": "8.4.40", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.40.tgz", "integrity": "sha512-YF2kKIUzAofPMpfH6hOi2cGnv/HrUlfucspc7pDyvv7kGdqXrfj8SCl/t8owkEgKEuu8ZcRjSOxFxVLqwChZ2Q==", - "dev": true, "funding": [ { "type": "opencollective", @@ -5776,7 +5764,6 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.0.tgz", "integrity": "sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -5995,7 +5982,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", - "dev": true, "engines": { "node": ">=4" } @@ -6082,7 +6068,7 @@ "version": "5.5.4", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.4.tgz", "integrity": "sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q==", - "dev": true, + "devOptional": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -6497,7 +6483,6 @@ "version": "3.4.35", "resolved": "https://registry.npmjs.org/vue/-/vue-3.4.35.tgz", "integrity": "sha512-+fl/GLmI4GPileHftVlCdB7fUL4aziPcqTudpTGXCT8s+iZWuOCeNEB5haX6Uz2IpRrbEXOgIFbe+XciCuGbNQ==", - "dev": true, "dependencies": { "@vue/compiler-dom": "3.4.35", "@vue/compiler-sfc": "3.4.35", @@ -6514,6 +6499,31 @@ } } }, + "node_modules/vue-demi": { + "version": "0.14.10", + "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.10.tgz", + "integrity": "sha512-nMZBOwuzabUO0nLgIcc6rycZEebF6eeUfaiQx9+WSk8e29IbLvPU9feI6tqW4kTo3hvoYAJkMh8n8D0fuISphg==", + "hasInstallScript": true, + "bin": { + "vue-demi-fix": "bin/vue-demi-fix.js", + "vue-demi-switch": "bin/vue-demi-switch.js" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + }, + "peerDependencies": { + "@vue/composition-api": "^1.0.0-rc.1", + "vue": "^3.0.0-0 || ^2.6.0" + }, + "peerDependenciesMeta": { + "@vue/composition-api": { + "optional": true + } + } + }, "node_modules/vue-tsc": { "version": "2.0.29", "resolved": "https://registry.npmjs.org/vue-tsc/-/vue-tsc-2.0.29.tgz", diff --git a/package.json b/package.json index 6c63d9b..3615bb0 100644 --- a/package.json +++ b/package.json @@ -43,8 +43,14 @@ }, "homepage": "https://github.com/AckermannJan/single-spa-vue#readme", "peerDependencies": { + "@vue/composition-api": "^1.7.2", "vue": "^2.7.0 || >=3.0.0" }, + "peerDependenciesMeta": { + "@vue/composition-api": { + "optional": true + } + }, "devDependencies": { "@babel/core": "^7.22.5", "@babel/preset-env": "^7.25.3", @@ -73,5 +79,8 @@ "vue": "^3.4.23", "vue-tsc": "^2.0.13", "vue2": "npm:vue@2.7.16" + }, + "dependencies": { + "vue-demi": "^0.14.10" } } diff --git a/src/parcel.ts b/src/parcel.ts index 8355ac4..f2fe13e 100644 --- a/src/parcel.ts +++ b/src/parcel.ts @@ -1,4 +1,4 @@ -import { defineComponent, h } from "vue"; +import * as Vue from "vue"; interface RenderedComponentProps { ref: string; @@ -20,7 +20,7 @@ interface Parcel { getStatus: () => string; } -export default defineComponent({ +export default Vue.defineComponent({ props: { config: [Object, Promise], wrapWith: String, @@ -32,7 +32,8 @@ export default defineComponent({ }, parcelProps: Object, }, - render() { + render(h: typeof Vue.h | undefined) { + h = typeof h === "function" ? h : Vue.h; const containerTagName: string = this.wrapWith || "div"; const props: RenderedComponentProps = { ref: "container" }; diff --git a/src/single-spa-vue.test.ts b/src/single-spa-vue.test.ts index 5083dd4..02a4b6e 100644 --- a/src/single-spa-vue.test.ts +++ b/src/single-spa-vue.test.ts @@ -1,10 +1,10 @@ -import singleSpaVue, { type Props } from "./single-spa-vue"; +import singleSpaVue, { type Props, SingleSpaVueOpts } from "./single-spa-vue"; import type { Mock, MockInstance } from "vitest"; // @ts-expect-error - `css.escape` has no types import cssEscape from "css.escape"; import type { VueConstructor } from "vue2"; import Vue from "vue2"; -import { createApp, h } from "vue"; +import { createApp, h, h as H } from "vue"; const domElId = `single-spa-application:test-app`; const cssSelector = `#single-spa-application\\:test-app`; @@ -24,6 +24,7 @@ describe("single-spa-vue", () => { }); beforeEach(() => { + // @ts-expect-error - We dont want to declare a domElement in the props props = { name: "test-app", mountParcel: vi.fn(), singleSpa: vi.fn() }; }); @@ -40,7 +41,7 @@ describe("single-spa-vue", () => { vueVersion: 2, Vue, appOptions: { - render: (h) => h("div", "test-app"), + render: (h: typeof H) => h("div", "test-app"), }, handleInstance, }); @@ -61,7 +62,7 @@ describe("single-spa-vue", () => { vueVersion: 2, Vue, appOptions: { - render: (h) => h("div", "test-app"), + render: (h: typeof H) => h("div", "test-app"), data() { return { customData: "customData", @@ -86,8 +87,9 @@ describe("single-spa-vue", () => { vueVersion: 2, Vue, appOptions: { - render: (h) => h("div", "test-app"), + render: (h: typeof H) => h("div", "test-app"), data: { + // @ts-expect-error - This is an edge case usually you should provide data as a function customData: "customData", }, }, @@ -107,7 +109,7 @@ describe("single-spa-vue", () => { vueVersion: 2, Vue, appOptions: { - render: (h) => h("div", "test-app"), + render: (h: typeof H) => h("div", "test-app"), }, }); @@ -130,7 +132,7 @@ describe("single-spa-vue", () => { Vue, appOptions: { el: "#my-custom-el", - render: (h) => h("div", { class: "test" }, "test-app"), + render: (h: typeof H) => h("div", { class: "test" }, "test-app"), }, }); @@ -154,7 +156,7 @@ describe("single-spa-vue", () => { Vue, appOptions: { el: domEl, - render: (h) => h("div", { class: "test" }, "test-app"), + render: (h: typeof H) => h("div", { class: "test" }, "test-app"), }, }); @@ -179,7 +181,7 @@ describe("single-spa-vue", () => { Vue, appOptions: { el: domEl, - render: (h) => h("div", { class: "test" }, "test-app"), + render: (h: typeof H) => h("div", { class: "test" }, "test-app"), }, }); @@ -208,7 +210,7 @@ describe("single-spa-vue", () => { vueVersion: 2, Vue, appOptions: { - render: (h) => h("div", { class: "test" }, "test-app"), + render: (h: typeof H) => h("div", { class: "test" }, "test-app"), }, }); @@ -228,8 +230,8 @@ describe("single-spa-vue", () => { singleSpaVue({ vueVersion: 2, Vue, - // @ts-expect-error - `el` should be a string or DOM Element appOptions: { + // @ts-expect-error - `el` should be a string or DOM Element el: 1233, }, }); @@ -261,7 +263,7 @@ describe("single-spa-vue", () => { vueVersion: 2, Vue, appOptions: { - render: (h) => h("div", { class: "test" }, "test-app"), + render: (h: typeof H) => h("div", { class: "test" }, "test-app"), }, }); @@ -283,7 +285,7 @@ describe("single-spa-vue", () => { it(`passes appOptions straight through to Vue`, async () => { const appOptions = { something: "random", - render: (h) => h("div", { class: "test" }, "test-app"), + render: (h: typeof H) => h("div", { class: "test" }, "test-app"), }; const lifecycles = singleSpaVue({ vueVersion: 2, @@ -303,7 +305,7 @@ describe("single-spa-vue", () => { appOptions: () => Promise.resolve({ something: "random", - render: (h) => h("div", { class: "test" }, "test-app"), + render: (h: typeof H) => h("div", { class: "test" }, "test-app"), }), }); await lifecycles.bootstrap(); @@ -320,7 +322,7 @@ describe("single-spa-vue", () => { appOptions: (_opts, localProps) => { expect(localProps).toBe(props); return Promise.resolve({ - render: (h) => h("div", { class: "test" }, "test-app"), + render: (h: typeof H) => h("div", { class: "test" }, "test-app"), }); }, }); @@ -336,7 +338,7 @@ describe("single-spa-vue", () => { vueVersion: 2, Vue, appOptions: { - render: (h) => h("div", { class: "test" }, "test-app"), + render: (h: typeof H) => h("div", { class: "test" }, "test-app"), }, handleInstance, }); @@ -356,11 +358,11 @@ describe("single-spa-vue", () => { opts.loadRootComponent.mockReturnValue( Promise.resolve({ - render: (h) => h("div", "test-app"), + render: (h: typeof H) => h("div", "test-app"), }), ); - const lifecycles = singleSpaVue(opts); + const lifecycles = singleSpaVue(opts as SingleSpaVueOpts); await lifecycles.bootstrap(); expect(opts.loadRootComponent).toHaveBeenCalled(); const instance = (await lifecycles.mount(props)) as Vue; @@ -375,7 +377,7 @@ describe("single-spa-vue", () => { vueVersion: 2, Vue, appOptions: { - render: (h) => h("div", "test-app"), + render: (h: typeof H) => h("div", "test-app"), }, }); await lifecycles.bootstrap(); @@ -392,7 +394,7 @@ describe("single-spa-vue", () => { vueVersion: 2, Vue: Vue as unknown as VueConstructor, appOptions: { - render: (h) => h("div", "test-app"), + render: (h: typeof H) => h("div", "test-app"), }, }); await lifecycles.bootstrap(); @@ -406,7 +408,7 @@ describe("single-spa-vue", () => { vueVersion: 2, Vue, appOptions: { - render: (h) => h("div", "test-app"), + render: (h: typeof H) => h("div", "test-app"), }, }); await lifecycles.bootstrap(); @@ -420,7 +422,7 @@ describe("single-spa-vue", () => { vueVersion: 2, Vue, appOptions: { - render: (h) => h("div", "test-app"), + render: (h: typeof H) => h("div", "test-app"), }, }); await lifecycles.bootstrap(); @@ -437,7 +439,7 @@ describe("single-spa-vue", () => { vueVersion: 2, Vue, appOptions: { - render: (h) => h("div", { class: "test" }, "test-app"), + render: (h: typeof H) => h("div", { class: "test" }, "test-app"), }, }); @@ -457,7 +459,6 @@ describe("single-spa-vue", () => { (instance as Vue).$destroy = (...args) => { return oldDestroy.apply(instance, args); }; - // @ts-expect-error - We know that $destroy exists obj.spy = vi.spyOn(instance, "$destroy"); } @@ -599,7 +600,7 @@ describe("single-spa-vue", () => { vueVersion: 2, Vue, appOptions: { - render: (h) => h("div", "test-app"), + render: (h: typeof H) => h("div", "test-app"), }, handleInstance, }); @@ -657,7 +658,7 @@ describe("single-spa-vue", () => { Vue, appOptions: { el: domEl, - render: (h) => h("div", "test-app"), + render: (h: typeof H) => h("div", "test-app"), }, replaceMode: true, }); @@ -682,7 +683,7 @@ describe("single-spa-vue", () => { Vue, appOptions: { el: domEl, - render: (h) => h("div", "test-app"), + render: (h: typeof H) => h("div", "test-app"), }, }); await lifecycles.bootstrap(); @@ -698,7 +699,7 @@ describe("single-spa-vue", () => { vueVersion: 2, Vue, appOptions: { - render: (h) => h("div", "test-app"), + render: (h: typeof H) => h("div", "test-app"), }, }); @@ -711,7 +712,6 @@ describe("single-spa-vue", () => { const newProps = { ...props, extraProp: "newValue" }; await lifecycles.update(newProps); - // @ts-expect-error - We know that _data exists expect(instance._data.extraProp).toBe("newValue"); await lifecycles.unmount(props); }); diff --git a/src/single-spa-vue.ts b/src/single-spa-vue.ts index 7f72ebd..485bc20 100644 --- a/src/single-spa-vue.ts +++ b/src/single-spa-vue.ts @@ -3,76 +3,58 @@ import type { ComponentPublicInstance, Component, CreateAppFunction, - ComponentOptionsBase, - ComputedOptions, - MethodOptions, -} from "vue"; -import type { - VueConstructor, - ComponentPublicInstance as ComponentPublicInstanceVue2, - h as H, - Component as ComponentVue2, ComponentOptions, -} from "vue2"; + Vue2, + h as H, +} from "vue-demi"; +type Vue = typeof Vue2; -interface AppOptionsObject { +export interface AppOptionsObject extends ComponentOptions { el?: string | HTMLElement; - data?: unknown; [key: string]: unknown; } -type AppOptionsFunction = ( +export type AppOptionsFunction = ( opts: SingleSpaVueOpts, props: object, ) => Promise; export type AppOptions = AppOptionsObject | AppOptionsFunction; -interface BaseSingleSpaVueOptions { +export interface BaseSingleSpaVueOptions { template?: string; - loadRootComponent?(): Promise; + loadRootComponent?(): Promise; replaceMode?: boolean; - rootComponent?: Component | ComponentVue2; + rootComponent?: Component; } -type SingleSpaOptsVue2 = BaseSingleSpaVueOptions & { +export type SingleSpaOptsVue2 = BaseSingleSpaVueOptions & { vueVersion: 2; - appOptions: AppOptions & ComponentOptions; - Vue: VueConstructor; + appOptions: AppOptions; + Vue: Vue; handleInstance?(app: Vue, props: Props): Promise | void; }; -type SingleSpaOptsVue3 = BaseSingleSpaVueOptions & { +export type SingleSpaOptsVue3 = BaseSingleSpaVueOptions & { vueVersion: 3; - appOptions: AppOptions & - ComponentOptionsBase< - any, - any, - any, - ComputedOptions, - MethodOptions, - object, - any, - any - >; + appOptions: AppOptions; createApp: CreateAppFunction; handleInstance?(app: App, props: Props): Promise | void; }; export type SingleSpaVueOpts = SingleSpaOptsVue2 | SingleSpaOptsVue3; -interface BaseInstance { +export interface BaseInstance { domEl?: HTMLElement; + root?: ComponentPublicInstance; [key: string]: unknown; } -type InstanceVue2 = BaseInstance & { - root?: ComponentPublicInstanceVue2; +export type InstanceVue2 = BaseInstance & { vueInstance?: Vue; }; -type InstanceVue3 = BaseInstance & { - root?: ComponentPublicInstance; +export type InstanceVue3 = BaseInstance & { vueInstance?: App; }; @@ -196,15 +178,14 @@ class SingleSpaVue { (instance as Instance).domEl = domEl; if (!appOptions.render && !appOptions.template && opts.rootComponent) { - appOptions.render = (h: typeof H) => - h(opts.rootComponent as ComponentVue2); + appOptions.render = (h: typeof H) => h(opts.rootComponent as Component); } if (!appOptions.data) { - appOptions.data = {}; + appOptions.data = () => ({}); } const originData = appOptions.data; - appOptions.data = function () { + appOptions.data = () => { const data = typeof originData === "function" ? originData.call(this, this) @@ -215,16 +196,7 @@ class SingleSpaVue { if (this.isVue3(opts)) { const currentInstance = instance as InstanceVue3; currentInstance.vueInstance = opts.createApp( - appOptions as unknown as ComponentOptionsBase< - any, - any, - any, - ComputedOptions, - MethodOptions, - object, - any, - any - >, + appOptions as unknown as ComponentOptions, ); if (opts.handleInstance) { await opts.handleInstance(currentInstance.vueInstance, props); @@ -241,9 +213,7 @@ class SingleSpaVue { } else { const currentInstance = instance as InstanceVue2; currentInstance.vueInstance = new opts.Vue(appOptions); - // @ts-expect-error - Bind should not exist, but I don't want to remove it to not break anything if (currentInstance.vueInstance?.bind) { - // @ts-expect-error - Bind should not exist, but I don't want to remove it to not break anything currentInstance.vueInstance = currentInstance.vueInstance?.bind( currentInstance.vueInstance, ); @@ -313,7 +283,6 @@ class SingleSpaVue { const root = instance.root || instance.vueInstance; for (const prop in data) { - // @ts-expect-error - This is a valid check root[prop] = data[prop]; } }