@wix/astro 1.0.21 → 1.0.23

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. package/build/index.js +3567 -4222
  2. package/build/index.js.map +1 -1
  3. package/build-browser-runtime/setup.js +3197 -3879
  4. package/build-runtime/chunk-MLKGABMK.js +9 -0
  5. package/build-runtime/chunk-RKE6XT5Z.js +3104 -0
  6. package/build-runtime/context/non-elevated.js +2 -1
  7. package/build-runtime/middleware/auth.js +14 -4
  8. package/build-runtime/middleware/html-embeds.d.ts +5 -0
  9. package/build-runtime/middleware/html-embeds.js +66 -0
  10. package/build-runtime/routes/auth/callback.js +10 -8
  11. package/build-runtime/routes/auth/login.js +16 -10
  12. package/build-runtime/routes/auth/logout-callback.js +1 -0
  13. package/build-runtime/routes/auth/logout.js +11 -4
  14. package/build-runtime/routes/service-plugins.js +2 -0
  15. package/build-runtime/routes/webhooks.js +2 -0
  16. package/package.json +3 -3
  17. package/src/context/non-elevated.ts +1 -1
  18. package/src/context/setup.ts +1 -1
  19. package/src/context/utils.ts +1 -1
  20. package/src/index.ts +9 -0
  21. package/src/middleware/auth.ts +20 -4
  22. package/src/middleware/html-embeds.ts +67 -0
  23. package/src/routes/auth/callback.ts +1 -1
  24. package/src/routes/auth/login.ts +11 -6
  25. package/src/routes/auth/logout.ts +8 -1
  26. package/src/schemas.ts +78 -69
  27. package/src/utils/authAsyncLocalStorage.ts +2 -2
  28. package/src/utils/createProjectModel.ts +1 -1
  29. package/src/utils/getSessionTokensFromCookie.ts +3 -6
  30. package/src/utils/loadEnvVars.ts +1 -1
  31. package/src/utils/transformStreamUtils.ts +39 -0
  32. package/src/utils/writeVirtualBackofficeExtensionFiles.ts +8 -3
  33. package/tsup.config.mjs +3 -0
  34. package/build-runtime/chunk-YMZMZCBN.js +0 -4063
@@ -1,6 +1,7 @@
1
1
  import {
2
2
  authAsyncLocalStorage
3
3
  } from "../chunk-C3QOE2TZ.js";
4
+ import "../chunk-MLKGABMK.js";
4
5
 
5
6
  // src/context/non-elevated.ts
6
7
  import { createClient, OAuthStrategy } from "@wix/sdk";
