@wix/astro 1.0.19 → 1.0.21

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 (38) hide show
  1. package/build/index.js +52 -48
  2. package/build/index.js.map +1 -1
  3. package/build-browser-runtime/setup.js +4082 -11
  4. package/build-runtime/middleware/auth.js +3 -3
  5. package/build-runtime/routes/auth/callback.d.ts +2 -2
  6. package/build-runtime/routes/auth/callback.js +6 -4
  7. package/build-runtime/routes/auth/login.d.ts +2 -2
  8. package/build-runtime/routes/auth/login.js +3 -3
  9. package/build-runtime/routes/auth/logout-callback.js +4 -2
  10. package/build-runtime/routes/auth/logout.d.ts +2 -2
  11. package/build-runtime/routes/auth/logout.js +12 -4
  12. package/package.json +2 -2
  13. package/src/context/non-elevated.ts +1 -1
  14. package/src/context/setup.ts +1 -1
  15. package/src/context/utils.ts +24 -13
  16. package/src/index.ts +2 -2
  17. package/src/routes/auth/callback.ts +6 -4
  18. package/src/routes/auth/login.ts +4 -4
  19. package/src/routes/auth/logout-callback.ts +3 -1
  20. package/src/routes/auth/logout.ts +12 -5
  21. package/src/routes/service-plugins.ts +2 -2
  22. package/src/routes/webhooks.ts +2 -2
  23. package/src/schemas.ts +2 -2
  24. package/src/utils/createProjectModel.ts +23 -21
  25. package/src/utils/fs-utils.ts +20 -20
  26. package/src/utils/generateAppManifest.ts +12 -12
  27. package/src/utils/generateVisitorTokens.ts +2 -1
  28. package/src/utils/getSessionTokensFromCookie.ts +3 -3
  29. package/src/utils/isValidBackofficeComponent.ts +4 -3
  30. package/src/utils/isValidServicePluginComponent.ts +6 -6
  31. package/src/utils/isValidWebhookComponent.ts +1 -1
  32. package/src/utils/loadEnvVars.ts +5 -2
  33. package/src/utils/saveSessionTokensToCookie.ts +10 -7
  34. package/src/utils/writeVirtualBackofficeExtensionFiles.ts +1 -1
  35. package/src/utils/writeVirtualServicePluginExtensionFiles.ts +1 -1
  36. package/src/utils/writeVirtualWebhookExtensionFiles.ts +1 -1
  37. package/tsup.config.mjs +17 -17
  38. package/build-runtime/{chunk-HVACFX6T.js → chunk-VMS3NKCF.js} +6 -6
@@ -3,7 +3,7 @@ import {
3
3
  } from "../chunk-C3QOE2TZ.js";
4
4
  import {
5
5
  saveSessionTokensToCookie
6
- } from "../chunk-HVACFX6T.js";
6
+ } from "../chunk-VMS3NKCF.js";
7
7
 
8
8
  // src/utils/generateVisitorTokens.ts
9
9
  import { OAuthStrategy } from "@wix/sdk";
