summaryrefslogtreecommitdiff
path: root/packages/integrations/vue/src
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--packages/integrations/vue/src/client.ts (renamed from packages/integrations/vue/client.js)25
-rw-r--r--packages/integrations/vue/src/context.ts26
-rw-r--r--packages/integrations/vue/src/server.ts (renamed from packages/integrations/vue/server.js)14
-rw-r--r--packages/integrations/vue/src/static-html.ts (renamed from packages/integrations/vue/static-html.js)0
-rw-r--r--packages/integrations/vue/src/types.ts4
5 files changed, 58 insertions, 11 deletions
diff --git a/packages/integrations/vue/client.js b/packages/integrations/vue/src/client.ts
index 4ec2b9e68..8f02d534e 100644
--- a/packages/integrations/vue/client.js
+++ b/packages/integrations/vue/src/client.ts
@@ -3,15 +3,23 @@ import { Suspense, createApp, createSSRApp, h } from 'vue';
import StaticHtml from './static-html.js';
// keep track of already initialized apps, so we don't hydrate again for view transitions
-let appMap = new WeakMap();
+let appMap = new WeakMap<
+ HTMLElement,
+ { props: Record<string, any>; slots: Record<string, any>; component?: any }
+>();
-export default (element) =>
- async (Component, props, slotted, { client }) => {
+export default (element: HTMLElement) =>
+ async (
+ Component: any,
+ props: Record<string, any>,
+ slotted: Record<string, any>,
+ { client }: Record<string, string>,
+ ) => {
if (!element.hasAttribute('ssr')) return;
// Expose name on host component for Vue devtools
const name = Component.name ? `${Component.name} Host` : undefined;
- const slots = {};
+ const slots: Record<string, any> = {};
for (const [key, value] of Object.entries(slotted)) {
slots[key] = () => h(StaticHtml, { value, name: key === 'default' ? undefined : key });
}
@@ -30,8 +38,9 @@ export default (element) =>
const app = bootstrap({
name,
render() {
- let content = h(Component, appInstance.props, appInstance.slots);
- appInstance.component = this;
+ // At this point, appInstance has been set so it's safe to use a non-null assertion
+ let content = h(Component, appInstance!.props, appInstance!.slots);
+ appInstance!.component = this;
// related to https://github.com/withastro/astro/issues/6549
// if the component is async, wrap it in a Suspense component
if (isAsync(Component.setup)) {
@@ -40,7 +49,7 @@ export default (element) =>
return content;
},
});
- app.config.idPrefix = element.getAttribute('prefix');
+ app.config.idPrefix = element.getAttribute('prefix') ?? undefined;
await setup(app);
app.mount(element, isHydrate);
appMap.set(element, appInstance);
@@ -52,7 +61,7 @@ export default (element) =>
}
};
-function isAsync(fn) {
+function isAsync(fn: () => any) {
const constructor = fn?.constructor;
return constructor && constructor.name === 'AsyncFunction';
}
diff --git a/packages/integrations/vue/src/context.ts b/packages/integrations/vue/src/context.ts
new file mode 100644
index 000000000..833755044
--- /dev/null
+++ b/packages/integrations/vue/src/context.ts
@@ -0,0 +1,26 @@
+import type { SSRResult } from 'astro';
+
+const contexts = new WeakMap<SSRResult, { currentIndex: number; readonly id: string }>();
+
+const ID_PREFIX = 's';
+
+function getContext(rendererContextResult: SSRResult) {
+ if (contexts.has(rendererContextResult)) {
+ return contexts.get(rendererContextResult);
+ }
+ const ctx = {
+ currentIndex: 0,
+ get id() {
+ return ID_PREFIX + this.currentIndex.toString();
+ },
+ };
+ contexts.set(rendererContextResult, ctx);
+ return ctx;
+}
+
+export function incrementId(rendererContextResult: SSRResult) {
+ const ctx = getContext(rendererContextResult)!;
+ const id = ctx.id;
+ ctx.currentIndex++;
+ return id;
+}
diff --git a/packages/integrations/vue/server.js b/packages/integrations/vue/src/server.ts
index 315909087..6b4c2a3f4 100644
--- a/packages/integrations/vue/server.js
+++ b/packages/integrations/vue/src/server.ts
@@ -1,21 +1,29 @@
import { setup } from 'virtual:@astrojs/vue/app';
+import type { AstroComponentMetadata } from 'astro';
import { createSSRApp, h } from 'vue';
import { renderToString } from 'vue/server-renderer';
import { incrementId } from './context.js';
import StaticHtml from './static-html.js';
+import type { RendererContext } from './types.js';
-function check(Component) {
+function check(Component: any) {
return !!Component['ssrRender'] || !!Component['__ssrInlineRender'];
}
-async function renderToStaticMarkup(Component, inputProps, slotted, metadata) {
+async function renderToStaticMarkup(
+ this: RendererContext,
+ Component: any,
+ inputProps: Record<string, any>,
+ slotted: Record<string, any>,
+ metadata: AstroComponentMetadata,
+) {
let prefix;
if (this && this.result) {
prefix = incrementId(this.result);
}
const attrs = { prefix };
- const slots = {};
+ const slots: Record<string, any> = {};
const props = { ...inputProps };
delete props.slot;
for (const [key, value] of Object.entries(slotted)) {
diff --git a/packages/integrations/vue/static-html.js b/packages/integrations/vue/src/static-html.ts
index 689b56a70..689b56a70 100644
--- a/packages/integrations/vue/static-html.js
+++ b/packages/integrations/vue/src/static-html.ts
diff --git a/packages/integrations/vue/src/types.ts b/packages/integrations/vue/src/types.ts
new file mode 100644
index 000000000..5dff5b0b4
--- /dev/null
+++ b/packages/integrations/vue/src/types.ts
@@ -0,0 +1,4 @@
+import type { SSRResult } from 'astro';
+export type RendererContext = {
+ result: SSRResult;
+};