@@ -19,7 +20,7 @@ var authProxy = new Proxy(
19
20
  return function(...args) {
20
21
  const store = authAsyncLocalStorage.getStore();
21
22
  if (store?.sessionTokens) {
22
- auth.setTokens(store.sessionTokens.tokens);
23
+ auth.setTokens(store.sessionTokens);
23
24
  }
24
25
  return value.apply(auth, args);
25
26
  };
@@ -4,6 +4,7 @@ import {
4
4
  import {
5
5
  saveSessionTokensToCookie
6
6
  } from "../chunk-VMS3NKCF.js";
7
+ import "../chunk-MLKGABMK.js";
7
8
 
8
9
  // src/utils/generateVisitorTokens.ts
9
10
  import { OAuthStrategy } from "@wix/sdk";
@@ -38,7 +39,7 @@ function getSessionTokensFromCookie(context) {
38
39
  if (rawCookie != null) {
39
40
  const tokensParseResult = tokensSchema.safeParse(rawCookie);
40
41
  if (tokensParseResult.success && tokensParseResult.data.clientId === WIX_CLIENT_ID2) {
41
- return tokensParseResult.data;
42
+ return tokensParseResult.data.tokens;
42
43
  }
43
44
  }
44
45
  }
@@ -47,17 +48,26 @@ function getSessionTokensFromCookie(context) {
47
48
 
48
49
  // src/middleware/auth.ts
49
50
  var onRequest = async (context, next) => {
51
+ const existingTokens = getExistingTokens(context);
52
+ const usedTokens = existingTokens ?? await generateVisitorTokens();
50
53
  const store = {
51
- sessionTokens: getSessionTokensFromCookie(context)
54
+ sessionTokens: usedTokens
52
55
  };
53
56
  const response = await authAsyncLocalStorage.run(store, () => {
54
57
  return next();
55
58
  });
56
- if (!context.isPrerendered && store.sessionTokens == null) {
57
- saveSessionTokensToCookie(context, await generateVisitorTokens());
59
+ if (!context.isPrerendered && existingTokens !== usedTokens) {
60
+ saveSessionTokensToCookie(context, usedTokens);
58
61
  }
59
62
  return response;
60
63
  };
64
+ function getExistingTokens(context) {
65
+ const existingTokens = getSessionTokensFromCookie(context);
66
+ if (existingTokens && existingTokens.accessToken.expiresAt + 600 > Date.now() / 1e3) {
67
+ return existingTokens;
68
+ }
69
+ return null;
70
+ }
61
71
  export {
62
72
  onRequest
63
73
  };
@@ -0,0 +1,5 @@
1
+ import { MiddlewareHandler } from 'astro';
2
+
3
+ declare const onRequest: MiddlewareHandler;
4
+
5
+ export { onRequest };
@@ -0,0 +1,66 @@
1
+ import "../chunk-MLKGABMK.js";
2
+
3
+ // src/middleware/html-embeds.ts
4
+ import { httpClient } from "@wix/essentials";
5
+
6
+ // src/utils/transformStreamUtils.ts
7
+ function injectAfterTransformStream(predicate, htmlToInject) {
8
+ let hasInjected = false;
9
+ return new TransformStream({
10
+ transform: (chunk, controller) => {
11
+ if (!hasInjected) {
12
+ const index = predicate.exec(chunk);
13
+ if (index) {
14
+ const position = index.index + index[0].length;
15
+ chunk = chunk.slice(0, position) + htmlToInject + chunk.slice(position);
16
+ hasInjected = true;
17
+ }
18
+ }
19
+ controller.enqueue(chunk);
20
+ }
21
+ });
22
+ }
23
+ function injectBeforeTransformStream(predicate, htmlToInject) {
24
+ let hasInjected = false;
25
+ return new TransformStream({
26
+ transform: (chunk, controller) => {
27
+ if (!hasInjected) {
28
+ const index = chunk.indexOf(predicate);
29
+ if (index > -1) {
30
+ chunk = chunk.slice(0, index) + htmlToInject + chunk.slice(index);
31
+ hasInjected = true;
32
+ }
33
+ }
34
+ controller.enqueue(chunk);
35
+ }
36
+ });
37
+ }
38
+
39
+ // src/middleware/html-embeds.ts
40
+ var bodyEndTransformStream = (htmlToInject) => injectBeforeTransformStream("</body>", htmlToInject);
41
+ var headTransformStream = (htmlToInject) => injectBeforeTransformStream("</head>", htmlToInject);
42
+ var bodyStartTransformStream = (htmlToInject) => injectAfterTransformStream(/<body(?![^>]*\/>)[^>]*>/, htmlToInject);
43
+ async function fetchScripts() {
44
+ return httpClient.fetchWithAuth("https://edge.wixapis.com/assets/scripts/v1/site-scripts").then((res) => res.json()).then((data) => data.siteScripts);
45
+ }
46
+ var onRequest = async (context, next) => {
47
+ const response = await next();
48
+ const contentType = response.headers.get("Content-Type");
49
+ if (contentType !== "text/html") {
50
+ return response;
51
+ }
52
+ if (context.url.pathname.startsWith("/_wix")) {
53
+ return response;
54
+ }
55
+ const scripts = await fetchScripts();
56
+ const headInjection = scripts.filter((x) => x.position === "HEAD").map((x) => x.html).join("\n");
57
+ const bodyStartInjection = scripts.filter((x) => x.position === "BODY_START").map((x) => x.html).join("\n");
58
+ const bodyEndInjection = scripts.filter((x) => x.position === "BODY_END").map((x) => x.html).join("\n");
59
+ return new Response(
60
+ response.body?.pipeThrough(new TextDecoderStream()).pipeThrough(headTransformStream(headInjection)).pipeThrough(bodyStartTransformStream(bodyStartInjection)).pipeThrough(bodyEndTransformStream(bodyEndInjection)).pipeThrough(new TextEncoderStream()),
61
+ response
62
+ );
63
+ };
64
+ export {
65
+ onRequest
66
+ };
@@ -2,20 +2,22 @@ import {
2
2
  saveSessionTokensToCookie
3
3
  } from "../../chunk-VMS3NKCF.js";
4
4
  import {
5
- z
6
- } from "../../chunk-YMZMZCBN.js";
5
+ object,
6
+ string
7
+ } from "../../chunk-RKE6XT5Z.js";
7
8
  import {
8
9
  auth,
9
10
  oAuthStateCookieName
10
11
  } from "../../chunk-UZPSWWI5.js";
12
+ import "../../chunk-MLKGABMK.js";
11
13
 
12
14
  // src/routes/auth/callback.ts
13
- var oauthCookieSchema = z.object({
14
- codeChallenge: z.string(),
15
- codeVerifier: z.string(),
16
- originalUri: z.string(),
17
- redirectUri: z.string(),
18
- state: z.string()
15
+ var oauthCookieSchema = object({
16
+ codeChallenge: string(),
17
+ codeVerifier: string(),
18
+ originalUri: string(),
19
+ redirectUri: string(),
20
+ state: string()
19
21
  });
20
22
  var GET = async (context) => {
21
23
  const oauthStateCookie = context.cookies.get(oAuthStateCookieName);
@@ -1,24 +1,30 @@
1
1
  import {
2
- z
3
- } from "../../chunk-YMZMZCBN.js";
2
+ _enum,
3
+ object,
4
+ string
5
+ } from "../../chunk-RKE6XT5Z.js";
4
6
  import {
5
7
  auth,
6
8
  oAuthStateCookieName
7
9
  } from "../../chunk-UZPSWWI5.js";
10
+ import "../../chunk-MLKGABMK.js";
8
11
 
9
12
  // src/routes/auth/login.ts
10
- var loginSearchParams = z.object({
11
- prompt: z.enum(["login", "none"]).optional(),
12
- returnToUrl: z.string().optional()
13
+ var loginSearchParams = object({
14
+ prompt: _enum(["login", "none"]).optional(),
15
+ returnToUrl: string().optional()
13
16
  });
14
- var GET = async ({ url }) => {
17
+ var GET = async ({ request, url }) => {
15
18
  const { prompt, returnToUrl = "/" } = loginSearchParams.parse(
16
19
  Object.fromEntries(url.searchParams.entries())
17
20
  );
18
- const oauthData = auth.generateOAuthData(
19
- new URL("/api/auth/callback", url).toString(),
20
- returnToUrl
21
- );
21
+ const callbackUrl = new URL("/api/auth/callback", url);
22
+ const referer = request.headers.get("referer");
23
+ if (referer != null) {
24
+ const originalUrl = new URL(referer);
25
+ callbackUrl.protocol = originalUrl.protocol;
26
+ }
27
+ const oauthData = auth.generateOAuthData(callbackUrl.toString(), returnToUrl);
22
28
  const { authUrl } = await auth.getAuthUrl(oauthData, {
23
29
  prompt,
24
30
  responseMode: "query"
@@ -5,6 +5,7 @@ import {
5
5
  auth,
6
6
  returnToQueryParamName
7
7
  } from "../../chunk-UZPSWWI5.js";
8
+ import "../../chunk-MLKGABMK.js";
8
9
 
9
10
  // src/routes/auth/logout-callback.ts
10
11
  var GET = async (context) => {
@@ -1,14 +1,16 @@
1
1
  import {
2
- z
3
- } from "../../chunk-YMZMZCBN.js";
2
+ object,
3
+ string
4
+ } from "../../chunk-RKE6XT5Z.js";
4
5
  import {
5
6
  auth,
6
7
  returnToQueryParamName
7
8
  } from "../../chunk-UZPSWWI5.js";
9
+ import "../../chunk-MLKGABMK.js";
8
10
 
9
11
  // src/routes/auth/logout.ts
10
- var logoutSearchParams = z.object({
11
- returnToUrl: z.string().optional()
12
+ var logoutSearchParams = object({
13
+ returnToUrl: string().optional()
12
14
  });
13
15
  var POST = async ({ redirect, request, url }) => {
14
16
  const { returnToUrl = "/" } = logoutSearchParams.parse(
@@ -16,6 +18,11 @@ var POST = async ({ redirect, request, url }) => {
16
18
  );
17
19
  const baseUrl = `${new URL(request.url).origin}/${import.meta.env.BASE_URL}`;
18
20
  const postFlowUrl = new URL("/api/auth/logout-callback", baseUrl);
21
+ const referer = request.headers.get("referer");
22
+ if (referer != null) {
23
+ const originalUrl = new URL(referer);
24
+ postFlowUrl.protocol = originalUrl.protocol;
25
+ }
19
26
  postFlowUrl.searchParams.set(returnToQueryParamName, returnToUrl);
20
27
  const { logoutUrl } = await auth.logout(postFlowUrl.toString());
21
28
  return redirect(logoutUrl);
@@ -1,3 +1,5 @@
1
+ import "../chunk-MLKGABMK.js";
2
+
1
3
  // src/routes/service-plugins.ts
2
4
  var ALL = async (context) => {
3
5
  const { ALL: ALL2 } = await import(
@@ -1,3 +1,5 @@
1
+ import "../chunk-MLKGABMK.js";
2
+
1
3
  // src/routes/webhooks.ts
2
4
  var ALL = async (context) => {
3
5
  const { ALL: ALL2 } = await import(
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wix/astro",
3
- "version": "1.0.21",
3
+ "version": "1.0.23",
4
4
  "devDependencies": {
5
5
  "@wix/dashboard": "^1.3.35",
6
6
  "@wix/essentials": "^0.1.23",
@@ -15,7 +15,7 @@
15
15
  "tsup": "^8.1.0",
16
16
  "variant": "^3.0.0-dev.27",
17
17
  "vite": "6.2.6",
18
- "zod": "^3.24.2"
18
+ "zod": "^3.25.67"
19
19
  },
20
20
  "exports": {
21
21
  ".": "./build/index.js",
@@ -48,5 +48,5 @@
48
48
  ]
49
49
  }
50
50
  },
51
- "falconPackageHash": "1582964b2e070bcdaacf19658e234f267a2a3080254a5cc19a91fca2"
51
+ "falconPackageHash": "5741caa5bbdd4030f672591a362f5f6d5cfc52902d127c7833873141"
52
52
  }
@@ -23,7 +23,7 @@ const authProxy = new Proxy(
23
23
  const store = authAsyncLocalStorage.getStore();
24
24
 
25
25
  if (store?.sessionTokens) {
26
- auth.setTokens(store.sessionTokens.tokens);
26
+ auth.setTokens(store.sessionTokens);
27
27
  }
28
28
 
29
29
  // eslint-disable-next-line @typescript-eslint/no-unsafe-function-type
@@ -9,6 +9,6 @@ export function setup(options: { clientId: string }): void {
9
9
  }
10
10
 
11
11
  if (!location.pathname.startsWith('/_wix/extensions/backoffice')) {
12
- getSessionClient(options).enableContext('module');
12
+ getSessionClient(options).enableContext('global');
13
13
  }
14
14
  }
@@ -1,7 +1,7 @@
1
1
  import type { WixClient } from '@wix/sdk';
2
2
  import { createClient, TokenRole } from '@wix/sdk';
3
3
  import { SiteSessionAuth } from '@wix/sdk/auth/site-session';
4
- import { z } from 'zod';
4
+ import * as z from 'zod/v4';
5
5
 
6
6
  export function getSessionClient(options: { clientId: string }): WixClient {
7
7
  return createClient({
package/src/index.ts CHANGED
@@ -89,6 +89,15 @@ const createIntegration = (
89
89
  `
90
90
  );
91
91
 
92
+ // inject HTML embeds
93
+ addMiddleware({
94
+ entrypoint: new URL(
95
+ '../build-runtime/middleware/html-embeds.js',
96
+ import.meta.url
97
+ ),
98
+ order: 'post',
99
+ });
100
+
92
101
  // support server side context calls
93
102
  addMiddleware({
94
103
  entrypoint: new URL(
@@ -1,21 +1,37 @@
1
- import type { MiddlewareHandler } from 'astro';
1
+ import type { APIContext, MiddlewareHandler } from 'astro';
2
2
  import { authAsyncLocalStorage } from '../utils/authAsyncLocalStorage.js';
3
3
  import { generateVisitorTokens } from '../utils/generateVisitorTokens.js';
4
4
  import { getSessionTokensFromCookie } from '../utils/getSessionTokensFromCookie.js';
5
5
  import { saveSessionTokensToCookie } from '../utils/saveSessionTokensToCookie.js';
6
6
 
7
7
  export const onRequest: MiddlewareHandler = async (context, next) => {
8
+ const existingTokens = getExistingTokens(context);
9
+ const usedTokens = existingTokens ?? (await generateVisitorTokens());
10
+
8
11
  const store = {
9
- sessionTokens: getSessionTokensFromCookie(context),
12
+ sessionTokens: usedTokens,
10
13
  };
11
14
 
12
15
  const response = await authAsyncLocalStorage.run(store, () => {
13
16
  return next();
14
17
  });
15
18
 
16
- if (!context.isPrerendered && store.sessionTokens == null) {
17
- saveSessionTokensToCookie(context, await generateVisitorTokens());
19
+ if (!context.isPrerendered && existingTokens !== usedTokens) {
20
+ saveSessionTokensToCookie(context, usedTokens);
18
21
  }
19
22
 
20
23
  return response;
21
24
  };
25
+
26
+ function getExistingTokens(context: APIContext) {
27
+ const existingTokens = getSessionTokensFromCookie(context);
28
+
29
+ if (
30
+ existingTokens &&
31
+ existingTokens.accessToken.expiresAt + 600 > Date.now() / 1000
32
+ ) {
33
+ return existingTokens;
34
+ }
35
+
36
+ return null;
37
+ }
@@ -0,0 +1,67 @@
1
+ import type { MiddlewareHandler } from 'astro';
2
+ import { httpClient } from '@wix/essentials';
3
+ import {
4
+ injectAfterTransformStream,
5
+ injectBeforeTransformStream,
6
+ } from '../utils/transformStreamUtils.js';
7
+
8
+ interface SiteScript {
9
+ html: string;
10
+ position: 'BODY_END' | 'BODY_START' | 'HEAD';
11
+ }
12
+
13
+ const bodyEndTransformStream = (htmlToInject: string) =>
14
+ injectBeforeTransformStream('</body>', htmlToInject);
15
+
16
+ const headTransformStream = (htmlToInject: string) =>
17
+ injectBeforeTransformStream('</head>', htmlToInject);
18
+
19
+ const bodyStartTransformStream = (htmlToInject: string) =>
20
+ injectAfterTransformStream(/<body(?![^>]*\/>)[^>]*>/, htmlToInject);
21
+
22
+ async function fetchScripts() {
23
+ return httpClient
24
+ .fetchWithAuth('https://edge.wixapis.com/assets/scripts/v1/site-scripts')
25
+ .then((res) => res.json() as Promise<{ siteScripts: SiteScript[] }>)
26
+ .then((data) => data.siteScripts);
27
+ }
28
+
29
+ export const onRequest: MiddlewareHandler = async (context, next) => {
30
+ const response = await next();
31
+ const contentType = response.headers.get('Content-Type');
32
+
33
+ if (contentType !== 'text/html') {
34
+ return response;
35
+ }
36
+
37
+ if (context.url.pathname.startsWith('/_wix')) {
38
+ return response;
39
+ }
40
+
41
+ const scripts = await fetchScripts();
42
+
43
+ const headInjection = scripts
44
+ .filter((x) => x.position === 'HEAD')
45
+ .map((x) => x.html)
46
+ .join('\n');
47
+
48
+ const bodyStartInjection = scripts
49
+ .filter((x) => x.position === 'BODY_START')
50
+ .map((x) => x.html)
51
+ .join('\n');
52
+
53
+ const bodyEndInjection = scripts
54
+ .filter((x) => x.position === 'BODY_END')
55
+ .map((x) => x.html)
56
+ .join('\n');
57
+
58
+ return new Response(
59
+ response.body
60
+ ?.pipeThrough(new TextDecoderStream())
61
+ .pipeThrough(headTransformStream(headInjection))
62
+ .pipeThrough(bodyStartTransformStream(bodyStartInjection))
63
+ .pipeThrough(bodyEndTransformStream(bodyEndInjection))
64
+ .pipeThrough(new TextEncoderStream()),
65
+ response
66
+ );
67
+ };
@@ -1,5 +1,5 @@
1
1
  import type { APIRoute } from 'astro';
2
- import { z } from 'zod';
2
+ import * as z from 'zod/v4';
3
3
  import { oAuthStateCookieName } from '../../constants.js';
4
4
  import { auth } from '../../utils/contextualAuth.js';
5
5
  import { saveSessionTokensToCookie } from '../../utils/saveSessionTokensToCookie.js';
@@ -1,5 +1,5 @@
1
1
  import type { APIRoute } from 'astro';
2
- import { z } from 'zod';
2
+ import * as z from 'zod/v4';
3
3
  import { oAuthStateCookieName } from '../../constants.js';
4
4
  import { auth } from '../../utils/contextualAuth.js';
5
5
 
@@ -8,15 +8,20 @@ const loginSearchParams = z.object({
8
8
  returnToUrl: z.string().optional(),
9
9
  });
10
10
 
11
- export const GET: APIRoute = async ({ url }) => {
11
+ export const GET: APIRoute = async ({ request, url }) => {
12
12
  const { prompt, returnToUrl = '/' } = loginSearchParams.parse(
13
13
  Object.fromEntries(url.searchParams.entries())
14
14
  );
15
15
 
16
- const oauthData = auth.generateOAuthData(
17
- new URL('/api/auth/callback', url).toString(),
18
- returnToUrl
19
- );
16
+ const callbackUrl = new URL('/api/auth/callback', url);
17
+ const referer = request.headers.get('referer');
18
+
19
+ if (referer != null) {
20
+ const originalUrl = new URL(referer);
21
+ callbackUrl.protocol = originalUrl.protocol;
22
+ }
23
+
24
+ const oauthData = auth.generateOAuthData(callbackUrl.toString(), returnToUrl);
20
25
 
21
26
  const { authUrl } = await auth.getAuthUrl(oauthData, {
22
27
  prompt,
@@ -1,5 +1,5 @@
1
1
  import type { APIRoute } from 'astro';
2
- import { z } from 'zod';
2
+ import * as z from 'zod/v4';
3
3
  import { returnToQueryParamName } from '../../constants.js';
4
4
  import { auth } from '../../utils/contextualAuth.js';
5
5
 
@@ -13,6 +13,13 @@ export const POST: APIRoute = async ({ redirect, request, url }) => {
13
13
  );
14
14
  const baseUrl = `${new URL(request.url).origin}/${import.meta.env.BASE_URL}`;
15
15
  const postFlowUrl = new URL('/api/auth/logout-callback', baseUrl);
16
+ const referer = request.headers.get('referer');
17
+
18
+ if (referer != null) {
19
+ const originalUrl = new URL(referer);
20
+ postFlowUrl.protocol = originalUrl.protocol;
21
+ }
22
+
16
23
  postFlowUrl.searchParams.set(returnToQueryParamName, returnToUrl);
17
24
 
18
25
  const { logoutUrl } = await auth.logout(postFlowUrl.toString());