@scayle/storefront-nuxt 7.41.0 → 7.42.1

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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,29 @@
1
1
  # @scayle/storefront-nuxt
2
2
 
3
+ ## 7.42.1
4
+
5
+ ### Patch Changes
6
+
7
+ - Ensure useNuxtApp is only called from a composable context
8
+
9
+ ## 7.42.0
10
+
11
+ ### Minor Changes
12
+
13
+ - Unify Storefront Core cache handling using the [Nitro Storage Layer - Mountpoints](https://www.nitropack.org/guide/storage#mountpoints)
14
+
15
+ This release changes how cache and session storage is managed in Storefront Core. Storefront Core will now use the `storefront-cache` mountpoint as the root for its cache storage, and `storefront-session` for sessions storage. These can be manually configured through Nitro, but Storefront Core also now includes `storefront.storage.cache` and `storefront.storage.session` config options to automatically create these mountpoints.
16
+
17
+ `storefront.storage.cache` is used to configure the primary global cache storage mounted under `storefront-cache`. If not configured, a dedicated memory driver is used.
18
+
19
+ `storefront.storage.session` is used to configure the global session storage mounted under `storefront-session`. If not configured, a dedicated memory driver is used.
20
+
21
+ The config options `storefront.redis`, `storefront.stores[X].redis`, `storefront.session.provider` and `storefront.cache.provider` have been deprecated in favor of the new `storage` config. In a future version, they will be replaced.
22
+
23
+ ### Patch Changes
24
+
25
+ - Update to Nuxt `v3.8.2` (See [Nuxt v3.8.2 Release notes](https://github.com/nuxt/nuxt/releases/tag/v3.8.2) for details.)
26
+
3
27
  ## 7.41.0
4
28
 
5
29
  ### Minor Changes
package/dist/index.d.mts CHANGED
@@ -1,7 +1,8 @@
1
- export { e as AdditionalShopConfig, A as AppKeys, d as AuthenticationConfig, B as BapiConfig, b as CacheConfig, i as CheckoutEvent, C as CheckoutShopConfig, M as ModuleOptions, O as OauthConfig, P as PublicShopConfig, c as RedirectsConfig, R as RedisConfig, a as SessionConfig, f as ShopConfig, g as ShopConfigIndexed, S as StorageProvider, h as StorefrontConfig } from './shared/storefront-nuxt.1cbf9601.mjs';
1
+ export { g as AdditionalShopConfig, A as AppKeys, f as AuthenticationConfig, B as BapiConfig, b as CacheConfig, k as CheckoutEvent, C as CheckoutShopConfig, M as ModuleOptions, O as OauthConfig, P as PublicShopConfig, e as RedirectsConfig, R as RedisConfig, a as SessionConfig, h as ShopConfig, i as ShopConfigIndexed, d as StorageConfig, c as StorageEntity, S as StorageProvider, j as StorefrontConfig } from './shared/storefront-nuxt.180408c8.mjs';
2
2
  export { rpcCall } from './rpc.mjs';
3
3
  export * from '@scayle/storefront-core';
4
4
  export { LogLevel } from '@scayle/storefront-core';
5
+ import 'unstorage';
5
6
  import 'nuxt/app';
6
7
 
7
8
  interface RpcMethodsStorefront {
package/dist/index.d.ts CHANGED
@@ -1,7 +1,8 @@
1
- export { e as AdditionalShopConfig, A as AppKeys, d as AuthenticationConfig, B as BapiConfig, b as CacheConfig, i as CheckoutEvent, C as CheckoutShopConfig, M as ModuleOptions, O as OauthConfig, P as PublicShopConfig, c as RedirectsConfig, R as RedisConfig, a as SessionConfig, f as ShopConfig, g as ShopConfigIndexed, S as StorageProvider, h as StorefrontConfig } from './shared/storefront-nuxt.1cbf9601.js';
1
+ export { g as AdditionalShopConfig, A as AppKeys, f as AuthenticationConfig, B as BapiConfig, b as CacheConfig, k as CheckoutEvent, C as CheckoutShopConfig, M as ModuleOptions, O as OauthConfig, P as PublicShopConfig, e as RedirectsConfig, R as RedisConfig, a as SessionConfig, h as ShopConfig, i as ShopConfigIndexed, d as StorageConfig, c as StorageEntity, S as StorageProvider, j as StorefrontConfig } from './shared/storefront-nuxt.180408c8.js';
2
2
  export { rpcCall } from './rpc.js';
3
3
  export * from '@scayle/storefront-core';
4
4
  export { LogLevel } from '@scayle/storefront-core';
5
+ import 'unstorage';
5
6
  import 'nuxt/app';
6
7
 
7
8
  interface RpcMethodsStorefront {
package/dist/module.d.mts CHANGED
@@ -1,7 +1,8 @@
1
1
  import * as _nuxt_schema from '@nuxt/schema';
2
- import { M as ModuleOptions } from './shared/storefront-nuxt.1cbf9601.mjs';
3
- export { e as AdditionalShopConfig, A as AppKeys, d as AuthenticationConfig, B as BapiConfig, b as CacheConfig, i as CheckoutEvent, C as CheckoutShopConfig, O as OauthConfig, P as PublicShopConfig, c as RedirectsConfig, R as RedisConfig, a as SessionConfig, f as ShopConfig, g as ShopConfigIndexed, S as StorageProvider, h as StorefrontConfig } from './shared/storefront-nuxt.1cbf9601.mjs';
2
+ import { M as ModuleOptions } from './shared/storefront-nuxt.180408c8.mjs';
3
+ export { g as AdditionalShopConfig, A as AppKeys, f as AuthenticationConfig, B as BapiConfig, b as CacheConfig, k as CheckoutEvent, C as CheckoutShopConfig, O as OauthConfig, P as PublicShopConfig, e as RedirectsConfig, R as RedisConfig, a as SessionConfig, h as ShopConfig, i as ShopConfigIndexed, d as StorageConfig, c as StorageEntity, S as StorageProvider, j as StorefrontConfig } from './shared/storefront-nuxt.180408c8.mjs';
4
4
  export { LogLevel } from '@scayle/storefront-core';
5
+ import 'unstorage';
5
6
 
6
7
  declare const _default: _nuxt_schema.NuxtModule<ModuleOptions>;
7
8
 
package/dist/module.d.ts CHANGED
@@ -1,7 +1,8 @@
1
1
  import * as _nuxt_schema from '@nuxt/schema';
2
- import { M as ModuleOptions } from './shared/storefront-nuxt.1cbf9601.js';
3
- export { e as AdditionalShopConfig, A as AppKeys, d as AuthenticationConfig, B as BapiConfig, b as CacheConfig, i as CheckoutEvent, C as CheckoutShopConfig, O as OauthConfig, P as PublicShopConfig, c as RedirectsConfig, R as RedisConfig, a as SessionConfig, f as ShopConfig, g as ShopConfigIndexed, S as StorageProvider, h as StorefrontConfig } from './shared/storefront-nuxt.1cbf9601.js';
2
+ import { M as ModuleOptions } from './shared/storefront-nuxt.180408c8.js';
3
+ export { g as AdditionalShopConfig, A as AppKeys, f as AuthenticationConfig, B as BapiConfig, b as CacheConfig, k as CheckoutEvent, C as CheckoutShopConfig, O as OauthConfig, P as PublicShopConfig, e as RedirectsConfig, R as RedisConfig, a as SessionConfig, h as ShopConfig, i as ShopConfigIndexed, d as StorageConfig, c as StorageEntity, S as StorageProvider, j as StorefrontConfig } from './shared/storefront-nuxt.180408c8.js';
4
4
  export { LogLevel } from '@scayle/storefront-core';
5
+ import 'unstorage';
5
6
 
6
7
  declare const _default: _nuxt_schema.NuxtModule<ModuleOptions>;
7
8
 
package/dist/module.json CHANGED
@@ -4,5 +4,5 @@
4
4
  "compatibility": {
5
5
  "nuxt": "^3.7.0"
6
6
  },
7
- "version": "7.40.6"
7
+ "version": "7.42.0"
8
8
  }
package/dist/module.mjs CHANGED
@@ -28,10 +28,6 @@ const module = defineNuxtModule({
28
28
  host: "https://bapi.scayle.cloud/",
29
29
  token: ""
30
30
  },
31
- redis: {
32
- port: 6379,
33
- host: "localhost"
34
- },
35
31
  shopSelector: "domain",
36
32
  stores: {},
37
33
  log: {
@@ -146,6 +142,9 @@ const module = defineNuxtModule({
146
142
  nuxt.hook("prepare:types", ({ references }) => {
147
143
  references.push({ path: template.dst });
148
144
  });
145
+ addServerPlugin(
146
+ resolve("./runtime/nitro/plugins/nitroRuntimeStorageConfig")
147
+ );
149
148
  addServerPlugin(resolve("./runtime/nitro/plugins/nitroSetXPoweredByHeader"));
150
149
  nuxt.hooks.hook("nitro:config", (nitroConfig) => {
151
150
  nitroConfig.externals = nitroConfig.externals || {};
@@ -162,6 +161,8 @@ const module = defineNuxtModule({
162
161
  "server/middleware/oauth",
163
162
  "server/middleware/redirects",
164
163
  "server/middleware/cache",
164
+ "server/utils/cacheStorage",
165
+ "nitro/plugins/nitroRuntimeStorageConfig",
165
166
  "nitro/plugins/nitroSetXPoweredByHeader"
166
167
  ];
167
168
  runtimePaths.forEach((path) => {
package/dist/rpc.d.mts CHANGED
@@ -1,6 +1,7 @@
1
1
  import { RpcMethodName, RpcMethodParameters, RpcMethodReturnType, RpcContext } from '@scayle/storefront-core';
2
2
  import { NuxtApp } from 'nuxt/app';
3
- import { P as PublicShopConfig } from './shared/storefront-nuxt.1cbf9601.mjs';
3
+ import { P as PublicShopConfig } from './shared/storefront-nuxt.180408c8.mjs';
4
+ import 'unstorage';
4
5
 
5
6
  /**
6
7
  * rpcCall can be used to invoke an RPC method either on the client or server
package/dist/rpc.d.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  import { RpcMethodName, RpcMethodParameters, RpcMethodReturnType, RpcContext } from '@scayle/storefront-core';
2
2
  import { NuxtApp } from 'nuxt/app';
3
- import { P as PublicShopConfig } from './shared/storefront-nuxt.1cbf9601.js';
3
+ import { P as PublicShopConfig } from './shared/storefront-nuxt.180408c8.js';
4
+ import 'unstorage';
4
5
 
5
6
  /**
6
7
  * rpcCall can be used to invoke an RPC method either on the client or server
@@ -13,6 +13,7 @@ function getFetch(nuxtApp, log) {
13
13
  export const useRpc = async (method, key, params, options = { autoFetch: true, lazy: false }) => {
14
14
  const currentShop = useCurrentShop();
15
15
  const log = useCoreLog("rpc");
16
+ const nuxtApp = useNuxtApp();
16
17
  const isAutoFetchEnabled = options?.autoFetch ?? true;
17
18
  log.debug(`useRpc: ${method}`);
18
19
  const data = useState(`${method}-${key}-data`);
@@ -27,7 +28,7 @@ export const useRpc = async (method, key, params, options = { autoFetch: true, l
27
28
  status.value = "pending";
28
29
  fetching.value = true;
29
30
  const apiBasePath = currentShop.value?.apiBasePath ?? "/api";
30
- const fetch2 = getFetch(useNuxtApp(), log);
31
+ const fetch2 = getFetch(nuxtApp, log);
31
32
  data.value = await fetch2(`/rpc/${method}`, {
32
33
  // @ts-ignore
33
34
  method: "POST",
@@ -6,6 +6,7 @@ export const useSearch = ({ params, key = "search" } = {}) => {
6
6
  `${key}-data`,
7
7
  () => void 0
8
8
  );
9
+ const nuxtApp = useNuxtApp();
9
10
  const searchQuery = useState(`${key}-searchQuery`, () => "");
10
11
  const pending = useState(`${key}-pending`, () => false);
11
12
  const error = useState(`${key}-error`, () => void 0);
@@ -19,7 +20,7 @@ export const useSearch = ({ params, key = "search" } = {}) => {
19
20
  }
20
21
  try {
21
22
  data.value = await rpcCall(
22
- useNuxtApp(),
23
+ nuxtApp,
23
24
  "searchProducts",
24
25
  toValue(shop)
25
26
  )({
@@ -0,0 +1,2 @@
1
+ declare const _default: any;
2
+ export default _default;
@@ -0,0 +1,159 @@
1
+ import memoryDriver from "unstorage/drivers/memory";
2
+ import { builtinDrivers } from "unstorage";
3
+ import { createConsola } from "consola";
4
+ import {
5
+ STORAGE_MOUNT_CACHE,
6
+ STORAGE_MOUNT_SESSION
7
+ } from "../../server/utils/cacheStorage.mjs";
8
+ import createLog from "../../createLog.mjs";
9
+ import { defineNitroPlugin, useRuntimeConfig, useStorage } from "#imports";
10
+ async function createMountDriver(options) {
11
+ if (options?.driver) {
12
+ const driver = await import(
13
+ // @ts-ignore
14
+ builtinDrivers[options.driver] || options.driver
15
+ ).then((r) => r.default || r);
16
+ return driver(options ?? {});
17
+ }
18
+ return memoryDriver();
19
+ }
20
+ async function mountStorage(storage, options) {
21
+ const { config, base } = options;
22
+ const mounts = storage.getMounts().map((existingMount) => existingMount.base.replace(":", ""));
23
+ if (!mounts.includes(base)) {
24
+ if (config) {
25
+ storage.mount(base, await createMountDriver(config));
26
+ } else {
27
+ storage.mount(base, await createMountDriver());
28
+ }
29
+ }
30
+ }
31
+ function transformLegacyConfig(provider = "memory", mode, log, redis, shopId = void 0) {
32
+ log.warn(
33
+ `${shopId ? "Shop " + shopId + " Storage" : "Global Storage"}: Using legacy storage config for ${mode}. The \`provider\` and \`redis\` options are deprecated.`
34
+ );
35
+ return {
36
+ driver: provider,
37
+ ...redis,
38
+ // For backwards compatability. Sessions previously used a hardcoded db 1 for sessions
39
+ ...mode === "session" ? { db: 1 } : {}
40
+ };
41
+ }
42
+ function getCacheConfig(config, log) {
43
+ if (config.storefront.storage?.cache) {
44
+ return config.storefront.storage?.cache;
45
+ }
46
+ if (!config.storefront.cache?.provider && !config.storefront?.redis) {
47
+ log.error(
48
+ `Failed to initialize global cache storage configuration. Neither new 'storefront.storage.cache' option nor legacy 'storefront.cache.provider' is set.`
49
+ );
50
+ return {};
51
+ }
52
+ return transformLegacyConfig(
53
+ config.storefront.cache?.provider,
54
+ "cache",
55
+ log,
56
+ config.storefront?.redis ?? {}
57
+ );
58
+ }
59
+ function getSessionConfig(config, log) {
60
+ if (config.storefront.storage?.session) {
61
+ return config.storefront.storage?.session;
62
+ }
63
+ if (!config.storefront.session?.provider && !config.storefront?.redis) {
64
+ log.error(
65
+ `Failed to initialize global session storage configuration. Neither new 'storefront.storage.session' option nor legacy 'storefront.session.provider' is set.`
66
+ );
67
+ return {};
68
+ }
69
+ return transformLegacyConfig(
70
+ config.storefront.session?.provider,
71
+ "session",
72
+ log,
73
+ config.storefront?.redis ?? {}
74
+ );
75
+ }
76
+ function getShopCacheConfig(config, shop, log) {
77
+ const storageConfig = shop.storage?.cache ?? config.storefront.storage?.cache;
78
+ if (storageConfig) {
79
+ return storageConfig;
80
+ }
81
+ const cacheProvider = config.storefront.cache?.provider;
82
+ const useLegacyShopConfig = !!cacheProvider || !!shop.redis || !!config.storefront.redis;
83
+ if (!useLegacyShopConfig) {
84
+ log.error(
85
+ `Failed to initialize shop ${shop.shopId} cache storage configuration. Neither new 'storefront.storage.session' option nor legacy 'storefront.session.provider' is set.`
86
+ );
87
+ return {};
88
+ }
89
+ return transformLegacyConfig(
90
+ cacheProvider,
91
+ "cache",
92
+ log,
93
+ shop.redis ?? config.storefront.redis ?? {},
94
+ shop.shopId
95
+ );
96
+ }
97
+ function getShopSessionConfig(config, shop, log) {
98
+ const storageConfig = shop.storage?.session ?? config.storefront.storage?.session;
99
+ if (storageConfig) {
100
+ return storageConfig;
101
+ }
102
+ const sessionProvider = shop.sessionConfig?.provider ?? config.storefront.session?.provider;
103
+ const useLegacyShopConfig = !!sessionProvider || !!shop.redis || !!config.storefront.redis;
104
+ if (!useLegacyShopConfig) {
105
+ log.error(
106
+ `Failed to initialize shop ${shop.shopId} session storage configuration. Neither new 'storefront.storage.session' option nor legacy 'storefront.session.provider' is set.`
107
+ );
108
+ return {};
109
+ }
110
+ return transformLegacyConfig(
111
+ sessionProvider,
112
+ "session",
113
+ log,
114
+ shop.redis ?? config.storefront.redis ?? {},
115
+ shop.shopId
116
+ );
117
+ }
118
+ export default defineNitroPlugin(async () => {
119
+ const storage = useStorage();
120
+ const config = useRuntimeConfig();
121
+ const log = createLog(
122
+ createConsola,
123
+ config.storefront.log.name,
124
+ config.storefront.log.level
125
+ );
126
+ const shops = config.storefront.stores;
127
+ try {
128
+ const globalCacheConfig = getCacheConfig(config, log);
129
+ await mountStorage(storage, {
130
+ base: STORAGE_MOUNT_CACHE,
131
+ config: globalCacheConfig
132
+ });
133
+ const globalSessionConfig = getSessionConfig(config, log);
134
+ await mountStorage(storage, {
135
+ base: STORAGE_MOUNT_SESSION,
136
+ config: globalSessionConfig
137
+ });
138
+ for (const shop of Object.values(shops)) {
139
+ const shopCacheMount = `${STORAGE_MOUNT_CACHE}:${shop.shopId}`;
140
+ const shopSessionMount = `${STORAGE_MOUNT_SESSION}:${shop.shopId}`;
141
+ const cacheConfig = getShopCacheConfig(config, shop, log);
142
+ if (cacheConfig) {
143
+ await mountStorage(storage, {
144
+ base: shopCacheMount,
145
+ config: cacheConfig
146
+ });
147
+ }
148
+ const sessionConfig = getShopSessionConfig(config, shop, log);
149
+ if (sessionConfig) {
150
+ await mountStorage(storage, {
151
+ base: shopSessionMount,
152
+ config: sessionConfig
153
+ });
154
+ }
155
+ }
156
+ } catch (error) {
157
+ log.error("Unable to create required cache driver during startup.", error);
158
+ }
159
+ });
@@ -2,12 +2,10 @@ import { defineEventHandler, getRequestURL } from "h3";
2
2
  import { createConsola } from "consola";
3
3
  import { createRemoteJWKSet, decodeJwt } from "jose";
4
4
  import { randomUUID } from "uncrypto";
5
- import redisDriver from "unstorage/drivers/redis";
6
- import memoryDriver from "unstorage/drivers/memory";
7
- import { createStorage } from "unstorage";
8
- import { useSession, UnstorageSessionStore } from "@scayle/h3-session";
5
+ import { useSession } from "@scayle/h3-session";
9
6
  import { buildContext } from "../../context.mjs";
10
7
  import createLog from "../../createLog.mjs";
8
+ import { useCacheStorage, useSessionStorage } from "../utils/cacheStorage.mjs";
11
9
  import {
12
10
  convertStoresToList,
13
11
  getCurrentShopForRequest,
@@ -15,7 +13,6 @@ import {
15
13
  } from "./bootstrap.utils.mjs";
16
14
  import { useOauth } from "./oauth.mjs";
17
15
  import { useRedirects } from "./redirects.mjs";
18
- import { createCache } from "./cache.mjs";
19
16
  import { useRuntimeConfig } from "#imports";
20
17
  const getShopConfig = (event, config) => {
21
18
  const storefrontConfig = config.storefront;
@@ -25,41 +22,6 @@ const getShopConfig = (event, config) => {
25
22
  );
26
23
  return $shopConfig;
27
24
  };
28
- const memoryStorage = memoryDriver();
29
- function createSessionStore(sessionConfig, redisConfig, log) {
30
- const ioredisConfig = {
31
- ..."user" in redisConfig && {
32
- username: redisConfig.user
33
- },
34
- ..."password" in redisConfig && {
35
- password: redisConfig.password
36
- },
37
- host: redisConfig.host,
38
- port: redisConfig.port,
39
- db: 1,
40
- tls: redisConfig.sslTransit ? {} : void 0
41
- };
42
- if (sessionConfig.provider === "memory") {
43
- log.warn("Creating in-memory session storage");
44
- log.warn("In-memory storage should not be used in production");
45
- return new UnstorageSessionStore(
46
- createStorage({
47
- driver: memoryStorage
48
- })
49
- );
50
- }
51
- log.debug(
52
- `Creating redis session storage. host: ${ioredisConfig.host} port: ${ioredisConfig.port} db: ${ioredisConfig.db} tls: ${ioredisConfig.tls}`
53
- );
54
- return new UnstorageSessionStore(
55
- createStorage({
56
- driver: redisDriver(ioredisConfig)
57
- }),
58
- {
59
- ttl: sessionConfig?.maxAge ?? 60 * 60 * 24
60
- }
61
- );
62
- }
63
25
  async function handleOauth(event, storefrontConfig, log) {
64
26
  if (!storefrontConfig.oauth.apiHost) {
65
27
  log.error("oauth.apiHost must be set in the module options.");
@@ -83,12 +45,10 @@ async function handleOauth(event, storefrontConfig, log) {
83
45
  async function bootstrap(event, log, url, $shopConfig, $storefrontConfig, apiBasePath, config) {
84
46
  const bootstrapLog = log.space("bootstrap");
85
47
  bootstrapLog.debug("Bootstrapping request: ", url.toString());
86
- const redisConfig = $shopConfig.redis ?? $storefrontConfig.redis;
87
- const $cache = createCache(
88
- $storefrontConfig.cache?.provider ?? "redis",
48
+ const $cache = useCacheStorage(
89
49
  String($shopConfig.shopId),
90
- bootstrapLog,
91
- { redis: redisConfig }
50
+ $shopConfig.shopId,
51
+ bootstrapLog
92
52
  );
93
53
  const sessionDefaults = {
94
54
  maxAge: void 0,
@@ -101,7 +61,11 @@ async function bootstrap(event, log, url, $shopConfig, $storefrontConfig, apiBas
101
61
  ...$storefrontConfig.session,
102
62
  ...$shopConfig.sessionConfig
103
63
  };
104
- const sessionStorage = createSessionStore(sessionConfig, redisConfig, log);
64
+ const sessionStorage = useSessionStorage(
65
+ sessionConfig,
66
+ $shopConfig.shopId,
67
+ log
68
+ );
105
69
  const generateSessionId = (event2) => {
106
70
  let userId;
107
71
  if (event2?.context.session?.data?.accessToken) {
@@ -0,0 +1,21 @@
1
+ import type { Log } from '@scayle/storefront-core';
2
+ import { UnstorageCache } from '@scayle/storefront-core/dist/cache/providers/unstorage';
3
+ import { type SessionStore } from '@scayle/h3-session';
4
+ import type { SessionConfig } from '../../../types/module';
5
+ export declare const STORAGE_MOUNT_BASE = "storefront";
6
+ export declare const STORAGE_MOUNT_CACHE = "storefront-cache";
7
+ export declare const STORAGE_MOUNT_SESSION = "storefront-session";
8
+ /**
9
+ * Create an unstorage-backed cache interface
10
+ * @param prefix
11
+ * @param shopId
12
+ * @param log
13
+ */
14
+ export declare function useCacheStorage(prefix: string, shopId: number, log: Log): UnstorageCache;
15
+ /**
16
+ * Create an unstorage-backed session cache interface
17
+ * @param sessionConfig
18
+ * @param shopId
19
+ * @param log
20
+ */
21
+ export declare function useSessionStorage(sessionConfig: SessionConfig, shopId: number, log: Log): SessionStore;
@@ -0,0 +1,37 @@
1
+ import { UnstorageCache } from "@scayle/storefront-core/dist/cache/providers/unstorage";
2
+ import { UnstorageSessionStore } from "@scayle/h3-session";
3
+ import { useStorage } from "#imports";
4
+ export const STORAGE_MOUNT_BASE = "storefront";
5
+ export const STORAGE_MOUNT_CACHE = `${STORAGE_MOUNT_BASE}-cache`;
6
+ export const STORAGE_MOUNT_SESSION = `${STORAGE_MOUNT_BASE}-session`;
7
+ function checkInMemoryProviderAndShowWarning(provider, mountpoint, log) {
8
+ if (provider !== "memory") {
9
+ return;
10
+ }
11
+ log.warn(
12
+ `Using in-memory cache for mountpoint ${mountpoint}. In-memory storage should not be used in production`
13
+ );
14
+ }
15
+ export function useCacheStorage(prefix, shopId, log) {
16
+ const storageBase = STORAGE_MOUNT_CACHE;
17
+ const mountPoint = `${storageBase}:${shopId}`;
18
+ const storage = useStorage(mountPoint);
19
+ const provider = storage.getMount(mountPoint)?.driver.name;
20
+ checkInMemoryProviderAndShowWarning(provider, mountPoint, log);
21
+ log.debug(
22
+ `Using '${provider}' on mount '${mountPoint}' as cache storage driver`
23
+ );
24
+ return new UnstorageCache(storage, prefix);
25
+ }
26
+ export function useSessionStorage(sessionConfig, shopId, log) {
27
+ const storageBase = STORAGE_MOUNT_SESSION;
28
+ const mountPoint = `${storageBase}:${shopId}`;
29
+ const storage = useStorage(mountPoint);
30
+ const provider = storage.getMount(mountPoint)?.driver.name;
31
+ const ttl = sessionConfig?.maxAge ?? 60 * 60 * 24;
32
+ checkInMemoryProviderAndShowWarning(provider, mountPoint, log);
33
+ log.debug(
34
+ `Using '${provider}' on mount '${mountPoint}' as session storage driver`
35
+ );
36
+ return new UnstorageSessionStore(storage, { ttl });
37
+ }
@@ -1,4 +1,5 @@
1
1
  import { LogLevel, HashAlgorithm, WithParams, ShopUser } from '@scayle/storefront-core';
2
+ import { BuiltinDriverName, BuiltinDriverOptions } from 'unstorage';
2
3
 
3
4
  type StorageProvider = 'memory' | 'redis';
4
5
  type CheckoutShopConfig = {
@@ -38,18 +39,22 @@ type SessionConfig = Partial<{
38
39
  domain: string;
39
40
  /**
40
41
  * The provider to use for the persistent storage.
42
+ * @deprecated Storefront Core is now relying on a unified cache configuration. Use the storage option instead.
41
43
  */
42
- provider: StorageProvider;
44
+ provider?: StorageProvider;
43
45
  }>;
44
46
  interface CacheConfig {
47
+ /** @deprecated Storefront Core is now relying on a unified cache configuration. Use the storage option instead. */
45
48
  provider?: StorageProvider;
46
49
  auth?: {
47
50
  username: string;
48
51
  password: string;
49
52
  };
50
- ssr?: {};
51
53
  enabled?: boolean;
52
54
  }
55
+ /**
56
+ * @deprecated
57
+ */
53
58
  type RedisConfig = {
54
59
  port?: number;
55
60
  host?: string;
@@ -63,6 +68,16 @@ type RedisConfig = {
63
68
  user: string;
64
69
  password: string;
65
70
  };
71
+ type CustomDriverName = string & {
72
+ _custom?: any;
73
+ };
74
+ type StorageEntity<Driver extends BuiltinDriverName | CustomDriverName = any, DriverOptions = Driver extends keyof BuiltinDriverOptions ? BuiltinDriverOptions[Driver] : any> = {
75
+ driver: Driver;
76
+ } & DriverOptions;
77
+ interface StorageConfig {
78
+ cache?: StorageEntity;
79
+ session?: StorageEntity;
80
+ }
66
81
  interface BapiConfig {
67
82
  host: string;
68
83
  token: string;
@@ -104,9 +119,11 @@ interface ShopConfig extends AdditionalShopConfig {
104
119
  auth: {
105
120
  resetPasswordUrl: string;
106
121
  };
122
+ /** @deprecated shop-specific storefront.redis config is being removed in favor of global nitro.storage config */
107
123
  redis?: RedisConfig;
108
124
  bapi?: BapiConfig;
109
125
  appKeys?: AppKeys;
126
+ storage?: StorageConfig;
110
127
  }
111
128
  type ShopConfigIndexed = Record<string, ShopConfig>;
112
129
  interface PublicShopConfig extends Pick<ShopConfig, 'shopId' | 'domain' | 'path' | 'locale' | 'currency' | 'currencyFractionDigits'> {
@@ -116,7 +133,9 @@ interface PublicShopConfig extends Pick<ShopConfig, 'shopId' | 'domain' | 'path'
116
133
  interface StorefrontConfig {
117
134
  session?: SessionConfig;
118
135
  bapi: BapiConfig;
119
- redis: RedisConfig;
136
+ /** @deprecated Global storefront.redis config is being removed in favor of `storefront.storage` config */
137
+ redis?: RedisConfig;
138
+ storage?: StorageConfig;
120
139
  auth: AuthenticationConfig;
121
140
  oauth: OauthConfig;
122
141
  appKeys: AppKeys;
@@ -160,4 +179,4 @@ declare module '@nuxt/schema' {
160
179
  }
161
180
  }
162
181
 
163
- export type { AppKeys as A, BapiConfig as B, CheckoutShopConfig as C, ModuleOptions as M, OauthConfig as O, PublicShopConfig as P, RedisConfig as R, StorageProvider as S, SessionConfig as a, CacheConfig as b, RedirectsConfig as c, AuthenticationConfig as d, AdditionalShopConfig as e, ShopConfig as f, ShopConfigIndexed as g, StorefrontConfig as h, CheckoutEvent as i };
182
+ export type { AppKeys as A, BapiConfig as B, CheckoutShopConfig as C, ModuleOptions as M, OauthConfig as O, PublicShopConfig as P, RedisConfig as R, StorageProvider as S, SessionConfig as a, CacheConfig as b, StorageEntity as c, StorageConfig as d, RedirectsConfig as e, AuthenticationConfig as f, AdditionalShopConfig as g, ShopConfig as h, ShopConfigIndexed as i, StorefrontConfig as j, CheckoutEvent as k };
@@ -1,4 +1,5 @@
1
1
  import { LogLevel, HashAlgorithm, WithParams, ShopUser } from '@scayle/storefront-core';
2
+ import { BuiltinDriverName, BuiltinDriverOptions } from 'unstorage';
2
3
 
3
4
  type StorageProvider = 'memory' | 'redis';
4
5
  type CheckoutShopConfig = {
@@ -38,18 +39,22 @@ type SessionConfig = Partial<{
38
39
  domain: string;
39
40
  /**
40
41
  * The provider to use for the persistent storage.
42
+ * @deprecated Storefront Core is now relying on a unified cache configuration. Use the storage option instead.
41
43
  */
42
- provider: StorageProvider;
44
+ provider?: StorageProvider;
43
45
  }>;
44
46
  interface CacheConfig {
47
+ /** @deprecated Storefront Core is now relying on a unified cache configuration. Use the storage option instead. */
45
48
  provider?: StorageProvider;
46
49
  auth?: {
47
50
  username: string;
48
51
  password: string;
49
52
  };
50
- ssr?: {};
51
53
  enabled?: boolean;
52
54
  }
55
+ /**
56
+ * @deprecated
57
+ */
53
58
  type RedisConfig = {
54
59
  port?: number;
55
60
  host?: string;
@@ -63,6 +68,16 @@ type RedisConfig = {
63
68
  user: string;
64
69
  password: string;
65
70
  };
71
+ type CustomDriverName = string & {
72
+ _custom?: any;
73
+ };
74
+ type StorageEntity<Driver extends BuiltinDriverName | CustomDriverName = any, DriverOptions = Driver extends keyof BuiltinDriverOptions ? BuiltinDriverOptions[Driver] : any> = {
75
+ driver: Driver;
76
+ } & DriverOptions;
77
+ interface StorageConfig {
78
+ cache?: StorageEntity;
79
+ session?: StorageEntity;
80
+ }
66
81
  interface BapiConfig {
67
82
  host: string;
68
83
  token: string;
@@ -104,9 +119,11 @@ interface ShopConfig extends AdditionalShopConfig {
104
119
  auth: {
105
120
  resetPasswordUrl: string;
106
121
  };
122
+ /** @deprecated shop-specific storefront.redis config is being removed in favor of global nitro.storage config */
107
123
  redis?: RedisConfig;
108
124
  bapi?: BapiConfig;
109
125
  appKeys?: AppKeys;
126
+ storage?: StorageConfig;
110
127
  }
111
128
  type ShopConfigIndexed = Record<string, ShopConfig>;
112
129
  interface PublicShopConfig extends Pick<ShopConfig, 'shopId' | 'domain' | 'path' | 'locale' | 'currency' | 'currencyFractionDigits'> {
@@ -116,7 +133,9 @@ interface PublicShopConfig extends Pick<ShopConfig, 'shopId' | 'domain' | 'path'
116
133
  interface StorefrontConfig {
117
134
  session?: SessionConfig;
118
135
  bapi: BapiConfig;
119
- redis: RedisConfig;
136
+ /** @deprecated Global storefront.redis config is being removed in favor of `storefront.storage` config */
137
+ redis?: RedisConfig;
138
+ storage?: StorageConfig;
120
139
  auth: AuthenticationConfig;
121
140
  oauth: OauthConfig;
122
141
  appKeys: AppKeys;
@@ -160,4 +179,4 @@ declare module '@nuxt/schema' {
160
179
  }
161
180
  }
162
181
 
163
- export type { AppKeys as A, BapiConfig as B, CheckoutShopConfig as C, ModuleOptions as M, OauthConfig as O, PublicShopConfig as P, RedisConfig as R, StorageProvider as S, SessionConfig as a, CacheConfig as b, RedirectsConfig as c, AuthenticationConfig as d, AdditionalShopConfig as e, ShopConfig as f, ShopConfigIndexed as g, StorefrontConfig as h, CheckoutEvent as i };
182
+ export type { AppKeys as A, BapiConfig as B, CheckoutShopConfig as C, ModuleOptions as M, OauthConfig as O, PublicShopConfig as P, RedisConfig as R, StorageProvider as S, SessionConfig as a, CacheConfig as b, StorageEntity as c, StorageConfig as d, RedirectsConfig as e, AuthenticationConfig as f, AdditionalShopConfig as g, ShopConfig as h, ShopConfigIndexed as i, StorefrontConfig as j, CheckoutEvent as k };
package/dist/types.d.mts CHANGED
@@ -13,4 +13,4 @@ declare module 'nuxt/schema' {
13
13
  }
14
14
 
15
15
 
16
- export type { AdditionalShopConfig, AppKeys, AuthenticationConfig, BapiConfig, CacheConfig, CheckoutEvent, CheckoutShopConfig, OauthConfig, PublicShopConfig, RedirectsConfig, RedisConfig, SessionConfig, ShopConfig, ShopConfigIndexed, StorageProvider, StorefrontConfig } from './module'
16
+ export type { AdditionalShopConfig, AppKeys, AuthenticationConfig, BapiConfig, CacheConfig, CheckoutEvent, CheckoutShopConfig, OauthConfig, PublicShopConfig, RedirectsConfig, RedisConfig, SessionConfig, ShopConfig, ShopConfigIndexed, StorageConfig, StorageEntity, StorageProvider, StorefrontConfig } from './module'
package/dist/types.d.ts CHANGED
@@ -13,4 +13,4 @@ declare module 'nuxt/schema' {
13
13
  }
14
14
 
15
15
 
16
- export type { AdditionalShopConfig, AppKeys, AuthenticationConfig, BapiConfig, CacheConfig, CheckoutEvent, CheckoutShopConfig, OauthConfig, PublicShopConfig, RedirectsConfig, RedisConfig, SessionConfig, ShopConfig, ShopConfigIndexed, StorageProvider, StorefrontConfig } from './module'
16
+ export type { AdditionalShopConfig, AppKeys, AuthenticationConfig, BapiConfig, CacheConfig, CheckoutEvent, CheckoutShopConfig, OauthConfig, PublicShopConfig, RedirectsConfig, RedisConfig, SessionConfig, ShopConfig, ShopConfigIndexed, StorageConfig, StorageEntity, StorageProvider, StorefrontConfig } from './module'
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@scayle/storefront-nuxt",
3
3
  "type": "module",
4
- "version": "7.41.0",
4
+ "version": "7.42.1",
5
5
  "description": "Nuxt integration for the SCAYLE Commerce Engine and Storefront API",
6
6
  "author": "SCAYLE Commerce Engine",
7
7
  "license": "MIT",
@@ -60,7 +60,7 @@
60
60
  "test:watch": "vitest watch"
61
61
  },
62
62
  "dependencies": {
63
- "@nuxt/kit": "3.8.1",
63
+ "@nuxt/kit": "3.8.2",
64
64
  "@scayle/h3-session": "0.3.4",
65
65
  "@scayle/storefront-core": "7.28.1",
66
66
  "@vueuse/core": "10.6.1",
@@ -69,29 +69,29 @@
69
69
  "defu": "6.1.3",
70
70
  "h3": "1.9.0",
71
71
  "jose": "4.15.4",
72
- "nitropack": "2.8.0",
72
+ "nitropack": "2.8.1",
73
73
  "ofetch": "1.3.3",
74
74
  "radash": "11.0.0",
75
75
  "uncrypto": "0.1.3",
76
+ "unstorage": "1.10.1",
76
77
  "vue-router": "4.2.5",
77
78
  "yn": "5.0.0"
78
79
  },
79
80
  "devDependencies": {
80
81
  "@nuxt/module-builder": "0.5.4",
81
- "@nuxt/schema": "3.8.1",
82
+ "@nuxt/schema": "3.8.2",
82
83
  "@nuxt/test-utils": "3.8.1",
83
84
  "@scayle/eslint-config-storefront": "3.2.5",
84
85
  "@scayle/prettier-config-storefront": "2.0.2",
85
- "@types/node": "20.10.0",
86
+ "@types/node": "20.10.1",
86
87
  "eslint": "8.54.0",
87
88
  "eslint-formatter-gitlab": "5.1.0",
88
89
  "node-mocks-http": "1.13.0",
89
- "nuxt": "3.8.1",
90
+ "nuxt": "3.8.2",
90
91
  "prettier": "3.0.0",
91
92
  "publint": "0.2.5",
92
- "unstorage": "1.10.1",
93
93
  "vitest": "0.34.6",
94
- "vue-tsc": "1.8.22"
94
+ "vue-tsc": "1.8.24"
95
95
  },
96
96
  "peerDependencies": {
97
97
  "nuxt": ">=3.8.1",
@@ -99,16 +99,16 @@
99
99
  "vue": ">=3.3.0"
100
100
  },
101
101
  "resolutions": {
102
- "@vue/compiler-core": "3.3.8",
103
- "@vue/shared": "3.3.8",
104
- "@vue/compiler-dom": "3.3.8",
105
- "@vue/compiler-sfc": "3.3.8",
106
- "@vue/compiler-ssr": "3.3.8",
107
- "@vue/reactivity-transform": "3.3.8",
108
- "@vue/reactivity": "3.3.8",
109
- "@vue/runtime-core": "3.3.8",
110
- "@vue/runtime-dom": "3.3.8",
111
- "@vue/server-renderer": "3.3.8"
102
+ "@vue/compiler-core": "3.3.9",
103
+ "@vue/shared": "3.3.9",
104
+ "@vue/compiler-dom": "3.3.9",
105
+ "@vue/compiler-sfc": "3.3.9",
106
+ "@vue/compiler-ssr": "3.3.9",
107
+ "@vue/reactivity-transform": "3.3.9",
108
+ "@vue/reactivity": "3.3.9",
109
+ "@vue/runtime-core": "3.3.9",
110
+ "@vue/runtime-dom": "3.3.9",
111
+ "@vue/server-renderer": "3.3.9"
112
112
  },
113
113
  "volta": {
114
114
  "node": "20.10.0"
@@ -1,13 +0,0 @@
1
- import type { Log } from '@scayle/storefront-core';
2
- import { UnstorageCache } from '@scayle/storefront-core/dist/cache/providers/unstorage';
3
- import type { RedisConfig, StorageProvider } from '../../../types/module';
4
- /**
5
- * Create an unstorage-backed cache interface
6
- * @param provider
7
- * @param prefix
8
- * @param log
9
- * @param options
10
- */
11
- export declare function createCache(provider: StorageProvider, prefix: string, log: Log, options?: {
12
- redis?: RedisConfig;
13
- }): UnstorageCache;
@@ -1,44 +0,0 @@
1
- import redisDriver from "unstorage/drivers/redis";
2
- import memoryDriver from "unstorage/drivers/memory";
3
- import { UnstorageCache } from "@scayle/storefront-core/dist/cache/providers/unstorage";
4
- import { createStorage } from "unstorage";
5
- const memoryStorage = memoryDriver();
6
- export function createCache(provider, prefix, log, options) {
7
- if (provider === "memory") {
8
- log.warn("Creating in-memory redirect cache");
9
- log.warn("In-memory storage should not be used in production");
10
- return new UnstorageCache(
11
- createStorage({
12
- driver: memoryStorage
13
- }),
14
- prefix
15
- );
16
- }
17
- if (provider === "redis") {
18
- const redisConfig = options?.redis;
19
- if (!redisConfig) {
20
- throw Error("options.redis must be specified for the redis provider");
21
- }
22
- const ioredisConfig = {
23
- ..."user" in redisConfig && {
24
- username: redisConfig.user
25
- },
26
- ..."password" in redisConfig && {
27
- password: redisConfig.password
28
- },
29
- host: redisConfig.host,
30
- port: redisConfig.port,
31
- tls: redisConfig.sslTransit ? {} : void 0
32
- };
33
- log.debug(
34
- `Creating redis redirect cache. host: ${ioredisConfig.host} port: ${ioredisConfig.port} db: ${ioredisConfig.db} tls: ${ioredisConfig.tls}`
35
- );
36
- return new UnstorageCache(
37
- createStorage({
38
- driver: redisDriver(ioredisConfig)
39
- }),
40
- prefix
41
- );
42
- }
43
- throw Error("Unknown cache provider");
44
- }