@@ -17,8 +17,8 @@ async function generateVisitorTokens() {
17
17
 
18
18
  // src/utils/getSessionTokensFromCookie.ts
19
19
  import { TokenRole } from "@wix/sdk";
20
- import { WIX_CLIENT_ID as WIX_CLIENT_ID2 } from "astro:env/client";
21
20
  import { z } from "astro/zod";
21
+ import { WIX_CLIENT_ID as WIX_CLIENT_ID2 } from "astro:env/client";
22
22
  var tokensSchema = z.object({
23
23
  clientId: z.string(),
24
24
  tokens: z.object({
@@ -35,7 +35,7 @@ var tokensSchema = z.object({
35
35
  function getSessionTokensFromCookie(context) {
36
36
  if (!context.isPrerendered) {
37
37
  const rawCookie = context.cookies.get("wixSession")?.json();
38
- if (rawCookie) {
38
+ if (rawCookie != null) {
39
39
  const tokensParseResult = tokensSchema.safeParse(rawCookie);
40
40
  if (tokensParseResult.success && tokensParseResult.data.clientId === WIX_CLIENT_ID2) {
41
41
  return tokensParseResult.data;
@@ -1,5 +1,5 @@
1
- import { APIContext } from 'astro';
1
+ import { APIRoute } from 'astro';
2
2
 
3
- declare function GET(context: APIContext): Promise<Response>;
3
+ declare const GET: APIRoute;
4
4
 
5
5
  export { GET };
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  saveSessionTokensToCookie
3
- } from "../../chunk-HVACFX6T.js";
3
+ } from "../../chunk-VMS3NKCF.js";
4
4
  import {
5
5
  z
6
6
  } from "../../chunk-YMZMZCBN.js";
@@ -17,14 +17,16 @@ var oauthCookieSchema = z.object({
17
17
  redirectUri: z.string(),
18
18
  state: z.string()
19
19
  });
20
- async function GET(context) {
20
+ var GET = async (context) => {
21
21
  const oauthStateCookie = context.cookies.get(oAuthStateCookieName);
22
22
  if (oauthStateCookie == null) {
23
23
  throw new Error(`Missing \`${oAuthStateCookieName}\` cookie`);
24
24
  }
25
25
  const oauthData = oauthCookieSchema.parse(JSON.parse(oauthStateCookie.value));
26
26
  if (!oauthData.originalUri.startsWith("/")) {
27
- throw new Error("Invalid `originalUri` cookie param");
27
+ throw new Error(
28
+ "Invalid `originalUri` cookie param, only relative URLs are allowed"
29
+ );
28
30
  }
29
31
  const { code, error, errorDescription, state } = auth.parseFromUrl(
30
32
  context.url.toString(),
@@ -42,7 +44,7 @@ async function GET(context) {
42
44
  });
43
45
  saveSessionTokensToCookie(context, memberTokens);
44
46
  return context.redirect(oauthData.originalUri);
45
- }
47
+ };
46
48
  export {
47
49
  GET
48
50
  };
@@ -1,5 +1,5 @@
1
- import { APIContext } from 'astro';
1
+ import { APIRoute } from 'astro';
2
2
 
3
- declare function GET({ url }: APIContext): Promise<Response>;
3
+ declare const GET: APIRoute;
4
4
 
5
5
  export { GET };
@@ -11,8 +11,8 @@ var loginSearchParams = z.object({
11
11
  prompt: z.enum(["login", "none"]).optional(),
12
12
  returnToUrl: z.string().optional()
13
13
  });
14
- async function GET({ url }) {
15
- const { prompt, returnToUrl } = loginSearchParams.parse(
14
+ var GET = async ({ url }) => {
15
+ const { prompt, returnToUrl = "/" } = loginSearchParams.parse(
16
16
  Object.fromEntries(url.searchParams.entries())
17
17
  );
18
18
  const oauthData = auth.generateOAuthData(
@@ -32,7 +32,7 @@ async function GET({ url }) {
32
32
  },
33
33
  status: 302
34
34
  });
35
- }
35
+ };
36
36
  export {
37
37
  GET
38
38
  };
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  saveSessionTokensToCookie
3
- } from "../../chunk-HVACFX6T.js";
3
+ } from "../../chunk-VMS3NKCF.js";
4
4
  import {
5
5
  auth,
6
6
  returnToQueryParamName
@@ -10,7 +10,9 @@ import {
10
10
  var GET = async (context) => {
11
11
  const returnTo = context.url.searchParams.get(returnToQueryParamName) ?? "/";
12
12
  if (!returnTo.startsWith("/")) {
13
- throw new Error(`Invalid \`${returnToQueryParamName}\` query param`);
13
+ throw new Error(
14
+ `Invalid \`${returnToQueryParamName}\` query param, only relative URLs are allowed`
15
+ );
14
16
  }
15
17
  saveSessionTokensToCookie(context, await auth.generateVisitorTokens());
16
18
  return context.redirect(returnTo);
@@ -1,5 +1,5 @@
1
- import { APIContext } from 'astro';
1
+ import { APIRoute } from 'astro';
2
2
 
3
- declare function POST({ redirect, request }: APIContext): Promise<Response>;
3
+ declare const POST: APIRoute;
4
4
 
5
5
  export { POST };
@@ -1,17 +1,25 @@
1
+ import {
2
+ z
3
+ } from "../../chunk-YMZMZCBN.js";
1
4
  import {
2
5
  auth,
3
6
  returnToQueryParamName
4
7
  } from "../../chunk-UZPSWWI5.js";
5
8
 
6
9
  // src/routes/auth/logout.ts
7
- async function POST({ redirect, request }) {
8
- const returnTo = request.headers.get("Referer") ?? "/";
10
+ var logoutSearchParams = z.object({
11
+ returnToUrl: z.string().optional()
12
+ });
13
+ var POST = async ({ redirect, request, url }) => {
14
+ const { returnToUrl = "/" } = logoutSearchParams.parse(
15
+ Object.fromEntries(url.searchParams.entries())
16
+ );
9
17
  const baseUrl = `${new URL(request.url).origin}/${import.meta.env.BASE_URL}`;
10
18
  const postFlowUrl = new URL("/api/auth/logout-callback", baseUrl);
11
- postFlowUrl.searchParams.set(returnToQueryParamName, returnTo);
19
+ postFlowUrl.searchParams.set(returnToQueryParamName, returnToUrl);
12
20
  const { logoutUrl } = await auth.logout(postFlowUrl.toString());
13
21
  return redirect(logoutUrl);
14
- }
22
+ };
15
23
  export {
16
24
  POST
17
25
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wix/astro",
3
- "version": "1.0.19",
3
+ "version": "1.0.21",
4
4
  "devDependencies": {
5
5
  "@wix/dashboard": "^1.3.35",
6
6
  "@wix/essentials": "^0.1.23",
@@ -48,5 +48,5 @@
48
48
  ]
49
49
  }
50
50
  },
51
- "falconPackageHash": "8a07e41b5e45d53fdec973ec91c81fea694425019d8792af6d2c9872"
51
+ "falconPackageHash": "1582964b2e070bcdaacf19658e234f267a2a3080254a5cc19a91fca2"
52
52
  }
@@ -27,7 +27,7 @@ const authProxy = new Proxy(
27
27
  }
28
28
 
29
29
  // eslint-disable-next-line @typescript-eslint/no-unsafe-function-type
30
- return (value as Function).apply(auth, args);
30
+ return (value as Function).apply(auth, args) as unknown;
31
31
  };
32
32
  },
33
33
  }
@@ -1,7 +1,7 @@
1
1
  import { wixContext } from '@wix/sdk-context';
2
2
  import { getSessionClient } from './utils.js';
3
3
 
4
- export function setup(options: { clientId: string }) {
4
+ export function setup(options: { clientId: string }): void {
5
5
  // check untyped global context which may be necessary if
6
6
  // both `page` and `before-hydration` hooks have been loaded together
7
7
  if (wixContext.client != null) {
@@ -1,29 +1,40 @@
1
- import { createClient } from '@wix/sdk';
1
+ import type { WixClient } from '@wix/sdk';
2
+ import { createClient, TokenRole } from '@wix/sdk';
2
3
  import { SiteSessionAuth } from '@wix/sdk/auth/site-session';
4
+ import { z } from 'zod';
5
+
6
+ export function getSessionClient(options: { clientId: string }): WixClient {
7
+ return createClient({
8
+ auth: SiteSessionAuth({
9
+ tokens: getCookieAsJson('wixSession')?.tokens,
10
+ ...options,
11
+ }),
12
+ });
13
+ }
14
+
15
+ const cookieSchema = z.object({
16
+ tokens: z.object({
17
+ accessToken: z.object({ expiresAt: z.number(), value: z.string() }),
18
+ refreshToken: z.object({
19
+ role: z.enum([TokenRole.MEMBER, TokenRole.NONE, TokenRole.VISITOR]),
20
+ value: z.string(),
21
+ }),
22
+ }),
23
+ });
3
24
 
4
25
  function getCookieAsJson(name: string) {
5
26
  const cookies = document.cookie.split('; ');
6
27
  const cookie = cookies.find((row) => row.startsWith(`${name}=`));
7
28
 
8
- if (!cookie) {
29
+ if (cookie == null) {
9
30
  return null;
10
31
  }
11
32
 
12
33
  try {
13
34
  const jsonString = decodeURIComponent(cookie.split('=')[1] ?? '');
14
- return JSON.parse(jsonString);
35
+ return cookieSchema.parse(JSON.parse(jsonString));
15
36
  } catch (error) {
16
- // eslint-disable-next-line no-console
17
37
  console.error('Error parsing cookie JSON:', error);
18
38
  return null;
19
39
  }
20
40
  }
21
-
22
- export function getSessionClient(options: { clientId: string }) {
23
- return createClient({
24
- auth: SiteSessionAuth({
25
- tokens: getCookieAsJson('wixSession')?.tokens,
26
- ...options,
27
- }),
28
- });
29
- }
package/src/index.ts CHANGED
@@ -49,7 +49,7 @@ const createIntegration = (
49
49
  { spaces: 2 }
50
50
  );
51
51
  },
52
- 'astro:config:done': async ({ config }) => {
52
+ 'astro:config:done': ({ config }) => {
53
53
  _config = config;
54
54
  },
55
55
  async 'astro:config:setup'({
@@ -308,7 +308,7 @@ const createIntegration = (
308
308
 
309
309
  await writeVirtualBackofficeExtensionFiles(model, backofficeCodegenDir);
310
310
  },
311
- 'astro:server:setup': async ({ logger, server }) => {
311
+ 'astro:server:setup': ({ logger, server }) => {
312
312
  server.middlewares.use(async (req, res, next) => {
313
313
  if (req.url === '/_wix/app-manifest.json') {
314
314
  const model = await createProjectModel(logger);
@@ -1,4 +1,4 @@
1
- import type { APIContext } from 'astro';
1
+ import type { APIRoute } from 'astro';
2
2
  import { z } from 'zod';
3
3
  import { oAuthStateCookieName } from '../../constants.js';
4
4
  import { auth } from '../../utils/contextualAuth.js';
@@ -12,7 +12,7 @@ const oauthCookieSchema = z.object({
12
12
  state: z.string(),
13
13
  });
14
14
 
15
- export async function GET(context: APIContext) {
15
+ export const GET: APIRoute = async (context) => {
16
16
  const oauthStateCookie = context.cookies.get(oAuthStateCookieName);
17
17
 
18
18
  if (oauthStateCookie == null) {
@@ -22,7 +22,9 @@ export async function GET(context: APIContext) {
22
22
  const oauthData = oauthCookieSchema.parse(JSON.parse(oauthStateCookie.value));
23
23
 
24
24
  if (!oauthData.originalUri.startsWith('/')) {
25
- throw new Error('Invalid `originalUri` cookie param');
25
+ throw new Error(
26
+ 'Invalid `originalUri` cookie param, only relative URLs are allowed'
27
+ );
26
28
  }
27
29
 
28
30
  const { code, error, errorDescription, state } = auth.parseFromUrl(
@@ -46,4 +48,4 @@ export async function GET(context: APIContext) {
46
48
  saveSessionTokensToCookie(context, memberTokens);
47
49
 
48
50
  return context.redirect(oauthData.originalUri);
49
- }
51
+ };
@@ -1,4 +1,4 @@
1
- import type { APIContext } from 'astro';
1
+ import type { APIRoute } from 'astro';
2
2
  import { z } from 'zod';
3
3
  import { oAuthStateCookieName } from '../../constants.js';
4
4
  import { auth } from '../../utils/contextualAuth.js';
@@ -8,8 +8,8 @@ const loginSearchParams = z.object({
8
8
  returnToUrl: z.string().optional(),
9
9
  });
10
10
 
11
- export async function GET({ url }: APIContext) {
12
- const { prompt, returnToUrl } = loginSearchParams.parse(
11
+ export const GET: APIRoute = async ({ url }) => {
12
+ const { prompt, returnToUrl = '/' } = loginSearchParams.parse(
13
13
  Object.fromEntries(url.searchParams.entries())
14
14
  );
15
15
 
@@ -32,4 +32,4 @@ export async function GET({ url }: APIContext) {
32
32
  },
33
33
  status: 302,
34
34
  });
35
- }
35
+ };
@@ -7,7 +7,9 @@ export const GET: APIRoute = async (context) => {
7
7
  const returnTo = context.url.searchParams.get(returnToQueryParamName) ?? '/';
8
8
 
9
9
  if (!returnTo.startsWith('/')) {
10
- throw new Error(`Invalid \`${returnToQueryParamName}\` query param`);
10
+ throw new Error(
11
+ `Invalid \`${returnToQueryParamName}\` query param, only relative URLs are allowed`
12
+ );
11
13
  }
12
14
 
13
15
  saveSessionTokensToCookie(context, await auth.generateVisitorTokens());
@@ -1,14 +1,21 @@
1
- import type { APIContext } from 'astro';
1
+ import type { APIRoute } from 'astro';
2
+ import { z } from 'zod';
2
3
  import { returnToQueryParamName } from '../../constants.js';
3
4
  import { auth } from '../../utils/contextualAuth.js';
4
5
 
5
- export async function POST({ redirect, request }: APIContext) {
6
- const returnTo = request.headers.get('Referer') ?? '/';
6
+ const logoutSearchParams = z.object({
7
+ returnToUrl: z.string().optional(),
8
+ });
9
+
10
+ export const POST: APIRoute = async ({ redirect, request, url }) => {
11
+ const { returnToUrl = '/' } = logoutSearchParams.parse(
12
+ Object.fromEntries(url.searchParams.entries())
13
+ );
7
14
  const baseUrl = `${new URL(request.url).origin}/${import.meta.env.BASE_URL}`;
8
15
  const postFlowUrl = new URL('/api/auth/logout-callback', baseUrl);
9
- postFlowUrl.searchParams.set(returnToQueryParamName, returnTo);
16
+ postFlowUrl.searchParams.set(returnToQueryParamName, returnToUrl);
10
17
 
11
18
  const { logoutUrl } = await auth.logout(postFlowUrl.toString());
12
19
 
13
20
  return redirect(logoutUrl);
14
- }
21
+ };
@@ -1,10 +1,10 @@
1
1
  import type { APIRoute } from 'astro';
2
2
 
3
3
  export const ALL: APIRoute = async (context) => {
4
- const { ALL } = await import(
4
+ const { ALL } = (await import(
5
5
  /* @vite-ignore */
6
6
  `/.astro/integrations/_wix_astro/extensions/service-plugins/${context.params.compId}.ts`
7
- );
7
+ )) as { ALL: APIRoute };
8
8
 
9
9
  return ALL(context);
10
10
  };
@@ -1,10 +1,10 @@
1
1
  import type { APIRoute } from 'astro';
2
2
 
3
3
  export const ALL: APIRoute = async (context) => {
4
- const { ALL } = await import(
4
+ const { ALL } = (await import(
5
5
  /* @vite-ignore */
6
6
  `/.astro/integrations/_wix_astro/extensions/webhooks/${context.params.compId}.ts`
7
- );
7
+ )) as { ALL: APIRoute };
8
8
 
9
9
  return ALL(context);
10
10
  };
package/src/schemas.ts CHANGED
@@ -210,9 +210,9 @@ export const devCenterComponentSchema = z.discriminatedUnion('compType', [
210
210
  devCenterEcomGiftCardsProviderSchema,
211
211
  ]);
212
212
 
213
- export type DevCenterComponent = z.infer<typeof devCenterComponentSchema>;
214
-
215
213
  export interface DevCenterAppManifest {
216
214
  appId: string;
217
215
  components: BaseDevCenterComponent[];
218
216
  }
217
+
218
+ export type DevCenterComponent = z.infer<typeof devCenterComponentSchema>;
@@ -14,9 +14,11 @@ import {
14
14
  import { pathExists, readJson } from './fs-utils.js';
15
15
  import { loadEnvVars } from './loadEnvVars.js';
16
16
 
17
- export async function createProjectModel(logger: AstroIntegrationLogger) {
17
+ export async function createProjectModel(
18
+ logger: AstroIntegrationLogger
19
+ ): Promise<Model> {
18
20
  const rootDir = cwd();
19
- const { appId, env } = loadEnvVars(rootDir, logger);
21
+ const { appId, env } = loadEnvVars(logger);
20
22
 
21
23
  const componentsPaths = await globby(
22
24
  pathToGlobby(join(EXTENSIONS_DIR, '*')),
@@ -31,14 +33,14 @@ export async function createProjectModel(logger: AstroIntegrationLogger) {
31
33
 
32
34
  for (const componentPath of componentsPaths) {
33
35
  const extensionManifest = await readExtensionManifest(componentPath);
34
- const knownManifest = await parseKnownExtensionManifest(extensionManifest);
36
+ const knownManifest = parseKnownExtensionManifest(extensionManifest);
35
37
 
36
38
  if (knownManifest != null) {
37
39
  components.push(createComponent(knownManifest, componentPath));
38
40
  continue;
39
41
  }
40
42
 
41
- const unknownManifest = await parseBaseExtensionManifest(extensionManifest);
43
+ const unknownManifest = parseBaseExtensionManifest(extensionManifest);
42
44
 
43
45
  unknownComponents.push(
44
46
  UnknownComponent.Unknown({
@@ -54,15 +56,11 @@ export async function createProjectModel(logger: AstroIntegrationLogger) {
54
56
  env,
55
57
  rootDir,
56
58
  unknownComponents,
57
- } satisfies Model;
59
+ };
58
60
  }
59
61
 
60
62
  // https://github.com/mrmlnc/fast-glob/releases/tag/3.0.0
61
63
  // globby using fast-glob under the hood accepts only forward slashes in patterns.
62
- function pathToGlobby(path: string) {
63
- return path.replaceAll('\\', '/');
64
- }
65
-
66
64
  function createComponent(manifest: DevCenterComponent, directory: string) {
67
65
  switch (manifest.compType) {
68
66
  case 'BACK_OFFICE_EXTENSION_MENU_ITEM':
@@ -133,18 +131,7 @@ function createComponent(manifest: DevCenterComponent, directory: string) {
133
131
  }
134
132
  }
135
133
 
136
- async function parseKnownExtensionManifest(extensionManifest: unknown) {
137
- const appManifestResult =
138
- devCenterComponentSchema.safeParse(extensionManifest);
139
-
140
- if (appManifestResult.error) {
141
- return null;
142
- }
143
-
144
- return appManifestResult.data;
145
- }
146
-
147
- async function parseBaseExtensionManifest(extensionManifest: unknown) {
134
+ function parseBaseExtensionManifest(extensionManifest: unknown) {
148
135
  const appManifestResult =
149
136
  baseDevCenterComponentSchema.safeParse(extensionManifest);
150
137
 
@@ -161,6 +148,21 @@ async function parseBaseExtensionManifest(extensionManifest: unknown) {
161
148
  return appManifestResult.data;
162
149
  }
163
150
 
151
+ function parseKnownExtensionManifest(extensionManifest: unknown) {
152
+ const appManifestResult =
153
+ devCenterComponentSchema.safeParse(extensionManifest);
154
+
155
+ if (appManifestResult.error) {
156
+ return null;
157
+ }
158
+
159
+ return appManifestResult.data;
160
+ }
161
+
162
+ function pathToGlobby(path: string) {
163
+ return path.replaceAll('\\', '/');
164
+ }
165
+
164
166
  async function readExtensionManifest(directoryPath: string) {
165
167
  const manifestFilePath = join(directoryPath, 'extension.json');
166
168
 
@@ -7,36 +7,36 @@ import {
7
7
  import { EOL } from 'node:os';
8
8
  import { dirname, relative } from 'node:path';
9
9
 
10
- function toJsonString(object: unknown, opts?: { spaces: number }) {
11
- return JSON.stringify(object, null, opts?.spaces).concat(EOL);
10
+ export async function outputDir(dir: string): Promise<void> {
11
+ await mkdir(dir, { recursive: true });
12
12
  }
13
13
 
14
- export async function writeJson(
15
- filePath: string,
16
- object: unknown,
17
- opts?: { spaces: number }
18
- ) {
19
- const str = toJsonString(object, opts);
20
- await outputDir(dirname(filePath));
21
-
22
- await writeFile(filePath, str, 'utf-8');
14
+ export function pathExists(path: string): Promise<boolean> {
15
+ return access(path)
16
+ .then(() => true)
17
+ .catch(() => false);
23
18
  }
24
19
 
25
20
  export async function readJson(file: string): Promise<unknown> {
26
21
  return JSON.parse(await fsReadFile(file, 'utf-8'));
27
22
  }
28
23
 
29
- export function pathExists(path: string) {
30
- return access(path)
31
- .then(() => true)
32
- .catch(() => false);
24
+ export function toRelativePath(from: string, to: string): string {
25
+ const rel = relative(dirname(from), to).replaceAll('\\', '/');
26
+ return rel.startsWith('.') ? rel : `./${rel}`;
33
27
  }
34
28
 
35
- export async function outputDir(dir: string) {
36
- await mkdir(dir, { recursive: true });
29
+ export async function writeJson(
30
+ filePath: string,
31
+ object: unknown,
32
+ opts?: { spaces: number }
33
+ ): Promise<void> {
34
+ const str = toJsonString(object, opts);
35
+ await outputDir(dirname(filePath));
36
+
37
+ await writeFile(filePath, str, 'utf-8');
37
38
  }
38
39
 
39
- export function toRelativePath(from: string, to: string) {
40
- const rel = relative(dirname(from), to).replaceAll('\\', '/');
41
- return rel.startsWith('.') ? rel : `./${rel}`;
40
+ function toJsonString(object: unknown, opts?: { spaces: number }) {
41
+ return `${JSON.stringify(object, null, opts?.spaces)}${EOL}`;
42
42
  }
@@ -14,7 +14,7 @@ import type {
14
14
  } from '../schemas.js';
15
15
  import type { Model } from '../types.js';
16
16
 
17
- export function generateAppManifest(model: Model) {
17
+ export function generateAppManifest(model: Model): DevCenterAppManifest {
18
18
  const extensions = model.components
19
19
  .map((component) => component.manifest)
20
20
  .map((manifest) => {
@@ -22,7 +22,7 @@ export function generateAppManifest(model: Model) {
22
22
  case 'BACK_OFFICE_EXTENSION_MENU_ITEM':
23
23
  return manifest satisfies DevCenterBackofficeExtensionMenuItem;
24
24
  case 'BACK_OFFICE_EXTENSION_WIDGET':
25
- if (manifest.compData.backOfficeExtensionWidget.iframeUrl) {
25
+ if (manifest.compData.backOfficeExtensionWidget.iframeUrl != null) {
26
26
  return manifest;
27
27
  }
28
28
 
@@ -36,7 +36,7 @@ export function generateAppManifest(model: Model) {
36
36
  },
37
37
  } satisfies DevCenterBackofficeExtensionWidget;
38
38
  case 'BACK_OFFICE_MODAL':
39
- if (manifest.compData.backOfficeModal.iframeUrl) {
39
+ if (manifest.compData.backOfficeModal.iframeUrl != null) {
40
40
  return manifest;
41
41
  }
42
42
 
@@ -50,7 +50,7 @@ export function generateAppManifest(model: Model) {
50
50
  },
51
51
  } satisfies DevCenterBackofficeModal;
52
52
  case 'BACK_OFFICE_PAGE':
53
- if (manifest.compData.backOfficePage.iframeUrl) {
53
+ if (manifest.compData.backOfficePage.iframeUrl != null) {
54
54
  return manifest;
55
55
  }
56
56
 
@@ -64,7 +64,7 @@ export function generateAppManifest(model: Model) {
64
64
  },
65
65
  } satisfies DevCenterBackofficePage;
66
66
  case 'ECOM_ADDITIONAL_FEES':
67
- if (manifest.compData.ecomAdditionalFees.deploymentUri) {
67
+ if (manifest.compData.ecomAdditionalFees.deploymentUri != null) {
68
68
  return manifest;
69
69
  }
70
70
 
@@ -78,7 +78,7 @@ export function generateAppManifest(model: Model) {
78
78
  },
79
79
  } satisfies DevCenterEcomAdditionalFees;
80
80
  case 'ECOM_DISCOUNTS_TRIGGER':
81
- if (manifest.compData.ecomDiscountsTrigger.deploymentUri) {
81
+ if (manifest.compData.ecomDiscountsTrigger.deploymentUri != null) {
82
82
  return manifest;
83
83
  }
84
84
 
@@ -92,7 +92,7 @@ export function generateAppManifest(model: Model) {
92
92
  },
93
93
  } satisfies DevCenterEcomDiscountsTrigger;
94
94
  case 'ECOM_PAYMENT_SETTINGS':
95
- if (manifest.compData.ecomPaymentSettings.deploymentUri) {
95
+ if (manifest.compData.ecomPaymentSettings.deploymentUri != null) {
96
96
  return manifest;
97
97
  }
98
98
 
@@ -106,7 +106,7 @@ export function generateAppManifest(model: Model) {
106
106
  },
107
107
  } satisfies DevCenterEcomPaymentSettings;
108
108
  case 'ECOM_SHIPPING_RATES':
109
- if (manifest.compData.ecomShippingRates.deploymentUri) {
109
+ if (manifest.compData.ecomShippingRates.deploymentUri != null) {
110
110
  return manifest;
111
111
  }
112
112
 
@@ -120,7 +120,7 @@ export function generateAppManifest(model: Model) {
120
120
  },
121
121
  } satisfies DevCenterEcomShippingRates;
122
122
  case 'ECOM_VALIDATIONS':
123
- if (manifest.compData.ecomValidations.deploymentUri) {
123
+ if (manifest.compData.ecomValidations.deploymentUri != null) {
124
124
  return manifest;
125
125
  }
126
126
 
@@ -134,7 +134,7 @@ export function generateAppManifest(model: Model) {
134
134
  },
135
135
  } satisfies DevCenterEcomValidations;
136
136
  case 'GIFT_CARDS_PROVIDER':
137
- if (manifest.compData.giftCardsProvider.deploymentUri) {
137
+ if (manifest.compData.giftCardsProvider.deploymentUri != null) {
138
138
  return manifest;
139
139
  }
140
140
 
@@ -148,7 +148,7 @@ export function generateAppManifest(model: Model) {
148
148
  },
149
149
  } satisfies DevCenterEcomGiftCardsProvider;
150
150
  case 'WEBHOOK':
151
- if (manifest.compData.webhook.callbackUrl) {
151
+ if (manifest.compData.webhook.callbackUrl != null) {
152
152
  return manifest;
153
153
  }
154
154
 
@@ -173,5 +173,5 @@ export function generateAppManifest(model: Model) {
173
173
  return {
174
174
  appId: model.appId,
175
175
  components: [...extensions, ...unknownExtensions],
176
- } satisfies DevCenterAppManifest;
176
+ };
177
177
  }